プログラマ能力指標表

2015年05月27日: 表が見にくいというご意見を頂いたため、原文著者に連絡のうえ体裁を修正しました。

上位のレベルには下位のレベルの知識も蓄積されているということに注意してください。つまり、レベルnであればnより低いレベルの知識も全てあります。

コンピュータサイエンス

データ構造

2n(レベル0) 配列と連結リストの違いを知らない。
n2(レベル1) 実際のプログラミング作業において、配列や連結リスト、ディクショナリなどを説明および使用できる。
n(レベル2) 基本データ構造の時間と空間のトレードオフや、配列と連結リストの違いが分かっている。ハッシュテーブルの実装方法や衝突への対処法、優先度付きキューとその実装方法などを説明できる。
log(n)(レベル3) B木、二項ヒープ、フィボナッチヒープ、AVL/赤黒木、スプレー木、スキップリスト、トライ木のような高度なデータ構造の知識がある。

アルゴリズム

2n(レベル0) ある配列に含まれる数値の平均値を求めることができない(信じ難いことですが、私はそのようなプログラマ志望者と面接したことがあります)。
n2(レベル1) 基本的なソート、検索、データ構造トラバーサル、データ取り出しアルゴリズムの知識がある。
n(レベル2) 木、グラフ、単純な欲張りアルゴリズムと分割統治アルゴリズム、およびこのマトリクスのレベル間の関係性を理解できる。
log(n)(レベル3) 動的プログラミングソリューションに気付いてコーディングすることができ、グラフアルゴリズムや数値計算アルゴリズムの知識が豊富で、NP問題などを特定することができる。

プログラミングコンテストtopcoderのランキング上位者と働けたら、信じられないほど幸運です。

システムプログラミング

2n(レベル0) コンパイラやリンカ、インタプリタが何か知らない。
n2(レベル1) コンパイラ、リンカ、インタプリタの基礎知識がある。アセンブリコードとは何か、システムがハードウェアレベルでどのように機能するかについて理解している。仮想メモリとページングに関して多少の知識がある。
n(レベル2) カーネルモードとユーザモードの違い、マルチスレッド、同期プリミティブ、そしてそれらの実装方法を理解し、アセンブリコードを読むことができる。ネットワークの仕組み、ネットワークプロトコル、ソケットレベルのプログラミングを理解している。
log(n)(レベル3) ハードウェア(CPU+メモリ+キャッシュ+割り込み+マイクロコード)、バイナリコード、アセンブリ、静的および動的リンク、コンパイル、解釈、JITコンパイル、ガベージコレクション、ヒープ、スタック、メモリアドレッシングなどのプログラミングスタック全体を理解している。

ソフトウェアエンジニアリング

ソースコードのバージョン管理

2n(レベル0) 日付順にフォルダをバックアップ。
n2(レベル1) VSSおよびCVS/SVN初心者。
n(レベル2) CVSとSVNの機能を使うのがうまい。ブランチを作成してマージし、リポジトリプロパティをセットアップするパッチを使用する方法などを知っている。
log(n)(レベル3) 分散型VCSシステムの知識がある。BzrやMercurial、Darcs、Gitを試したことがある。

ビルドの自動化

2n(レベル0) IDEからビルドする方法しか知らない。
n2(レベル1) コマンドラインからシステムをビルドする方法を知っている。
n(レベル2) スクリプトを作って基本的なシステムをビルドできる。
log(n)(レベル3) スクリプトを作ってシステムだけでなくドキュメントとインストーラもビルドし、リリースノートを生成し、ソース管理のコードにタグを付けることができる。

自動テスト

2n(レベル0) テストは全てテスト担当者の仕事だと思っている。
n2(レベル1) 自動化された単体テストを記述したことがあり、記述されているコードの良い単体テストケースを考え出せる。
n(レベル2) TDD方式でコードを記述したことがある。
log(n)(レベル3) 機能テスト、ロードテスト、性能テスト、UIテストを理解し、自動化することができる。

プログラミング

問題の分解

