はじめに
ここ数年で, ある程度の規模(クラス数が最終的に50~100オーダー)を持つソフトウェアモジュールのアーキテクチャ設計に携わる機会があり, 色々と本を読み漁りつつ実践経験を積んできた.
それらの本の中から今も特に有用だと思う書籍を5冊取り上げ, その紹介をしつつ良い設計のためのポイントをいくつかまとめられたらと思う.
中心となる概念はETC原則(Easier To Change / 変更容易性の原則)である.
達人プログラマー (第2版)
この本のスコープは設計に限った話ではなく幅広い意味で名著であるが, 特に2版で追加された内容(だったはず)の設計の話が非常に良かったので, 2テーマほど引用したい.
ETC (Easier To Change) 原則
(P.35) Tip 14 よい設計は悪い設計よりも変更しやすい
(P.36) 我々が知る限り、この世の中のあらゆる設計原則はETC原則を特殊化したものとなっています。
疎結合, 単一責務, コードの可読性, 全ては変更しやすいコードであるための原則である, と.
言われてみればその通りだなと思いつつ, この点をここまで明確に言及した表現は見たことがなかった.
いや, もちろん変更のしやすさが重要であることは過去の名著でも何度となく言及されているが, 「それに名前を与えた」のはあまりなかったように思う.
複数の設計の選択肢を比較する際にまず立ち返るべき原点と言える.
継承は使うな
(P.205) 3つのテクニックがあり、そのいずれかを使用すれば今後、いっさい継承を使わなくても済むようになるはずです。
- インターフェースとプロトコル
- 移譲
- mixin と trait
(P.207) Tip 52 ポリモーフィズムの表現にはインターフェースを愛用すること
(P.208) Tip 53 サービスに移譲すること: has-a は is-a に勝る
(P.211) Tip 54 機能の共有にはmixin を使用する
オブジェクト指向言語の経験が長い人ほど刺さるかも知れない内容.
言語によっては継承とインタフェースが区別されていなかったり(C++とか)mixinを言語機能としてサポートしていなかったり(C++とかC#とか)するので適宜読み替えが必要ではあるが, 雑に言えば「メンバ変数を継承するな」という言い方になるかもしれない.
メンバ変数を含む実装を継承してしまうと親子やその孫が強結合してしまい, ETC原則に反する.
なので継承を用いず, 他の代替手段を用いることで疎結合を保とう, ということになる.
思えばいわゆるデザインパターンも, インタフェースと移譲を駆使してクラス設計をしよう, ということの具体例であると思う.
リーダブルコード
言わずもがなの名著. 個人的に, コーディングをする機会のある非エンジニアに設計の本を1冊勧めるならこれだと思っている.
読みやすさの基本定理 (最短理解)
(P.3) コードは他の人が最短時間で理解できるように書かなければいけない。
この本ではこれが基本原則であるが, なぜ理解しやすくなければいけないかというと, その方がコードを変更しやすいからに他ならない(ETC原則).
具体的にどうすれば読みやすくなるかの詳細はここでは特に紹介しないが(すでに世の中に書評も山ほどあるし), 変数や処理に「良い名前をつける」(名前重要)ということに尽きるような気がする.
リファクタリング
ちゃんと読んだことがあるのはRubyエディションなのだが, エッセンスは変わっていないはず, 多分.
引用文のページ数はRubyエディションに基づく.
コードの臭い
(P.97) いつリファクタリングすべきかを説明するのは、それほど簡単にはいかない。~ Kentは ~ リファクタリングの「いつ」を説明する概念として「臭い」を持ち出した。
良くないコードの徴候すなわち「コードの臭い(Code Smell)」とはどんなものであるか, それらに対してどういう対処を検討するとよいのか, という具体例が豊富に掲載されている.
コードの臭いの基本原則のようなものは明記されていなかったように思うが, 要するにETC原則の裏返し, すなわち「変更しづらいコードとは具体的にどのようなものか」が書かれていると言える.
最近はどちらかというと, 自分で書くときよりも他人のコードや設計をレビューするときにここに立ち返る機会が増えた.
自分で書くときは感覚で行けても, 人に指摘をするときにはきちんと言語化しなければいけないので, そのときにいろいろな事例に名前が付いていることが非常に便利である.
テストを書け
(P.114) リファクタリングはテストを必要とする。リファクタリングをしたければ、テストを書かなければならない。
いわゆるTDDの文化を私はあまり実践できていないのでそのあたりを強くは言えないのだが, 少なくともユニットテストによって振る舞いを壊していないことを確認しながらリファクタリングを行うことが決定的に重要であることは間違いない.
書籍中のそれぞれのリファクタリング実施手順にも「テストする」というステップが必ず書かれている.
パフォーマンスは?
(P.94) パフォーマンスの面白いところは、実際に分析してみると、実行時間の大半がコードのごく小さな一部で消費されていることである。
(P.95) 私の経験では、リファクタリングをすると、高速なソフトウェアを書きやすくなる。短期的な視点で見れば、リファクタリング中にソフトウェアのスピードは下がるかもしれないが、最適化の段階に入ったときに、ソフトウェアに手を入れやすくなる。
変更しやすい, 綺麗な設計にしようという話で避けて通れないのが性能の話題である.
一般に, 性能を追い込もうとすると可読性や変更のしやすさを犠牲にせざるを得ないイメージがあるが, その点はどうなのか.
その回答が上記の引用である.
つまり, 可読性その他の設計の良さを犠牲にしなければいけない箇所は極力小さくし, その「悪さ」を漏れ出ないようにしたい, そのためには元々のコードが変更しやすくなっているとずっと扱いやすい, というわけである.
Clean Architecture
有名な同心円のアーキテクチャ図とかSOLID原則とか色々出てくるが, 個人的にこの本で印象に残っているのは序盤のプログラミングパラダイムの説明のあたり.
ポリモーフィズムと依存性逆転
(P.70) OO(オブジェクト指向)とは「ポリモーフィズムを使用することで、システムにあるすべてのソースコードの依存関係を絶対的に制御する能力」である。
達人プログラマーでも「直交性」「分離」など依存関係に関するテーマはもちろん扱われているが, ポリモーフィズムがあれば「制御の流れ」と「依存の方向」とを独立にすることができる, という点を強調しているのはこの本の1つの特徴だと思う.
具体的には「依存性逆転の原則」によって, インターフェースを境界にして実装詳細に依存しないようにする設計パターンのことを言っている.
境界線を引く
(P.167) ソフトウェアアーキテクチャとは、境界線を引く技芸である。
(P.172) 境界線は「重要なもの」と「重要ではないもの」の間に引く。
(P.177) 境界線は 変更の軸 があるところに引く。境界線を挟んだコンポーネントは、それぞれ変更の頻度や理由が違っているのである。
どのような単位でコンポーネントを分解してどの向きに依存させると良いのか, 様々な例が扱われているが, 全ては変更しやすくするため(ETC原則)である.
そのとき, 前項でも触れたが, 依存の向きも自由に選べる, その実装手段があると認識しておくのが重要.
Design It!
前に紹介した4冊よりぐっと抽象度が上がる. 部分的に役立ててはいるものの, まだまだ勉強中である.
7章のアーキテクチャパターンのカタログのあたりが目的で購入したような記憶があるが,「ステークホルダーに共感する」「設計をtangible(有形)にする」などなど小規模なクラス設計のレベルでは出てこなかった話題も多く, ソフトウェア設計という活動の視座を確実に上げてくれる本と言える.
設計判断を遅らせる
(P.96) 簡単に元に戻せない決定、つまりアーキテクチャ上の設計判断は、重大だ。~ 1つの戦略は、責任を持てる限り拘束力のある判断を遅らせることだ。
(P.97) 設計判断を後から変えるのが容易なのであれば、それはもはやアーキテクチャ上の関心事ではない。可能であれば、変更の可能性がある部分については後続の設計者が設計判断を下せるよう、アーキテクチャを設計しよう。
このレベルの設計ともなると全てを変更が容易であるように保つのは難しいが, ソフトウェアを扱う以上, もちろんETC原則は重要である.
まとめ
変更容易性(ETC) である.
コードを読みやすくしろ, 良い名前を付けろ, コメントを書け/書くな, 巨大な式・文・関数・クラスを分割しろ.
二重管理を避けよ, 疎結合にせよ, 単一責務とせよ, 詳細を隠蔽せよ, 抽象に依存せよ.
すべては, コードの変更を容易にするためである.
なぜ変更が容易でなければいけないかというと, 世の中の流れは速く, 要求も仕様も変化を迫られ, その結果としてソフトウェアも変化に素早く対応できなければいけないからである.
たとえAIがコーディングの主体になろうとも, 誰かが書いたコードを読んでそれに対する変更を実装するという動作をする限りは, AIにとっても変更容易なコードは重要であろう.
少なくとも, 自然言語による仕様記述から動くソフトウェアが瞬時に「コンパイル」されるようになる日が来るまでは, 変更しやすい設計は今後も重要であり続けるように思う.
参考文献
今回紹介した書籍のまとめ.
- 達人プログラマー (第2版) - https://www.ohmsha.co.jp/book/9784274226298/
- リーダブルコード - https://www.oreilly.co.jp/books/9784873115658/
- リファクタリング:Rubyエディション - https://www.fukkan.com/fk/CartSearchDetail?i_no=68327896
- 今入手するなら2版が良さそう - https://www.ohmsha.co.jp/book/9784274224546/
- Clean Architecture - https://asciidwango.jp/post/176293765750/clean-architecture
- Design It! - https://www.oreilly.co.jp//books/9784873118956/