『プリンシプルオブプログラミング』を読んだ

雨すぎる。
先々週にAmazon Prime ビデオで『ソラニン』を観たせいで、Amazonが宮崎あおいの出演作品を無限にオススメしてくる。宮崎あおいに習熟しつつある。
Amazon Prime ビデオで観れる映画でオススメあれば教えてください。

どんな本か

サブタイトルにもあるとおり、なんとなくコードは書けるようになったけど、品質やスピードを上げたい、という層が対象とされている。フトウェア開発の歴史で積み重ねられてきた原理原則のまとめ本。

なぜ読んだか

設計技法とかUNIX哲学みたいなのってググればアホほど情報が出てくるし、それぞれに特化した本を読めばいくらでも学べる。ただ、それらをさらっと見て把握しておきたいという欲求に駆られたため。
試し読みしたところ、各項目が「What」「Why」「How」の統一的なフォーマットで整理されていて、良さそうと思った。

感想など

全体

最近読んだ本の中では最も平易で、プログラミング能力が0の自分でもさらさら読めた。 項目名をみて、流石にこれは知ってるというやつは読み飛ばしたりしながら(かつ以下のメモを書きながら)、だいたい3時間ほど。

内容は平易だが、サンプルコードもなければ具体例もなく、かなり一般論や精神論に近い文章なので、ある程度歴史のあるサービス開発やチームでの開発を経験していない人にとってはイメージしづらいかもしれない。逆に、それなりの経験がある人にとっては、あまりに当たり前で物足りなさそう。そういう意味でサブタイトルの「3年目までに身につけたい」いうのはターゲット層を的確に示している。

プリンシプルのほとんどは知っていたが、それを常に意識して実践できているかというとまったくそんなことはない。現実に落とし込むにはまたひとつハードルがあるように感じる。せっかく読んだからには、以下にあげた要素くらいは記憶に残して意識していきたい。

各章

何か思ったところを引用する方式にしてみました。

第1章 前提 ~プログラミングの変わらぬ真実~

上流の「基本設計」から「詳細設計」「プログラミング」「テスト」「デバッグ」まで、すべてが「設計」であり、そのアウトプットが、設計書である「コード」です。「製造」にあたるのはリリースビルドになります。(p.23)

製品の「製造」の工程で機能をよくすることはなく、それは「設計」なので、プログラミングは設計である、という認識。こういう考え方をしたことはなかった。

第2章 原則 ~プログラミングのガイドライン~

プログラミング中、「動作させるために、もっともシンプルなものは何か」と常に問い続けることです。(p.30)

KISS(Keep It Simple, Stupid)のための指針。
ここでいう「シンプル」をどうとらえるかで頻繁に迷子になる。局所的には最小現なんだけど、全体からみるとコンテキストにそっていなかったりして複雑化してしまっている、など。(要件を満たしていることを前提とすると)いまの自分だけでなく未来の自分や同僚たちにとってシンプルで読みやすいか、を問いたい。
この後に出てくる原則『PIE(Program Intently and Expressively)』にも通ずるものがある。「文芸的プログラミング」という言葉、シャレオツ。

第3章 思想 ~プログラミングのイデオロギー~

コードで良好なコミュニケーションを取るには、コードを書いている時、他の人のことを考えるようにすることです。(p.68)

コードは文書であり、文書の本質はコミュニケーションツールである、という捉え方。はい。先述のシンプルにすることの意義も詰まるところは同じ。
自分の書いたコードが巡り巡って、ガッキーが読むことになる可能性も0とは言い切れない。ガッキーのためと思って丁寧に書こう。

抽象は、「捨象」「一般化」という2つの観点からまとめられます。(p.82)

アーキテクチャの根底技法のひとつとして紹介されている抽象についての説明。 抽象という言葉をこういう観点で捉えたことはなかった。「捨象」とは、ある対象が持つ複数の性質のうち特定の性質を抽出することであり、「一般化」とは、ある対象がもつ複数の性質のうち共通の性質を抽出すること。人間が複雑な事柄を理解するときに自然と考えることであり、それをプログラミングにおいても適用すべきっぽい。
詳しくは、『具体と抽象』という本が良さそう。

7つの設計原理とは、障害を作り込まないために考慮すべき、コード構造上の7つの核心観点のことです。(p.117)

