Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

ドメイン駆動設計のためのオブジェクト指向入門

33,665 views

Published on

関西DDD.java 勉強会 2016-3-5
(DDD Alliance 勉強会 2016-1-21 @東京の京都再演版)

Published in: Software

ドメイン駆動設計のためのオブジェクト指向入門

  1. 1. ドメイン駆動設計のための オブジェクト指向入門 2016年3月5日 増田亨(@masuda220) 有限会社システム設計 代表 ギルドワークス株式会社 取締役 1 DDD Alliance 2016年1月21日@東京の再演 関西DDD.java
  2. 2. 本日の内容 • 基礎知識 – ドメイン駆動設計 – オブジェクト指向設計 • 事例「転職支援サービス」 – システムの概要 – ドメイン層の隔離 初級・中級・上級 – ドメインオブジェクト 「善い部品」 – より深い洞察に向かうリファクタリング • 学び方のヒント – 言葉⇒体験⇒言葉 – 推薦図書/参考資料 2
  3. 3. 基礎知識 ドメイン駆動設計 オブジェクト指向設計 3
  4. 4. ドメイン層のソフトウェア設計 オブジェクト指向設計 インクリメンタルな設計(XP) ドメイン駆動設計 4
  5. 5. ドメイン駆動設計 ドメイン モデル ドメインの 「重要な関心事」を 鋭く説明する 選び抜かれた 重要な関心事を コードで表現する 会話を繰り返して 「要点」を明確にする 「重要な語彙」を チームで合意する 1章 2章 3章 5 第1章 ドメインの知識をかみ砕く 第3章 モデルと実装を結びつける 第2章 言葉を使った意図の伝達
  6. 6. ドメイン駆動設計 ドメインを分析する人がコードを書く 毎日、分析し、毎日、コードを書く 「会話」をしながら意図を確認する コードを書く人がドメインを分析する 分析・設計・実装を「フェーズ」に分けない 分析・設計・実装の「担当者」を別にしない 「コード」と動くソフトウェアで意図を確認する 分析と実装を、同じ人が毎日やるなら、ドキュメントは不要 オブジェクト指向/XP 6 保守の現場ではあたりまえ?
  7. 7. ドメインを学び 学んだことを コードで表現する ドメイン駆動設計 7 オブジェクト指向/XP
  8. 8. ドメインの隔離 ドメインの知識の置き場所 ソフトウェアの中核 他の3層に依存しない 4章 8
  9. 9. 実装 業務の知識の置き場所 ソフトウェアの中核 他の3層に依存しない 9
  10. 10. ドメイン層のオブジェクト • Plain Old Java Object – Not Plain Old Java Beans (getters/setters) • 業務の「関心事」を表現したオブジェクト – 業務で知りたいこと(誰が、いつ、なにを、なぜ、…) – 業務のルール(制約、しきい値、手順、…) – ルールが破られた時の業務ルール(制限、通知、…) • 業務サービスの実行役 – 「判断」の結果を返す – 「計算」の結果を返す – 「加工」の結果を返す – (基本データ型は返さない) 10 業務上の「判断」「計算」「加工」
  11. 11. オブジェクト指向:コードの整理 • 「クラス」単位に関連するコードを整理する • どこに何が書いてあるか特定しやすくなる • 変更があちこちに飛び火しない – データクラスと機能クラスを分けると、機能クラス に、コードの重複が増え、変更が飛び火する • 変更した箇所のテストOKなら全体もOK 11
  12. 12. アンチパターン 変更コストが高くなる設計 機能クラスAと、機能クラスBに、同じデータを扱うロジックが重複する 変更時に、読む範囲が広がり、変更箇所が増え、テスト範囲が広がる 12 ビュー コントローラ サービス データアクセス … ビュー コントローラ サービス データアクセス …
  13. 13. 変更コストが下がる設計 判断・計算・加工のロジックを一箇所に集める 変更時に、一箇所を読み、一箇所を変更し、一箇所テストする 13
  14. 14. オブジェクト指向:ドメイン層の構造 集約(アグリーゲート)が開発単位 ・分析+設計+実装 × 画面単位の分析・設計・実装 × 機能単位の分析・設計・実装 14
  15. 15. オブジェクト指向:ネットワーク構造 • システムは、オブジェクトが集まったネットワーク 構造 – オブジェクト同士で、依頼と応答を繰り返す • 強く関連する部品は「集約」する(アグリゲート) • 「アグリゲート」同士は、分離性を高め、必要最 小限につなげる • 「変更」を前提にしたネットワーク構造 – メタファ • LAN(オブジェクトの集約) • INTERNET(システム全体) 15
  16. 16. オブジェクト指向:工法 • 「変更」が前提だから – インクリメンタル(+1)に開発する – 少しずつ成長する全体 – 毎日変化する全体 • いつでもすぐに変更できるように – 分析・設計・実装で「フェーズ」を分けない – 分析・設計・実装を同じ人間が担当する – 毎日、分析・設計・実装をする 16
  17. 17. オブジェクトの設計 独自の「型」を設計する オブジェクトの「コラボレーション」を設計する 実現手段(how)を隠ぺいする 17
  18. 18. オブジェクトの設計 独自の「型」を設計する • 「型」 – クラス/インタフェース – オブジェクトの種類 – 関心事の分類 – メソッドの引数 – メソッドの戻り値 • ドメイン層は「独自の型」だらけにする – 「独自の型」=利用者の関心事 – 基本データ型=コンピュータの関心事 18 5章 モデルの構成要素 9章 概念を掘り出す 10章 概念の輪郭
  19. 19. オブジェクトの「コラボレーション」の設計 責任駆動設計 コラボレーション 共同作業 協調動作 メッセージ・ パッシング オブジェクト インタラクション オブジェクト コミュニケーション 役割分担 擬人化 相互作用 契約による設計SRP GRASP どれもわかりにくい言葉だが、基本は同じことをいっている 19 ご近所 (neigborhood) 集約 (aggregate) 集団 (cluster) あるオブジェクトと別のオブジェクトが、協力して仕事をする
  20. 20. 「コラボレーション」の設計原則 • お互いが対等の立場のオブジェクト • 双方向の権利と義務、その明文化 • 一時的な関係(契約期間) • 相手を詳しく知りたがってはいけない 契約による設計 Design by Contract by バートランド・メイヤー 与えた影響: ワーフスブラック 「オブジェクトデザイン」 ケントベック 「XP」「リファクタリング」「実装パターン」 エリックエヴァンス 「ドメイン駆動設計」 … 20 注意! assert 構文が契約による設計ではない
  21. 21. 「契約による設計」 理解するには、現実世界の「契約」の知識が必要。 技術者にはあまり良いメタファーではない。 一方、ビジネスでは「契約」は重要な関心事。 業務ルールの基本でもある。 「ドメイン駆動設計」をやるなら「契約」を勉強しよう。 「業務知識」の学習と、「契約による設計」の学習 で二度おいしい。 21
  22. 22. 「契約による設計」 悪い関係 顧客クラスが判断・加工・計算をする(機能クラス) そのために供給者クラスは生データを提供する (データクラス) 22 良い関係 顧客クラスが、判断・加工・計算を「依頼」する 供給者クラスが適切に、判断・加工・計算をする 相手にまかせるから「契約」が重要になる 自分でやるなら契約はいらない
  23. 23. 「契約による設計」 23 悪い関係 顧客クラスが判断・加工・計算をする そのために供給者クラスは生データを提供する String オブジェクトから char[] getCharArray()して、 顧客クラスで、char[]を操作しないよね? BigIntegerオブジェクトから int[] getIntArray() して、 顧客クラスで、int[] の計算しないよね? LocalDate オブジェクトから、 get(year), get(month), get(day) して、顧客クラスで日付計算しないよね? getter/setterだけのデータクラスを使うのは、そういう ことをしている String BigInteger LocalDate …
  24. 24. オブジェクトの設計 実現手段(how)を隠ぺいする if/switch for/while List, Set, Map Stream char byte ==, >=, <= +, - String StringBuilder LocalDate Java 言語仕様 Java API null こういうものを ドメイン層で「表だって」 使ってはいけません。 徹底的に隠しましょう。 業務の関心事の表現手段として「不適切」 特に public なメソッド(=業務知識の表現)の 引数の「型」、戻り値の「型」として使わない。 配列[] 24 ユビキタス言語ではない BigInteger BigDecimal int,short,long float,double boolean Optional
  25. 25. ドメイン層では 実現手段(how)は隠ぺいする • int/String/LocalDateは「値オブジェクト」で包む • for/while/List/Set/Map/Stream/Optional は、 特別なクラス(「ファーストクラスコレクション」)で 包む • 「列挙型」(enum)で、if/switchを減らす • Bean Validation で、if を減らす • null/Optional を渡さない/返さない • 基本データ型を渡さない/返さない • コレクション/配列を渡さない/返さない コード例は後ほど紹介 25
  26. 26. 事例の研究 「転職支援サービス」 アーキテクチャ コード例 メトリクス 26
  27. 27. 転職支援サービス 27
  28. 28. アーキテクチャ 28
  29. 29. ドメイン層の隔離 初級 中級 上級 フレームワークと規約 web/service/model/ datasource … 誰でもできる 貧血ドメインモデル 実際はドメインロジック が各層に飛び散る ドメインのロジックを プレゼンテーション層/ サービス層/データソー ス層からはがして、ドメイ ン層に「移動」する 浅い「リファクタリング」の 頻繁かつ丁寧な繰り返し 知識豊富になったドメイン層の 「見通し」を良くする 深い「リファクタリング」 「コア(主要な関心事)」の隔離 「コア(主要な関心事)」の抽象化 29 4章から7章 9章から12章 8章、13章、15章
  30. 30. コード例 求人情報(Offer) 30
  31. 31. アーキテクチャ 31
  32. 32. 32 この列の実装例
  33. 33. プレゼンテーション層 OfferController.java @Controller @RequestMapping("/offers/{offerId}") public class OfferController { @Autowired OfferService offerService; @ModelAttribute("offer") public Offer offer(@PathVariable("offerId") Integer id) { return offerService.findBy(new OfferIdentifier(id)); } @RequestMapping(value = "", method = RequestMethod.GET) public String show( @ModelAttribute("offer") Offer offer, Model model) { return "offers/offer"; } } 仕事番号を含むURL サービスのインジェクション Offerアグリゲートの取得 HTMLテンプレート名 ( offer.html ) 33
  34. 34. サービス層 OfferService.java @Service public class OfferService { @Autowired OfferRepository repository; public Offer findBy(OfferIdentifier id) { return repository.findBy(id); } public OfferSummaries listOf(Criteria criteria) { return repository.listOfOfferSummary(criteria); } } 検索条件 ドメインの「型」を渡し、ドメインの「型」を返す 基本データ型を使わない 34 リポジトリのインジェクション
  35. 35. データソース層 OfferDatasource.java @Repository public class OfferDataSource implements OfferRepository { @Autowired OfferMapper mapper; @Override public Offer findBy(OfferIdentifier id) { return mapper.findBy(id); } } SQL Mapperのインジェクション interface OfferMapper { Offer findBy(OfferIdentifier id); } <select id="findBy" resultMap="offer"> SELECT offer.offer_id, offer.title, ... </select> DAO自動生成のおまじない SQLと Offerオブジェクトのマッピング定義 ドメインの「型」を返す 35
  36. 36. 36 この列の実装例
  37. 37. ドメイン層 Offer.java public class Offer { OfferIdentifier id = new OfferIdentifier(); OfferTitle title = new OfferTitle(); Description description = new Description(); Features features = new Features(); EmploymentType employmentType = new EmploymentType(); Location location = new Location(); Holiday holiday = new Holiday(); AnnualSalaryRange annualSalaryRange = new AnnualSalaryRange(); CompanySummary company = new CompanySummary(); ... } Offer アグリゲートのルート 37 初期化
  38. 38. ドメイン層 OfferRepository.java public interface OfferRepository { Offer findBy(OfferIdentifier id); OfferSummaries listOfOfferSummary(Criteria criteria); } public class OfferSummaries { int totalCount; List<OfferSummary> values; … } public class OfferSummary { OfferIdentifier identifier = new OfferIdentifier(); OfferTitle title = new OfferTitle(); Description description = new Description(); Location location = new Location(); } 求人一覧用の要約オブジェクト OfferSummaries.java 求人一覧(ファーストクラスコレクション) OfferSummary.java 38
  39. 39. メトリクス クラス数とか行数とか 39
  40. 40. 転職支援サービス 40
  41. 41. アーキテクチャ 41
  42. 42. 42 Thymeleaf (HTMLフレンドリー) MyBatis (SQL フレンドリー)
  43. 43. メトリクス 項目 求職者 転職アドバイザ 画面種類(HTMLテンプレート) (内、登録系) 193 (47) 260 (46) プレゼンテーション層 @Controller 128 96 サービス層 @Service クラス 更新系機能(メソッド数) 参照系機能(メソッド数) 105 (90) (188) 100 (78) (173) ドメイン層のクラス数 内リポジトリ数(=アグリゲート数) クラス数/アグリゲート(単純平均) 1,110 (89) (11) 956 (75) (11) データソース層 @Repository + Mapper interface 185 174 SQL Map定義(SQLテンプレート) 79 77 テーブル数 303 ざっくり20か月、100人月くらい43
  44. 44. ドメイン層のクラスの行数 クラス数 行数 30行から60行で7割 10行以下はインタフェース宣言 44
  45. 45. クラス数が1,000くらいでは混乱しない 45 関連づけながら覚える 言葉のネットワークだから 集約単位に「知識」が グルーピングできているから この抜粋版で すでに10クラス こういう塊が100個
  46. 46. 語彙の整理 46 それぞれの集約の内部の語彙を、 一度に知る必要はない 語彙が1000語くらい では混乱しない 集約のルートのクラスを 覚えれば、全体を見通せる (業務の基本用語ばかり)
  47. 47. ドメインオブジェクト 「善い部品」 47 善い:地道に繰り返すべき正しい努力
  48. 48. 善い部品の基準 by メイヤー • 分解のしやすさ • 組み立てやすさ • わかりやすさ • 連続性 • 保護性 48 Δコード Δ仕様 この比率が1に近く かつ不連続に変化しないことが善い部品 副作用が波及する範囲が狭いこと
  49. 49. 善い部品の基準 by エヴァンス • 組み立てやすい部品 – 意図の明白なインタフェース – 副作用のない関数(immutable) – 表明(顧客クラスと供給者クラスの約束) • 内部を読まなくても、予測可能で、信頼できること • 適切に分解された部品 – 概念の輪郭 (ドメインの関心事の単位との一致) – 独立したクラス (import が少ないクラス) – 閉じた操作(引数も返す型も、自分自身と同じ型) • 独立性を高めることで、変更や組合せの副作用を減らす 49 10章 しなやかな設計
  50. 50. ドメインオブジェクトの設計 (おさらい) • 独自の「型」を設計する – コードの整理の単位 – 知識の表現の手段 • オブジェクトの「コラボレーション」の設計 – 役割分担 – 協力関係 • 実現手段(how)を隠ぺいする – Java 言語仕様の隠ぺい ( int, String, if, for , .. ) – Java API の隠ぺい ( Collection, Stream , … ) 50 5章 モデルの構成要素 9章 概念を掘り出す 10章 概念の輪郭
  51. 51. ドメインオブジェクト 「善い部品」 参照オブジェクト 値オブジェクト ファーストクラスコレクション 振る舞いを持つ区分定数 how より what 51
  52. 52. 参照オブジェクト (Entityパターン) 52
  53. 53. 参照オブジェクト ドメイン駆動設計の Entity パターン 53 集約のルート オブジェクトのコラボレーションの元締め 主要な関心事への参照点 顧客との会話の語彙の起点
  54. 54. 参照オブジェクト vs @Entity • 参照オブジェクト(ドメイン駆動設計のEntity) – 業務の主たる関心事の表現手段 – 集約のルート – どういう「データ」を持つかではなく「何を知りたいか」を表現する • JPA の @Entity – データの入れものクラス(基本データ型のかたまり) • テーブルのフラットな構造と対応づけ(@Tabel, @Column, @JoinColumn, …) • 設計と実装が基本データ型だらけになりがち – 業務の関心事との乖離 • 業務の関心事の基本は抽象データ型(計算結果や加工結果) • テーブル間のキーによる関連づけが、必ずしも業務の主たる関心事ではない – プログラムの変更コストがあがる • @Entity を使う機能クラスがあちこちにできて、同じコードが重複しがち • テーブルとオブジェクトの密結合が、リファクタリングの障害になる 54JPAは、ドメイン駆動設計を実践するための適切な手段ではない
  55. 55. 値オブジェクト 55
  56. 56. 値オブジェクト String List<String> BigDecimal Integer … LocalDate Long 起算日 InitialDate 期限 DueDate 有効期間 ValidTerm 金額 Money 数量 Quantity 単位 Unit 品名 ProductName 備考 Remarks 摘要 Abstract 言語で用意された「型」 (汎用) 独自に定義した「型」 (目的特化) 56
  57. 57. 値オブジェクト • 基礎部品:業務の関心事の基本語彙 – 日付、期間、数量、金額、単位、名称、備考、… • 目的に特化して制約をかける – String, BigDecimal, LocalDate, … 汎用のデータ型をラッ ピングする – 値の範囲、文字種、形式を業務要件に沿って制約する – 制約による「安定」 • ロジックの集約 – そのデータを使う判断・計算・加工のロジックを一箇所に 集める – コードの重複がなくなり、変更が楽になる 57
  58. 58. 値オブジェクトの実装パターン • 完全コンストラクタ – すべてのインスタンス変数は、生成時に設定 • 不変 – setter を書かない(状態を変えない) – 値を変更する時は、別のオブジェクトを生成して返す – 不変による「安定」 • ロジックの置き場所 – インスタンス変数を使った、判断・加工・計算 – 何もしないで素のデータを返す getter はNG 58
  59. 59. 実装例 59 public class NumberOfChangingJob { @NotNull(message = "転職回数を選択してください。", groups = Default.class) @Range(min=0, max=10, message="転職回数は0から10の間で入力してください。") Integer value = 0; … } public class PersonName { @NotEmpty(message = "名を入力してください。") String firstName = ""; @NotEmpty(message = "姓を入力してください。") String lastName = ""; public String fullName() { return String.format("%s %s", lastName, firstName); } } 転職回数は、その分野の専門家の微妙な関心事…
  60. 60. 実装例 60 public class DateOfBirth { Integer year = LocalDate.now().getYear() - 35; Integer month; Integer day; public LocalDate getValue() { return LocalDate.of(year, month, day); } @AssertTrue(message = "生年月日を入力してください") public boolean isNotEmpty() { if (year == null || month == null || day == null) return false; return true; } public String getAgeText() { return String.format("%s歳", getAge()); } } 年齢は、その分野の専門家の微妙な関心事…
  61. 61. 値オブジェクトの効果 • コードにドメインの言葉が増える (暗黙の概念が明示的に) – × String getName( Long id ) – ◎ PersonName fullName(CustomerNumber id) • コードの重複を防ぐ – データを使う判断・加工・計算のロジックを、データを 持つクラスに集約して、一元管理する • コードが安定する – 値の範囲や文字種を用途に合わせて限定 (不正データが混入しない) – 状態が変わらない(いつ参照しても同じ結果) 61 9章 概念を掘り出す 10章 概念の輪郭
  62. 62. 一覧オブジェクト (ファーストクラスコレクション) 62
  63. 63. 一覧オブジェクト (ファーストクラスコレクション) • ListやSetをラップしたドメインオブジェクト • Offers • MailBox • SkillSet • 「一覧」や「履歴」という関心事の表現 – 「一覧」は利用者の関心事が集中する場所 – 「一覧」の議論は、重要な関心事の発見の良い機会 • コレクションの操作は、コードがごちゃごちゃしや すく、変更の副作用が多い – クラスとして独立させ、そのクラスに閉じ込める 63 9章 概念を掘り出す 10章 概念の輪郭
  64. 64. 一覧オブジェクト vs. SQL 問合せ • SQLの抽出条件を単純にして、微妙な抽出や 加工は、一覧オブジェクトにやらせる、という 選択肢もある • どちらのやり方がドメインの関心事をうまく表 現できるか • 変更があった時に、どちらが楽で安全か • CPU/通信/メモリのコストダウンによって、適 用できる範囲が広がってきている 64
  65. 65. 区分オブジェクト (振る舞い持ったEnum) 65
  66. 66. 区分オブジェクト • 振る舞いを持った Enum • 区分ごとのロジックを別クラスに記述 • Java言語使用に組み込まれた Strategy/Stateパターン • if 文/switch文を書かない工夫 説明とコード例は、googleで 「場合わけの書き方あれこれ」で検索、 または技術評論社ムック本 「オブジェクト指向をきちんと使いたいあなたへ」 場合ごとのルールを理解し表現する道具 66
  67. 67. 実装例 67 interface PayAmount { Yen amount(); String name(); String description(); } //それぞれのクラスでインタフェースを実装する class DeadAmount implements PayAmount {...} class RetiredAmount implements PayAmount {...} class NormalAmount implements PayAmount {...} class Client { private PayAmount amount ; Yen getAmount() { return amount.getAmount(); } } 「給付金額」を知りたいクライアント側のクラス
  68. 68. 列挙を使った実装例 68 enum PaymentType{ dead( new DeadAmount() ), retired( new RetiredAmount() ), normal( new NormalAMount() ); private PayAmount amount; private PaymentType( Payamount amount ) { this.amount = amount; } Yen getAmount() { return amount.getAmount(); } } PaymentType type = PayamountType.valueOf("dead"); ... Yen amount = type.getAmount(); 区分ごとの生成も if文やswitch文は不要
  69. 69. 区分オブジェクトの効果 • 関心事の明示的なコード表現 • 複雑な if文記述の解消 – 区分ごとの分岐記述( if文 or switch文 )は、一箇所 になる – 場合によっては、まったく書かなくてよくなる • どこに何が書いてあるかわかりやすくなる – 区分ごとの業務ルールや知識のロジックの置き場所 をクラス単位で分離 • 区分の追加や削除をした時の、変更の副作用が 少ない 69 9章 概念を掘り出す 10章 概念の輪郭
  70. 70. How より What (意図の明確なインタフェース) 70
  71. 71. expireDate.add(-1); expireDate.previousDay(); expireDate.dayOfFinalAlert (); 業務要件:期限切れの前日にアラートメールを送る How より What 業務の関心事を明示的に表現する 71
  72. 72. 課金ポリシー 適用する() シーズン料金 レート() 夏料金 レート() 冬料金 レート() 料金 計算() <<interface>> 計算方法(How)を記述 料金の用語(What)をクラスで表現 計算()メソッドに埋もれ、 暗黙化する業務知識 シンプルな設計に見えるが、 ルールの変更・追加のたびに 計算()メソッドが肥大化し、 if 文が増殖する 業務知識をそのまま、クラスとして表現 複雑に見えるが、ルール変更・追加が、 楽で安全になる How より What 72 9章 概念を掘り出す 10章 概念の輪郭
  73. 73. 深い洞察に向かう リファクタリング 73 8章から13章
  74. 74. リリース後に発生したちょっとした改善 要望: スカウトの開封/未開封が見づらい 修正: メール状況で「未読」の場合、赤表示にした 74 増田 亨 (管理) 増田 亨 (管理)
  75. 75. 変更したコード +.mail-status-unread { + color: #990000; + font-weight: bold; +} css/custom.css -<td th:text="${mailSummary.mailStatus.name()}">返信済み </td> message/list.html +<td th:text="${mailSummary.mailStatus.name()}" th:classappend="${mailSummary.mailStatus.unread()}? 'mail-status- unread'">返信済み </td> mailStatus#unread()は作ってあったので、ドメイン層は変更しなかった 75
  76. 76. ちょった待った ドメイン層で この関心事は どう表現している? 76
  77. 77. メールの状態 public enum MailStatus { 未読, 既読, 返信済み, 未選択; public boolean unread() { return this == 未読; } public boolean opened() { return this == 既読; } public boolean replied() { return this == 返信済み; } public boolean unknown() { return this == 未選択; } ... } MailStatus.java メール全体で「共通」の状態管理用のenum 「スカウトメール」に特化していない 要望は「未読/既読」の2択 ギャップがある 77 要望: スカウトの開封/未開封が見づらい
  78. 78. スカウトメール一覧 public class ScoutMailSummary { MailId mailId; MailStatus mailStatus; ScoutStatus scoutStatus; MemberForAgencySummary receiver; Agent sender; Subject subject; EvaluationType evaluationType; CountOfTotalAgencySend total; SendDate sendDate; ... } ScountMailSummary.java 一覧表示用の情報が、平坦にならんでいる 「スカウトメール」の「未読/既読」が埋もれている 78
  79. 79. 改善のアイデア public class ScoutMailSummary { ScoutMailStatus mailStatus; ScoutStatus scoutStatus; MemberForAgencySummary receiver; Agent sender; Subject subject; MailId mailId; SendDate sendDate; EvaluationType evaluationType; CountOfTotalAgencySend total; ... } ScountMailSummary.java 使った人からの改善要望 ⇒ ドメインの学習機会 ドメインの関心事を深く理解する ⇒ コードに反映する 「スカウトメール状態」クラスを新規作成 段落で、別格の関心事であることを表現 画面に表示しない(関心事が低い)情報を格下げ 79
  80. 80. 学び方のヒント 80
  81. 81. オブジェクト指向設計の学び方 言葉⇒体験⇒言葉 本やスライドで用語を学ぶ 実際にやってみる(コードを書く) 学んだ本やスライドを読み直す オブジェクト指向の「用語」はわかりにくい コードで書いてみて、「もう一度」、説明を読み直すと わからなかった「用語」がわかるようなっていることが多い 81
  82. 82. 成功を体験する 「変更作業」が学びのチャンス • 既存コードを変更しながら以下を意識する – コードを読んだ範囲 – 変更箇所の数 – テストが必要な範囲 – 副作用の有無(安心感) • オブジェクト指向設計に書き換えてから変更してみる – 「変更」の前にリファクタリング • 名前の変更、メソッドの抽出、クラスの抽出、メソッドの移動 • 「善い部品」が自然に増える • 既存コードの設計と比較して、変化を実感する – コードを読む範囲 – 変更箇所の数 – テストが必要な範囲 – 副作用の有無(安心感) 82
  83. 83. 成功体験をするための 推薦図書 • リファクタリング • 実装パターン – オブジェクト指向の効果を引き出す コードの書き方の実践ノウハウ • 技術評論社 Software Design 再編集版 (3月発行予定) – オブジェクト指向の「入門記事」を集めたムック本 • オブジェクト指向入門 – 読むのは「そうとう」たいへん – 良いことがたくさん書いてある – なんど読んでも新しいヒントが見つかる • (もちろん)ドメイン駆動設計 – なんど読んでも新しいヒントが見つかる 83 注意! 「入門」ではない ハードルが高すぎる
  84. 84. 参考資料 • オブジェクト指向エクササイズのススメ – http://www.slideshare.net/yojik/ss-1033616 • 責務を持ったオブジェクトの「コラボレーション」の設計を、 わかりやすく学べる • オブジェクト指向の設計と実装の学び方 – http://www.slideshare.net/masuda220/ss-14263541 • 「学び方」に焦点をあてた、オブジェクト指向設計入門 • 創造的な学習のコツ 「学習パターン」 – http://learningpatterns.sfc.keio.ac.jp/ • 「学び」のコツ • 「ドメイン」を学ぶためのヒント満載 • 「ドメイン駆動設計」や「オブジェクト指向設計」の学びにも 84
  85. 85. 参考資料 85 特に 0章 最近のオブジェクト指向 1章の1 基本を学ぶ 2章の1 3つの基礎練習 3章 実践的な考え方とやり方
  86. 86. ドメイン層のソフトウェア設計 オブジェクト指向設計 インクリメンタルな設計(XP) ドメイン駆動設計 86
  87. 87. ドメインを学び 学んだことを コードで表現する ドメイン駆動設計 87 オブジェクト指向/XP
  88. 88. ドメイン駆動設計 ドメイン モデル ドメインの 「重要な関心事」を 鋭く説明する 選び抜かれた 重要な関心事を コードで表現する 会話を繰り返して 「要点」を明確にする 「重要な語彙」を チームで合意する 1章 2章 3章 88 第1章 ドメインの知識をかみ砕く 第3章 モデルと実装を結びつける 第2章 言葉を使った意図の伝達
  89. 89. ドメイン駆動設計 ドメインを分析する人がコードを書く 毎日、分析し、毎日、コードを書く 「会話」をしながら意図を確認する コードを書く人がドメインを分析する 分析・設計・実装を「フェーズ」に分けない 分析・設計・実装の「担当者」を別にしない 「コード」と動くソフトウェアで意図を確認する 分析と実装を、同じ人が毎日やるなら、ドキュメントは不要 オブジェクト指向/XP 89 保守の現場ではあたりまえ?

×