2n(レベル0) コピー&ペーストで再利用するような直線的コードのみ。
n2(レベル1) 問題を複数の関数に分割することができる。
n(レベル2) 問題全体を解決する再利用可能な関数やオブジェクトを考え出すことができる。
log(n)(レベル3) 適切なデータ構造とアルゴリズムを使用し、変更対象である問題をいくつかの側面にカプセル化するような汎用コードやオブジェクト指向のコードを考え出すことができる。

システムの分解

2n(レベル0) 単一のファイルもしくはクラスのレベルを超えて考えることができない。
n2(レベル1) 同じプラットフォームかテクノロジ内でさえあれば、問題空間を分割してソリューションを設計できる。
n(レベル2) 複数のテクノロジやプラットフォームにまたがるシステムを設計できる。
log(n)(レベル3) 複数のプロダクトラインと外部システムとの統合で複雑なシステムを視覚化し、設計できる。また、監視やレポート、フェイルオーバといった運用サポートシステムの設計もできる。

コミュニケーション

2n(レベル0) 同僚に対して思考やアイデアを表現できない。スペルや文法に弱い。
n2(レベル1) 同僚同士で何を言われているか理解できる。スペルや文法に強い。
n(レベル2) 効果的に同僚とコミュニケーションできる。
log(n)(レベル3) 思考や設計、アイデア、仕様を明確に理解して伝達でき、文脈に合わせてコミュニケーションできる。

これは軽視されがちですが、プログラマを評価するための非常に重要な基準です。英語が母国語でない場所へのプログラミング作業のアウトソーシングが増えるにつれて、この問題はより顕著になってきました。私は、プログラマがコミュニケーションの意図を理解できなかったせいで失敗したプロジェクトをいくつか知っています。

同一ファイル内におけるコードの秩序

2n(レベル0) ファイル内においてコードに秩序が見られない。
n2(レベル1) メソッドが論理的に、またはアクセシビリティによってグループ化されている。
n(レベル2) リージョンごとにグループ化され、また別のソースファイルへの参照を含んだコメントが十分に書かれている。
log(n)(レベル3) ライセンスヘッダ、サマリ、十分なコメントを含むと共に、一貫性のある余白の使い方がなされており、見やすいファイルとなっている。

ファイル間におけるコードの秩序

2n(レベル0) ファイル間でコードに秩序を持たせるという考えがない。
n2(レベル1) 関連するファイルは同じフォルダに格納されている。
n(レベル2) 各物理ファイルが固有の目的を持っている。例えば、あるファイルはクラス定義、あるファイルは機能の実装、など。
log(n)(レベル3) 物理的なコードの構成が設計とほぼ一致しており、ファイル名やフォルダ構成を見れば設計を想像することができる。

ソースツリーの秩序

2n(レベル0) 全て1つのフォルダに格納されている。
n2(レベル1) コードが簡易的に分別され、それらが論理的にフォルダ分けされている。
n(レベル2) 循環依存がなく、バイナリ、ライブラリ、ドキュメント、ビルド、サードパーティのコードが全て適切にフォルダ分けされている。
log(n)(レベル3) 物理的なソースツリー構造が論理的階層や構造とほぼ一致しており、ディレクトリ名と構造を見ればシステムの設計を想像することができる。

この項目と前項目は共に秩序に関するものですが、秩序の規模が異なります。ソースツリーの秩序はコードに限らず、システムの構成物全てに関連するのです。

コードの可読性

2n(レベル0) 名前が一音節で付けられている。
n2(レベル1) ファイル、変数、クラス、メソッドなどに適切な名前が付けられている。
n(レベル2) 長い関数がない。珍しいコードやバグフィックス、コードの前提を説明するコメントが書かれている。
log(n)(レベル3) アサーションを使ってコードの前提が検証されている。条件やメソッドのネストが深くなく、コードが自然に流れている。

防御的プログラミング

2n(レベル0) 防御的プログラミングの概念を理解していない。
n2(レベル1) コード内の全ての引数をチェックし、重要なコードの前提についてはアサーションを行う。
n(レベル2) 戻り値のチェック、および問題が起こり得るコードについての例外チェックが確実になされている。
log(n)(レベル3) 防御的プログラミングに役立つ独自のライブラリを持っている。障害をシミュレートする単体テストを書く。

エラー処理

