7つのリニューアル!『改訂新版 良いコード/悪いコードで学ぶ設計入門』

こんにちは、リファクタリング大好きなミノ駆動です。⁠良いコード/悪いコードで学ぶ設計入門』の著者です。このたび2024年12月25日に、本書の改訂新版を出版します。

なるべくバグを発生させず、すばやく正確にコードを変更できる度合いを変更容易性といいます。変更容易性が低いコードは、バグを埋め込みやすく、正確にコードを変更できるまでに時間がかかってしまいます。

変更容易性の設計ノウハウに関する技術書は数多くありますが、レベルが高いものが多いです。そのため、初学者にとって手を出しにくく、どう学べばいいのかわからないといったハードルがあります。

そうした課題を解消するのが本書です。

豊富な良いコード/悪いコードを題材に、変更容易性の設計ノウハウをやさしく学べる内容となっています。

本書初版は大変多くの方に手に取っていただきました。そのおかげもあって、ITエンジニア本大賞2023技術書部門の大賞を受賞しました。

私のさまざまな知見のアップデートを経て、このたび改訂新版を出す運びとなりました。改訂内容は主に以下の7つです。

  • 【変更】凝集度、結合度からカプセル化、関心の分離へ
  • 【加筆】インターフェースと実装の分離
  • 【変更】interfaceの解説を改善
  • 【加筆】インターフェースと実装の分離にもとづいたinterface設計
  • 【加筆】アンカリング効果
  • 【加筆】ジョシュアツリーの法則
  • 【加筆】説明による設計スキルアップ

順番に説明します。

【変更】凝集度、結合度からカプセル化、関心の分離へ

「凝集度」⁠結合度」一切使わない説明に書き直しました。

凝集度、結合度の観点で解説していた内容は、カプセル化と関心の分離の観点へ全面的に置き換えています。これが改訂新版で最も大きく変わったポイントです。

理由を説明します。

凝集度は、モジュール内における、データとロジックの関係性の強さを表す指標です。結合度は、モジュール間の、依存の度合いを示す指標です。

初版では、コードの良し悪しを凝集度と結合度の観点で説明していました。しかし、初版出版後、これらの概念に違和感を覚えるようになりました。

まず凝集度についてです。

凝集度で最も品質が高い構造は機能的凝集です。これは、ひとつの関数がひとつの機能を実行する構造を指します。

しかし凝集度が高い構造であっても、変更容易性が低くなる場合があります。それが次のコードです。

// 金額を表現するクラス
class Money {
  int amount;         // 金額値
  Currency currency;  // 通貨単位
}

class Util {
  // このaddメソッドは機能的凝集の構造
  // しかしMoneyクラスに定義されていないので変更容易性は低い
  static Money add(Money money1, Money money2) {
    if (!money1.currency.equals(money2.currency)) {
      throw new IllegalArgumentException("通貨単位が違います。");
    }

    Money added = new Money();
    added.amount = money1.amount + money2.amount;
    added.currency = money1.currency;

    return added;
  }
}

Utilクラスのaddメソッドは機能的凝集の構造です。

しかし、Moneyクラスのインスタンス変数と、そのインスタンス変数を操作するロジックがバラバラです。このような実装は、どこで何が行われているのか理解が難しくなります。結果として重複コードや修正漏れが発生しやすくなり、変更容易性が低下します。

結合度についても、同様のことが当てはまります。

ドメイン駆動設計で用いられる集約(Aggregate)を例に挙げて考えてみましょう。集約とは、整合性を維持すべきオブジェクト群をひとまとめに扱う構造です。

このように、複数のオブジェクトを所有しひとまとめにする構造をコンポジション構造と呼びます。

集約構造の注文クラス
Aggregate.png

結合度を下げて品質を高めることだけに注目し杓子定規に依存関係を減らしてしまうと、整合性を維持することが難しくなります。

前述の通り、バラバラな構造は結果的に変更容易性の低下を招くのです。

結合度を下げるためにバラバラにすると変更容易性が低下する
UnAggregated.png

本書で解説している変更容易性の高い構造には、凝集度や結合度の観点だけでは、必ずしも品質が高いとは言えないものも含まれています。

初版では、いささか不自然な解説もあったのではないかと考えました。どのような解説であるべきだったのか熟慮した結果、カプセル化と関心の分離の観点で書き直すことに決めました。

カプセル化とは、データとそのデータを操作するロジックをひとつにまとめることです。

関心の分離とは、それぞれの関心でモジュールを独立させ、他の関心と分離する考え方です。

  • 強く関係するものどうしをカプセル化する。
  • 関係の弱いものどうしを分離する。

この観点で見直すと、凝集度と結合度の観点で生じていた違和感が解消します。

初版において、凝集度と結合度の観点で説明していた内容を、カプセル化と関心の分離の観点に置き換えた結果、一貫性のある内容に改善しました。

【加筆】インターフェースと実装の分離

