Rのつく財団入り口

ITエンジニア関連の様々な話題を書いているはずのブログです。

【感想】『達人プログラマー 熟達に向けたあなたの旅(第2版)』:折に触れて読み返したくなる名著 (後半)

達人プログラマー

同書の感想記事の6章〜最後までと全体です。

f:id:iwasiman:20210507092642p:plain
達人プログラマーを読もう

第6章 並行性 Concurrecy

  • 並行処理:複数のコードが同時に実行されているように振舞う。ファイバーやスレッド、プロセスなどを使ったソフトウェアのメカニズムの話。
  • 並列処理:実際に同時に動く。2つのものごとを同時に実行できるハードウェアの関心事。すなわち複数コアや複数CPU、複数マシンが必要。

と定義してこれらを論ずる章。

33 時間的な結合を破壊する

 大抵の人間は線形に、時系列に物事を考えてしまうので切り離して考える。並行性を向上させるためにワークフローを分析する。すると同時に並行処理できる処理、何かに時間が掛かっている間に他の処理を行う並行処理ができる箇所が見つかったりする。言語ではElixirコンパイラーが並列処理を行える。

f:id:iwasiman:20210507065306p:plain
達人プログラマー

34 共有状態は間違った状態

 レストランの陳列棚にパイが残り1個の状態で、2つのテーブルの客がウェイターにこれを注文した処理を例にdさう。普通にコードで表現するとアトミック(原子性)のある処理ができない。
 ある時点で誰か1人しか占有できないものを「セマフォ―」と呼ぶ。これをロックして処理、異常終了を含め終了したらアンロックする処理が必要。RDBならトランザクションが使えるが、共有できるリソースでは常にこの問題が起こる可能性がある。無秩序なエラーはよく並行処理が原因で起こる。

f:id:iwasiman:20210507065306p:plain
達人プログラマー

35 アクターとプロセス

 局所的で固有の状態を持った独立した仮想プロセッサーが「アクター」で、個別のメールボックスを持ち、メッセージが来たらそれを1つづつ処理するイメージ。一方通行で応答はしない。より汎用的なプロセッサーが「プロセス」。
 JavaScriptNactライブラリを使うと、このアクターを使った並行処理が実現できる。言語ではElixirの元になったErlangがアクターを実装している。

f:id:iwasiman:20210507065306p:plain
達人プログラマー

36 ホワイトボード

 どんな立場の誰でも自由に、内容も自由で事件の手がかりを書いていけるホワイトボードのイメージ。ワークフローを協調させるにはこのホワイトボードのコンセプトが使える。

 この章は難しかったです……! 復習せねば。

f:id:iwasiman:20210507065306p:plain
達人プログラマー

第7章 コーディング段階

 コーディングは機械的な作業ではなく常に熟考が必要な作業であり、常に気を配って作業して災害を避け、うまくやっていこうという章。

37 爬虫類脳からの声に耳を傾ける

 プログラマーとして経験を積んでいくと暗黙知が貯まり、無意識からの本能的な警告が生じることがある。ここから何かを得ようという話。

  • 空白ページの恐怖:知覚できないところに何か疑いがあるのかもしれない。また失敗を恐れているだけの場合もある。
  • 自らと戦う:コーディングがぬかるみを歩いていくように一進一退を繰り返していたら止まってみる。おそらくアーキテクチャや設計のどこかが間違っているのかもしれない。
  • 爬虫類脳との対話方法:作業を止めて一休み、他のことをしたりゴムのアヒルちゃん(ラバーダック)に話しかけてみる。ひらめきが生まれてくることがある。
  • お遊びの時間!:既存コードは脇に置いて、似たようなプロトタイプを作ってみる。問題が具現化したら元の作業に戻る。
  • あなたのコードだけではない:人のコードを読み進んで、重要箇所にコメントしたりパターンを抜き出す。
  • コードに留まらない:要件定義や設計も。何かが間違っていると感じたら立ち止まる。

