天の月

ソフトウェア開発をしていく上での悩み, 考えたこと, 学びを書いてきます(たまに関係ない雑記も)

増田亨さんによる「設計の考え方とやり方」勉強会に参加してきた

asken.connpass.com

こちらのイベントに参加してきたので、会の様子と感想を書いていこうと思います。

会の概要

以下、connpassのイベントページから引用です。

株式会社askenでは、設計をより良くするために増田さんに来ていただき、設計の勉強会を開催してきました。初回に「設計の考え方とやり方」という講演をしていただいたのですが、大変学びがあり、エンジニアチームの設計の議論に深みをもたらすことができました。エンジニアブログに当日の様子を記事にしていますので是非御覧ください。

この知見を社内にとどめておくのはもったいないと思いまして、増田さんにお願いし、オープンな場で再演していただくことになりました。様々な方にとっていい時間になると思いますので、是非お気軽にご参加ください。

会の様子

良い設計とは?

良い設計は悪い設計より変更が楽で安全である(=達人プログラマーにあるEasy to change)という原則を持っていて、この変更が楽で安全である設計を考えることが開発者の仕事だという話がまずありました。

変更が起きる理由は様々*1ありますが、変更が楽で安全であればこの変化に対応するスピードが早まり、開発者の成長や事業の進歩につながるというお話でした。

クラス設計のスタイル

上記で記載した良い設計を達成するために、トランザクションスクリプト方式ではなくドメインモデル方式を採用(=ビジネスルールを中心とする)していると話がありました。

具体的には、

  • 業務をしている人から見ればデータを操作するロジックはビジネスルールであり、ソフトウェアを複雑にする根源であるため、データとデータを操作するロジックは一つのクラスにカプセル化する
  • アプリケーションで出てくる「金額」や「商品区分」などをそのアプリケーション独自のクラスとして定義する
  • 契約プログラミングを実施する。(引数の型でオブジェクトを渡される限り(=nullが渡されない限り)は、必ずXXX型のオブジェクトを返すことを約束する。つまり、nullはreturnしない)

を実行しているということです。*2

ドメインモデル方式を採用することで、トランザクションスクリプト方式の問題*3を回避することができるため、より良い設計に近づくというお話でした。

契約プログラミングをしつつビジネスルールをドメイン層に閉じ込めることで、複雑さ*4を下げることが可能で、アプリケーション層は単純な処理*5のみを記述するということです。

テーブル設計のスタイル

テーブル設計では、イミュータブルなデータモデルを必ず構築しているということです。このことで、以下のメリットが得られるということでした。

  • insert onlyとすることで、書き込みが単純になり、競合を心配する必要がなくなる。挙動が安定する。
  • ドメインモデル方式と相性が良い。ビジネスルールは事実のみを用いて計算判断するため、同じ事実であれば必ず同じ結果になる。
  • 分散システムと相性が良くなる。同じ事実をあちこちで複製しても不整合が起きない。
  • データの状態を意識したWhere句がなくなり、SQLも単純になる。

イミュータブルなデータモデルの構築にあたっては、

  • データベース制約を徹底する
  • テーブルのカラム数を減らす。発生時点が同じカラムのみをテーブルに集めたり、updateを禁止することで状態が上書きされたことを検知するカラムを消せる。

開発のやり方

増田さんはまずビジネスロジックを記述したクラスを作り、そのクラス(=部品)を利用したアプリケーションクラスを作っていくというお話でした。

また、とっととコードを書き始めて*6動くものを積み上げつつ定常的にリファクタリングをしてクラスを作り直すということで、開発を進めながら分割不足(低凝集で大きなクラスの存在)を見つけては分割し、分割意図をパッケージ名やクラス名で記述するそうです。
更にその後も、分割された要素を凝集度の観点から改善させ、クラスやメソッド, インスタンス変数, パッケージ/サブパッケージを移動するということでした。

直近はクラウドの台頭もあって、構想の変化がやりやすくなっていることも、この開発スタイルが追い風になっているということでした。

設計スキルを上げるために

設計スキルの向上は、目の前の課題と経験則を高速にマッチングするためのスピードアップと言い換えられると考えているとお話がありました。