7つの設計原理は、「単純原理」「同型原理」「対照原理」「階層原理」「透明原理」「明証原理」「安全原理」「線形原理」。プログラミングのレビュー観点として使う、と紹介されているが、プログラミングのみならず、広義のユーザインターフェースを有するあらゆるものづくりにおいて意識されるべき観点な気がする。つまりは、ユーザの理解を容易にするための構造化が適切になされているかの指針になる。
この後のUNIX思想も同様で(こっちはよりソフトウェアに近いけど)、例えば「驚き最小の原則」はまさにそれ。

ソフトウェアは、表示を最小限に抑えて、寡黙に仕事を進めます。(p.147)

UNIX思想のひとつ「沈黙の原則」。出力が多いと、必要な情報が埋もれてしまう。ほんとうに必要な情報だけ伝えましょうよ、というやつ。一貫性の観点から冗長な情報を許容したりする場合もあり、難しいと最近思った。
あと、人間同士でも情報を伝えすぎてしまうきらいがある。そういうときはだいたい情報発信者がその内容を真に理解していない。ソフトウェアと同様に人間も適度に寡黙でありたい。

プロトタイプ作成が早ければ早いほど、製品のリリース早まります。(p.165)

UNIX哲学のひとつ「即行プロトタイプ」。シャの偉大な先輩方のご指導のおかげか意識はしていると思うが、まだまだ遅い。単純に技術的な能力不足によるところもあるが、それ以上に、無意識に良いコードを書こうとしてスピードを弱まえている。「第3のシステム」という発想があり、プロトタイプなくして完成形はありえない。解脱したい。

第4章 視点 ~プログラマの観る角度~

凝集度のレベルは7つです。レベルが高い(数字が大きい)ほど純粋であり、強く、よいモジュールです。(p.184)
結合度のレベルは6つです。レベルが高い(数字が大きい)ほど関係が薄く、疎結合であり、よいモジュールとされています。(p.191)

凝集度、結合度をレベル分けしたものを初めてみた。過去に読んだ本に出てたかもしれない。不勉強すぎる。とはいえ、なるべく疎結合かつ高凝集なコードを書くことを感覚的に理解している人は多いと思うし、それで問題はなさそう。

「コードの臭い」とは、コードの中で、理解しにくい、修正しにくい、拡張しにくい、と感じられる部分のことです。(p.205)

太古の昔、「君からはコードの臭いがしない」みたいな言説がインターネッツでいじられていた記憶がある。この定義によるとそれはすばらしい褒め言葉だったのでは。
嗅覚という言葉が使われているが、読もうとしてるけどよくわからないコードはだいたいダメというだけのことで、世界中のプログラマは、アホすぎるぼくでも理解できるコードを書くように心がけて欲しい。

暫定ソリューションには「慣性の法則」が働きます。いったん暫定ソリューションができると、既成事実化するのです。(p.211)

技術的負債に関連して、工数の制約から生まれる暫定的なコードのお話。わかりみ of わかりみ。いったん動くコードを書いてしまうとなおすのめっちゃ大変。
技術的負債の「管理」、つまり全体像を把握してどうすれば改善できるかを見積もった状態にできれば、そこに工数をさく意義やその優先度について議論が生まれるはずだが、まずその前提状態に至るのがかなり困難。長い歴史を経て積み上がった巨大なコードを管理することの困難さよ。おっとだれか来たようだ。

第5章 習慣 ~プログラマのルーティーン~

プログラマが思っているほど、ユーザはその部分のパフォーマンスに価値を感じていない可能性もあります。(p.224)

パフォーマンスチューニングについて。そもそもパフォーマンス観点での最適化は多くの場合保守性とトレードオフになりうる。その前提の上で最適化をするなら、その必要性を証明せよ、ということ。自分も身につまされる。チューニングは楽しいのでついついやりがち。
高度に訓練されたユーザはその状態が当たり前になっていて、必要性を自認できていない場合もありそうで、難しい。前職の社内システムが思い出されて泣ける。

・瞬時に答えを得ようとする態度は誤りです。瞬時にわからなくても考え続けましょう。(p.230)
・考え始めて、すぐに結論に飛びつくのは誤りです。条件を満たすものがひとつ見つかったときに思考停止せず、思い込みを排除して、ほかの可能性も検討しましょう。(p.230)
・覚えておくのは大変なので、書きながら考えるようにしましょう。(p.230)

