新訳版『テスト駆動開発』に学ぶオブジェクト指向設計

テスト駆動開発テスト駆動開発

和田卓人(t-wada)さんによる『テスト駆動開発』の新訳版が出版されました。

オブジェクト指向でソフトウェアを開発するのであれば、この本とマーチンファウラーの『リファクタリング』は必読書だと思います。この古典ともいえる『テスト駆動開発』が和田さんの手によって新訳版として復刊されたことは、ほんとうにすばらしいことです。

この本が出版された経緯と、和田さんはじめ関係者の方々のご努力については、和田さんの、このブログをぜひ読んでいただければと思います。
新訳版『テスト駆動開発』が出ます

新訳本は、単に原著が日本語で読めるようになっただけではありません。和田さんの手によって、原著にはない新たな価値が付け加えらました。

一つは、サンプルコードの工夫です。

  • できるだけ省略はしない
  • 変更箇所を目立つようにした
  • 各章末にその時点での全コードを記載する

これらの工夫により、本に書かれた内容が、より具体的に理解がしやすくなりました。また、実際に手を動かしてみるときに、迷子になりそうな個所も一掃されました。大勢の技術者にテスト駆動開発を伝える活動をされてきた和田さんの知見とノウハウ、思いが、このサンプルコードの工夫に結びついているのだと思います。

もう一つすばらしい内容が、付録Cとして追加された訳者の和田さん自身の解説「テスト駆動開発の現在」です。テスト駆動開発というムーブメントの歴史を振り返りつつ、現在の状況と、これからの展望が、わかりやすくまとめらています。
「テスト駆動開発の現在」で和田さんが書かれているように、いろいろな意味で状況が変わった現在こそ、もう一度、テスト駆動開発の本来の意味を考え、何が大事なことなのかを改めて理解して手に入れる好機です。新訳版『テスト駆動開発』は、和田さんのこの解説により、原著以上の今日的な新しい価値が加わりました。

この「テスト駆動開発」の内容を、オブジェクト指向の設計の考え方とやり方に焦点をあてながら、簡単に紹介したいと思います。
本の帯にも書かれているように、「TDDはテスト技法ではない。分析技法であり、設計技法であり、開発のすべてのアクティビティを構造化する技法」なのです。

テスト駆動開発の2つのシンプルなルール


  • 自動化されたテストが失敗したときのみ、新しいコードを書く
  • 重複を除去する
(「まえがき」から)

一つ目のルールは、テスト駆動開発の基本として多くの人が理解し実践していると思います。しかし、2番目のルールはどうでしょうか? 「オブジェクト指向の設計」という観点からは、この2番目のルールが重要な意味を持ちます。
コードの重複を排除することで、コードを読みやすくし、変更があった時の影響を狭い範囲に閉じ込めるのが、オブジェクト指向で設計する目的です。
TDDの基本サイクルは、レッド・グリーン・リファクタリングです。リファクタリングを繰り返しながら「重複を除去する」活動こそがTDDの本質です。

この本のサンプルを読み進めるときには、この2番目のルール「重複を除去する」ために、どのようなリファクタリングを行っていくかに注目してみてください。オブジェクト指向の設計では、どのようにコードの重複を除去するのかを、手を動かしながら体験できるのが、この本のすばらしい点です。

開発活動の目的と背景を理解する


ソフトウェア開発には、背景と目的があり、それぞれの置かれた状況があります。この本の最初のサンプルである「多国通貨」がなぜ必要になったのか、「多国通貨」にどのようなビジネス価値があり、変更の対象となるコードはどのような状況にあり、開発者たちのどのような経験を積み重ねてきているか。

そういう目的や背景が「はじめに」で説明されています。サンプルコードに飛び込む前に、この「はじめに」を熟読すべきです。ソフトウェア開発とは、こういう目的と背景の中で、積み重ねてきた経験や技術資産の延長として行うものです。TDDを取り入れるということは、こういう目的・背景・状況をよく理解することが前提だということです。

ビジネス価値については、技術者が直接コントロールすることはできません。しかし、スキルを身につけること、コードの整理やテストの整備は、技術者自身がコントロールすべきことがらです。一朝一夕にできることではありませんが、日々の開発の中で、少しずつコードの整理とテストの整備を積み重ね、そのためのスキルを磨いてていく活動を進めていくことがTDDの基本です。

ビューを使って仕様をざくっと理解する


第1章「仮実装」の冒頭で、レポート機能のサンプルが提示されています。レポートや画面のように、利用者が目にする情報(ビュー)は、要件を分析し、理解するためのわかりやすい手がかりです。
このレポートの出力例を元にして、何をすべきかをTODOとして書き出していく。これが「分析」活動です。

簡単な例ですが、TDDの考えるソフトウェア開発の基本の流れが明示されています。コードを書く人間が、利用者が使うレポートを参考にしながら、どのような仕様を満たすべきかを考える、ということです。

ここには、仕様を誰かから教えてもらう、という行動はしていません。このチームが、このプロダクトの開発に何年もかかわってきて、この問題領域(ドメイン)について、かなりの知識を持っているという背景もあります。しかし、開発者にとっても「多国通貨」という領域は未知の領域だったはずです。
それにもかかわらず、開発者たちは仕様について、自ら考えながら、TODOリストを書きだしています。この開発スタイルがTDDの基本です。仕様は、開発者が能動的に考える。これは、ドメイン駆動設計の根底にある考え方と共通です。

モジュール化の方針


要求仕様はレポート機能の分析から開始しています。しかし、書こうとしているプログラムの単位は、「レポート機能」とか「レポートサービス」ではありません。レートを換算するための RateConverterクラスとか、RateConversionService を書こうとはしていません。

そうではなく、最初に作成するクラスは、Dollarクラス(Dollar.java)です。

「換算する」という機能に注目するのではなく、換算するためには、DollarクラスとCHF(スイスフラン)クラスという単位でプログラムを書こうという発想です。

機能に注目するか、換算の対象であるDollarやCHFに注目するか。クラスの設計方針の大きな分かれ道です。

「換算する」という機能に注目して、それをそのままプログラミングの単位として手続き(サブルーチン)に分解しようというのが、手続き型のアプローチです。データを持つクラスと処理を持つクラスを分け、トランザクションスクリプトを開発するスタイルです。

それに対し、ドルやスイスフランという関心事の単位にプログラムを分割する発想が、オブジェクト指向のスタイルです。
「換算」という機能よりも、もっと基本的な部品である「ドル」や「スイスフラン」をどうオブジェクトとして表現するかからスタートしています。問題領域の関心事をオブジェクトで表現するという典型的なドメインモデルの開発スタイルです。

手続きとしてトップダウンにプログラム単位を分割していくか、何を扱いたいかの具体的な対象に注目して、ボトムアップに部品を用意していくか。この二つのアプローチの違いは、ソフトウェアの設計方針の大きな分かれ道です。

そして『テスト駆動開発』では、当たり前のように、Dollar.java からスタートしています。第1章「仮実装」で、ここからスタートしていることは、オブジェクト指向の設計という観点からは、ほんとうに味わい深い内容です。
レポート機能とその出力サンプルを分析しながら、プログラミング単位は、機能単位や出力のビュー単位ではありません。問題領域の具体的な関心事である、「ドル」と「スイスフラン」をオブジェクトとして表現することから手を付けています。

