🐾

『ちょうぜつソフトウェア設計入門』に感動した話

2023/01/20に公開

この記事は

『ちょうぜつソフトウェア設計入門――PHPで理解するオブジェクト指向の活用』 を読んでめちゃくちゃ感動し、初めて書評(というより、感想)的なものを書こうと思いました。

TL;DR

  • 本全体の構成として、明確な一本のストーリーに基づいていて理解しやすかった。
  • それぞれの表現についても、平易な日本語・分かりやすいワードチョイスで書かれていて頭に入りやすかったです(平易な日本語、というのはO’Reillyの和訳にありがちな、アメリカ風ジョークのノイズがないみたいな話)。
  • 自分のエンジニアとしての成長に鈍化を感じていたところ、この本を読んで次に目指すべきところや、新たな成長のイメージを見つけられたと思います。

背景

自分の経歴とか

この記事は自分についての紹介ではなく本についての紹介なのであまり自分語りをするべきではないとも思いますが、この本を読み終え「今の自分の状況でこの本を読めたのは、タイミング的な意味で非常に恵まれていた」と思ったため、同じような経験年数の人が読むと良い読書体験になるのではないかなと思い書いておきます。
また、この本は、副題が「PHPで理解するオブジェクト指向の活用」となっていて、PHPを普段書かない方が購入を躊躇うこともあるのではないかと思います。自分もPHPは普段書いていないですが、それでもこの本を読む上で支障はなかったです。

  • 開発歴は大体2.5年、実務(お金を貰うという意味?)では2年弱くらいです。
  • 非情報系学部の大学4年生で、プログラミングを始めたのは大学2年生になります。学園祭実行サークルのデザイン系の部署で趣味程度にプログラミングをしていて、気がついたら先輩に誘われて今の会社でインターンをしていました。
  • 会社では主にTypeScriptでVue, React, React Nativeを書いています。趣味ではNim LangとかJuliaとかを触っています。

感想

緻密なストーリー

一冊の本の中にしっかりとしたストーリーがあり、とても理解がしやすかったです。たとえば、「凝集度」や「疎結合」、「依存関係」・「依存性の注入」、「クリーンアーキテクチャ」といった単語は、エンジニアをやっていれば自然と耳にする言葉で、実際にコードを書く時に多少なりとも意識することになります。ただ、自分の場合、これらの単語にはどのような繋がりがあるのかということをあまり分かっていませんでした。本書では、このような単語の関係性が丁寧に説明されています。

たとえば、クリーンアーキテクチャの導入は「凝集度」「依存」「安定度」といった概念の説明がなされた後で、以下のように行われています。シンプル!

ここまでの「凝集度」「依存」「安定度」を総合すると、次の条件を満たせばきれいな設計ができそうです。
1.ひとつの関心がひとつの箇所に閉じている
2.利用する/されるの関係箇所を可能なかぎり減らす
3.できるだけ変更頻度の高い事情に依存しない

他にも、オブジェクト指向の導入は

「クリーンアーキテクチャの 3層目がユースケースとドメインモデルに一方的に依存するかたちは想像しやすいでしょう。では同じように、もっとも外側の 4層目のインフラストラクチャが、 3層目のアプリケーション構造に依存できるでしょうか。アプリケーションのコントロールをするには、技術的問題を担うライブラリの機能を使う必要があります。「え?  これ思想は立派なんだけど、 3層目は 4層目に依存せざるをえないんじゃないの?
(中略)
この一見不自然な依存関係をどのように実現するかに、オブジェクト指向が役に立ちます。クリーンアーキテクチャに欠かせない特有の要素、本当に訴えたいことの核心は、プログラミングテクニックを使った、この依存方向の自由な制御です。ただ、どうやって実現するか説明するには、まだオブジェクト指向についての解説が不足しています。後の章でその答えを導き出していくことにしましょう。オブジェクト指向への理解が進むと、この依存の向きへの疑問はあるとき急に、嘘のように解消します。

SOLID原則の導入は

「SOLIDの最後の部分を理解すると、クリーンアーキテクチャ実現のうえで最後に残っていた謎が、ついに解き明かされるでしょう。どうして技術実現レイヤーが、それを呼び出すはずのビジネスロジックレイヤーに依存できるのか、まだ答えを保留していました。オブジェクト指向の原則を通じて、それがごく自然に起こるものだという理解を進めていきましょう。

といった風に、やはりそれぞれの概念同士の関係性がストーリーに沿って述べられて、非常に分かりやすいです。

ゴツい言葉も噛み砕かれて

ソフトウェアに関する本を読んでいると、さまざまな○○原則が登場します。その中には「Liskov substitution principle」といった、何かの呪文かと思うようなゴツい言葉もあります。こうしたどこか取っつきづらさがある原則について、本書では適切な前提知識に基づく平易な説明がされていました。

