プログラミング力とは何か?
プログラミング力という言葉を定義せずに使ってきましたが、この連載で述べるプログラミング力とは何かについて定義していきます。
あるITシステムを作成することを考えます。システムの作成は、おおまかには、システムがどう動くか定義する部分(いわゆる要件定義~外部設計あたり)と、それを実際に設計・実装する部分(外部設計~内部設計~実装あたり)に分けることができるでしょう。その後、テストやリリース、運用、保守などもありますが、作成という段階では一旦実装までを対象とします。
前者のシステムがどう動くか定義する部分では、あるべきシステムを定義するためには、実際の業務プロセスを理解しなければなりません。この理解した知識は、しばしば業務知識と呼ばれます。業務知識の重要性はみなさんもご存知でしょう。業務知識がないと、その後どれだけ優れた開発を行なっても、実際に現場で使えるソフトウェアにはならず、宝の持ち腐れになってしまいます。
後者の実際にシステムを設計・実装するという部分では、システムをコンピュータの上に設計・実装していく以上、コンピュータのハードウェアやソフトウェアの理解が必要です。この連載では、実際にシステムを作る能力を総称して「プログラミング力」と呼ぶことにします。ここでは、業務知識を取り払い、要件が定義されたシステムを実際に設計・実装する部分だけを考えてプログラミング力と呼びます。
プログラミング力は何から構成されているのでしょうか? プログラミング力を少し分解して、知っておくべき「知識」と、知識をどう「応用」するかの大きく2つに分けて考えることにします。
「知識」のベースとなるのは、Pythonなどの特定のプログラミング言語を使って要求仕様を満たすプログラムを書いたり、競技プログラミングのようなコンテストで良い成績を収める能力だけではなく、ITの全般的な知識です。システムは、通常複数のコンピュータを連携させ、また、既存のソフトウェアも複数組み合わせて実装されます。そこで利用されるOS、ネットワーク、データベースなどの知識が必要になります。また、ここにコンテナなどの仮想化技術も加わるでしょう。最近のソフトウェアはウェブブラウザで動くように作ることも多いので、ブラウザがどう動くかを知っていることも重要です。プログラムを書く上ではアルゴリズムやデータ構造に関する知識も必要です。これらのコンピュータサイエンス的な知識に加えて、ソフトウェアをどう作ると失敗しづらいかや、ソフトウェアの実装の良さ、ミスの多さを測るソフトウェア工学的な知識も必要とされます。……と、1つのシステムを作る上でも非常に多岐にわたる知識が必要とされます。これだけの知識がないとシステムがまともに構成できないというのはIT業界がまだ発展途上であることを示しているかもしれません。ノーコードやローコードと呼ばれる開発環境も出てきていますが、簡単なタスクや限られたデータに「お試し」で使ってみることはできても、その後、より規模の大きい業務システムに組み込もうとしたり、結果が想定通りにならず改善案を検討したりするときに、やはり上述のような知識が必要になってしまうのが現状です。
一方の「応用」は、知識を実際に活用するための力です。これを簡単な言葉で定義するのは非常に難しいのですが、無理を承知で試みますと、「論理的思考力」と、「うまくいくことが分かっているパターンの数」が大きな要素を占めると筆者は考えています。うまくいくと分かっているパターンを多く持っておくと、システムを開発する上でうまくいくか分かっていない部分だけに思考を注力することができ、労力を非常に節約することができます。かつ、最終的にできあがるシステムも良いことが多いです。囲碁・将棋における定石・定跡のようなものだと捉えていただけば良いでしょう。ただしパターン化が通用するのは一部のみで、残りは自分で考えなければなりません。また、パターンの組み合わせにも良し悪しがあります。そのあたりを補うために論理的思考力がどうしても必要になります。
プログラミング力の必要性
プログラミング力として求められる知識と応用力は非常に幅広く、一朝一夕には身につきません。そこから目を背けるように、「プログラミングは外注すればいいから業務知識の方が重要だ」とか、「単価の安いプログラマがプログラミングすればいいのであって、プログラミング力は必要ない」という趣旨のことが言われていると、しばしば漏れ伝わってきます。
その場合の筆者の危惧は、プログラミング力を軽視した結果、そもそも業務でも使いにくいプログラムを設計してしまっている、あるいは開発が非常に大変になる仕様を選択してしまっているため本来不要であったコストが異常にかかっているということです。
あまりプログラミング力が高くない人が仕様を決めるとどうなるという話をしましょう。これから話す話はいくらなんでもレベルが低いのでは? と思われるかもしれませんが、私がかつて勤めていたベンダーでもこのレベルの話は実際にありました。
EC(Eコマース)系のシステムを作っているとします。将来的な商品数Nは100万程度を想定すべきですが、開発時はNが1,000程度で開発をしているとします。ここで、N^2の処理を要するシステムが定義されたらどうなるでしょうか? 基本的な計算量の知識があればN^2の処理に非常に時間がかかることがわかります。当然そのような仕様は要件定義や外部設計のときにはねられてしかるべきですし、より計算量の少ない仕様を考えるべきです。しかし、計算量の概念がないと、しばしば誰も気づかないまま負荷テストが始まるまで放置され、そこで初めて問題が発覚したりします(負荷テストで気づくだけマシかもしれません)。それをなんとかするために出てくる仕様も、数日計算をする、マシンを増やすなど、システムを分割するなど、頓珍漢なアイデアしか出てきません。
他、実際にいろんな事例を見聞きしてきました。「画面を変更するだけだから1日でできるでしょ?」などと裏側の処理を全く想定できない程度ならまだ可愛いものです。メモリとディスクの区別がついてなかったり、「memcachedだとローカル変数にアクセスするより速いんですか?」という質問を受けたり(筆者はこういう場合もにっこり笑ってすごく基礎から説明するタイプです)。実際にシステムを作るということがどういうことかわかってなかったり、裏側で何が行われているのかわかってないがゆえに、非常に解像度の低い仕様の策定や提案が行われます。
このような誤った理解が横行している現場でプロジェクトがうまくいくことがあるならば、「わかっている人」からの指摘によって、このような仕様が開発前に排除されているからです。あまりに変なアイデアであれば指摘は容易ですが、中には高レベルな人でないと事前に指摘できないものもあります。筆者も何度も見逃してきました。
ソフトウェアの開発は難しいものばかりではありません。大体が易しいレベルの開発からなると言っても良いでしょう。だからといって、高レベルの開発ができる人が不要というわけにはいかないのです。ここでいう高レベルの問題には、システムのアーキテクチャの策定だったり、データベースの定義だったり、その後のシステムの作りやすさを決めるものが多数含まれます。
私はしばしば、システム開発の難易度を非プログラマに伝えるときに、多数の中学レベルの問題と少数の高校レベルの問題とがまじったテストの様なものだと例えます(実際に中学・高校レベルだと言いたいわけではなく、相対的な話をしています)。ただこのテストは少々変わっていまして、しばしば高校レベルの問題(アーキテクチャの策定など)が先にあり、その結果を用いて中学レベルの問題(大部分のプログラミング)を解いていくことがあります。普通の中学生がいくら集まったところで高校レベルの問題を解くことはできません。問題を解くための知識も足りないし、思考力も足りないからです。稀によくできる中学生がいて、どこからか高校レベルの知識を持ち込んだり編み出したりしますが、それは単に奇跡です。及第点を取るためには、高校レベルの問題が解ける人を連れてこなければならないのです。
また、中学レベルの問題ばかりやっていても、いつまでたっても高校レベルの問題を解けるようにはなりません。「わかっている人」側へ行くためには、一定のプログラミング力が付ける必要であることがおわかりいただけたかと思います。