最終的には換算機能を実現するわけですが、そこに近づくために、まず、基本的な部品から手をつけるという、このボトムアップのスタイルこそ、オブジェクト指向らしい設計スタイルです。

クラスの粒度、ユニットテストの単位


第1章「仮実装」から第16章「将来の読み手を考えたテスト」までは、レポート機能に多国通貨に対応するための部品となるオブジェクトを、発見し、成長させていく過程が具体的に描かれています。実施に手を動かしながら、その過程をぜひ体験してみてください。
そして、その時にTDDの2番目の基本ルール「重複を除去する」活動に、注目してください。まどろっこしいような手順を踏んでいる理由のいくつかは、この「重複を除去する」という活動を例示するためだ、ということが体感できるはずです。

16章までのプロセスと成果物の振り返りが、第17章「多国通貨全体ふりかえり」です。
この章で注目したいのは、136ページの「コードメトリクス」です。

クラス数


プロダクトコードのクラス数は5です。テストコードのクラス数は1です。
つまり、一つのユニットテストは、ひとつのクラスではなく、5つのクラスを対象にしています。5つのクラスは、moneyパッケージとしてまとめられています。テストの対象の「ユニット」は、個々のクラスではなく、moneyパッケージです。

このテストクラス数とプロダクションのクラス数の比率は、オブジェクト指向で設計する場合のおおまかな粒度の指針として参考になります。ひとかたまりのユニットとしてテストする内容は、5つくらいのクラスを組み合わせた処理になる、という比率です。一つのプロダクションクラスに一つのユニットテストというのは、おそらく、プロダクションのクラスの粒度が大きすぎます。
関心事を小さなクラスに分けて、それを組み合せる、というのがオブジェクト指向設計の基本です。また、パッケージが、テストの単位という点もパッケージ設計やテスト設計の指針になります。

第16章の章末に記載された次の5つのクラスへ分割する設計をぜひ味わってみてください。
  • Money.java
  • Sum.java
  • Expression.java
  • Bank.java
  • Pair.java

まだ、開発途中ということもありますが、いちばん大きなMoneyクラスでも100行未満です。通貨の組み合わせを表現するために、Pairという10行程度のクラスを導入しています。

こういう用途をより具体的にした小さなクラスを部品として用意する、というオブジェクト指向らしい設計スタイルを、この本を通じて体験することができます。小さなクラスに分けて組み合わせることが、コードを整理し、重複をなくし、その結果、変更が楽で安全になります。そういうオブジェクト指向らしい設計スタイルとその効果が、この多国通貨の例から実感できます。

他のメトリクスも見てみましょう。

メソッドの行数


プロダクションコードでは、4.5行/メソッドです。メソッドの宣言と中括弧もカウントしていますから、実質的には、3行未満ということです。これは、開発途中だから、ということではありません。「重複を除去する」を徹底すると、自然に、こういう短いメソッドが増えるということです。

テストコードは、7.8行/メソッドです。これは、表の注釈にあるように、テストコードのほうは「重複を除去しきれていない」からです。

TDDの2番目のルール「重複を除去する」をどの程度、実践できているかは、このメソッドあたりの行数から推測することが可能です。

オブジェクト指向の設計で、コードの重複を除去する活動の結果は、メソッドの行数としてある程度は観測できるということです。

循環的複雑度


この尺度は、簡単に言えば、if文の分岐が多いか少ないかの指標です。
テストコードは、1.0。つまり、if文(条件分岐)がまったくないということです。

そしてプロダクションコードでも、なんと、1.05です。プロダクションコードでもif文(条件分岐)がほとんど登場していない、ということです。

if文は、複雑さの根源です。オブジェクト指向で設計するということは、この複雑さを取り除くことも重要な目標です。サンプルコードを読みながら、どのように、条件分岐の複雑さを除去していっているかをぜひ手を動かしながら味わってみてください。途中で継承が登場しますが、重複を徹底的に除去していく過程で、最終的には、継承を取り除くリファクタリングは、なかなか味わい深いものがあります。



『テスト駆動開発』の第一部の「多国通貨」の例について、オブジェクト指向設計という観点から、本の内容を簡単に紹介してみました。この本は、読み物というより、手を動かして体験学習をするための教材なんだと思います。ぜひ、実際にコードを書きながら、コードの変化していく様子と、なぜ、そうするのか、何が変わるのか、を味わってみてください。

オブジェクト指向設計のスキルが一段階あがることはまちがいありません。

たくさんの書評、ありがとうございます

本を書きました


『現場で役立つシステム設計の原則』
書影

7月5日に発売になったこの本ですが、いろいろな方に書評を書いていただいけました。
ありがたいことです。こういうフィードバックは、うれしいし、とっても勉強になります。

私が自分でブックマークした範囲ですが、みなさんの書評を紹介させていただきます。

「現場で役立つシステム設計の原則」はプログラミング設計の普遍的な教科書 - ビープラウド社長のブログ

ブックマーク:543

佐藤さんのこの書評は、大きな反響があったみたいですね。おかげさまで、本の売れ行きがぐんと伸びました(笑)。
本の全体の構成や話の流れを俯瞰的に、かつ要点を押さえた内容を、図をうまく使いながら紹介していただきました。
まえがきかなにかに「本書の構成」として書いてしかるべき内容ですね。もし第2版を書く機会(?)があれば、この内容をぜひ参考にさせていただいて「本書の構成」を追加させてもらおうと思っています。

私以上に、オブジェクト指向を熱く語っていただいので、オブジェクト指向アレルギー(?)の方には刺激が強すぎるかも(笑)。

「現場で役立つシステム設計の原則」の目次流し - 日々常々

ブックマーク:100

irofさんのこの書評は、章ごとの要約をうまくまとめていただいた印象です。
この段階では「目次流し」なので、きっとじっくり読んだ後に、するどい突っ込み満載のブログが公開されるものと、期待しています(笑)。

@irofさん、@haljikさん, @yukieenさんたちが中心になって、大阪でこの本の読書会をやっていただいているようなので、そちらからのフィードバックも期待したい。機会があれば、読書会におじゃまさせてもらいたいなと考えています。

現場で役立つシステム設計の原則 - ひしだまの変更履歴

ブックマーク:93

ひしだまさんが公開されているJavaの技術情報には、いつもほんとうにお世話になっているので、書評を書いていただいた時は、うれしい驚きでした。

ご指摘いただいた内容はとても参考になりました。性能面は、この本では意識的に触れないようにしたのですが、やはり、現場での実践的な原則として、そういう点まで含めた説明にすべきだったのかもしれません。

Web APIでの日付の扱いについては説明不足でした。
考え方としては、アプリケーションレベルでは、基本的には日時は、LocalDate/LocalTimeを使っているので、それをWeb API の日付の扱いでも同じようにする、という発想です。もちろん、「現地」を特定できる情報が対になることが前提なんですが、そこらへんは、完全に言葉足らず。
業務アプリケーションでの日付の扱いは、いろいろな考えることが多いので、java.timeパッケージの、LocalDate/LocalTime , OffsetDateTime, ZonedDateTime, Instant の使い分けの話も含めて、このブログでいちど、私の考えていることをまとめてみたいと思います。

書評『現場で役立つシステム設計の原則』 - まっつんの日記

ブックマーク:90

