The mythical 10x programmer

Salvatore Sanfilippo

伝説の10xプログラマー

原文は Salvatore Sanfilippo により に公開されました。 このブログを購読する

プログラミングの神話における「10xプログラマー」とは、普通のプログラマーの10倍もの仕事をこなせるプログラマーのことだ。ここでいう普通のプログラマーとは、仕事はきちんとこなせるが、10xプログラマーのような魔法のような能力は持たない人物を想像すればいい。より正確に言えば、「普通のプログラマー」とは、この分野のプロフェッショナルであるプログラマーたちの平均的なアウトプットを持つ者のことだ。

プログラミング界隈では、このような存在が実在するかどうかについて意見が真っ二つに分かれている。10xプログラマーなど存在しないと言う人もいれば、いや実在するどころか、探し方さえ知っていれば100倍のプログラマーさえいるのだと言う人もいる。

プログラミングを「線形的」な仕事だと捉えるなら、10xプログラマーは非現実的に見えるだろう。どうすればあるランナーが他のランナーの10倍速く走れるだろうか。あるいは、建設作業員が同じ時間で他の作業員の10倍のものを作れるだろうか。しかしプログラミングは、非常に特殊な意味でデザインの仕事である。たとえプログラマーがプログラム自体のアーキテクチャ設計に関わっていなくても、それを実装するという行為自体が、実装戦略というサブデザインを必要とするのだ。

したがって、プログラムの設計と実装が線形的な能力でないとすれば、経験、コーディング能力、知識、不要な部分を見抜く力といったものは、私見では単なる線形的な優位性ではない。それらはプログラムを作るという行為において、互いに掛け合わさって作用するのだ。もちろん、この現象はプログラマーが設計と実装の両方を担える場合に、より顕著になる。タスクが「ゴール志向」であればあるほど、潜在的な10xプログラマーは自らの能力を発揮して、はるかに少ない労力でゴールに到達できる。逆に、目の前のタスクが硬直的で、使うべきツールや実装方法について具体的なガイドラインが定められている場合、10xプログラマーが短時間で大量の仕事をこなす能力は弱まる。もちろん、その場合でも「局所的」な設計の余地を活かしてずっと良い仕事をすることはできるが、ゴールに至る道筋をより根本的に変えることはできない。その道筋の変更には、仕様の一部をプロジェクトから完全に取り除くことさえ含まれるかもしれない。そうすれば、目指すゴールはほぼ同じに見えながら、そこに至るための労力は大幅に削減されるのだ。

プログラマーとして働いてきた20年間で、私は共に働く他のプログラマーたちを観察してきた。同僚として、あるいは私の指導のもとで特定のゴールを目指す者として、またRedisや他のプロジェクトにパッチを提供するコントリビューターとして。同時に、多くの人から私は非常に速くコードを書くプログラマーだと言われてきた。私は決してワーカホリックではないことを考えれば、自分自身も「速くコーディングする」一つのサンプルとして参照してよいだろう。

