開発チームの設計力を強化する

2016.11.10

  • オリジナル記事

Edit by
増田 亨

増田です。

最近、いろいろな会社の社内の開発チームの方と話す機会が増えました。その中で、感じることが多いのが「現場の開発チームの設計力」の弱さです。5年以上の経験がある方でも、ご自身の設計力に悩んでいる。チームを引きいる立ち場になると、チームとして設計力の不足を痛感される方が多いようです。

チームの設計力を改善するには、どうすればよいか。それが今日のテーマです。

※注意:この記事は2014年9月4日にGuildWorks Blogで公開したエントリをリライトしたものです。

設計の目的と効果をメンバーで共通理解にする

ソフトウェア設計の目的は「変更コスト」を下げることです。

変更が容易なプログラムもあれば、手を加えることが現実的には不可能なプログラムもあります。この違いを生むのが「設計」です。変更が楽で安全になるように、コードの書き方やコードの整理の仕方を工夫する。それがソフトウェアの設計です。
プログラムの変更に苦しんでいるなら、それは設計がうまくいっていない証拠です。設計を改善すれば、もっと変更は楽で安全になります。
設計の改善に手間ひまをかける理由は、それが「変更コストを下げる」という具体的な見返りがあるからです。変更が必要になった時、むやみにコードと格闘するのではなく、いったん既存のコードの書き方を見直して、整理しなおしてみる。コード書き方、コードの整理の工夫しだいで、ソフトウェアの変更がずっと楽で安全になります。
この設計の目的と効果をチームのメンバー全員が理解し、また、設計の効果に実感を持つことがチームの設計力改善の第一歩です。

設計をいつやるのか

設計は、開発の初期に集中的に行うものではありません。むしろ、ある程度コードが増えてきてからの日々の「小さな設計活動」のほうが効果が大きい。
開発の初期はわからないことだらけです。わからない状態で、設計にたくさん時間をかけても、かなりの部分はまちがった設計になります。
そうではなくて、日々の開発作業の中で、小さな設計改善を累積する。そのほうが、設計の改善効果が大きい。開発中は、コードが増えるいっぽうです。増えるコードの書き方や整理の仕方を、毎日、メンバー全員が地道に工夫する累積効果のほうが、初期の集中的な設計よりも、変更コストの削減に効果的です。
開発初期に集中して設計するやり方なら、少数の設計者が設計を担当する、という考え方もあるかもしれません。
日々「小さな設計活動」を継続するやり方では、チーム全員が設計する必要があります。チーム全員が毎日コードを書いています。設計も毎日、チームメンバー全員でやるのがいちばん効果的です。

設計力のばらつきを改善する

もちろん、ソフトウェアの設計力は、個人の経験や知識によって「ばらつき」があります。 「レベル」の違いよりも「ばらつき」が問題です。
設計力の「レベル」の高いメンバーだけを集めても、設計の考え方ややり方に「ばらつき」が大きいと、プログラム全体では設計の一貫性がなくなり、理解が難しく変更がたいへんなソフトウェアになってしまいます。
設計力の「ばらつき」を改善することがチームの設計力改善の重要なポイントです。設計力の「ばらつき」を改善するにはどうすればよいでしょうか。

設計の基本の考え方をチームメンバーで共有する

設計のガイドラインやルールを細かく決めても、うまくいきません。細かいルール決めは、むしろ「設計の思考停止」をおこします。命名やコードのレイアウトは形式的に整っている。いざ変更しようとすると、どこに何が書いてあるかわかりにくく、副作用だらけになる。「設計の思考停止」はきまってそういうプログラムを生みだします。
ガイドラインやルール決めよりも、「設計の基本の考え方」をチームで共通理解にしたほうが効果が大きい。
個々の設計判断、コードの書き方をメンバーにまかせても、基本の考え方が同じであれば、全体として一貫した設計を維持できます。
チームで共有すると効果の大きい設計の基本のキーワードは次の三つです。

  • ドメイン駆動
  • モデル駆動
  • オブジェクト指向

この三つの設計の考え方を抽象的な説明ではなく、なぜそうするのかを現場感覚でコードレベルで共通理解にする。それが、チームの設計力を改善し、ソフトウェアの変更コストを下げることに絶大な効果をもたらします。

ドメイン駆動