まっつんさんのこの書評は、とにかく早いんでびっくりしました。発売が7月5日なのに、なんと、6月30日に公開していただきました。発売に先行していくつかの書店で試験販売したものをご購入いただいたようです。
まっつんさんとは、ネット上でも何度か意見交換とかさせていただいていて、私の設計の考え方に共感いただけている部分が多いのかなと思いました。

まっつんさんのお仕事がら「教育コンテンツ」としての評価をいただけたことは、とてもうれしかったです。
「Java入門レベルはクリアしているけど、現場での設計には、まだまだ悩みが多い」という人たちに参考になれば、と思って書いた本なので。

「現場で役立つシステム設計の原則」を読んでみたよ - runaround’s diary

ブックマーク:78

run-aroundさんから、付箋がびっしりとついたこの本の写真がtwitterで流れたのを見た時は、ほんとうにうれしかったです。自分の書いた本を、興味をもって読んでいただけていることが実感できた瞬間でした。
書いていただいた内容も、ご自身の経験と照らし合わせながらの具体的な感想で、とても興味深く読ませていただきました。
ほんとうにうれしいフィードバックでした。

>>2017/8/16 追記

【書評】現場で役立つシステム設計の原則 - システム開発で思うところ

ブックマーク:63

vermeerさんは、細かい点までほんとうに丁寧に読んでいらっしゃるなあ、というのが率直な印象です。そして、vermeerさん自身のご意見の記述が具体的で、とても参考になります。私の過去のスライドとの差異までご指摘いただいたのは、正直驚きました。スライドのほうも丁寧に見ていただけてるようで、うれしい限りです。
ご指摘された箇所の図は、処理の流れのイメージとしてこっちのほうがわかりやすいと思って、ドメインモデルへの矢印を、アプリケーション層だけに絞ってみました。

契約による設計は、本の説明が中途半端というか、わかりにくかったですね。改良の余地が大いにありです。

if文でブロック(ブレース括弧 {})を使っていない点は、レビュー段階から、いろいろな人から指摘されています。
これは、説明不足なんですが、if文でブロックは使わないほうが良いと思って、そうしています。
どういうことかというと、if文のブロックは必ずメソッドに抽出して、次のような一行記述にすることを徹底するという考え方です。

if( condition ) statement ; // 改行せずに一行で書く

condition は、isValid() などのメソッド。statement も return errorResult() などのメソッド。

else句は原則使わないようにしているので、ほとんどのif文は、このような一行形式で記述でき、実際にやってみて、わかりやすく、変更が安全になることに手ごたえを感じている書き方です。

「集中できる時間は『息を止められている時間』」というのは、その通りですね。個人的には、ボイラープレートコードは読みたくないので、メソッドに抽出するというひと手間をかけてでも隠したい派です。

>>ここまで追記

そのほかにも、いろいろな方に書評を書いていただいています。
みなさん、ほんとうにありがとうございます。

「現場で役立つシステム設計の原則」を読んでいる - 三流プログラマが脱三流するために書くブログ


『現場で役立つシステム設計の原則』という本に対して思うこと - Toy と帽子と ADP BE


『現場で役立つシステム設計の原則』を読んだ - SE(たぶん)の雑感記


「現場で役立つシステム設計の原則」を読んだ - TSUGULOG


「現場で役立つシステム設計の原則」を読み終わりました - シュンツのつまづき日記


『現場で役立つシステム設計の原則 ~変更を楽で安全にするオブジェクト指向の実践技法』(増田亨)の感想(2レビュー) - ブクログ




ドメイン駆動設計の実践:モデリングと設計の基本ツール

UML?


モデリングのツールは、思考のツールであり、関係者でお互いの考えていることをすり合わせ確認する道具です。
オブジェクト指向のモデリングツールといえば、UMLが有名です。クラス図やオブジェクト図、ユースケース図など、視覚的に、かつ、論理性を保って、モデルを検討し、視覚化するための約束事をまとめたものですね。


ドメイン駆動設計のモデリング手段


エヴァンスのドメイン駆動設計は、UML流の図がいくつか掲載されていますが、本を読んでいただければわかる通り、UMLを使ったモデリングのやり方は、基本的に登場しません。


ドメイン駆動設計のモデリングの基本手段は「言葉」です。それも、文章ではなく、会話によるモデリングを非常に重視しているのが、ドメイン駆動設計の特徴です。(2章を参照)


図や文章表現は、あくまでも補助的な手段。「言葉」を聞いた時の違和感、「言葉」をしゃべったときの感触。この人間の言語能力、会話能力を、ドメインを理解し、ドメインの要点を明確にするために最大限に活用する。それがドメイン駆動設計のモデリングのアプローチです。


モデルと実装を結びつける


人間の言語能力を駆使して作り出した「モデル(ドメインの要点)」を、プログラミング言語で表現することが、ドメイン駆動設計の実践の核心です。


つまり、ドメイン駆動設計を実践するための基本スキルは次の2つです。



  • 自然言語を、できるだけ正確に使う

  • プログラミング言語を、データ処理の記述手段ではなく、モデルの表現手段として使う


自然言語を正確に使う


モデリングのツールとして自然言語を活用するには、あいまいさや矛盾はできるだけ減らさなければいけません。たとえば、「あれ」「これ」「だいたい」のような、何気なく口にする言葉を、一つ一つ、より明確な言葉に置き換えて言い直します。「取引先」と「取引相手」という似た言葉がでてきたら、同じ意図なのか、別の意図があるのか、注意深く確認します。


そうやって、言葉に耳を傾け、自分で言葉にしてみて、あいまいさや矛盾がないかをいつも気にするのが、ドメイン駆動設計のモデリング活動です。


言葉を使ったモデリングで、私が注意していることが2つあります。一つは、「カタカナ禁止」。カタカナ言葉は、人によって解釈の違いが大きいので、ぎこちなくても、日本語の別の言葉に置き換えることを徹底します。もう一つは「繰り返し語ってみる」です。言葉で正確に表現できていれば、同じことをしゃべれば、同じ言い回しになるはずです。しかし、実際には、同じように語ることは意外に難しい。たとえば、チームで議論しているときに、「私も前の人の発言と同じ理解です」とかいう人がいる。で、その人に「同じでいいから言葉にしてみて」というと、まるで違ったことをしゃべりだす。意図も伝わっていないし、共通理解とはほど遠いことを思い知らされます。


こういうことに気を付けながら、「言葉」を正確に使うように意識してモデリングを進めるのが、ドメイン駆動設計のモデリングの基本です。


プログラミング言語でモデルを表現する


言葉にあいまいさが減り、それなりに納得できるモデルが手に入ったら、それをプログラミング言語で表現してみます。


これがまた難しい。私たち技術者は、プログラミング言語を、基本的にはコンピュータにデータ処理をさせるための道具として習得してきています。自然言語で表現されたモデルを、そのまま写し取るための道具としての経験がありません。


ドメイン駆動設計では、自然言語を使って洗練した「モデル」(理解や知識)を、プログラミング言語で、直接的に表現することを重視します。概念モデルと実装モデルを正確に一致させることが、ドメイン駆動設計の目標の一つです。


