webとモバイルアプリの逆転

webアプリとモバイルアプリの開発に関する話や本・ゲームなどの趣味の話を雑多にしていきたい

Clean Architectureの11章まで読んでの感想

Clean Architectureを完全に理解するために前回の続きから思ったことや気づいたことを引き続き書いていきたい。 ただ、1章ごとに書いていくのやたら時間がかかることに気づいたから次からもう少しまとめて行きたいと思う。

第5章 オブジェクト指向プログラミング

オブジェクト指向プログラミングとは何かを説明せよ!!っていざ言われるとあまりうまく説明できない…と気づいてしまったので、この章をじっくりと読んでみる。 「オブジェクト指向とは何か?」について、この本では「ポリモーフィズムを使用することで、システムにあるすべてのソースコードの依存関係を絶対的に制御できる力」と書かれていた。 制御できることで上位のモジュールと下位のモジュールを独立することができ、個別な開発を可能にすることやソースコード変更した際のデプロイ範囲の独立が可能になるとのこと。

文中にポリモーフィズムはパワーだ!書かれていたけど、確かに考えてみるととこの特性はかなり強力だなと自分の中で納得。 独立した開発が可能になれば並列に開発することができるため開発速度も向上するし、プラグインとして独立すれば別のプロジェクトでも使いまわすことができて生産性が向上するでとても良い。 より細かい原則はこの後出てくると思うので、そこで改めて考えていきたいところ。

アーキテクチャを考える上では何がどのような役割を持つのか、データの制御はどうするのかを考える必要があるためオブジェクト指向の理解はアーキテクチャを学ぶ上で身に着ける必要があるなとこの章を読んで改めて思った。

第6章 関数型プログラミング

みんな大好き関数型!!

関数型言語の変数は変化しない」と書かれており、これはアーキテクトの観点で重要と書かれている。 確かに設計をするうえで堅牢にしたいなら、変更できなくしてしまえば並列処理でも全く問題もないというのも納得。 あと変化できなくなると変な場所で間違えて代入するということもなくなるので、自分のポカも減らせるのでうれしい。

不変性は最近のコーディングの規約でもできるだけ不変な変数で定義することは一般的にやられているのでなじみ深くなってるなと思ったり(KotlinのvalやTypescriptのconstなど)。

この章では最後にこれまであげた3つのプログラミングパラダイムについて改めてまとめられていた。ここでもう一度主張されていたのは、ソフトウェアというのは、順次・選択・反復、そして間接参照で構成されていること。 そして、プログラミングパラダイムは上記を実現するための方法を制限して、安全にソフトウェアを構築するための方法であると主張されていた。 この事実を心に刻みつつ、次の設計の原則についてやっていく。

第3部 設計の原則

SOLID原則についての導入。データ構造や関数をどのようなクラスにまとめればよいか、クラスとの接続をどのように考えればいいかを教えてくれる原則をまとめたもの。 ここの原則の内容を学んだことはあったが、アーキテクチャ的にどういう意味をもつのかといった体系的な知識になっていなかったのでちょうどいい機会だということで以降の章を読んでいく。

第7章 SRP:単一責任の原則

単一責任とは何かということを具体的な例を交えつつ説明する章。 単一責任とは、モジュールはたったひとつのアクターにたいして責任を負うように設計することを指している。 アクターとは変更を望む人達をまとめた単位(例だと、経理部門・人事部門などの1部門がアクター)。 この章を読んで、クリーンなソフトウェアを作る際にはだれが使うのかを意識することが重要であることを再度認識した。 確かに、一つのモジュールにたいして変更を要請する人が複数存在すると、片方の変更がもう片方に影響を与えてしまう可能性が高まってしまって良くないなと納得。

第8章 OCP:オープン・クローズドの原則

思考実験を交えつつオープンクローズドの原則について説明する章。
この原則を達成するために重要なこととして、コンポーネントを適切に分割することとコンポーネントを階層構造にまとめることを挙げていた。

この原則でも適切なクラス分割を行うことを推奨している内容だった。ただ、若干前の章とは分割のためのモチベーションが異なっていた。 SRPではアクターから変更の湯棒があったとしても、他のモジュールに影響を与えないように責務を単一にすることをモチベーションにしていたが、 OCPでは、システムを容易に拡張できるようにするために、影響範囲を限定するために分割することがモチベーションになっていた。 モチベーションは違っていても、どちらも同じように変更による影響範囲を考えて分割しましょうという結論になるのは面白いな。

そのほかにもインターフェースを分離することで、他のクラスの情報を隠蔽し依存しすぎないようにすることで拡張に強くする方法も挙げられていた。詳しい説明はまた別の章で行われるとのことだった。

第9章 LSP:リスコフの置換原則

あるクラスから派生したクラスはもとのクラスと置き換えてもソフトウェアの振る舞いが変わらないときに満たされる法則。 この法則に違反したクラスを作ってしまいシステムに組み込んでしまうと、違反しているクラスをif文で分岐させえて別の処理を記述する必要が出てきてしまい振る舞いに制限が出てしまうとのこと。 クラスだけでなくRESTなどのあらゆるインターフェースで考えることができるため、色んな場所で考慮したほうが良さそうな法則。 特に派生が起きそうなクラスを設計する際にはどういうクラスが使われる可能性があるか?を考慮してアーキを設計することが大切な気がする。

第10章 ISP:インターフェース分離の原則

インターフェースを分離して使ってないメソッドに依存することをさけるためにインターフェースを分離しようと説明している。 ちゃんと分離しておかないと、使っていないメソッドにすら依存してしまうため、依存しているデータベースをデプロイするたびにシステムをすべて再デプロイするはめになってしまうという例が書かれており納得。 コンポーネントの凝集性でさらに細かい話があるとのこと。

第11章 DIP:依存関係逆転の原則

ソースコードの依存関係が具象ではなく抽象だけを参照していることを示した原則。 ここで書かれていた面白いと思ったことは、すべてを抽象に依存させるのではなく、変化しやすい具象要素に対してこの原則を適用するということだった。 StringなどのOSに近いものは非常に安定していて壊れることがないため、抽象化しなくてもよいとのこと(というかできない)。 DIPをどこまで適用する?ということを考えるときに、そのクラスが安定しているかどうか?という判断基準は意識していきたいと思った。

第Ⅲ部では、全体的にクラスの分離に関する話が中心的になっていた。どこまでクラスで責任をもつのか、どのようにクラスを分離すればよいかなど。 次の部からは適切に分離・結合したクラスをどのように扱っていくのか?ということを扱っていくのでまた読んでいきたい。