「爬虫類脳」という表現が日本語だと分かりにくいですが、本能から来る直感のようなものも信じようという話ですね。自分も気分転換をしたり帰りの電車とか家とか休日にハッと思いついたり、次の日頭がクリアな状態で再開したら朝イチですぐ問題が解決したりしたことが何回もあります。
 ラバーダックの話もいろんな本に出てきます。新人研修で話を聞く役の先輩とかマネージャーになるとこのアヒル役によくなります。

ja.wikipedia.org and-engineer.com

f:id:iwasiman:20210507065306p:plain
達人プログラマー

38 偶発的プログラミング

 幸運やいきあたりばったりに頼る、たまたまうまく動いていたような偶発的プログラミングはよくない。慎重なプログラミングを選ぶ。

  • 実装の事故:ライブラリや関数化された他の処理は想定された呼び出し方をする。想定外の使い方でたまたま上手く動いてしまう場合もある。
  • 幻のパターン:事象にはパターンがあるように見えて単なる偶然かもしれない。仮定でなく証明する。
  • コンテキストの事故:言語設定やディレクトリの書き込み権限、明らかになっていないことを前提にしない。コードをコピペしてきた際もコンテキストに注意。
  • 暗黙の仮定:仮定でなく事実に基づいて仮定すること。
  • 慎重なプロミング:常に何をやっているのか意識する。詳細を説明できるようにする。プランを立ててからコードを書く。信頼のおける物事だけを前提にする。優先順位をつける。過去のコードに囚われず必要になったら置き換える。

 自分も今思うと駆け出しのころはこの偶発的プログラミングをやってたんじゃないかな……と顧みるところであります(切腹)。
様々な人と一緒に仕事をすると相手のスキルも様々なのですが、確かに今自分で書いている実装部分の説明ができない人、バグ修正があてずっぽうの人というのも中にはいます。
 ここの演習問題がトリッキーで、答えを見たときにハッとしました……!

f:id:iwasiman:20210507065306p:plain
達人プログラマー

39 アルゴリズムのスピード

 O記法で表すことができる。O(n2)であればそのソートは2の2乗に比例して時間が掛かる。データが2倍なら処理時間4倍。

  • O(1) 配列の要素アクセスや簡単なステートメント実行。
  • O(log n) 対数のバイナリーサーチ。ループ内でデータを二分割してくようなロジック。
  • O(n) 線形のシーケンシャルサーチ。ループの中にループがあったらm*nになる。
  • O(n log n) クイックソートヒープソートの平均時間。入力を分割して操作し最後に結合させるような分割統治法。
  • O(n^2) 選択ソートや挿入ソートが2乗。
  • O(n^3) 2つの行列の積が3乗。
  • O(C^n) 巡回セールスマン問題、集合分割。

 アルゴリズムのオーダーを見積り、実際に検証すること。最高速が常に最善ではない場合もある。また最適化は作業の前半にやるものではない。

 出たー、アルゴリズムの話。演習問題にRustまで出てきて本格的です。あまり使わないので高校数学を復習せねば……ぐぬぬ……という気持ちになりました。

f:id:iwasiman:20210507065306p:plain
達人プログラマー

40 リファクタリング

 ソフトウェア開発のメタファーはビルの建築よりもガーデニングが相応しい。即ちすべてが設計図通りに順調に進むのでなく、より有機的で日々の変更が大きい。コーディングの過程で日常的にリファクタリングを行っていく。

  • いつ行うべきか?:よい考えが思い浮かんだその時。DRY原則を守ったり直交性を高めたり、パフォーマンスを上げたり。
  • 現実世界の複雑さ:完成後に時間を取って大規模リファクタする訳にもいかない。早めに、こまめに行う。
  • どのように行うか:機能追加と同時に行ってはいけない。テストを用意し、小規模な所から行う。割れた窓を放置すると傷が大きくなるので早く治す。

 詳しくはこちらも2版が出ている名著「リファクタリング」へ。本書では最近のIDEは自動リファクタリングの機能がだいたい付いていることも注釈で触れています。

iwasiman.hatenablog.com

f:id:iwasiman:20210507065306p:plain
達人プログラマー