そのためには、データ操作をするための詳細を隠ぺいすること、クラス名、メソッド名、パッケージ名に、技術的な発想を混ぜないこと、などを相当に意識してやる必要があります。また、クラス間の構造も、技術的な整合性や技術者にとっての慣れ親しんだパターンに設計しがちです。しかし、自然言語で表現されたモデルは、そういう発想やパターンとは基本的に異なっています。技術的な発想としては、違和感があるが、モデルを素直に表現するとしたら、こういう実装になるという方向に、いろいろ検討することが、ドメイン駆動で設計する基本的な活動です。


オブジェクト指向の発想にはもともとは、人間の関心事や概念を、そのままコンピュータ上で表現することを重視していました。しかし、現実には、オブジェクト指向言語を使ったソフトウェア開発は、人間の考えていることを素直に表現する手段としてよりは、コードをわかりやすく整理し、変更容易性やコードの再利用生を高める手段として、広がってきました。


ドメイン駆動設計は、そういう意味で、オブジェクト指向の原点に立ち戻ったものと言えます。オブジェクト指向の基本を丁寧に学び直すことが、人間の考えていることを直接的にプログラミング言語で表現しようという、ドメイン駆動設計の実践の近道です。


ワークショップ(有料)のご案内


宣伝です。


ドメイン駆動設計の基本である「言葉を使ったモデリング」と「モデルをプログラミング言語で表現する」を、体験的に学べるワークショップを開催します。


(6月18日(土)と6月25日(土)の二日間)


実践的ドメイン駆動設計ワークショップ(第4回)

2週連続の土曜日開催で、有料なので、気軽に参加はできないかもしれませんが、それだけの価値がある講座です。ご興味がある方は、ぜひ、ご参加ください。そして、このブログに書いてきた内容を、私といっしょに、いろいろ議論しながら、ぜひ体験してみましょう。ご参加をお待ちしています。


再利用できるドメインオブジェクトの開発

 オブジェクト指向設計の目的は、開発効率をあげ、保守しやすい変更が容易なソフトウェアを作ること。そのために、「クラス」(オブジェクトの型)を基本単位にした「モジュール化」を行い、そのモジュールの再利用性を高める設計を目指す。

 ドメイン駆動設計の文脈から、オブジェクト指向が狙った「再利用」の現状を考えてみる。
 プレゼンテーション層とデータソース層では「フレームワーク」を使うことで、オブジェクト指向による「部品の再利用」のありがたさを日々実感している。

レイヤ構造

 実行基盤として Spring Boot, プレゼンテーション層の Spring MVC と Thymeleaf、データソース層の MyBatis を使うことで、開発期間を短縮でき、実績のあるフレームワークなので、安定した品質も確保できている。オブジェクト指向が狙った「再利用」が実現されている。
 しかし、ドメイン層は、毎回、独自に部品を開発しているのが実情。再利用できていない。
 電話番号、氏名、住所などは再利用できそうなドメインオブジェクトだが、実際にやってみると、個々の案件ごとの微妙な要求の違いを実装する必要があり、かえってコードが複雑になり、共通部品としてメンテナンスがたいへんな割には、再利用によるメリットがあまり感じられなかった。
 結局、参考にすることはあっても、毎回、白紙から書いている。

再利用への道


 バートランドメイヤーの「オブジェクト指向入門」を読み返していたら「第4章 再利用性へのアプローチ」に、部品の再利用について、いろいろ示唆に富んだ議論が展開されていた。
 もっとも、印象に残ったのが次の原則

 再利用の生産者になろうとする前に再利用の消費者になれ

 再利用の部品を作る前に、既存の良くできた部品を再利用することの経験を積むのが原則である、ということ。自分たちのドメインオブジェクトの再利用部品化の試みがなぜうまくいかなかった原因が、あるいは、世の中に、再利用可能なドメインオブジェクト部品が広がらない理由が、ここにありそう。

 プレゼンテーション層は、 Servlet プログラミングからスタートして、Spring MVC のような役に立つ再利用可能部品を使う経験を積んできた。 データソース層も、JDBCプログラミングから、MyBatis のような O-R マッピングフレームワークを部品として再利用することが当たり前になった。

 しかし、ドメイン層については、そういう定評のある再利用可能部品は、見当たらない。つまり、消費者として、良い部品の再利用の経験がないということ。 この状況で、「再利用できる部品」をうまく設計できるはずがない。

 参考にできる再利用性の高いドメインオブジェクト部品が無い現状では、再利用の消費者としての経験を積むことができない。だから、いつまでたっても再利用可能なドメイン層の部品の生産者にはなれないというジレンマに陥る。どうすればよいか。

やってみたいが...


 その突破口は、メイヤーが「再利用のアプローチ」の最後に書いている、「それでも再利用部品の生産者になろうという情熱」なんだろうと思う。また、今では定番になっているフレームワークも、生まれた時から圧倒的に支持されていたわけでなく、未成熟なフレームワークを使うくらいなら自作したほうが早くて確実、という評価の中で、フレームワークの開発者たちが情熱をもって、改良を続け、熱心な消費者(フレームワークの利用者)たちのフィードバックを糧に、質を向上させてきた、という発展の経緯をあらためて、認識することが大切なんだと思う。

 今の自分は、ドメイン駆動設計というアプローチに情熱をもって、個別の案件ごとのドメインオブジェクトの設計に日々取り組んでいる。
 では、それを再利用可能な部品として発展させる情熱があるかと言われると、正直、そこまでの強い思いは持てていない。今のところ、ドメイン駆動設計の実践ネタを勉強会やスライドで公開するくらいが関の山。

 しかし、ラフな試作品を公開するところからはじめ、さまざまなフィードバックを受けながら、再利用可能なドメインオブジェクトを発展させることは、本気で取り組んでみたいテーマではある。

 もし、再利用可能なドメインオブジェクトの開発に熱意や興味を持たれている方がいたら、ぜひ、情報交換をしてみたい。メールなりtweetなりでお声掛けください。

※ドメイン層で Bean Validation は積極的に使っている。これも再利用可能な部品であることはまちがいない。だが、脇役というか、ドメインオブジェクトそのものではない。


□この記事に登場した本
評価:
バートランド・メイヤー
翔泳社
¥ 7,776
(2007-01-10)
コメント:読むのがたいへんだが、ソフトウエア設計の考え方を基本的なところから勉強にするには、良い本。


ドメイン駆動設計の原則を体験的に学ぶ

ドメイン駆動設計の原則を体験的に学べるワークショップを開催します。(有料)

募集ページはこちら。

実践的ドメイン駆動設計ワークショップ

このワークショップの意図と内容を紹介します。

ドメイン駆動設計の3原則


ドメイン駆動設計の3原則

ドメイン駆動設計の基本原則は、1章、2章、3章に集約されています。

■原則その1:ドメインの知識をかみ砕く

・ドメイン(そのアプリケーションの対象領域)に関する「知識」を継続的に学ぶ
・ドメインの「知識」を広げながら掘り下げ、より深く理解する

 ドメインの知識の習得と理解は、どんな開発手法でも重要なテーマです。ドメイン駆動設計(あるいは、オブジェクト指向設計)では、コードを書く技術者が、自ら積極的にドメインの知識を学び続けることを重視します。

 開発者が要件定義書や仕様書がでてくるのを待つのは、ドメイン駆動設計のアプローチではありません。

■原則その2:言葉を使って意図を伝達する