プログラムの書き方/コードの整理のやり方を、ソフトウェアの対象領域(ドメイン)の用語や考え方に合わせる、という設計の考え方です。「ドメイン」はわかりにくい言葉です。そのソフトウェアが使われる「事業領域」とか「サービス領域」を指す、という理解でよいと思います。
ドメイン駆動設計の具体的な設計のやり方は、たとえば、クラス名やパッケージ名を、業務の言葉と一致させる。メソッド名や変数名も業務の言葉と一致させる。
このやり方で設計すると、ソフトウェアの変更コストが大きく下がります。
ソフトウェアの変更は、ほとんどが、サービス内容や事業内容の変更に起因します。変更が必要になった時、クラス名と業務用語が一致していれば、どこを変更すべきか、簡単に特定できます。
業務の用語を軸にしてコードを整理しておくと、変更の影響範囲は、業務の仕組みの影響範囲と一致します。
ある変更をしたために、業務上、わけのわからないところに変更の副作用がでるようなことはなくなります。
「変更コスト」を下げるためには、「業務の用語」にそって、クラス設計やメソッド設計をする。これがチームが当たり前の発想になってくれば、ソフトウェアの変更コストは劇的に下がります。

モデル駆動

「モデル」とは、現実世界の「模型」です。現実世界を単純化し、全体を一目でわかるようにしたものです。
ソフトウェアの設計で陥りがちな落とし穴は「部分最適」です。部分最適の設計をするたびに、全体の見通しが悪くなり、また要点をはずした設計になりがちです。部分最適の変更を繰り返すたびに、ソフトウェアは変更がたいへんになり、危険になっていきます。
「モデル駆動」をそれを防ぐ設計の考え方です。
「モデル」は開発の初期にラフな模型を作成します。そして正しい全体像をわかりやすく伝えるために「モデル」をいつも更新し、最新の状態に保つ活動を続けます。
「モデル」の作成と更新には全員が参加すべきです。かけだしのメンバーは、経験や知識が不足していて全体像を理解したり、活用することは難しいかもしれません。
それでも、新人クラスにも「世界地図」を持たせるべきです。最初は「世界地図」が理解不能でも、チーム全員が同じ地図をもって行動し、話し合うことの効果は絶大です。

オブジェクト指向

オブジェクト指向もわかりにくい言葉ですが、設計のたいせつな考え方です。ソフトウェアの変更コストを下げる工夫として、オブジェクト指向の考え方とやり方は、ぜひチームメンバーで共通理解にすべきです。
特に、次の考え方がたいせつです。

  • ・関連するデータは、同じクラスで扱う
  • ・そのデータを使うロジック(処理)は、データを持つクラスに置く

特に、処理対象のデータを持つクラスにロジック(処理)を置く、というのが大切なポイントです。
データを持つクラスに、そのデータを使うロジック(処理)を集めると、変更対象と影響範囲が限定しやすくなります。
データを持つクラスと、ロジックを持つクラスを分けてしまうと何がおきるでしょうか。データを持つクラスが、getValue()メソッドを持ち、プログラムのあちこちから、別のクラスがgetValue() して、処理をするという、オブジェクト指向とは逆の設計スタイルです。
変更が必要になった時に、getValue()している箇所をすべて洗い出して、そこに書かれたロジックを調べる必要があります。
おそらくあちこちでgetValue()した後に、同じような処理をしているはずです。同じデータを処理しているのですから、重複したロジックになるのが当たり前です。
データと、そのデータを扱うロジックを同じクラスに集めておけば、このような重複をなくすことができます。しかも、調べる箇所も変更する箇所もそのクラスだけに限定できます。
「関連するデータとロジックは同じクラスに集める」という、この考え方をチームで共有するだけで、ソフトウェアは見違えるように変更がやりやすくなります。
「ドメイン駆動」で説明したように、クラス名やパッケージ名を業務の用語に合わせることで、変更は、さらに楽で安全になります。

現場で、コードレベルで、実際に

ここで書いた設計の考え方とやり方は、現場で、コードで、実際にやってみながら覚えるのがいちばんです。
ギルドワークスでは、こういう設計の考え方を、現場で実際にやってみながら現場の開発力を改善のお手伝いをしています。
ご興味を持たれた方はギルドワークスのホームページからお気軽にお問い合わせください。

https://flic.kr/p/8G9ztL by Damien Pollet, on Flickr