41 コードのためのテスト

 テストの利点はバグを見つけることではなく、テストについて考えて書いている時にあるというのが本書の主張。

  • テストについて考える:テストデータも考えながらメソッドを書くと、より良いAPIの気づきがあったりする。
  • テスト駆動コーディング:外部からメソッドを客観的に捉えられるようになり、結合度も下がる。
  • テスト駆動開発良い方法だが、カバレッジ常に100%を目指したり冗長なテストを作らないよう気を付ける。設計がボトムアップ寄りになる傾向もある。
  • テストしやすいコード:初期の段階からソフトウェアの中にテスト機構を組み込むとよい。
  • ユニットテスト契約による設計(DbC)の契約に対するテストだと考えてみると良い。
  • アドホックなテスト:コードを手作業でつつき回して実行するその場限りのテストのこと。これもテストパターンなので既存のユニットテストで活用するとよい。
  • テストウィンドウを構築する:ログにトレースメッセージを入れたり、特定URLやキー操作で状態を出すウィンドウを仕込んだり、診断機能を隠しで入れたり、デバッガー以外にも工夫する。
  • テスト文化:テストはプログラミングの一部である。

 こちらも詳しくは「テスト駆動開発」へという感じで、テストを掘り下げています。こういう話を読むたびにTDDやってなくてゴメンナサイ...(切腹)というお気持ちになりますが、テストを意識してコーディングするとよいというのは同感です。

テスト駆動開発

テスト駆動開発

f:id:iwasiman:20210507065306p:plain
達人プログラマー

42 プロパティーベースのテスト

 契約による設計。そして処理結果の不変性。この2つを見つけたら「プロパティー」と呼び、それらを使ってテストを自動化できる。Pythonを使ったユニットテストの例を紹介。

 テストメソッドを書いていくことでそのメソッドの動きがが明らかになる...ということなのでしょうか。「プロパティ―」という用語の意味含め、本項はちょっと理解しきれませんでした。

f:id:iwasiman:20210507065306p:plain
達人プログラマー

43 実世界の外敵から身を守る

 本書第一版の頃から世界は大きく変わり、セキュリティ対策はかなり重要になった。

  • アタックサーフェス(攻撃界面)の最小化:簡潔で強固なコードを。入力情報はサニタイズする。認証不要サービスは標的になる。権限を与えるユーザ数は最小にする。デバッグ情報も攻撃者にはヒントになる。KISS原則を適用する。
  • 最小権限の原則を厳守:1979年代からある原則。小さくすることはアタックサーフェスの最小化に繋がる。
  • デフォルトをセキュアなものにする:パスワードは表示したりしない。
  • 機密データを暗号化:すべてのものをバージョン管理対象とする話の例外。APIキーやSSH秘密鍵などは保存しない。
  • セキュリティアップデートの適用:パッチはすぐに適用する。また暗号化機能はなるべく信用のあるOSSのライブラリなどを使い自作しない。

 本項だけはなんだかセキュリティの本を読んでいるようでした。「アタックサーフェス」という言葉は日本ではあまり使わない気がする(情報処理安全確保支援士の資料では聞いたことがないような……)のですが、Attack Surface Analyzerというツールもあるし英語だとより一般的なのでしょうか。

forest.watch.impress.co.jp

f:id:iwasiman:20210507065306p:plain
達人プログラマー

44 ものの名前

 名前付けはとても重要。人間の脳は単語を目にすると他の感覚より先に知覚情報で理解する。

  • 文化の尊重:ループでijを使うのはFORTRAN時代からの伝統で、プログラミング言語の入門書に使わないよう書いてあるのは誤り。また言語のコミュニティごとにキャメルケースとスネークケースなど違いがあるので尊重する。
  • 首尾一貫性:プロジェクトではある単語には同一の意味を使う事。コミュニケーションを奨励したり、用語一覧を作ると浸透する。
  • 名前の変更は難しい:誤用はさらに広がっていく。問題を見つけたら早期に直す。リネームを躊躇しない。変更できないとしたら、Easy To Change原則に反していることになり設計に問題があるのを疑う。

 様々なプログラミングの原則で最重要とされている名前重要の話ですね。本書では色のついたひらがなが列挙されていて、人間が知覚情報に強く影響されるのが実際に分かるようになっています。