・利用者やその分野に専門家と「言葉」を使って、活発な意図の伝達(コミュニケーション)を行う

 これは、XPなどのアジャイルな開発では、基本の活動です。

 ウォータフォール式の開発では、要件定義や分析は「フェーズ」でした。その「フェーズ」の成果物を「ドキュメント」としてまとめ、次のフェーズで(要件定義者とは別の)技術者に渡されます。

 ドメイン駆動設計はアジャイルなやり方が前提です。ドメイン駆動設計では、要件定義や分析は「フェーズ」ではありません。日々の「タスク」です。

 要件定義の成果物として、他者に引き渡すためのドキュメントは必要ありません。開発者が自ら獲得した業務の知識・理解を、そのままコードに書きとめます。そうやって作った業務知識が豊富なソフトウェアを動かしながら、業務の経験者やプロダクトオーナと活発に会話をして、さらに詳細に仕様を決めていきます。

 きれいにまとまった「ドキュメント」を作っても、関係者の間で、理解が食い違うことはよくあります。また、人間の作るものですので、ヌケモレや記述ミスがあちこちに潜んでいます。
 なによりも問題なのは、ドキュメントをいくら作っても、それだけではソフトウェアは動かないことです。

 不確実で役に立たない「ドキュメント」をせっせと作るよりも、関係者で会話して意図や仕様の詳細を確認したほうが、手っ取りばやいし、確実。つまり、費用対効果が高い。これが、XPで言葉を使った会話による意図伝達を重視する理由です。

■原則その3:モデルと実装を一致させる

 開発者が、業務知識を増やし、プロダクトオーナーの意図を正確に理解したら、それをそのままコードで表現するのが、ドメイン駆動設計の重要な原則です。

 開発者の業務知識の理解と、コード表現とは、ずれてしまうことが多い。
 業務知識は、その業務固有の考え方ややり方に基づく知識であり、その分野の業務用語を使います。プログラムのソースコードは、どうしても、コンピュータの仕組みや、プログラミング言語や言語仕様に引っ張られます。

 優秀な開発者であれば、頭の中の業務理解と、コンピュータよりのコード表現とを、無意識に変換できるかもしれません。

 しかし、これは危険です。 業務の知識を表現できてないコードは、後になって、コード内容を理解したり、機能の追加や修正をやろうとした時に、意味が不明なコードだらけになりがちです。それが、ソフトウェアの変更コストをあげる大きな原因になります。

・どこになにが書いてあるかわからない
・業務的には単純なことが、プログラムのあちこちを修正しないと実現できない
・うっかり変更すると、わけのわからないところに影響がでた
...

 こういうことを防ぐために、コード、特にドメイン層のプログラムは、業務知識、業務を理解した概念モデルを、そのままコードで表現することにこだわります。

 これがドメイン駆動設計の基本原則です。

ワークショップの内容


 今回のワークショップは、このドメイン駆動設計の3原則を、チームで実際に体験しながら学習してみることを目的としています。

特に重視しているのが、次の3点です。

・「言葉」を使った意図の伝達
・「チーム」としてのアウトプットづくり
・タイムボックス(時間制限)

■「言葉」を使ったモデリングの体験学習

 UMLやプログラミング言語ではなく「言葉」を使ってモデリングや設計するやり方を経験します。

 UMLやプログラミング言語は、論理的な記述にはすぐれていますが、人間の「意図」の伝達や理解には、あまり向いていません。

 人間が「意図」を伝える基本の道具はなんといっても「言葉」であり「会話」です。

 アプリケーション、特にドメイン層の基本設計を、まず「言葉」を使ってモデリングしながら、コード表現に持っていく。あるいは、コード表現を説明しながら、モデルやコードの問題点を発見する。

 このワークショップでは、この「言葉」と「コード」の双方向のいったりきたりを繰り返すことが、費用対効果の高いモデリングと設計の手段をあることを体験しながら学べます。

■「チーム」としてのアウトプットづくり

 アプリケーション開発は、チーム活動です。
 チームとしてゴールイメージを共有し、共同作業をして成果を生みだす活動です。

 業務の理解、プロジェクトのゴールイメージ、設計の考え方は、プロジェクトの最初では、個人個人でばらばらです。そして、プロジェクトが進むにつれてチームとして学習しながら、しだいに共通理解を増やしながら、ソフトウエアプロダクトを成長させていきます。

 このワークショップでは、見ず知らずの3人がチームになって、最初のばらばらの状態から、チームとして、共通理解を広げ、深めていく過程を、体験しながら学びます。

 その時に「言葉」という道具の使い方の工夫と、その効果を実感することを狙ったさまざまなワークを行います。

■タイムボックス(時間制限)

 すべてのワークは、15分とか、30分とかいう時間制限付で行います。

 短い時間の中で、考え方も経験も異なる3人が、一つの結論を出すことは、とても困難です。

 このワークショップでは、あえて短時間の制限をもうけることで、3人が難しい意思決定をすることを強制します。その限られた時間の中で、チームとしての成果を最大にするための、やり方や考え方のコツを体験しながら学びます。

 この場合も、「言葉」を使った会話が重要な役割を演じます。

ぜひご参加を


 この内容に興味を持たれたかたは、ぜひ、ご参加ください。
ドメイン駆動設計の考え方を現場で役に立つ、さまざまなモデリングや設計のやり方を体験しながら、学べる機会です。

お申込み、お問合せはこちらから

実践的ドメイン駆動設計ワークショップ

イベント案内:オブジェクト指向設計の勘所

ギルドワークスがシリーズで開催している「チーム開発力強化セミナー」の設計編、第2弾をやります。

8月16日(火)に開催した第一弾「オブジェクト指向設計の基本を学ぶ」の続編です。

日時:8月26日(火)13:30−16:00
場所:東京都港区六本木一丁目
参加費:5000円

イベントの詳細:チーム開発力強化セミナー 〜 オブジェクト指向設計の勘所 〜

前回に続いて、今回も、マーチンファウラーの「リファクタリング」の第1章に登場するサンプルプルグラムが題材です。

このサンプルプログラムは、ファウラーが書いている通り「変更に弱い」設計です。

今回は、参加者で、コードレビューをしながら、

・どこが問題か?
・なぜ問題か?
・変更に強い設計に改善する時にどこに注目すべきか?

を意見交換しながら、進めたいと思います。
全体で100行あまりの小さなプログラムですが、なかなかツッコミどころ満載です。

セミナーの内容は、本に書いてあることばかりの基本的な内容です。
その基本的なことを、一人で本を読むのとは違った体験をすることで、オブジェクト指向らしい、変更に強い設計の勘所を体感してみましょう、という企画です。

残席わずかです、興味のある方はぜひ、ご参加ください。

イベントやります:オブジェクト指向設計の基本を学ぶ

「リファクタリング」の新装版がオーム社から出版されましたね。
それを祝してというわけではないんですが...

「オブジェクト指向設計の基礎をちゃんと学んでみよう」

という趣旨の講座をやります。

8月12日(火)13:30−16:00
東京都港区六本木一丁目
5000円

イベントの詳細:チーム開発力強化セミナー 〜 オブジェクト指向設計の基本を学ぶ 〜

内容は「リファクタリング」のエッセンス、という感じです。

・コードの固まりをメソッド単位に分けて整理する
・データとロジックを適切なクラスに配置する
・if文(条件分岐)を単純化する

