モダンなSIer開発手法 勉強会

昨日、株式会社ディマージシェアさん主催の モダンなSIer開発手法 勉強会 - connpassでお話した内容です。

発表に使った資料

要約

  • 発展性に焦点をあわせる(プロジェクト型からプロダクト型へ転換する)
  • オブジェクト指向ソフトウェア構築の考え方(型によるモジュール化)を基本にする
  • ドメイン駆動設計の考え方(ドメインロジックに焦点を合わせ、コアドメインに集中する)を取り入れる
  • 要件定義・仕様・実装を並行して行う
  • 仕様の記述にプログラミン言語(Java)を使う
  • ソースコードから仕様を可視化する
  • 段階的に継続的に品質を向上させる

補足

ソフトウェア開発の複雑さを多面的に捉える

ソフトウェアシステムアーキテクチャ構築の原理(第2版)の枠組みで考えてみる。

7つの視点

  • 合目的性
    • コンテキスト
    • 機能
    • 情報
  • 構造性
    • 開発
  • 実行性
    • 並行性(実行モデル)
    • 実行環境
    • 運用

合目的性を、RDRA2.0で要件定義をする
構造性を、型によるモジュール化で実践する現場で役立つシステム設計の原則

  

仕様をJavaで記述し、設計を可視化する

Jig : 設計可視化ツール
Jig チュートリアル

オブジェクト指向プログラミングを学ぶための推薦図書

オブジェクト指向プログラミングを学ぶ

オブジェクト指向プログラミングという言葉は、広い意味で使われている。 オブジェクト指向プログラミングをキーワードにすべての情報をかき集めて理解するというアプローチは現実には無理。 目に付いた重要そうなところを見繕って集めてみても、たぶん混乱するだけ。

この記事では、オブジェクト指向プログラミングのいろいろなアプローチの中で、

  • クラスを使って独自の「型」を定義するプログラミングスタイル
  • 関連するデータとロジックをまとめて、小さな入れ物に格納する「カプセル化」を重視するプログラミングスタイル

を学ぶための参考図書を紹介したい。

型とカプセル化に重点を置く設計スタイルがわかってくると、それとは異なるスタイル、異なる力点を置くアプローチとの違いが具体的にわかるようになってくる。*1 *2

まずは、オブジェクト指向プログラミングの中で、型・クラス・カプセル化に力点を置く設計スタイルを身につけることを現場で役立つ実践的な学び方として推奨したい。

型とカプセル化を重視したスタイルを学ぶための三冊

以下の三冊は、必携書。すべてを読み切り理解することはできないかもしれないが、手元において少しずつ身に着けていきたい古典的名著。

読み方のヒント

どの本も全部を順番に読んでいくというより、ざっと全体を眺めたら、とりえあず、要点をみつくろって読むのが良い。基本は拾い読み。 あとは、何かの機会に、少しずつ、拾い読みの範囲を広げたり、拾い読みしたところを、なんども読み直してみる。

リファクタリング」の読み方

「第3章 コードの不吉な臭い」に列挙されている臭いの最初の6つ(「変更の分散」まで)を、重点的に読む。そして、その中に登場する、リファクタリングパターンだけは、一通り読むようにする。同じパターンが何度もでてくるので、何が、リファクタリングの基礎的な技法かが理解できる。

それだけでも、だいぶ、クラスの使い方とかカプセル化の感じがつかめるようになってくる。

ドメイン駆動設計」の読み方

読みにくい本です。まず、その前提で拾い読みする。

すぐに理解できるかどうかは別として、この本の根底にある考え方や、何に重点を置いているかに触れるための、最初の必読個所は、以下。

  • まえがき
  • 第9章 暗黙的な概念を明示的にする
  • 第15章 蒸留
  • 結論

ドメイン駆動設計という設計スタイルが、何を重視しているかに触れるには、この4か所を、ぜひ読んでほしい。すべてが理解できなくても、エヴァンスのこだわりポイント、設計スタイルがよくでている個所。