f:id:iwasiman:20210507065306p:plain
達人プログラマー

第8章 プロジェクトを始める前に Before the Project

 プロジェクト立ち上げ時の話。

45 要求の落とし穴

 自分が欲しいものを正確に認識している人はいない。

  • 要求の神話:要求仕様を正確に出すのは、コンピューターの実行コストが高かった昔の伝統。今の現実世界はもっと複雑で矛盾だらけで、きっちりした仕様は出せない。ユーザが欲しているものに自分で気づくように助けるのがプログラマーの仕事。
  • セラピーとしてのプログラミング:要求を聞いたら質問をして、一緒に探求しながら本質を探る。
  • 真実の要求はプロセスの中に:対話でのフィードバックの繰り返しが結果になり、修行の場にもなる。
  • 相談者の靴を履いて歩く:ユーザと共に働き、ユーザーのように考えると理解が深まって信頼も生まれる。
  • 要求vsポリシー:権限設定などのポリシーは機能とは違い、メタデータであったりする。
  • 要求を文書化する:最終的にはコードだが、成果物でないレベルでドキュメントは必要。
  • 要求文書は相談者のためのものではない:分厚いドキュメントを作ってもユーザは読まない。
  • 要求文書は計画のためものもの:カードに書いてホワイトボードに貼りつけたりするとプロジェクトに役立つ。
  • 詳細に踏み込みすぎること:曖昧でよいという意味ではないが、抽象的でよい。要求はアーキテクチャや設計ではない。
  • もうひとつ:相談者とのフィードバックを欠かさずにすると双方の理解が深まる。
  • プロジェクトの用語集:これを作ると良い。

f:id:iwasiman:20210507065306p:plain
達人プログラマー

46 不可能なパズルを解決する

 予想以上に難しいコードのような難解なパズルに直面したら、答えがどこか他のところにないか考えてみる。「ゴルディアスの結び目」

ja.wikipedia.org

  • 自由度:枠に囚われずに考えるのではなく、より大きい枠を見つけ出す。制約と自由度を認識する。
  • さらに簡単な方法は?:心理学の研究によると、人間の複雑な問題の解決能力は、他の作業に気を取られている時の方が高い。気分転換したり人に話してみたりする。
  • 幸運は用意された心のみに宿る:エンジニアリング日誌を付けておくと情報が送り込まれてひらめきが増す。

 本項にパズルが載っているのですが、これが答えを見るとなるほど……これが本当の枠か! となります。(自分はこれ解けませんでしたw)

f:id:iwasiman:20210507065306p:plain
達人プログラマー

47 共に働く

 ユーザーと緊密に働くと良い。ペアプロやモブプロをすると、低水準のコード詳細の事柄と高水準の事側で脳を分担できてより創造的な作業ができる。短い時間で交代するとよい。一人ぼっちでコーディングに取り組んではいけない。

ぼっちプログラミングはいけないという話でした……!

f:id:iwasiman:20210507065306p:plain
達人プログラマー

48 アジリティーの本質

 Agileは名詞ではなくものごとの進め方を表す形容詞である。形式化したアジャイルやツールや肩書を持つ人々も増えてきた。

  • アジャイルソフトウェア開発宣言の左側ではなく右側が大事。
  • これを実行すればアジャイルになるという絶対的なプロセスなどない。助けに過ぎない。
  • 自分の現在地点を見つけ、目的に向かって1歩進み、そこでフィードバックを得て修正するの繰り返し。
  • 優れた設計は変更しやすいもので、このフィードバックの繰り返しが優れた設計を後押しする。

 広まるにつれて形骸化や誤解があった中、アジャイルの原点に立ち戻った方がよいという話はUncle Bobさんの『Clean Agile』にも似たような話がアツく語られています。アジャイルソフトウェア開発宣言のその場にいた人々は同じような想いを抱えているのかなあと感じました。

iwasiman.hatenablog.com

f:id:iwasiman:20210507065306p:plain
達人プログラマー