実際のコードをリファクタリング(設計改善)しながら、ビフォー/アフターの違いを実感し、自然にオブジェクト指向設計のやり方/考え方を体感できることを目標にしています。

・オブジェクト指向設計がよくわからない
・オブジェクト指向設計でやっているつもりだが、なかなかうまくいかない

こういう方を対象にした実践的なオブジェクト指向設計の体験機会です。

ぜひ、ご参加ください。

なお、この後も、オブジェクト指向設計/モデルリング/ドメイン駆動設計などをテーマにした講座をシリーズ化する予定です。

乞うご期待!

正しいものを正しく作る:ギルドワークス株式会社を設立しました

4月1日に、仲間と新しい会社を立ち上げました。

ギルドワークス株式会社

正しいものを正しく作る


これが、私たちの基本理念です。
とことんこだわりたい。

「正しいものを正しく作る」ために、お客様のニーズを、why から掘り下げ、深く理解する。
その手段の一つが「ドメイン駆動設計」です。

このブログで、いろいろ書き連ねてきたことを、新しい仲間たちと、もっともっと現場で実践していきたい。
それが、お客様にほんとうに価値があるソフトウェアを提供できると信じているから。

適時適チーム


お客様により大きな価値を提供するために、日本中の技術者、デザイナのみなさんとチームを組んで、ソフトウェアを創っていく。これも、ギルドワークスの基本理念です。

必要な時に、ネットワークを通じて、最高の人材を集めたチームを作る「適時適チーム」。

正しいものを正しく作るために、志を同じくする全国の仲間といっしょにお客様に価値を創造していく。

志をもった、つわものたちが集まってくる「水滸伝」の「梁山泊」。
ギルドワークスは、そんな世界を創っていくことを本気で追いかけて行く。

それがお客様に価値を提供し、技術者としてやりがいのある仕事をしながら成長を続ける道だから。

さっそく、仙台からこんな仲間が参加してくれました。

SIerを退職しギルドワークスと仕事を始めます

こういう仲間を、ほんとうに日本全国に増やしていきたい。

JUGEMテーマ:インターネット


オブジェクト指向プログラミングの教え方?

技術者仲間で話していたら、4月入社の新人に、オブジェクト指向プログラミングをどうやって教えたらよいか?、という話になった。

想定している言語は Java。

■動物・犬・猫モデルの説明から
■基本用語の説明から:「カプセル化とは」「継承とは」...
■サンプルコードから: System.out.println( "hello world" )
...

どのパターンでもうまくいかなかったので、今度の新人研修では何か工夫したいね、という話。
結論から言うと「これだ」というアイデアがでたわけではないが、話の内容は、いろいろ興味深かったのでメモ書き。

Java はオブジェクト指向の言語なの?


Java は、ある意味 C言語の仲間。ある側面はほとんど同じ言語。

・int, long (プリミティブなデータ型)
・配列操作
・if/for/return

ここだけ見れば、C言語のまま。つまり命令型、手続き型の言語。

public static void main( String[] args) なんかもオブジェクト指向というより C 言語風。

どうも、いきなり Java = オブジェクト指向 という教え方は間違いだろう、というのが一つの結論。

オブジェクト指向の前に基本が大切なのでは


たとえば、こんなアイデアがでた。

  1. まず命令的、手続き的な書き方に振り切って、プログラムを書いて動かす味を覚える。

  2. すこし大きめの課題に挑戦しながら、構造化プログラミング、特に手続き呼び出しの基本を学ぶ。メソッドの抽出リファクタリングは、この段階で教えてしまう。

  3. 次の段階で「複数」のクラスに分割してプログラムを作成することを教える。
    クラスの抽出のリファクタリングを実際にやって覚える。

  4. この段階では(本来のオブジェクト指向ではなく) getter/setter だけのデータ入れ物オブジェクトと、そのオブジェクトからデータを get したり set するという、データと処理を分離したスタイルで教える。

  5. その後で、データを get する側のオブジェクト(クラス)に書いてあるロジックを、データの入れ物オブジェクトに移動することを覚えてもらう。


この 5 を教えるときに、これが「カプセル化」であり「ロジックの移動」という「リファクタリング」である、という「言葉」もいっしょに教える。

この段階でも「これがオブジェクト指向である」という言い方(教え方)はしない。

あくまでも、

◎プログラムはメソッドやクラスに分割すること
◎データと関連するロジックは同じクラスにまとめたほうが良いこと

の2点を強調する。

あと、どんな簡単なプログラムでも「パッケージ」宣言は必須であると教えたほうが良い、という意見もでた。
なんでも public ではなく、基本はパッケージスコープということを最初から覚えたほうが良い。
複数のパッケージに分ける発想も早めに覚えたほうが良さそう。

基本的なリファクタリング

◎名前の変更
◎メソッドの抽出
◎クラスの抽出
◎ロジックの移動
◎データの移動
◎パッケージ間のクラスの移動

は手をどんどん動かしながら早い段階から覚えてもらうべき、という意見もでた。

「動いたら次の課題」を繰り返すと「動いた、OK」だけの技術者になってしまいそう。
そうではなく「動いた後」で、コード(設計)を改善するためにリファクタリングをすることまでがプログラミングである、と覚えてほしい。

カプセル化


教え方までは議論できなかったけど「カプセル化」は徹底的に体で覚えるべき、で意見が一致。

◎関連するデータとロジックをひとかたまりにすること。
◎データ構造は外には見せないこと(単純な getter/setter は書かないこと)

そうするのが「良いこと」という感覚をなんとか会得してもらう。

オブジェクト指向のプログラミングでは、プログラム全体のどこも見てもカプセル化が徹底しているのは、まちがいなく良いソフトウェア。

だから「カプセル化」=「良いこと」=「いつでもやるべきこと」を徹底的に教えておきたい。

「カプセル化」という言葉を使って説明すべきかは、賛否が別れた。

継承


Java は言語の仕組みとして、型継承(implements)と実装継承(extends)があり、この使い分けも含めて「継承」はもちろん重要な教育テーマ。

問題は「継承」をどう位置づけて、どのタイミングで、どう教えるか?

「カプセル化」は、プログラムのどこでもやるべきこと(良いこと)。

でも「継承」はそうではない。

プログラムのありとあらゆる場所が、型継承/実装継承だらけのソフトウェアは、どうみても良いソフトウェアではない。

少なくとも「オブジェクト指向らしいプログラミング」=「継承を使いまくる」=「よいプログラミング」という、刷り込みは絶対にすべきではない。

むしろ「継承」は「使いどころが難しいよ」ということを最初から強調したほうがよさそう。

だから研修の初期では「継承」はさらっと「そういう仕組みもあるけど、具体的には後で」という先送り。

業務アプリケーションでドメイン層を実装することに限定すれば、実装継承(extends)を使うべきケースはほとんどないと思っている。
共通のロジックは共通部品として「コンポジション」として実装するほうが業務の概念に合っていることが多い。

型継承(implements)も、あちこちで積極的に使うべき仕組みではない、と思っている。

開発の初期段階で発見した(つもり)の継承関係は、要件を深く掘り下げていくと、まちがった理解であることが多い。

経験上、ドメインの理解が表面的なプロジェクトの初期に、継承関係をあちこち設計・実装してしまうと、ドメインを深く理解できるようになったあとで、ドメインの本来あるべき構造と、実装してしまった継承構造が大きく捻じれていて苦労する失敗パターンばかりの気がする。

