神話上の「10倍プログラマー」
10倍プログラマーとは、プログラミングの神話に登場する、普通のプログラマーの10倍の仕事ができるプログラマーです。ここでいう普通のプログラマーとは、10倍プログラマーのような魔法の能力は持たないものの、自分の仕事をうまくこなせる人だと考えればよいでしょう。ただし、「普通のプログラマー」をより正確に説明するなら、この分野のプロとして働くプログラマーたちの中で、平均的な成果を出す人を指すと言ったほうが適切です。
プログラミング界隈では、そのような存在が本当にいるのかどうかについて、意見が極端に分かれています。10倍プログラマーなど存在しないと言う人もいれば、実際には存在するどころか、探す場所さえ知っていれば100倍プログラマーすらいると言う人もいます。
プログラミングを「線形」な仕事だと考えるなら、10倍プログラマーは明らかに非現実的な可能性に見えます。あるランナーが別のランナーの10倍速く走ることなど、どうすればできるでしょうか。同じ時間で、ある建設作業員が別の作業員の10倍のものを作ることなど、可能でしょうか。しかしプログラミングは、とても特殊な意味で設計の仕事です。プログラマーが実際のプログラムのアーキテクチャ設計に関わらない場合でも、それを実装する行為には、実装戦略についての小さな設計が必要になります。
つまり、プログラムの設計と実装が線形な能力でないのだとすれば、経験、コーディング能力、知識、役に立たない部分を見抜く力などは、単なる線形の優位性ではありません。プログラムを作る行為の中で、それらは掛け合わせるように作用します。もちろん、プログラマーがプログラムの設計と実装の両方を扱える場合、この現象はさらに強く現れます。作業が「目標指向」であればあるほど、潜在的な10倍プログラマーは自分の能力を活用して、はるかに少ない労力で目標に到達できます。一方、何を使い、どのように実装するかについて具体的なガイドラインが定められているなど、目の前の作業が厳格に制約されている場合、10倍プログラマーが短時間で大量の仕事をこなす能力は弱まります。それでも「局所的な」設計の可能性を活用して、はるかによい仕事はできます。しかし、目標に到達するための道筋を、より根本的な形で変えることはできません。その道筋には、目標自体はほとんど変わらないまま、達成に必要な労力を大幅に減らすため、仕様の一部をプロジェクトから完全に取り除くことまで含まれる可能性があります。
プログラマーとして働いてきた20年の間に、私は一緒に働いた同僚たちや、ある目標を達成するために私が指導したプログラマーたちが、Redisなどのプロジェクトにパッチを提供する様子を見てきました。同時に、多くの人から、私はとても速くプログラミングする人間だと言われてきました。自分は決して仕事中毒ではないので、コーディングを速く行う場合の基準として、ここでは自分自身も使うことにします。
以下は、プログラマーの生産性に最も大きな違いを生むと私が考えている資質の一覧です。
基礎的なプログラミング能力:サブタスクを完了する力
プログラマーの明らかな限界、あるいは強みの一つは、プログラムの一部、つまり関数やアルゴリズムなどを実際に実装するサブタスクに対処する能力です。意外なことに、何かを実装するために基本的な命令型プログラミングの構文を非常に効率よく使う能力は、思われているほど広く身についていません。チームで働いていると、単純なソートアルゴリズムさえ知らない、非常に力量の低いプログラマーが、理論上は極めて有能でありながら、解決策を実装する実践力に乏しい大卒プログラマーよりも多くの仕事をこなす場面を、私は何度も見てきました。
経験:パターンマッチング
ここでいう経験とは、繰り返し現れるさまざまな作業について、すでに試した解決策の集合を意味します。経験豊富なプログラマーは、最終的にはさまざまなサブタスクへの対処法を知っています。そのため、設計にかかる作業を大幅に減らせます。とりわけ、単純さにとって最大の敵の一つである設計上の誤りに対して、非常に強力な武器になります。
集中:実際の時間と仮想的な時間
コードを書くのに何時間費やしたかは、その時間の質を見なければ意味がありません。集中を妨げる要因には、内的なものと外的なものがあります。内的な要因は、先延ばし、目の前のプロジェクトへの関心の欠如(好きでもないことをうまくやることはできません)、運動不足や心身の不調、睡眠不足などです。外的な要因は、頻繁な会議、実質的な個人オフィスのない職場、頻繁に割り込んでくる同僚などです。集中力を高め、割り込みを減らそうとすれば、プログラミングの生産性に無視できない効果があるのは自然なことに思えます。集中するためには、極端な手段が必要になることもあります。たとえば私は、メールをたまにしか読まず、その大半には返信しません。
設計上の妥協:5%を捨てて90%を得る
プロジェクトの本質ではない目標が設計の複雑さの大部分を生み出していることや、本質的な機能とそうでない機能の間に設計上の緊張関係があるため、別のより重要な目標を達成しにくくしていることを認めようとしないと、複雑さが生まれることがよくあります。設計者にとっては、設計の中にある「簡単に得られる成果」ではない部分、つまり、労力と利点が比例していない部分をすべて見抜くことが非常に重要です。成果を最大化するために実行されるプロジェクトは、まさに重要で、妥当な時間で実装できる側面に集中します。たとえばメッセージブローカーであるDisqueを設計していたとき、メッセージの順序をベストエフォートで保証するだけにすれば、プロジェクトの他のあらゆる側面、つまり可用性、クエリ言語、クライアントとの対話、単純さ、性能を大幅に改善できると、私は途中で気づきました。
単純さ
これは明白なポイントですが、あらゆる意味にも、何の意味にもなり得ます。単純さとは何かを理解するには、複雑さがどのように生まれることが多いのかを確認するのがよいでしょう。複雑さを生む主な要因は、設計上の妥協を避けようとすることと、設計作業の中で誤りが積み重なることだと私は考えています。
設計の過程を考えてみてください。間違った道を選ぶたびに、最適な解決策からどんどん遠ざかっていきます。最初の設計ミスは、扱う人が悪ければ、同じシステムを再設計することにはつながりません。最初のミスを帳尻合わせするために、別の複雑な解決策を設計することになります。こうしてプロジェクトは、誤った一歩を踏み出すたびに、より複雑で非効率になっていきます。
単純さを実現するには、頭の中で小さな「概念実証」を行うという考え方が役立ちます。そうすれば、プログラマーは多くの単純な設計を頭の中で検討し、最も実行可能で直接的に見える解決策から作業を始められます。その後は、経験と個人の設計能力によって設計を改善し、解決すべきサブ設計について妥当な解決策を見つけられるようになります。
ただし、複雑な解決策が必要になったときは、その複雑さを避ける方法について長い時間をかけて考えることが重要です。まったく異なる選択肢まで検討しても、よりよい可能性が見つからなかった場合にだけ、その方向へ進み続けるべきです。
完璧主義、あるいは生産性を殺し設計を歪める方法
完璧主義には二つの形があります。プログラムで測定可能な最高の性能を目指すエンジニアリング文化と、性格的な特徴としての完璧主義です。どちらの場合も、私はこれをプログラマーが物事を速く届けるうえで最大の障壁の一つだと考えています。完璧主義と外部からの評価への恐れは、心理的な基準や、単純に測定しやすいパラメーターだけに従って設計を磨こうとする偏りを生みます。その結果、堅牢性、単純さ、期限内に届ける能力といった要素が、ほとんど考慮されないまま、質の低い選択をすることになります。
知識:理論が役に立つこともある
複雑な作業に取り組むとき、データ構造、計算の根本的な限界、特定の作業のモデル化に非常に適した自明でないアルゴリズムについての知識は、適切な設計を見つける能力に影響します。何もかも知り尽くした超専門家になる必要はありません。しかし、ある問題に対する潜在的な解決策を数多く、少なくとも知っていることは確実に役立ちます。たとえば、設計上の妥協(ある程度の誤差を受け入れること)と、確率的な集合濃度推定器に関する知識を組み合わせれば、ストリーム内の一意な項目を数えるための、複雑で遅く、メモリ効率の悪い解決策を避けられます。
低レベル:マシンを理解する
高水準言語を使っている場合でも、プログラム上のさまざまな問題は、コンピューターが特定の作業をどのように実行するのかを誤解していることから生じます。その結果、使っているツールやアルゴリズムに根本的な問題が見つかり、プロジェクトをゼロから再設計し、再実装する必要さえ生じることがあります。Cに関する十分な能力、CPUの動作への理解、カーネルがどのように動き、システムコールがどのように実装されているかについての明確な認識があれば、後期段階での望ましくない驚きを避けられます。
デバッグ能力
バグを見つけるために、膨大な作業時間を費やしてしまうのは簡単です。バグの状態を少しずつ把握し、合理的な手順で修正する能力と、そもそも多くのバグを含みそうにない単純なコードを書く姿勢。この二つが合わさると、プログラマーの効率に大きな効果をもたらします。
上記のようなプログラマーの資質が、成果に10倍もの影響を及ぼし得ることは、私にとって驚きではありません。これらを組み合わせることで、実行可能なモデルから出発した設計をうまく実装でき、その設計は代替案より何倍も単純になり得ます。単純さを重視する方法として、私は「機会主義的プログラミング」と呼ぶ考え方を気に入っています。基本的には、開発の各段階で、最小限の労力でプログラムのユーザーに最大の効果をもたらせるよう、実装する機能の集合を選びます。
記事をランダムに読む