エヴァンスの考え方の特徴は「ある重要な部分に集中する」ことを重視している点。全体を同じ設計スタイルで均一に仕上げる、という発想とは正反対。アプリケーションソフトウエアの全体に影響を及ぼすのは、ドメインロジックであり、ドメインロジックの中でも中核の関心事と周辺的な関心事がある。中核のドメインロジックの設計と実装に焦点を合わせることで、ソフトウェア全体の構造と秩序が保たれ、さらなる発展が可能になる、という考え方。

この設計スタイルを支える技法の説明としては、次の2つの章が基本。

  • 第5章 ソフトウェアで表現されたモデル
  • 第10章 しなやかな設計

ただし、この2つの章は、必読ではない。オブジェクト指向プログラミングの基本的な技法の話なので、型とかカプセル化が理解できていれば、改めて、この2つの章を読み直す必要はない。 この2つの章が「わけがわからん」と思ったら、値オブジェクトを具体例で解説した情報や、リファクタリング本にあたったほうが良い。

なお、エヴァンスの書き方は、章のはじめでわけのわからない(?)たとえ話から始まることが多い。なんのたとえ話か最初はわからず混乱してしまうのが、多くの人が陥るワナ。私もそうだった。最初は、たとえ話は読み飛ばすくらいでよいと思う。後ろの内容が理解できて、はじめて意味がわかる例え話が多い。

もう一つ注意点。 クラス図やデータベースが登場する個所を、データモデリングの話として読んでしまうことも、わりと多くの人が陥るワナ。データモデリングや手続き的なアプリケーションプログラミングができる人ほど、このワナに陥りやすい。そう読もうと思えば、そう読むこともできる。まあ、そういう視点から読むと、エヴァンスの書いていることは稚拙というか的外れというか、なんじゃこりゃ、という評価になるんだと思うけど。

「型」や「カプセル化」の話なんだ、ということをいつも意識して読んだほうがエヴァンスの伝えたいことをすなおに読み取ることができる。 たとえば、最初はメソッド定義のないクラス図の個所は読み飛ばすべきだし、データベースと関連づけて説明されている個所も読み飛ばしたほうが良い。 関心の焦点はあくまでもドメインロジックをどうやって独自の型で定義するか、そして、独自の型の定義にどんな意図と効果があるか、ということを読み取ることに焦点を合わせたい。

オブジェクト指向入門」の読み方

分厚いし内容も難解なので、読破しようなどとは考えないほうが良い。 しかし、オブジェクト指向プログラミングの考え方を学ぶには、この本には有用な情報が詰まっている。 契約による設計とか、コマンドとクエリの分離など、良く知られた設計原則は、この本で提唱されている内容。

著者のバートランドメイヤーさんは、ご本人がおっしゃっているように「分類マニア」。とにかく、品質の分類、判断基準の分類、継承の分類、... など、分類好き。テーマごとに細かく分類し、それをひとつずつ解説するものだから、この厚さになってしまう。 だから、基本的には、「ああ、また分類病がはじまったな」くらいの感覚で、最初はちょっと距離を置いて、全体をぼんやり追いながら、全体としてどんなことが書いてあるかを掴むことから始めるとよいと思う。

この本を隅から隅まで精読する必要はないと思うけど、

  • ソフトウェア構築の基本はモジュール性
  • オブジェクト指向は型によるモジュール化を選ぶ
  • 型をカプセル化するクラスが唯一のモジュール単位であるべき

というメイヤーの考えを知って損はない。 同意するかどうかは別として。

拾い読みするとしたら、重点ポイントは、以下。

  • 第3章 モジュール性
  • 第5章 オブジェクト技術への道
  • 第11章 契約による設計:信頼性の高いソフトウェアを構築する
  • 第17章 型付け
  • 第22章 クラスの見つけ方
  • 第23章 クラス設計の原則
  • 第27章 オブジェクト指向分析
  • 第28章 オブジェクト指向構築過程
  • 第29章 オブジェクト指向という手法を教える

拾い読むといってもちょっと多いかな。まずは、何が書いてあるかを知るには、ざっとこのくらいは目を通しておきたい。 「継承」について書いてある章は意識的に割愛してあります。メイヤーさんは、熱烈な実装継承押しなんですが、私は、逆に実装継承は、やらない派なので。 リスコフは、実装継承はカプセル化の原則をやぶるため好ましくないであろう、と予測していた。そして、その後の開発現場での実践でその予測が正しいことは、すでに実証された。つまり、実装継承はやめたほうがよいよ、という立場です。

