ひだまりソケットは壊れない

ソフトウェア開発に関する話を書きます。 最近は主に Android アプリ、Windows アプリ (UWP アプリ)、Java 関係です。

まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。

読んだ : Clean Architecture 達人に学ぶソフトウェアの構造と設計 (Robert C. Martin 著)

Robert Cecil Martin 氏、いわゆるアンクル・ボブ (ボブおじさん; Uncle Bob) による Clean Architecture についての書籍。

Clean Architecture 達人に学ぶソフトウェアの構造と設計

Clean Architecture 達人に学ぶソフトウェアの構造と設計

アンクル・ボブの Clean Architecture といえば、下記記事を読んだことがある人も多いだろう。

ここ数年の Android アプリ開発界隈でも Clean Architecture はよく話題に上がっているように思う。 私自身も web 上で Clean Architecture について調べて学んだりしてきた。

しかし、web 上の情報を追いかけるだけだと、レイヤ分けや依存関係のルールはわかっても、より本質的な思想の部分まではなかなか理解できなかった。 例えば、「クリーンアーキテクチャにおいてサーバーとクライアントの構成にする場合にどういう扱いにするのが妥当なのか?」 というのは長年考えてきてなかなか自分の中で納得した答えは出せなかったもののひとつである。

本書を読むことで、Clean Architecture の本質的な思想についても深く理解できた。 また、そもそもの 「アーキテクチャとは何か?」 といった部分まで考えることができた。 ソフトウェアアーキテクチャについてより深い洞察を得たい人におすすめの一冊である。

本書の流れ

本書は、「設計とアーキテクチャは地続きのものであり、本質的な違いはない」 というところから始まる。 そして、構造化プログラミングや関数型プログラミングといったコーディングのパラダイムが説明される。 その後に設計の原則 (SOLID 原則)、コンポーネントの原則 (REP、CCP、CRP) についての説明がある。 ここまでが本書の前半である。

本書の後半では、前半の話を踏まえて、アーキテクチャの説明に入っていく。 アーキテクチャの話だけ読みたい人もいるだろうが、個人的には SOLID 原則や REP、CCP、CRP といった部分についても改めて学ぶことができて非常に良かった。

学びや感想

設計とアーキテクチャ、その目的について

1 章で、「設計とアーキテクチャについて、本質的には違いはない」 ということが言われる。 通常、アーキテクチャは下位レベルの詳細とは切り離された文脈で使用され、設計は下位レベルの構造や意思決定を意味しているが、実際のところ下位レベルの詳細と上位レベルの構造が全体の設計の一部になる。 そうした連続した構造がシステムの形状を定義するので、設計とアーキテクチャを明確に区別することはできない。 上位レベルから下位レベルまで決定の連続であり、その目的は下記の通りである。

ソフトウェアアーキテクチャの目的は、求められるシステムを構築・保守するために必要な人材を最小限に抑えることである。

ソフトウェアの振る舞いが正しいものであることを重視し、アーキテクチャを軽視すると、開発を続けていくうちに生産性がどんどん低くなっていく。 「振る舞いが正しいこと」 と 「変更しやすいこと (良いアーキテクチャ・設計であること)」 のどちらが重要であるかという質問に対して、ビジネスマネージャは、「振る舞いが正しいこと」 であると答えることが多く、開発者もそれに賛同することが多い。 しかし、下記のように考えると、より重要なものは 「アーキテクチャ」 である。

  • 振る舞いが正しく、変更しづらい (アーキテクチャ・設計が良くない) プログラムは、今は正しくとも将来的な要件の変更に追従できなくなり、やがて役に立たなくなる。
  • 振る舞いが誤っており、変更しやすい (アーキテクチャ・設計が良い) プログラムは、今の正しくない振る舞いを正しく修正することも容易であり、将来的な要件の変更にも追従しやすく、長く価値を保つ。

開発者以外に対してアーキテクチャ・設計の重要性を説明することは非常に難しいと思っていたが、上記の観点で説明すると結構説明しやすい気がした。

優れたソフトウェア開発チームは、真正面から闘争に立ち向かう。 ステークホルダーたちと対等に、ひるむことなく口論する。 ソフトウェア開発者もステークホルダーであることは忘れてはいけない。 保護すべきソフトウェアに対する責任がある。 それが、あなたの役割であり、義務である。 それが、あなたが雇われている大きな理由だ。


テストと反証可能性について

Dijkstra は 「テストはバグが存在しないことではなく、バグが存在することを示すものである」 と述べた。 つまり、テストによってプログラムが正しくないことは証明できるが、プログラムが正しいことは証明できないのである。 テストに十分な労力をかけていれば、そのプログラムは目的のために十分に真であるとみなせる。

この事実は、驚くべきことを示している。ソフトウェア開発は、数学的な構成要素を操作しているかのように思えるかもしれないが、実際には数学的な試みではない。 むしろソフトウェア開発は科学のようなものである。 どれだけ最善を尽くしても正しくないことを証明できないことによって、その正しさを明らかにしているのである。

数学的なアプローチか科学的なアプローチか、という観点は持っていなかったので、「なるほどー」 と思った。

最小の機能から最大のコンポーネントまで、あらゆるレベルにおいて、ソフトウェアは科学のように、反証可能性によって動かされている。ソフトウェアアーキテクトは、簡単に反証できる(テスト可能な)モジュール、コンポーネント、サービスを定義しようとする。そのために、さらに上位のレベルにおいて、構造化プログラミングのような制限を課している。


単一責任の原則

SOLID 原則の一つである単一責任の原則 (SRP) について、「たった一つのことだけ行うべき」 だと思っていたけど、正しくは 「モジュールが責務を負うべきアクター (ソフトウェアの変更を望む人たちのグループ) がひとつだけになるようにすべき」 ということだった。 アクターをどう定義するかが難しい気もするけど、アクターの定義をどうするかを含めてしっかり考えていく必要があるんだろうなぁと思う。


コンポーネントの原則


アーキテクチャについて

アーキテクチャについては、下記の内容が非常に刺さったり共感するものだった。

  • アーキテクチャユースケースを叫ぶものでなければならない。 どういう技術を採用するかということに意識がいきがちだけど、重要なのはユースケースであって、どういう技術を採用するかではない。
  • アーキテクトとしては詳細の決定はできるだけ遅らせるようにすること。 DB に何を採用するのかとか、通信プロトコルに何を採用するのかなど、そういったものは技術的な実装詳細であり、優れたアーキテクチャはそれらの決定を遅らせられるものである。
  • 入出力はテストしづらい部分なので、依存関係の一番外側に持ってくること。
  • フレームワークへの依存は避けるべきフレームワークは実装詳細であり、アーキテクチャとして重要なものではない。

つまり、冒頭で述べた私のこれまでの疑問の話で言うと、(クライアントとサーバーの両方で一つのソフトウェアなのであれば) クライアント・サーバー間の通信なども詳細であり、アーキテクチャとしてはクライアントもサーバーも含めてユースケースを考える、というのが優れたアーキテクトとしての姿勢なのだと感じた。

ツイートメモ