思考も作業もステップバイステップで進めることが重要、という話の中で挙げられている、論理的思考のコツ。はい。ごめんなさい。

第6章 手法 ~プログラマの道具箱~

プログラミングにおける「曳光弾」とは、優先的に検証したい部分を、先行的にプログラミングすることです。簡易で構わないので、実際の環境下で動作して、確認できる、エンドツーエンドのソフトウェアを作成します。(p.234)

この言葉は初めて知った。
プロトタイプは仕様の理解を検証するための使い捨てコードであるのに対し、曳光弾はアーキテクチャの骨格と全体の連携を提示する本番コード。設計上の潜在的なリスクをもつ箇所を先行して書いてみる、ということと同じだと思うし、実際そうしている気がする。遅いけど。

説明をし始めたと途端に気づいて「あ、もういいや、変なところがわかったよ。ごめんごめん」ということになり、照れくさい思いをすることもあります。(p.253)

ラバーダッキング。(コードに限らず)誰かに説明することで本当に理解しているのか、正しいことをしているのかを確認できるというもの。ここでいう「誰か」は他者である必要もなく、ゴムのアヒルでもええんやで、ってやつ。
悩んで誰かに相談しはじめると、うまく相談できないということをもっておかしい点に気づいたり、相談内容を伝えているはずなのに気づいたら結論を自分で導いていることが稀に頻繁によくある。これからはガッキーの写真をデスクに貼り、ガッキーへの説明を通して問題を理解する手法をとりたい。

プログラミングのように高度な知的作業では、「調子に乗る」ことはきわめて大切で、フロー状態は必要不可欠です。フロー状態になって、初めて仕事がうまく運ぶと言っても過言ではありません。(p.261)

シャでは特に割り込みが多く発生するわけではないが、自分は他の人と比べてちょっとしたことに注意をもっていかれやすいので、会話が聞こえてきたり視野内で何かが動いたりすると一瞬で集中が切れる。あと、「待つ」という行為が苦手すぎるので、ビルドを待つ一瞬で集中が切れたりする。そこからまた集中するまでに無限に時間がかかる。
自分の集中状態を守る環境を自ら作っていくことが必要かもしれない。コードを書くときはだいたいイヤホンで音楽を聞いているが、それでも集中は持っていかれる。ノイズキャンセリングイヤホンが気になっている。実際どうなんだろう。あと0㌨秒でビルドされたい。

アリストテレスは、「知識」を「エピステーメ」「テクネ」「フロネシス」の3つに分類しました。(p.264)

3つはそれぞれ現代の日本語で言うと、科学、工学、知的美徳、的なこと。
エピステーメは世の中に起こる事象を説明するし、テクネは実用的な知識でありスキル。フロネシスは、全体最適を導く判断能力につながる実践的な智慧。よりよいコードを書くためにはこれらすべての知識が必要っぽい。フロネシス足りてる?とか煽っていきましょう。
ちなみにアリストテレスが本職の哲学以外にも様々な研究領域で業績を残しており、上記はその中の倫理学の分野のもの。アリストテレスの息子であるニコマコスが編纂して「ニコマコス倫理学」と呼ばれている。詳しくは 『ニコマコス倫理学』アリストテレス,京都大学学術出版会(2002) をどうぞ。

第7章 法則 ~プログラミングのアンチパターン~

プログラマは、自制心を働かせ、「多機能主義」にならないようにしましょう。(p.286)

セカンドシステム症候群。あるあるすぎてつらい。ソフトウェアの究極の価値はシンプル。これ以上はノーコメント。

問題だけが芋づるに発生して、ポップがプッシュに追いつかず、脳内スタックがオーバーフローすることがしばしばあります。(p.294)

しばしばある。
ある問題に取り組もうとしたときに、それに付随する周辺の問題が次々に出てきて、なかなか本来の問題にたどり着けない、という現象は、「ヤクの毛刈り」と呼ばれるらしい。
脳内で処理できる量の問題だと思って手を付けはじめて、いつのまにか問題がでかくなって扱いきれなくなる、ということなので、問題を書きとめながらひとつひとつ順に解決していきたい。