もっと読みやすい本が欲しいよね

ということで、書いたのが、拙著。

現場で役立つシステム設計の原則 ~変更を楽で安全にするオブジェクト指向の実践技法

特に、以下の4つの章で、型とカプセル化の考え方をできるだけわかりやすくコードの具体例で説明してみた。

  • 1章 小さくまとめてわかりやすくする
  • 2章 場合わけのロジックを整理する
  • 3章 業務ロジックをわかりやすく整理する
  • 10章 オブジェクト指向の学び方と教え方

この本は、「Java言語入門」的な本と、難解な「ドメイン駆動設計」との間を埋める本が求められているのでは、という企画から生まれた本。 最初に話をもらった時、私自身、そういう間を埋める本があったらいいな、と思っていたので二つ返事で引き受けた。 出版できるまでは、いろいろあったんだけど、なんとか世に送り出すことができた。 おかげさまで、出版から2年たった今でも地味に売れ続けているので、それなりの評価はしてもらえていそう。 「若手にススメた」みたいな話を時々目にするので、本の企画意図通りの読まれ方がされているのかな、とうれしく思っている。

この本を書く時、「継承」「カプセル化」「ポリモーフィズム」「型」とか、いう言葉はださずに、コードの書き方の工夫に振り切って、なぜそうすることのメリットがあるかをできるだけ、わかりやすく書こうと思った。

わかりやすさという点では、それなりの結果がだせたのではと自負している。 まあ、そういうわかりやすさが気に入らない人もいるんだなあ、ということもわかった(笑)。役に立つことが書いてあるけど、書き方が悪い、というコメントを見たとき、役に立つことは伝わったんだよね?、伝わったのに書き方が悪いってどういうこと?という感じで、とても不思議だった。

あと、現実的ではないとか、実際には導入できない、というコメントもいくつか見かけたけど、「自分が実際にやって、それなりの結果を出してきた内容だけ」を書いたので、うーん、実際にやっているんですけど、という感じなんだよね。逆に言うと、例えば国際化対応とか、テスト駆動開発とか、私自身が実際にやっていないことは、何も書いてないんですよね。

まあ、わかりやすいので、読む人の持っている設計スタイルとの干渉が強くて、そういう反応もあるんだろうな、と思っている。何が書いてあるかは、それなりに伝わっているんだろうなあと。

今、読み直してみると、もうちょっと「型」と「カプセル化」という用語の説明をどこかでしたほうが良かったかなと思う。 あと「ポリモーフィズム」も、多重定義・総称性・部分型の三種類あることの説明と、それぞれのポリモーフィズムについてちゃんと説明してもよかったかもしれいない。

この本は、ドメイン駆動設計への入門書的な意味あいは確かにある。ドメインモデルを中心に設計することの意味とその効果について、そうとう意識して書いた。

ドメイン駆動設計と並んで、私が意識していたのは、バートランド・メイヤーのオブジェクト指向入門。 メイヤーさんは、オブジェクト指向はプログラミング技法にとどまらず、ソフトウェア全体の構造と秩序、ソフトウェアの開発プロセス、設計の学び方や設計の知見の共有と流通まで、ソフトウエア開発のさまざまな側面が大きく変わる革命なのだ、ということを力説している。 私自身、型とカプセル化を重視する設計スタイルを現場でいろいろ実践する中で、ソフトウェア開発のさまざまな側面に影響がでることを日々実感している。9章 オブジェクト指向開発プロセス、10章 オブジェクト指向の学び方と教え方の2つの章は、そういう現場で得た知見を元に、開発のやり方が変化しつつあること、型とカプセル化を重視する設計スタイルのわかりやすい教え方について、言葉にしてみた。

まとめ

後半は、自著の説明になっちゃったけど、独自の型を定義し、ドメインロジックをカプセル化する設計スタイルを学ぶ入門書としては、お役にたてるのではと思っています。