説明されている言葉をリストアップすると、

  • パッケージに関する原則
    • REP: Reuse-Release Equivalent Principle
    • CRP: Common Reuse Principle
    • CCP: Common Closure Principle
    • ADP: Acyclic Dependencies Principle
    • SDP: Stable Dependencies Principle
    • SAP: Stable Abstractions Principle
  • SOLID原則
    • SRP: Single Responsibility Principle
    • OCP: Open Closed Principle
    • LSP: Liskov Substitution Principle
    • ISP: Interface Separation Principle
    • DIP: Dependency Inversion Principle

等です。こうして書き出してみると圧巻です…
とくに依存性逆転法則(Dependency Inversion Principle)の説明に関しては、第一章の「クリーンアーキテクチャ」など、前の章で詳しく説明されていた内容が一つの具体例となっていたため、すんなりと頭に入ってきました(この本がなかったら一生理解できなかったかもしません)。

オブジェクト指向について

何かと不要論が唱えられ、論争が絶えないトピックである「オブジェクト指向・OOP」について、本書ではモジュール間の依存性を操作する際に有用な設計技法として導入され、巷によくある誤解を解きほぐすようにとりわけ丁寧な説明がなされていました。

筆者の主張は、オブジェクト指向を定義することはできないということです。オブジェクト指向とは何かを説明しようとしても、実は「物が物体として存在するイメージでプログラミングをうまくやろう」としか言えません。歴史的に、オブジェクト指向というのは、明確な定義から発展したものではないのです。なので、何であるかを主張することにはあまり意味がありません。けれど、陥りやすい誤った理解だけは避けるべきです。

そして、オブジェクト指向は

  • 現実を再現しない
    -プログラミング言語の文法ではない
  • 状態管理は関係ない
  • 手続き型は関係ない
  • 構造型プログラミングではない
  • 関数型と対置される概念ではない

といった立場が表明されています。その上で、オブジェクト指向という言葉はどうしても一人歩きしがちで、現代においてはもはや明確な定義がないとしつつも、SOLID原則に沿っているプログラミングにはオブジェクト指向らしさがあると述べています。

個人的にこの本を読んで、オブジェクト指向という考え方に対する認識がかなり変化しました。それまでは、現実にあるモノのアナロジーを使用し、人間がそのモノと接する際の認識のあり方と親和性のある方法で、あるモジュールに機能を生やしていく程度に考えていました。しかし、この本を読んでからは「現実にあるモノ」のアナロジーを使用するかどうかは本質的ではないという気付きがありました(そもそも、「時間」など、無形かつ観念的なものに対してもオブジェクト指向は適用できるはずですし)。
本を読んで得たオブジェクト指向のエッセンスを、自分なりの言葉で説明するなら「インターフェイスを定めて他のモジュールの存在を仮定し、具体的な処理を書かずともその存在の効力を発揮させることができ、その結果モジュール間の依存性を自由に操れる」という具合になります。
このインターフェイスを定めれば具体的な存在なしに何かの効力を得ることができるという方法論は中々日常生活では馴染みがない気がします。個人的には、クリストファー・ノーランのSF映画「TENET」に登場する「記録」「POSTERITY」と呼ばれる仕組みを連想しました(ところで、TENETはAmazon Primeで鑑賞できるようになりました。おすすめです)。

実践的でもある

エンジニアリング関係の本だとよく、「○○のような設計をするべき」「○○のようにプログラミングをするべき」が述べられていても、例の量も少ない上、実践のための体系的な方法論が一切述べられていないことが多いです。それに対し、本書では後半およそ50%も使用して、前半戦で説明された「優れたソフトウェア設計」の実践法が書かれています。この実践法としては、TDD・Dependency Injection・デザインパターンが紹介されています。個人的にはTDDが設計に有用であるというのは目から鱗でした。

最後に

冒頭でも述べたのですが、この時期にこの本に出会えたのはとてつもなく幸運でした。2年程度プログラミングをしてきて、大体のタスクは期限通りに遂行できるようになってきた反面、エンジニアとして自分がこれ以上成長するイメージが掴みづらい状態にありました。ここで言っているエンジニアとしての成長というのはどちらかと言うと狭義なものを指していて、例えばマネージャー系統の仕事にシフトする、新しい言語や技術を身につけるといった水平方向の成長ではなく、平たく言うと垂直方向の「ソフトウェアと向き合う本質的な能力」の成長でしょうか。
本書を読むことにより、このような「ソフトウェアと向き合う本質的な能力」を成長させる明確なイメージが得られたと感じています。実際に、端書きには

この本は、プログラミング言語の入門を済ませたけれど、もっと良く書きたいと思っている、中級者へのステップアップを目指す方のための本です。プログラムというものは不思議なもので、習熟して思いどおりに書けるようになってくると、最初の「自分はこれで何でもできるんじゃないか」と思えた頃と打って変わって、だんだんと自分の無力さが見えてきます。

と書かれています。ぜひ自分と同じような、開発経験1~3年程度のエンジニアの方におすすめしたいです!

Discussion