· 7分で読了

『The Worst Kind of Programmer』を読んで

この記事は中国語から自動翻訳されたものです。翻訳によりニュアンスが失われている場合があります。

これは原文『The Worst Kind of Programmer』を読んだ感想だ。

この記事の著者は明らかに似たような経験をしており、記事の中からも彼の偏見を感じ取るのは難しくない。しかし、議論に値する点や参考にすべき部分も多くあると感じたので、ここに記録しておく。

記事の中で彼は、過去のプロジェクトにいたあるフロントエンドリードの話を挙げている。そのリードは並々ならぬ熱意でプロジェクトアーキテクチャを設計し、AngularやNx、Rxを選定した。バックエンドのテックリードもSpring Bootフレームワークの上に様々なライブラリを追加し、とにかく「クールでイケてる技術」をふんだんに取り入れていた。

プロジェクトの要件が増えるにつれ、このフロントエンドリードはさらにアーキテクチャに手を加え、ビジネスロジックと技術コアを分離しようとした。そしてジュニアメンバーには、APIドキュメントの作成やテストコードの記述といった比較的単純な要件だけを担当させた。

その後、このフロントエンドリードは退職した。チームは複雑になりすぎたコードを保守できなくなり、開発のアウトプットを維持するために火消しのエキスパートを雇った。しかしアーキテクチャの複雑さは依然としてチームのアウトプット速度を低下させ続けた。そして、リファクタリングするにせよゼロから書き直すにせよ、そのコストは莫大なものになっていた。

問題はどこにあるのか?

僕から見れば、これはむしろ経験の浅いエンジニアこそがやってしまいがちな行動に見える。(過去の自分にもよく似ていて、まずは懺悔したい🙏)

先ほどの例で言えば、このフロントエンドリードは非常に熱心で、もしかしたら自分の履歴書に華々しい実績を1ページ追加できたのかもしれない。導入を終えたらさっさと立ち去ったわけだが、実際にはチーム全体の開発スピードを大きく引き下げてしまった。

だからこそ僕は、初期段階でのオーバーエンジニアリング(過度な設計)は諸悪の根源だと常々強く思っている。新しいフレームワークを絶対に使ってはいけないというわけではない。だが、記事を数本読んだだけで安易に新しいフレームワークやライブラリを導入してしまうと、最初はたいした問題に見えなくても、実際にはプロジェクトに極めて甚大な影響を及ぼすことになる。

優れたエンジニアリングのプロセスとは、常にシンプルで「ちょうどいい」解決策を模索するものであるべきだ。僕が気に入っている例の一つに、ピアノのアクション機構(弦を打つ仕組み)の進化がある。これまでに見た中で最も分かりやすかったのは、Mark Roberのこの動画での解説だ。アニメーションが非常に分かりやすい。

なぜピアノのアクション機構はあんなに複雑に見えるのか? なぜ単に棒のようなもので弦を叩くだけではダメなのか? 鍵盤を押している間は音を伸ばし、指を離した瞬間に止めるにはどうすればいいのか?

これらはすべて単純な問いから始まり、段階的な進化を経て現在の形になったものであり、最初から得られた答えではない。なぜそうなっているのかを理解すると、その仕組み全体がいかに「必要十分で過不足のない設計」であるかに感嘆させられる。ソフトウェア開発も全く同じだ。最初からあらゆるフレームワークを導入するのではなく、今直面している課題に対して一歩ずつ最適解を見出していくべきなのだ。

記事の後半には、僕がそれほど賛同できない部分もある。例えば彼は、抽象的な問題を解決する能力、長時間働けること、ソフトウェア開発への情熱といった点を挙げて批判しているが、僕自身はこれらはどれも素晴らしい資質だと思う。もちろん、長時間労働に関しては人生のステージによって変化し、他のことに重点を置きたくなる時期もあるだろう。

もう一つ、見落とされがちな指標として**コードが「変更しやすく、削除しやすいか」**という点がある。

僕が関連するコードに手を入れるとき、連鎖的な不具合を引き起こすことなく自信を持って特定の箇所を削除できるか。あるいは、実装を容易に差し替えられるような設計になっているか。さらに言えば、他の人がコードを変更したいとき、素早く理解して同じ方針で修正できるかどうかも重要だ。この観点から、僕はAdapterパターンがとても気に入っている。インターフェースさえ決めてしまえば、その裏側の実装はどう作っても構わないからだ。

コードレビューにおいて過度に厳格な人がいるが、そうした人は往々にして機能全体の設計やコードの可読性を高めるための提案ではなく、個人の好みや主観に基づいて批判しがちだ。

フォーマット(書式)についてとやかく言うのは論外だ。もしチーム内の議論の大半がコードフォーマットに費やされているなら、ESLintやPrettierの設定が適切かどうかを見直すべき時期に来ている。

コミュニケーション

チームにおいて、重大な決定を下す際には、最低でも事前にチームと議論を交わすべきだと僕は考えている。

全員が合意する必要はないが、チームの仲間をバカ扱いして自分のやり方が一番優れていると思い込む必要もない。正常な状態であれば、誰もがプロダクトをより良くし、開発をより円滑にしたいと願っているはずだ。

ここで注意すべき点が2つある:

  1. チームメンバーが現在の書き方に慣れているために、無意識に新しい提案に反対してしまうことがある。その場合は背景を共有し、なぜ新しい提案のほうが優れていると考えるのかを丁寧に説明すると良い。
  2. チームのシニアメンバーとしては、新しい提案を見た際に、より多くのコンテキストや過去の経緯・データを提供して検討材料にしてもらうと良い。

ジェフ・ベゾスとレックス・フリードマン(Lex Fridman)のポッドキャストの中で、「Disagree and commit(反対してもコミットする)」という言葉が出てくる。

僕はこの考え方が大好きだ。

納得していなくても全力でコミットする。各陣営が意見を出し合って泥沼の水掛け論に陥るのを防ぐため、一度方針が決まったら、たとえ反対意見を持っていたとしても全力を尽くして支持する。少なくともプロジェクトは前に進み、無駄な消耗を避けられる。これは非常に素晴らしい姿勢だと思う。

特にチームが優秀な人たちで構成されていれば、意見が食い違う部分など本来ほんのわずかなはずだ。(もちろん、精鋭チームであることが前提だが)

Disagree and commit is a really important principle that saves a lot of arguing. There will be disagreements in any endeavor in life where you have teammates. In society, and inside companies, we have a bunch of mechanisms we use to resolve disputes. And a lot of them are really bad. An example of a really bad way of coming to an agreement is compromise.

ここでベゾスは、最もひどい合意形成のやり方は「妥協」だと述べている。各方面の折衷案を選んだ結果、生まれてくるのはフランケンシュタインのようなキメラ(縫合怪)に過ぎない。

この点には僕も深く共感する。自分に十分な裁量権がなかったり、信頼関係・名声がまだ築けていなかったりするときは、確かに妥協を受け入れざるを得ないこともある。そしてこのことは、ソフトウェア開発の多くが「要件が下りてきて、それを見積もって開発チームが実装する」という受動的な状態にとどまり、開発チームがアイデアの構想段階にあまり関与できていない現状についても考えさせられる。

その結果、技術力は決して低くないのに、いざ自分でプロダクトを作ろうとすると何も生み出せなかったり、作ったものがユーザーに求められていなかったりする現象が起きる。これも僕が最近直面している課題の一つだ。皆さんは何か良いアプローチを持っているだろうか?

関連記事

他のトピックを探索