第9章 達人のプロジェクト Pragmatic Project

 プロジェクト進行中に関わる最終章。

49 達人のチーム

 知的で強い意志と意見を持ち独立心が強いプログラマーのチームは、猫の群れに喩えられる。大人数でなく10-12人までの小規模で安定したチームでやっていくこと。達人からなるチームは以下に留意している。

  • 割れた窓をなくす:メンバは欠陥を見逃さずにその都度直す。
  • カエルの煮物:スコープの増大や追加機能、残時間の減少、環境の変化など変化に常に注意して、ゆでガエルになるのを避ける。
  • 知識ポートフォリオの充実に向けた計画:旧システムのメンテで経験を積んだり、プロセスの振り返りをしたり、新しい技術を実験したり、学習とスキルの向上に当てたり。メンバーがこれらを実施するにはまずスケジューリング。
  • 伝達しよう:チームには個性があり、外部の人たちにもよい説明ができる。ユニークなチーム名を作るのもGood。
  • DRY原則二重化をなくして即時的なスムーズなコミュニケーションで情報を伝える。スタンドアップミーティングが週1回だけでは足りない。
  • 曳光弾:最初は小さく、エンドツーエンドで一通り動くものを作ってフィードバックを得、必要なスキルに親しんでおく。完璧に機能するチームを編成する。
  • 自動化:IDEのフォーマティング機能やCI/CDを活用して手作業をなくす。
  • 絵画制作のやめ時を知る:メンバーへのお膳立てをしてプロジェクトが価値をもたらすようにし、過剰品質まで作りこまないよう注意。

 「猫の群れ」というメタファーは1985年のワシントンポストマガジンから続いているそうです。確かにプログラマーは猫っぽいかも……よくTwitterで「にゃーん」とか言ってるし!(それは違う)

f:id:iwasiman:20210507065306p:plain
達人プログラマー

50 ココナツでは解決できない

 ある島に文明人が来て飛行機で交易したていろいろな素晴らしい品々を提供したが、やがて去って行った。品も住民たちはココナッツの殻で飛行場や管制塔を真似してそっくりのものを作ったが動作せず、文明人たちは帰ってこなかった。中身が伴っていない形を真似ただけものものを「カーゴカルト」と呼ぶ。

ja.wikipedia.org

 目に映りやすいことに投資して作ることで魔法のような結果が呼びこまれると期待してしまう現象が、プログラミングの世界でも良く起こる。注意しなければならない。

ja.wikipedia.org

  • コンテキストが重要:SpotifyNetflixなどの成功企業を単に真似するだけでは上手く行かない。コンテキストが違う。流行を追いかけるのではなく、効き目があることだけを実行する。まず小規模な単位で試すと良い。
  • 万能の方策はない:必要なのは既存のルールを超えたものを見据え、長所として活用できる能力。方法論の良いところだけを抜き出して現実に適合させる。単に「~のように行動する!」はBad。
  • 真のゴール:要求された新機能をちゃんと機能するソフトウェとして提供すること。ユーザーが必要としたタイミングで調達できるよう、サイクルは短い方がよい。

 この「カーゴカルト」の話は時々見聞きします。本書は普遍的に価値を持つ本らしく表面的な流行を追いかけることに強く警鐘を鳴らしていますが、気を付けねばと思います。
 人類史上実際に起こったカーゴカルトの現象の中のひとつには、第2次世界大戦時代に日本軍と交戦していた連合国側がメラネシアの島々に落としていった余った軍事物資が原因になったものもあったそうで、事実は小説より奇なりだなあと思います。

f:id:iwasiman:20210507065306p:plain
達人プログラマー