継承構造は、実装したクラスが増えてきて、ロジックやコードブロックで具体的な共通性を把握できてから、必要に応じて、段階的に、リファクタリングをしながら導入していくのが、実践的な良いやり方だと思う。

「継承」は「リファクタリング」の学習の中で覚えていくべき技術かもしれない。

ポリモーフィズム


大切であることは全員一致。
ただし、そのために「継承」を教える、というのは「なんか違う」というのが一つの結論。

そもそも「ポリモーフィズム」という「言葉」から教えたり、その実現手段として「継承」を強調するのは、ダメパターンだった、というのがいままでの経験。

もっと業務アプリケーションを書く上での具体例、必然的な例で「実装のやり方」という振り切り方で教えるのが良いのでは?

「ポリモーフィズム」という「言葉から入る」のではなく「if 文をなくすテクニック」という切り口で教えてみる。

if( value == null ) ...

という null チェック をプログラミングの基本のお作法として教えるのではなく、null object パターンあるいは簡単な strategy パターン を、かなり早い段階の研修内容に含める。
(パターンの名前そのものは使わない。コード例でのみ教える。簡単なクラス図は書いたほうがよさそう)

購入日オブジェクトがあるとして、

・正しい日付
・正しくない日付( 2月30日と入力された場合とか )
・不明の日付

を表示する場合、表示ロジックを if 文で書きわけるのではなく、

・購入日インタフェースでasText()メソッドを宣言

・有効購入日 (「年月日」を表示)
・無効購入日 (「年月日」を表示。「不正」の警告も表示)
・不明購入日 (「未記入」を表示)

の実装クラスごとに、個別の asText() メソッドを実装する。

こういう書き方を、if 文 を覚えた直後に教えてもいいくらいなのでは?

「ポリモーフィズム」という言葉を一切語らず、「if 文を減らすテクニック」をいろいろ教えることで、結果的に「ポリモーフィズム」を習得する、というのがいいんじゃないかと。

null オブジェクトパターン以外にも、

・boolean を enum に置き換える
・enum に振舞を持たせる
・Map を使った場合分け
・Set を使った場合分け

など、if 文の代替手段は、いろいろある。

「ポリモーフィズム」とは何か、なぜ必要か、という教え方でなく、「 if 文以外の条件分岐の書き方」という振り切り方で教えたほうが、実践的なんではないかと。

すくなくとも「これでわかった Java 入門」みたいな本をテキストとして使うより、はるかに効果的な教え方だと思うんだけどなあ。

ドメイン駆動設計:4つのアンチパターン

6月23日(土)午後、大阪で、ドメイン駆動設計について、しゃべる予定。
第47回 SEA関西プロセス分科会のご案内

紹介の紹介の紹介、みたいな不思議なつながりで、講演の依頼があった。
「ドメイン駆動設計」を監訳された今関さんも参加いただける。

土曜の午後なので、時間が多め。
一方的にしゃべって終わりではなく、今関さんも交え参加者で、いろいろ話す時間を一時間以上とってもらいました(さらに懇親会もゆっくりと)。とても楽しみなイベントです。

ドメイン駆動設計は、訳本がでてから、あちこちで勉強会や読書会が開かれているようだし、ドメイン駆動設計に興味持ったり、現場で取り組む人が、すごく増えた気がしている。
ネットで流れる情報も「ドメイン駆動ってなんぞや?」的なものだけでなく「私は、こう理解している、やっている」的なものが多くなったんじゃないかなあ。
訳本の威力は絶大。

さて、講演の準備は、いつものようにドメイン駆動設計(訳本+原書)の読み直しから。
毎度のことながら「そうかこんなことも書いてあったんだ」と、たくさんの新しい発見。

最近の私のドメイン駆動設計の実践


ここ数カ月、中堅のSIer さんの開発プロジェクトで、ドメイン駆動設計をベースにしたモデリング・設計の支援をさせてもらっている。

伝統的なエクセル仕様書、ウォータフォール的な分業カルチャーの現場だけど、コアメンバーは「ソフトウェアの保守・変更のたいへんさ」に本当に苦しんだ経験があるチーム。
だから、ドメイン駆動設計の考え方やこだわりポイントには、共感してもらえることが多い。
やりがいがある仕事になっている。

クラス図を本格的に書くのは初めてというメンバーが多くても、もともと、その業務分野の知識とソフトウェア開発経験が豊富なメンバーなので、ポイントが共有できると話がとてもはやい。

このコンサルティングと並行して、ここ数週間は  Heroku という素敵な開発環境で、モデリングとプロトタイピングを、自分でコードを書きながら、毎日、数回、公開環境にデプロイしながら、試作している。

もちろん、ドメインのモデリング・実装が中心。
画面遷移、CSVアップロード/ダウンロード、メール送信は、本番用のコードで実装している。
永続化だけは、データベースではなく、Map でドメインオブジェクトを管理するフェイク実装。
ドメインモデルが安定するまで、テーブル設計と ORマッピングは後回し。

今回の講演内容は、この、現場でのモデリング・設計支援経験、自分自身でのモデリング・試作作業から、いろいろ手に入れたものを盛り込もうと思う。
本の読み直しでも、けっこう、目から鱗ネタがあった。
自分では、いままでの勉強会等での発表とは違った、新しいステージの内容になりそうな予感がしている。ちょっとしたブレークスルー感覚。
(妄想?まあ、何か作りはじめる前は、いつもそんなもの)

講演資料の準備もかねて、いくつか気が付いたことを、ブログ書きながら整理してみようと思う。

今回のテーマは「ドメイン駆動設計:4つのアンチパターン」。

アンチパターン:ごった煮コード


ドメイン層が分離できていないコード。

Web アプリケーションだと、HTTPRequest・Session・データベースアクセスなどの関心事と、業務の知識や業務ルールが、同じクラスやパッケージに混在している。

ひどい症状だと、メソッドの中に、業務判断の if 文と HTML 生成コードが、いっしょになっていたりする。

発想として、これをアンチパターンと思っていない開発者もいる。(メタなアンチパターン?)

ドメイン駆動設計というより、「関心の分離」というソフトウェア設計の基本に違反したアンチパターンですね。

ドメイン駆動設計の場合「ドメイン層」を、それ以外の層から分離・独立させる。
ドメイン層が「独立する」とは、他の層がドメイン層に依存する、ということ。
ドメイン層が他の層に依存してはいけない。

「ごった煮コード」は、これができていないわけだから、ドメイン駆動設計的には、完全なアンチパターン。

ここらへんは、発想や意識の問題もあるけど、アーキテクトがフレームワークの選定や使い方をリードしてしまうのが特効薬だと思っている。

既存のコードベースが大きいと現実的には難しいかな?

私たちは、Spring フレームワークを使って実践している。
Spring フレームワークは、ドメイン層とそれ以外の層、という発想が明確なフレームワークで「ドメイン層の独立」を実現するには良い選択肢だと思っている。

このアンチパターンは、小さなリファクタリングの積み重ねでは解消しない気がする。

いちばん重要なのは「発想の転換」。
「ごった煮」じゃだめなんだ、という価値観をチームで共有するのが近道。
地道に改良して改善していける問題ではないと思う。