私の本の内容がものたりなかったら、ぜひ、前半でとりあげた三冊を手元に置いて、最初は拾い読みでよいので、読んでみてください。 型とカプセル化にこだわるオブジェクト指向プログラミングがわかってくると、世の中のさまざまなオブジェクト指向に関する情報の関係性(と無関係性?)が、いろいろ見えてくると思います。

*1:アプローチの違いは、こちらにわかりやすい説明と、参考情報へのリンクがあります→オブジェクト指向とは何ですか

*2:こちらも大きな流れとして参考になります→新人プログラマに知っておいてもらいたい人類がオブジェクト指向を手に入れるまでの軌跡

ドメイン駆動設計を理解する3つのキーワード

ドメイン駆動設計との出会い

10年前に、エヴァンスのドメイン駆動設計を初めて読んだ時は、書いてある内容がほとんど理解できなかった。 あまり、面白いとも思わなかった。

当時は、現場でバグだらけのコードと格闘していた。障害が報告されるたびに、リファクタリング本を参考に、該当個所の長いメソッドや大きなクラスを片端からリファクタリング。その結果、コードがわかりやすくなり、やっかいなバグが単純な修正で解消できてしまうことの効果に驚き、設計の重要性を再認識していた。

それ以前は、UNIXC言語OraclePL/SQLという、オブジェクト指向ではない世界で技術を身に着けてきた。 どちらかというとオブジェクト指向には、ネガティブな印象を持っていた。現場では役に立たんだろうと。

バグとの格闘の中で、リファクタリング(設計改善)の威力を肌で感じ、その考え方とやり方がオブジェクト指向に由来するということを知るにつけ、オブジェクト指向も食わず嫌いではなくもう少し学んでみようと思った。

ワーフスブラックの「オブジェクトデザイン」とバートランドメイヤーの「オブジェクト指向入門」を買い込んで読み始めてみた。 両方とも面白いと思うところもあったが、何を書いてあるのか、よくわからないところも多かった。

実践的なオブジェクト指向との出会い

大きな転換点は、ケントベックの「実装パターン」を読んでからだった。

オブジェクト指向とは何か、という説明ではなく、「変更の影響の局所化」「コードの重複の除去」「ロジックとデータの一体化」「宣言型の表現」などの設計原則を、なぜそうするのか、具体的にどうやるのかが、わかりやすいサンプルコードで説明されていた。

特に「実装パターン」の中の「Value Object」は、大きな転機になった。 この転機については、こちらの記事でも書いた。 masuda220.jugem.jp

「実装パターン」を何度も読み直し、いろいろ実践した後で、改めて「ドメイン駆動設計」、「リファクタリング」、「オブジェクト指向入門」、「オブジェクトデザイン」を読み直してみたら、それぞれの本の内容がだいぶわかるようになってきた。 特に「ドメイン駆動設計」の現場でのエヴァンスの設計に奮闘するさまざまなエピソードが、生きた事例として理解できるようになってきた。

その後、Value Object 以外にも、「ドメインを隔離する」「アグリゲート」「リポジトリー」「境界づけられたコンテキストとモデルの整合性パターン」などに関心を広げ、現場での設計に取り入れるようになった。

その結果、コードが整理され、エヴァンス本が目指す「進化と成長を続けるソフトウェア」というものがどういうものか、ある程度、理解できるようになった。ドメイン駆動設計は、ソフトウェアの変更を楽で安全する技法として実践的で効果的だという手ごたえを感じるようになった。

もやもや感

そういう手ごたえもあって、現場で実践するだけではなく、ドメイン駆動設計について、ブログを書いたり、イベントで登壇したり、他の現場に出かけて意見交換や助言をしたり、本を書いたり、いろいろアウトプットをしてきた。

アウトプットしながら、新たな気づきがあり、また次の実践とアウトプットということを繰り返してきた。

しかし、どうもすっきりしないもやもや感も抱えていた。 簡単に言えば、表面的形式的には実践できているかもしれないが、本質をとらえ切れていない、あるいは、本質を言語化できていない、という違和感。

現場でのソフトウェア開発の中で、エヴァンス本にでてくるブレークスルー的な手ごたえをいくども経験できたが、偶然感がつよく、もっと意図的にそこに近づく道があるのでは、という漠然とした予感めいたものもあった。