以下は、プログラマーの生産性に最も大きな差を生むと私が考える資質のリストである。

  • 素のプログラミング能力:サブタスクを片付ける力

    プログラマーの最も明白な限界、あるいは強みの一つは、プログラムの一部、すなわち関数やアルゴリズムなどを実際に実装するというサブタスクをこなす能力である。驚くべきことに、何かを実装するために基本的な命令型プログラミングの構文を効率よく使いこなす能力は、私の経験上、思われているほど広く普及していない。チームの中で、単純なソートアルゴリズムさえ知らないような非常に未熟なプログラマーが、理論上は極めて有能であるはずの、しかし解決策を実装する実践においては非常に拙い大卒のプログラマーよりも多くの仕事をこなすのを何度か目にしてきた。

  • 経験:パターンマッチング

    ここでいう経験とは、繰り返し現れる数々のタスクに対して、すでに探求済みの解決策の集合を意味する。経験豊富なプログラマーはいずれ、さまざまなサブタスクへの対処法を身につけている。これにより多くの設計作業を省けるだけでなく、とりわけ設計上の誤りに対する極めて強力な武器となる。設計上の誤りは、シンプルさにとって最大の敵の一つだからだ。

  • 集中力:実際の時間 vs. 仮定の時間

    コードを書くのに費やした時間数は、その時間の質を見なければ意味がない。集中力の欠如は、内的要因と外的要因の両方から生じる。内的要因としては、先延ばし、目の前のプロジェクトへの興味の欠如(愛していないことを得意になることはできない)、運動不足や体調不良、睡眠の質の低さや睡眠不足などが挙げられる。外的要因としては、頻繁な会議、個室のない職場環境、同僚からの頻繁な中断などがある。集中力を高め、中断を減らそうとすることが、プログラミングの生産性に少なからぬ効果をもたらすのは当然のことだろう。集中を得るためには、時に極端な手段が必要になることもある。例えば私は、メールは時々しか読まず、そのほとんどに返信しない。

  • 設計上の犠牲:5%を切り捨てて90%を得る

    複雑さはしばしば、プロジェクトの非本質的なゴールが設計の複雑さの大部分を占めていることや、本質的な機能と非本質的な機能の間に設計上の緊張関係があるために、より重要な別のゴール達成が極めて困難になっていることを認めようとしないときに生まれる。設計者にとって、楽に勝てる部分ではない、すなわち労力と得られる利点が釣り合っていない設計の部分をすべて見極めることは非常に重要だ。アウトプットを最大化するために遂行されるプロジェクトは、まさに重要であり、かつ合理的な時間で実装可能な側面に焦点を当てることになる。例えば、メッセージキューであるDisqueを設計していたとき、ある時点で、メッセージの順序保証をベストエフォートにするだけで、プロジェクトの他のあらゆる側面、すなわち可用性、クエリ言語やクライアントとのインタラクション、シンプルさやパフォーマンスを大幅に改善できることに気づいた。

  • シンプルさ

    これは当たり前のようでいて、すべてを意味し、同時に何も意味しないような論点だ。シンプルさとは何かを理解するには、複雑さがどのように生まれるかを見るのがよい。私が考えるに、複雑さの二大要因は、設計上の犠牲を払おうとしないことと、設計活動における誤りの蓄積である。

    設計プロセスについて考えてみれば、誤った道を進むたびに、私たちは最適解からどんどん遠ざかっていく。初期の設計ミスは、能力のない者の手にかかると、同じシステムの再設計を生むのではなく、初期の誤りに対処するための、さらに複雑な別の解決策の設計につながる。こうしてプロジェクトは、誤った一歩ごとに、より複雑で非効率になっていくのだ。

    シンプルさを達成する方法は、頭の中での小さな「概念実証(プルーフ・オブ・コンセプト)」という形で考えることだ。そうすれば、プログラマーの頭の中で膨大な数のシンプルな設計を探求でき、最も実現可能性が高く直接的な解決策に見えるものから作業を始められる。その後、経験と個人的な設計能力によって設計を改善し、解決すべきサブデザインに対して妥当な解決策を見つけていくことができる。

    しかし、複雑な解決策が必要になるたびに、その複雑さをどう回避できるかを長い時間をかけて考えることが重要だ。そして、まったく異なる代替案まで考慮してもより良い可能性が見つからない場合にのみ、その方向へ進むべきである。

  • 完璧主義、あるいは生産性を殺し設計を歪める方法

    完璧主義には二つの形がある。プログラムにおいて測定可能な最高のパフォーマンスを追求するエンジニアリング文化としてのものと、性格特性としてのものだ。どちらの場合においても、これはプログラマーが物事を速く届ける上での最大の障壁の一つだと私は見ている。完璧主義と外部からの評価への恐れは、設計にバイアスをかけ、心理的な、あるいは表面的に測定しやすいパラメータだけに沿って設計を磨き上げようとすることで、貧弱な選択を招く。その際、堅牢性、シンプルさ、期限内に届ける能力といったことは、しばしばまったく考慮されないのだ。

  • 知識:ある程度の理論は役に立つ

    複雑なタスクに取り組む際、データ構造、計算の根本的な限界、特定のタスクのモデル化に非常に適した非自明なアルゴリズムなどに関する知識は、適切な設計を見つける能力に影響を与える。あらゆることの超専門家である必要はないが、少なくともある問題に対する多数の潜在的な解決策を認識していることは確かに必要だ。例えば、設計上の犠牲(ある程度の誤差を許容すること)と、確率的な集合の濃度推定器についての知識を組み合わせれば、ストリーム内のユニークなアイテムを数えるために、複雑で遅くメモリ効率の悪い解決策を避けることができる。

  • 低レイヤー:マシンを理解する

    高水準言語を使っている場合でさえ、プログラムにおける多くの問題は、コンピュータが与えられたタスクをどのように実行するかについての誤解から生じる。それが原因で、使用しているツールやアルゴリズムに根本的な問題があるために、プロジェクトを一から設計し直し、実装し直す必要に迫られることさえある。C言語の確かな能力、CPUがどのように動くかの理解、そしてカーネルがどのように動作しシステムコールがどのように実装されているかについての明確な知識は、後になってからの嫌な驚きから救ってくれる。

  • デバッグ能力

    バグを見つけるために膨大な労力を費やすことは非常にたやすい。バグに関する状態を段階的に把握し、合理的な一連の手順で修正するのが上手であることと、そもそも多くのバグを含みそうにないシンプルなコードを書こうとする姿勢とが合わさることで、プログラマーの効率に大きな効果をもたらし得る。

上記のようなプログラマーの資質が、アウトプットに10倍もの影響を与え得ることは、私にとって少しも驚くことではない。それらが組み合わさることで、実現可能なモデルから出発し、代替案よりも何倍もシンプルになり得る設計を、うまく実装することが可能になる。シンプルさを徹底する方法の一つとして、私が「日和見プログラミング(opportunistic programming)」と呼びたいものがある。基本的に、開発の各ステップで、最小限の労力でプログラムのユーザーベースに最大の影響を与えるように、実装すべき機能の集合が選ばれるのだ。

この記事は「muse-spark-1.2-contributor」を使用して翻訳されました。

コメント