2n(レベル0) エラーを想定せずにコードを書く。
n2(レベル1) 例外を投げたりエラーを返すようなコードに対して、基本的な処理ができる。
n(レベル2) エラーや例外があってもプログラムが良い状態であるようにしておく。リソースやコネクション、メモリを全て適切にクリアしている。
log(n)(レベル3) 起こり得る例外を事前に検出できるようなコードを書く。全ての層のコードにおいて、一貫した例外処理戦略が維持されている。全システムにおける例外処理ガイドラインを考える。

IDE

2n(レベル0) IDEは主にテキストエディタとして使用している。
n2(レベル1) IDEのインタフェースを理解しており、メニューを使ってIDEを活用できる。
n(レベル2) よく使われるショートカットキーを知っている。
log(n)(レベル3) カスタムマクロを作成したことがある。

API

2n(レベル0) ドキュメントを頻繁に見直さなくてはならない。
n2(レベル1) よく使われるAPIが頭に入っている。
n(レベル2) APIについて、広く深い知識を持っている。
log(n)(レベル3) よく使われるタスクを単純化したり、APIで足りない部分を補ったりするためにライブラリを作成したことがある。

APIの例としては、Javaライブラリ、.NET Framework、またはアプリケーション向けのカスタムAPIがあります。

フレームワーク

2n(レベル0) 主要なプラットフォーム以外ではフレームワークを使ったことがない。
n2(レベル1) そのプラットフォームに対応している一般的なフレームワークについて聞いたことがある。しかし使ったことはない。
n(レベル2) 1つ以上のフレームワークを実務で使ったことがある。また、フレームワークに関連した用語をよく知っている。
log(n)(レベル3) フレームワークを作成したことがある。

要求仕様

2n(レベル0) 指定された要件に従い、仕様通りにコードを書く。
n2(レベル1) 仕様の漏れについて疑問を持つ。
n(レベル2) 仕様の全体像が理解でき、さらに定義が必要な領域を見つけ出すことができる。
log(n)(レベル3) 経験に基づき、より良い仕様の代替案やフローを提案することができる。

スクリプト言語

2n(レベル0) スクリプト言語について何も知らない。
n2(レベル1) バッチやシェルが使える。
n(レベル2) PerlやPython、Ruby、VBScript、Powershellが使える。
log(n)(レベル3) 再利用可能なコードを作成し、公開したことがある。

データベース

2n(レベル0) Excelはデータベースだと思っている。
n2(レベル1) 正規化、ACID、トランザクションなどデータベースの基本的な概念を理解しており、簡単なSELECT文が書ける。
n(レベル2) 将来実行されるクエリを念頭に置きながら、適切かつ正規化されたデータベーススキーマを設計することができる。ビューやストアドプロシージャ、トリガ、ユーザ定義型を使いこなすことができる。クラスタ化インデックスと非クラスタ化インデックスの違いが分かる。ORMツールを使いこなすことができる。
log(n)(レベル3) 基本的なデータベース管理、パフォーマンスやインデックスの最適化ができる。高度なSELECT文が書ける。カーソル処理をリレーショナルなSQLに置き換えることができる。データやインデックスが内部的にどのように保持されるかを理解している。データベースのミラーリングやレプリケーションなどの仕組みを理解している。2相コミットの仕組みを理解している。

経験

業務レベルで使用経験のある言語

2n(レベル0) 命令型言語もしくはオブジェクト指向言語
n2(レベル1) 命令型言語、オブジェクト指向言語、そして宣言型言語(SQL)。加えて静的型付けと動的型付けの違いや、弱い型付けと強い型付けの違い、型推論について理解していればなお望ましい。
n(レベル2) 関数型言語。加えて遅延評価やカリー化、継続について理解していればなお望ましい。
log(n)(レベル3) ErlangやOzのような並行プログラミング言語、そしてPrologのような論理型プログラミング言語。

業務レベルで使用経験のあるプラットフォームの数

2n(レベル0) 1
n2(レベル1) 2~3
n(レベル2) 4~5
log(n)(レベル3) 6以上

職業プログラマとしての経験年数

2n(レベル0) 1年
n2(レベル1) 2~5年
n(レベル2) 6~9年
log(n)(レベル3) 10年以上

専門知識