三つのキーワード

去年の夏に、あるイベントのワークショップ用に資料を作っている時に、その違和感を解消する手がかりをつかんだ。 ドメイン駆動設計と他の設計方法を比較して説明するスライドを作っていた時だった。

その資料と作った時点では、まだうまく言語化できていなかったが、それから数カ月、自分なりに手がかりを、なんとか言語化しようと試みてきた。 イベントやワークショップで、実際にいろいろなキーワード(の候補)を使って説明し、その反応を受けとめる中で、三つのキーワードが中核の概念として明らかになってきた。

それが次の三つのキーワード

  • ビジネスルール
  • 計算モデル
  • 型指向のプログラミング
ビジネスルール

エヴァンス本に繰り返しでてくる「ドメインロジック」「ドメインの知識」「ドメインの理解」などの言葉は、具体性に欠ける。 対象が広くぼんやりとしている。

ドメインロジック」をビジネスアプリケーションの分野に限定すれば、ビジネスロジックとなる。 そして、ビジネスロジックはビジネスルールとほぼ同じ意味になる。

ビジネスルールとビジネスロジックを区別するとすれば、ビジネスルールは、プログラムで表現するかしないかとは無関係な、実際のビジネスの活動の中の取り決めや約束事。ビジネスロジックは、ビジネスルールのある部分をプログラムで表現したもの。

いずれにしても「ドメインロジックに焦点を合わせる」は「ビジネスルールに焦点を合わせる」と捉えることができる。 実際のところ、エヴァンス本にも「ルール」という言葉は300回近く登場する。「ポリシー」や「制約」という言葉も含めれば、ドメイン駆動設計の重要な関心事の一つが「ビジネスルール」にあることはまちがいない。

ドメインロジック」を「ビジネスルール」と置き換えてみると、エヴァンスの意図するところが、より具体的に理解できるようになる。

ドメインの知識とは「ビジネスルールの知識」であり、ドメインエキスパートとは「ビジネスルールについての知識と経験が豊かな人」であり、「ドメイン層」はビジネスルールを記述する場所、というわけだ。

ドメイン駆動設計の考え方を理解し実践するカギは、「ドメインロジック」を「ビジネスルール」という、より具体的な対象としてとらえることだ。

計算モデル

ドメインモデル」も、あいまいでわかりにくい言葉だ。

エヴァンス自身が書いているように、ドメイン駆動設計でいうところの「ドメインモデル」はオブジェクト指向のコミュニティで生まれた設計の考え方の一部である。 オブジェクト指向も、いろいろな解釈がある。私は、データモデルへの対比という意味も含めて、オブジェクト指向のモデルとは「計算モデル」だと思っている。

実際に、エヴァンス本に登場するドメインモデルの例は、次のような計算モデルである。

  • 投資シンジゲートの配分比率計算(シェアパイ)
  • コンテナへの荷物の格納ルール
  • 輸送経路を自社に有利にするための経路選択のバイアスポリシー
  • プリント基板の配置ルールを基にした部品配置と配線の妥当性の判定

ドメインモデル」は、なんらかのルールに基づいた「計算と判定のモデル」ととらえると、だいぶすっきりする。

アプリケーション全体としては、データを永続化したり参照したりする仕組みが必要になる。しかし、「ドメインモデル」だけに注目すれば、データの記録と参照からは隔離した、純粋な「計算モデル」という理解がしっくりくる。

「計算モデル」を実行するには、計算の準備としてデータの参照が必要だし、計算結果を記録することも必要だろう。しかし「計算モデル」を、データの参照と記録から意図的に分離することで、「計算モデル」はプログラミングの対象として、よりわかりやすく、扱いやすくなる。

エヴァンス本では、リポジトリや集約の説明のところで、データの永続化の問題が登場するために、この「ドメインモデル=計算モデル」という図式が、ぼやけてしまっている。しかし、全体を読めば、ドメインモデルは「計算と判定のモデル」であり、「データの記録と参照」からは隔離されたものとして扱われていることがわかる。