51 達人のスターターキット

 技術スタックなどに関係なく、すべてのチームが必要とする最も基本的なスターターキットは以下の3つだと見出した。

  • バージョン管理を実現する:これによってビルド/テスト/リリースを駆動する。
  • 回帰テスト早めに、何度も、自動化してテスト。テストが終わるまでコーディングは終わったことにはならない。テストをテストするには故意にバグを発生させるような破壊工作を行う。カバレージはコードに対する%でなく状態に対してが重要。あるバグを見つけたら同種のバグを一度に見つける。
  • 完全な自動化:手作業を排除して完全な自動化を目指す。繰り返し作業は人間は不得意。

 同種のバグを一緒に見つける話は、ジャパニーズトラディショナルな現場だと「横展開」とか「ヨコテン」でよく実施されているような気もします。
 自分もこのスターターキットなるものはある程度実施しているのですが、テストコードによる自動テストや完全な自動化はまだまだだな……むむむ、と思うことしきり。

f:id:iwasiman:20210507065306p:plain
達人プログラマー

52 ユーザーを喜ばせる

 重要な目標はこれである。プロジェクトが完了した後の一定期間を心安らかに過ごせるにはどうしたらいいか考えると良い。
 ソフトウェア・デベロッパー、ソフトウェア・エンジニアであってもあなたの本当の肩書は、「問題の解決者」である。

f:id:iwasiman:20210507065306p:plain
達人プログラマー

53 自負と偏見

 達人プログラマーはチャレンジを受け入れ、作ったものに責任と誇りを持つ。あなたの作品に署名しよう。
しかしコードの所有権は個人ではないので、傲慢になったり偏見を持ったりしてはいけない。
名前があることでしっかり作られていることを確認できるようなプロの仕事をするのが達人プログラマー

 誇りあるプロフェッショナルとしてものづくりをしよう……と最後に相応しい話でした。そして後書きでは追加のTipsとして世の中に害をなすようなものは作らない、極悪なことを実行できるようにしない、そして最後は

これはあなたの人生だ、皆と共有し、祝福し、生み出していくこと。そして思いっきり楽しむこと!

という100個めのTipsで締めくくられています。なんというエモく爽やかな読後感……!

f:id:iwasiman:20210507065306p:plain
達人プログラマー

まとめ:折に触れて読み返したくなる名著ふたたび

 第1版の原書が1999年、日本語版が2000年。僕が新装版を読んだのはもっと後で自身のキャリア後期なのですが、その時もかなり感銘を受けて影響された記憶があります。そして第2版が2020年。
 時代を超えて通用する普遍的な事柄や精神的なことも扱った本ですが技術スタックは刷新されており、キーワードだけですがTwitterAmazon S3が出てきたり、登場する言語ではRubyPythonJavaScriptが増えた印象。GoRust、マニアックにElixirも時々顔を出します。成功企業の例でNetflixが出てくるあたりに時代を感じます。

 僕も達人プログラマーには程遠くてもそれなりにキャリアを積み重ねてきましたので、そうそうここは実践してるのよね、という所もあれば、この真理は駆け出しの頃は分からなかったけど今だと分かるようになったのよね、というところもあり。
このへん実践できてない……とかやっぱりわからん! とか数学勉強しなおしてきます! とか平伏や切腹したくなるところもあり。各章セクションそれぞれについて様々な感想を持ちました。すべての読者にとってそうでしょう。

 全般を取り扱っているので組込・Webやフロントエンド・バックエンドなどなど立場にこだわらず、エンジニアリングに関わる全ての人にお勧めできます。各セクションも基本はあまり長くないエッセイ形式なので、一部分だけでも気軽に読むことができます。新人のうちから読むのもプログラマー・エンジニアの姿勢について多くを得ることができ、中堅・ベテランにもまた異なった形で得るものがあるでしょう。

 副題に「熟達に向けたあなたの旅」とあるように、旅の途中で折に触れてまた読み返したくなる、エンジニアリングの本棚に必ず置いておきたくなる本でした。
 日本でも世界でも多くのエンジニアが称賛し、各所のお勧め技術書にもたびたび名前が挙がる名著のひとつです。間違いなくお勧めです。

f:id:iwasiman:20210507092642p:plain
達人プログラマーを読もう

関連サイト

オーム社のぺージ。登場時にはてブ400超えと大きく注目を浴びました。達人出版会のページもはてブ多し。

www.ohmsha.co.jp

tatsu-zine.com

各所の感想記事を集めてみました。