2n(レベル0) 知識なし
n2(レベル1) ある領域において少なくとも1つのプロダクトに関わったことがある。
n(レベル2) ある領域において複数のプロダクトに関わったことがある。
log(n)(レベル3) ある領域のエキスパートであり、いくつかのプロダクトやソリューションの設計および実装を行ったことがある。対象領域の約束事や慣習に精通している。

知識

ツール知識

2n(レベル0) Visual Studio.NETやEclipseなどの主なIDEしか知らない。
n2(レベル1) 有名で標準的なツール以外にもいくつか知っている代替ツールがある。
n(レベル2) いろいろなエディタやデバッガ、IDE、そして代替となるオープンソースなどにもよく通じている。例えばScott Hanselmanの強力なツールリストの多くを知っている。ORMツールを使ったことがある。
log(n)(レベル3) 実際にツールやスクリプトを開発したことがある。それを公開した経験があればなお望ましい。

触れたことのある言語

2n(レベル0) 命令型言語もしくはオブジェクト指向言語
n2(レベル1) 命令型言語、オブジェクト指向言語、そして宣言型言語(SQL)。加えて静的型付けと動的型付けの違いや、弱い型付けと強い型付けの違い、型推論について理解していればなお望ましい。
n(レベル2) 関数型言語。加えて遅延評価やカリー化、継続について理解していればなお望ましい。
log(n)(レベル3) ErlangやOzのような並行プログラミング言語、そしてPrologのような論理型プログラミング言語。

コードベースの知識

2n(レベル0) コードベースを見たことがない。
n2(レベル1) コードの構成について基本的な知識があり、システムをビルドする方法が分かる。
n(レベル2) コードベースについて実用的な知識があり、いくつかのバグフィックスや小規模な機能を実装した経験がある。
log(n)(レベル3) 複数の大規模な機能をコードベース上に実装したことがあり、多くの機能やバグフィックスにおいて必要な変更をすぐに視覚化することができる。

最新技術に関する知識

2n(レベル0) 最新技術について知らない。
n2(レベル1) 自分の分野の最新技術について知っている。
n(レベル2) アルファ版やCTP版やベータ版をダウンロードしたり、記事やマニュアルを読んだりしたことがある。
log(n)(レベル3) プレビュー版を実際に触ってみて、何かを作ったことがある。それを一般公開していればなお望ましい。

プラットフォームの内部

2n(レベル0) プラットフォームの内部について何も知らない。
n2(レベル1) プラットフォームの内部的な動作の仕組みについて基本的な知識がある。
n(レベル2) プラットフォームの内部について深い知識があり、プラットフォームがプログラムを実行可能なコードに変換する仕組みを視覚化することができる。
log(n)(レベル3) 逆アセンブラや逆コンパイラ、デバッガなど、プラットフォームの内部を改善したり、情報を提供するようなツールを作成したことがある。

読んだことのある書籍

2n(レベル0) Unleashedシリーズや21 daysシリーズ、24 hoursシリーズ(訳註: SAMS Publishing)発行の入門書)、またはFor Dummiesシリーズ(訳註: John Wiley & Sons発行の入門書シリーズ)。
n2(レベル1) 『コードコンプリート』、『ウェブユーザビリティの法則』、『詳説 正規表現』
n(レベル2) 『オブジェクト指向における再利用のためのデザインパターン』、『ピープルウエア』、『珠玉のプログラミング』、『アルゴリズム設計マニュアル』、『達人プログラマー』、『人月の神話』
log(n)(レベル3) 『計算機プログラムの構造と解釈』、『コンピュータプログラミングの概念・技法・モデル』、『The Art of Computer Programming』、『データベースシステム概論』、『Thinking Forth』、『Scheme手習い』

ブログ

2n(レベル0) 存在は知っているが読む時間がない。
n2(レベル1) テクノロジ、プログラミング、ソフトウェアエンジニアリングに関するブログやポッドキャストを定期的にチェックしている。
n(レベル2) 自分が見つけた有用な記事やツールをまとめたブログを管理している。
log(n)(レベル3) プログラミングについての個人的な洞察や考えをブログ上で発表している。

この記事をWeb向けに再構成してくれたJohn Haugelandに感謝します。