最近、小〜中規模のプログラムを保守性高く記述するにはどうすればよいかが気になっていて、 ソフトウェアのアーキテクチャについて調べていました。
本を読んでみる
以下の本を浅めに読み通してみました。どの本もそれぞれ学ぶべき点があって興味深かったです。
- .NETのエンタープライズアプリケーションアーキテクチャ第2版
https://www.amazon.co.jp/dp/B00ZQZ8JNE
C#での設計の話。ドメイン駆動設計など、設計に関わるトピックが広く触れられていて良い。 - Adaptive Code C#実践開発手法 第2版
https://www.amazon.co.jp/dp/B07DJ2BL4Y
C#での実装の話。SOLID原則を中心に、実装に関わるトピックが広く触れられていて良い。 - Clean Architecture 達人に学ぶソフトウェアの構造と設計
https://www.amazon.co.jp/dp/B07FSBHS2V
もう少し具体的な話に突っ込んでほしい気はしつつ、アーキテクチャについての問題意識を全体的に学ぶことができる。 - アプリケーションアーキテクチャ設計パターン
https://www.amazon.co.jp/dp/B076BY4VJH
Javaのごつめのフレームワークを含む話。実務の問題意識に基づいていて具体的なのは好印象。 - 新装版 リファクタリング 既存のコードを安全に改善する
https://www.amazon.co.jp/dp/B0831M1RK5
リファクタリングで行う処理に名前を付けてパターン化したもの。基本ではあるが、なるほどという感じ。 - Game Programming Patterns ソフトウェア開発の問題解決メニュー
https://www.amazon.co.jp/dp/B015R0M8W0
GoFのデザインパターンでなく、実際にゲーム関係で使われるデザインパターンが説明されているのが良い。 Unityの思想が少し理解しやすくなる。 - C++のためのAPIデザイン
https://www.amazon.co.jp/dp/B00EYXMA6Q
C++でAPIを設計するという視点から、他の本で触れられていないトピックも扱われていて良い。
学んだこと
疎結合の重要性
とにかく疎結合にすることが重要。分割すると脳のリソースにも優しいし、分担して作業できるし、テストもできる。
インターフェイス
インターフェイスは、振る舞いだけを定義し、基本的に実装を記述しない要素。
C#などの強い型付けの言語では使われるが、Pythonなどではあまり使われない印象がある(Pythonのabcモジュールはあるが)
インターフェイスを使うと、具体的なクラスでなく振る舞いに対して記述することが強く意識付けられ、
具体的なクラスに依存しづらくなるため、疎結合なプログラムを作りやすいように思える。
依存性の注入(Dependency Injection)
「依存オブジェクトの注入」と理解した方が良さそう。
依存オブジェクトを内部で生成するとテストがしづらいが、コンストラクタなどから与えるとモックなどを使ったテストができるようになる。
注入が必要な依存オブジェクトが増えると面倒になるが、その場合にはDIフレームワークを用いる選択肢がある。
(参考)SOLID原則
※各原則は私の要約です。(書籍などに明確に定義が記述されていないものもあるため)
S - 単一責務の原則
「クラスを変更する理由はひとつのみであるべき」
クラスの責務はひとつのみであるべき。それはそう。
O - 開放・閉鎖の原則
「拡張に対して開いており、変更に対して閉じているべき」
要するに、モジュールの振る舞いを拡張できるとともに、拡張したときに既存のコードに変更が発生しないということ。
これを満たすには、モジュールの機能をどう拡張するかの拡張ポイントを考えることになる。
L - リスコフの置換原則
「SがTの派生型であるとすれば、T型のオブジェクトをS型のオブジェクトと置き換えたとしても、プログラムは動作しつづけるはず」
要するに、あるオブジェクトを派生型のオブジェクトに置き換えたとしても動作しつづけるはずということ。
これもそれはそう。
I - インターフェイス分離の原則
「クライアントが使用しないメソッドに依存するよう強制されるべきではない」
上記「インターフェイス」参照
D - 依存性反転の原則
「上位レベルのモジュールは下位レベルのモジュールに依存すべきではない。両方とも抽象に依存すべき」
「抽象は詳細に依存してはならない。詳細が抽象に依存すべき」
確かにそれはそう。実現するには、インターフェイスを使った上で依存関係を上手くほぐしていく必要がありそう。