リポジトリは計算モデルを入出力の関心事から分離する仕組みであり、集約(アグリゲート)はデータの集約ではなく、「計算の集約」を表現する手段だということだ。集約が維持するのは、データベース上のデータの整合性ではなく、計算の整合性であり一貫性ということだ。

型指向のプログラミング

計算モデルをプログラミング言語で表現する場合、例えばFORTRANのような手続き型の言語でももちろんできるが、エヴァンス本が採用している実装技法は、オブジェクト指向である。 エヴァンス本人が、あるイベントで述べているように、本を書いた当時は "I loved Object Oriented." 、 現在は "I still like it" と続けている。温度感は変わっているが、オブジェクト指向が基本であることは変わっていない。

問題は「オブジェクト指向」といってもいろいろなとらえ方があること。 ここらへんの詳しい話は、以下の説明が必読。

jp.quora.com

簡単に言えば「メッセージパッシング」で代表されるオブジェクト指向と、「型」で代表されるオブジェクト指向があり、両者は本質的に異なるアプローチであるということ。 エヴァンス本を読むと、若干の混乱があるが、基本的には「型」を基本とするオブジェクト指向と理解してまちがいないだろう。

ビジネスルールを「計算モデル」ととらえ、計算モデルをコードで表現するには、「型」に基づくオブジェクト指向プログラミングが役に立つ。

「型」とは、計算の対象となる「値の種類」であり、有効な値の範囲と、その値を使った計算を定義したもの。 計算モデルの表現技法として、「型」中心のプログラミングがぴったりというわけだ。

ビジネスアプリケーションであれば、金額、数量、日付、日数、期間などの値の種類を、それぞれ独自の型として定義し、型ごとに、有効な値の範囲と、必要な計算を定義する。

BigDecimal型やLocalDate型は、有効は値の範囲がとてつもなく広く、可能な計算も多岐にわたる。ビジネスの計算モデルを記述するには、焦点がぼやけてしまう。また、ちょっとした記述のミスでバグが混入する可能性が大きくなる。

その問題領域の計算モデルにあわせて、厳密に値の範囲を制限し、必要最小限の計算だけを定義した独自の型を用意することで、プログラムがみちがえるようにわかりやすく安全になる。

エヴァンス本の、配分比率の計算、コンテナの格納条件の判定、経路選定のバイアス計算などは、型指向でプログラミングする具体例になっている。暗黙の概念を明示したり、制約を表現したり、設計の意図を明確にし、変更を楽に安全にする技法として、クラスを使って型を定義するプログラミングスタイルを採用しているわけだ。

実際、価格計算とか日付計算がともなうビジネスルールでは、型指向のプログラミングで記述することで、ロジックを一か所にまとめてわかりやすく整理できる。

値を「型」として扱う設計パターンの代表であるValue Object パターンは、ビジネスルールの計算モデルを実装するための、基本であり最強の道具といってよいだろう。

実験は続く

「ビジネスルール」「計算モデル」「型指向のプログラミング」

この三つのキーワードでドメイン駆動設計を解釈し、実践してみる実験は、まだはじめたばかり。

自分としては、そうとう手ごたえを感じているけど、実際のコードでもっともっと実験し小さな失敗を繰り返しながら、知見を増やし、こうやってブログで書いたりイベントで登壇したり、いろいろな現場で設計に関心とエネルギーを持つ技術者たちと意見交換をすることで、さらに多くの学びができそうな予感にわくわくしている。

参考情報

ビジネスルール・計算モデル・型指向のプログラミングで作ってみたサンプルアプリケーション github.com

このサンプルアプリケーションを解説したときに使った資料

www.slideshare.net

型指向のプログラミングの設計ガイド: 設計ガイドライン · masuda220/business-logic-patterns Wiki · GitHub

参考書籍: gihyo.jp

アウトプットから始まる学び

ドメイン駆動設計やオブジェクト指向設計について、あれこれ考えていることを、自分なりに言語化して、少しずつアウトプットしてみようと思う。

アウトプットの機会を作ると、いろいろなインプットと試行錯誤が始まって、自分の学びが加速するはず。

創造的な学び方のコツ:ラーニングパターン #7 アウトプットから始まる学び