関心の分離に関してテクニックを追加しました。

一連の処理手順が長く書き連ねられている構造をトランザクションスクリプトパターンと呼びます。

トランザクションスクリプトパターンのメソッドは、長いものでは数十行、数百行になるものもあります。多くの関心が混在する構造で変更が困難です。

この問題を解決する有用なテクニックとして、このたびインターフェースと実装の分離を加筆しました。

インターフェースと実装の分離とは、ひとつのモジュールをインターフェースパートと実装パートに分ける考え方です。

インターフェースと実装の分離に基づいて設計することで、関心をうまく分離できます。

トランザクションスクリプトパターンにお困りの方は多いでしょう。構造改善に有用なテクニックなので、ぜひ学んでほしいです。

【変更】interfaceの解説を改善

interfaceはJavaなどが備える多態性を実現するしくみのひとつです。

interfaceを使うと、条件分岐と同じことが実現できます。そのため、interfaceを適切に使うことで条件分岐が減り、ロジックがシンプルになります。私としては、interfaceをもっと使いこなせるようになってほしいと思っています。初版ではそのような思いでinterfaceの設計方法について書きました。

しかし、読者からの反応はあまり良くなく、interfaceのメリットやノウハウを十分に伝えきれなかったのではないかと感じました。

そこで、interfaceのメリットや設計のしかたがわかりやすくなるよう、解説を改善しました。

「interfaceを使って機能を取り換える」という表現や図を用いた、より理解しやすい内容に変わりました。

【加筆】インターフェースと実装の分離にもとづいたinterface設計

interfaceを使いこなせるようになるには、やはりイチからinterfaceを使って機能開発できるようになるのがポイントです。

しかしどうすればinterfaceをうまく設計できるでしょうか。

interfaceの設計でも有用なのが、前述したインターフェースと実装の分離です。この考え方に基づいて、イチからinterfaceを設計するノウハウを解説します。

interface設計で押さえるべきポイント、考え方を学べます。

【加筆】アンカリング効果

クラスやメソッドへの命名は、単に可読性を高めるためだけではありません。名前の付け方ひとつで構造がガラリと変わってしまいます。あいまいな命名をすると、さまざまな関心が混ざり込み、巨大化・複雑化してしまいます。

一方で、適切な命名をすると関心をうまく分離でき、変更容易性が向上します。

こうした命名のテクニックを、本書では名前設計と称して解説しています。名前設計は、本書における奥義とも言うべきテクニックです。

名前設計においてはさまざまなテクニックを解説していますが、初版で不十分だった解説に加筆しました。

そのひとつがアンカリング効果です。

アンカリング効果とは、最初に提示された数値や情報が基準になってしまい、その後の判断を歪めてしまう認知バイアスです。

アンカリング効果は命名でも生じます。思い込みに縛られて、うまく名前を改善できないことがよくあります。

アンカリング効果から抜け出し、適切な名前を設計するテクニックについて加筆しました。

【加筆】ジョシュアツリーの法則

名前設計に関しては、アンカリング効果の他にジョシュアツリーの法則についても加筆しました。

ジョシュアツリーの法則とは、名前を知ってはじめて存在を知覚できるようになるという認知法則です。裏を返せば、名前を知らないままでは適切な構造を設計することが難しい、という重要な示唆を与えてくれる法則でもあります。

ジョシュアツリーの法則を踏まえた設計の進め方について加筆しました。

【加筆】説明による設計スキルアップ

設計スキルを効率的にすばやく身につけるにはどうすればいいのか、お悩みの方は多いでしょう。初版では「設計技術の理解の深め方」と題して、効率的な学習方法を解説しました。

このコンテンツに、人に説明することでスキルアップする学習ノウハウを加筆しました。

人に説明すると、学びが深まります。これはコードを設計実装することと同等、もしくはそれ以上に重要な学習ステップだと考えます。ただやみくもに説明しても、設計スキルの向上にはなかなかつながりません。設計スキルを効率よく高めるための押さえるべきポイントをまとめました。

本書を片手に快適な開発を目指そう

以上が主な変更点です。

ほかにも説明不足だった箇所の補足や細かな表現の修正を行い、全体的にさらに読みやすい文章へと改善しました。

パワーアップした本書をぜひ手にとってください。そしてバグに苦しめられず、快適に開発していける世界を私たちみんなで築いていきましょう。

ミノ駆動(みのくどう)

X(旧Twitter):@MinoDriven

青森県出身。大手電機メーカーからWeb業界へ転身。アプリケーションアーキテクトとして,リファクタリングやアーキテクチャ改善,若手の設計スキル育成といった,設計全般を推進する業務に従事。悪しきコードとの戦いの中で設計の魅力に気付く。暇さえあれば脳内でリファクタリングしている。X(旧Twitter)ではプログラミングの風刺動画を不定期で投稿。

登壇実績多数。Developers Summitではベストスピーカー賞など受賞多数。