アンチパターン:トランザクション・スクリプト


ドメイン駆動設計的には、トランザクション・スクリプトはアンチパターン。

手続き的な発想(パラダイム?)でいる限り「ドメイン駆動設計」でエバンスが書いていること、ほとんど理解できないだろうし、実践や応用は無理だと思う。

オブジェクト指向の分析設計スタイルが、ドメイン駆動設計の前提になっている。

何をもってオブジェクト指向のスタイル・発想とするかは難しいけど。

実際、私たちはドメイン層では、継承・抽象クラス・多態性は、原則として使わない。
開発言語も (手続き型のC言語の臭いが強く残る) Java だし、見方によっては、オブジェクト指向プログラミングはしていないのかもしれません。

ドメイン駆動設計的には、

・業務上、関連する情報を、ひとかたまりにする
・その情報を扱う操作は、同じ場所に集める
・その情報と操作の塊を、クラスやパッケージで明示的にカプセル化
・パッケージ間の依存関係は、できるだけ疎結合に

を重視する。
これがオブジェクト指向の発想なんだと思ってやっている。

というわけで(オブジェクト指向スタイルではないので)トランザクションスクリプトは「ドメイン駆動設計的には」アンチパターン。

ところで、私は、実は「トランザクション・スクリプト」パターンで記述した、独立したドメイン層のコードを見たことがありません。

見たことがあるのは、ドメイン層とそれ以外の層を「ごった煮」で、手続き的に延々と書き連ねたコードだけです。

ごった煮コードは、ドメインロジックの記述パターンとしての「トランザクション・スクリプト」とは別物でしょう。

ドメイン層をピュアに「トランザクション・スクリプト」で記述するなんて、ほんとは誰も実践していないのかも?
アンチパターンに取り上げるネタじゃないか。

アンチパターン:どこでも業務ロジック


■UI に、業務判断の if 文がある。
例:ロールが承認者で、状態が承認待ち、だったら承認ボタンを enable にする。

■データアクセス(SQL文)に、業務判断の where 文がある。
例:申込日が、締切の一ヶ月以上前だったら、早期申込みフラグを1 にする。

■テーブルに、業務ルールのトリガーがある。
例:10万円以上の購入依頼があったら、上長承認依頼レコードを作成する

...

例をあげれば、きりがない。
ソフトウェア一般としては、こういう書き方もありなんだと思う。

しかし、ドメイン駆動設計的には、ひどいアンチパターン。

ドメイン層のオブジェクトが、こういう知識・判断力を持つべき。
UIやSQL文で、この業務知識を利用するなら、業務判断能力があるドメインオブジェクトから、判断結果をもらうようにする。

他の層がドメイン層に依存すべし、というのは、こういうこと。

ここらへんも、発想の転換とかパラダイムシフトなんだと思う。

私の場合は、原書と格闘しながらドメイン駆動設計の実践のチャレンジを、2年くらいたったある日、若手の書いたコードとモデルをレビューしていた時に、とつぜん、この発想が変わったのを覚えている。

それ以降は、ビュー記述や、SQLにドメインの知識がまぎれこんで隠蔽されることを、かなり的確に見つけることができるようになった気がする。

UIやSQLに散在して記述している業務知識を、ドメイン層のオブジェクトに移動して集めていけば、業務知識の豊富なドメイン層が自然に育ってくる。

「どこでも業務ロジック」アンチパターンは、「豊かなドメイン層」に発展できる元ネタの宝庫ともいえる。

このアンチパターンの改善は、やっぱり発想の転換が必要。
作業自体は、地道なリファクタリング(ロジックの移動)の繰り返しですね。

アンチパターン:ドメインオブジェクトの getter/setter 大忙し


getter/setter は、内部に private に隠ぺいしたフィールドを、そのまま get したり set したりするメソッド(と定義しておきます)。

ビューを記述する時や、永続化のフレームワークで、こういう getter/setter が必要ではあるので、ドメイン層のクラスは、getter/setter を持つな、という意図ではありません。

問題は、ドメインオブジェクト同士(ドメイン層内部)で getter や setter を頻繁に使うこと。

これは、完全なアンチパターン。

まず setter はドメイン層の中で使う必要性はないはず。

パラメータ付のコンストラクタで生成した不変型のオブジェクト、つまり Value Object を使う限り setter は使う機会はありません。

Java の String クラスがそうですね。オブジェクトの内部情報を書きかえる setter メソッドはゼロです。

ドメイン層のオブジェクトの多くは、こういう Value Object で、設計・実装できるはずなんです。

getter も怪しい。

ある値を get してから、何をやっているんでしょう?

もし if 文とかで条件判断に使っているなら、その if 文ごと get 元のオブジェクトにロジックを移動すべきでは?

もっと低レベルの話だと getFirstName(), getFamilyName() と2回 get して、getした側で firstName + " " + familyName とか加工している。

get 元のオブジェクトに getFullName() メソッドを用意すべきですよね。

これは、ビュー記述や SQL 記述でも、同じことが言える。

ビュー記述( JSP とか velocity マクロ)で get しまくった内容を、ビュー記述側で、合成したり判断をしていたら、ドメイン層に、メソッドを追加したり、便利なサービスを提供するクラスの追加を検討する。

ドメイン駆動設計で、ドメインモデルを充実させると、アプリケーションプログラマが getter/setter を利用する機会は、どんどん減ります。減らすことが良いことなんです。

機械的な getter/setter 利用は、フレームワークにまかせる。

4つのアンチパターン、まとめ


結局、ドメイン駆動設計のアンチパターンになるのは、

◎関心の分離
◎わかりやすい役割分担
◎自然な協調関係

に失敗しているから。

この失敗は、どのレイヤのクラスやパッケージの設計に共通する課題。
ソフトウェア設計の基本スキルをみがくべし。

「ドメイン駆動設計」にフォーカスすると...

ドメイン層のオブジェク群の、

◎関心の分離
◎わかりやすい役割分担
◎自然な協調関係

のヒントは、ドメインエキスパートの頭の中に詰まっている、という考え。

もちろん業務の専門家が、設計原則を意識してるわけではない。
ましてや、設計をリードしてくれるわけではありません。

開発者が、業務の専門家と会話を繰り返しながら、その業務専門家が持っているはずのヒントを見つけにいく。
そうやって、ドメイン層のモデリングと設計を洗練させていく活動が、ドメイン駆動設計だと思っている。

業務がちゃんとできている人は、業務上のさまざまな概念やルールを、(ほとんど無意識に)体系的な知識として使っている。
その「体系的な知識」を、業務の専門家の頭の中から、うまくひっぱりだすのがドメイン駆動設計の基本の活動。

そうやって獲得した体系的な業務知識を、すなおに設計・実装したソフトウェアは、利用者の問題解決にほんとうに役に立つだろうし、業務の都合から発生する、さまざまな追加の要求にも、自然に、安全に対応できるようになる。

それがドメイン駆動設計を実践する成果なんですね。

calendar
     12
3456789
10111213141516
17181920212223
24252627282930
31      
<< March 2024 >>
システム設計日記を検索
プロフィール
リンク
システム開発日記(実装編)
有限会社 システム設計
twitter @masuda220
selected entries
recent comment
recent trackback
categories
archives
others
mobile
qrcode
powered
無料ブログ作成サービス JUGEM