そのため、とにかく経験則を増やすことが重要だと考えているそうで、実際に作ってみたり、他人の経験則を知識として学んだり、他人の経験談から新しい経験則を導き出すことで設計スキルの向上が見込めるというお話がありました。
ただしこの経験則は一定時間が経つと脳から消えてしまうため、常に手を動かし続けることが重要だということです。*7

経験則がある程度ついた後は、体系だった書籍の関連付けや書籍の構造にフォーカスしたり、微妙にパターンを変えてみてどのような違和感が生じるかを検証してみることで、さまざまな文脈(現場)でスキルが活用できるということでした。

質疑応答

イミュータブルモデルについてもっと知りたい

WEB+DB PRESS Vol.130を参考にしてほしい。

DBの容量は?

クラウドのおかげで正直ほとんど気にしなくて良い。

とっとと作るをもう少し具体的に知りたい

複雑になりそうな部分や重要になりそうな部分から手を付ける。ドメインモデルから作り出すのは会で話した通り。
また、チームで何から作るんだっけ?という意見を出し合うことはしているし、その時間にはすごく価値があると思っている。

また、設計スキルを学びながら、学んだらとっとと作るという意味も込めていた。

上司にどう納得してもらうか?

納得してもらったことはない。ただ、自分がいいと思っていることしかエネルギーが出ないので、自分がやりたいようにやってもしやり方を許容してもらえないなら会社を辞めていた。

チームメンバーはどう編成するの?

最初から今日説明した方式を納得しているチームメンバーで揃えるのは難しい。
そのため、チームメンバーに共通理解を形成してもらうための話し合いは必要。

ただ正直なところ、現状に対して問題意識を強く持っている*8チームじゃないと、共感を得ることは難しい。

テストはどれくらい書くか?

DBとも接続させた上でサービスクラスの機能が一式動くことを担保するテストは必ず書く。
ただ、ドメインモデルにテストは書かない。(例外として他通貨対応が必要で小数点8桁までの精度が求められるものは書いた)

リファクタリングの感覚

typoを直すくらいの感覚でリファクタリングしている。
IDEコンパイラが怒らないならとりあえずリファクタしてみるかあ、という感覚でリファクタして、すぐに戻る。

継承地獄

継承は使わない。継承より委譲。

設計スキルを上げるための練習問題は?

設計方法について書かれた本と現場を行ったり来たりしている。練習問題を解く、みたいな活動をしたことはない。

技術書を月何冊読むか?

一部の本を何回も何回も読んでいる。現場で役立つシステム設計の原則に書いてあるおすすめ文献を読んでもらえればいいと思う。

最近出た本だと事業分析・データ設計のためのモデル作成技術入門は良い。

ボキャブラリーを増やすには

ドメインにまつわるドキュメントはオンラインの製品カタログや類義語辞典、原語辞典は愛読している。*9

なお、日英辞典は名前をつけるためには使わない方がいいと。*10

日本語ってコードに使う?

変数やメソッド名は日本語にすることはある。型名とパッケージ名は英語にしている。

会全体を通した感想

スライドや話の構成が見事にモデリングされていて、増田さんの主張が非常によく伝わってきた発表でした。

企業でやられたイベントの反響がよかったことをきっかけにこうした場を設け、講演を外部公開をしてくださったaskenさんには心から感謝したいです。

*1:事業の環境、競合の存在、事業の推敲能力、事業方針変更、開発者の能力、事業活動に対する理解...

*2:上述した方法がドメインモデル方式の本質的な特性ではない点には注意が必要

*3:どこにどんなロジックがあるか探しにくい、変更対象を特定しても変更して影響が出ないことに自信が持てない、些細な変更に対して大規模なテストを実行する

*4:=if文

*5:通知するだけ...

*6:コードファーストだが、仕様やドキュメントは勿論活用する。ラフなスケッチをまず書いたり、自動生成ツールを使いこなす

*7:一定期間手を動かし続けると、あるタイミングから脳内に残るようになるので、反射的に手が動くようになる

*8:こんなシステムではもう開発していられない、と思う人

*9:オンラインも愛用しているそうですが、16冊は辞書を読んでいるということでした

*10:日本語と英語をマッピングさせるために無理やり語彙を紐づけていることがあるため