投稿日
最終更新日

中級プログラマにとっての奥義だと思うこと

対象読者

次のセクションで説明する個人開発の中級1〜中級2になりたいプログラマが対象です。

クヌースの言うように、「97%ぐらいの場合、小さな効率については考えるべきではない。早まった最適化は諸悪の根源だ。」ということで、最適化まではせずに正しく動作するプログラムがかけることを目指します。

世の中にあるプログラムはゲームやリアルタイム処理などを除けばほとんどは速度を求める必要が無い「正しく動作する」プログラムがかけるだけで充分なことが多いです。

管理人は昔、一定以上のサイズのコードが書けませんでした。 大抵どこかでバグが出て、二進も三進もいかなくなってしまっていました。 この記事では、それを乗り越えたときに必要な技術が何だったかを振り返って解説します。

プログラミングの段階について

異論、反論はあるかと思いますが、ここでは次のようにプログラマを分類します。 なお、ここで対象としているのはフロントエンドではなくバックエンドのプログラマが対象です。フロントエンドのプログラマにとっては、例えばHTMLなどはプログラムとしては抽象化力が低いため、この記事で述べるような対策が難しいからです。

プログラマの練度中身
初心者数十行のコードがかける
初級者数百行のコードがかける
中級1数千行のコードがかける
中級2数万行のコードがかける
中級3数万行のコードがかけ、速度を最適化できる
上級無制限のサイズのコードがかけ、速度を最適化できる

中級プログラマにとっての奥義だと思うこと(重要度の高いものから)

1.リファクタリング

管理人が大きいプログラムを書けるようになった理由を1つだけあげるとすれば、それはリファクタリングです。

リファクタリングにも色々ありますが、その中でも最も重要だと思うことを述べます。

ずばり、それは「2回以上同じコードを書いたら関数化して1つにまとめる」ことです。

もし、2回同じコードを書く場所が10ヶ所場合分け的にあったとしたら、2^10=1024通りの場合分けが必要になります。個人的には、8通りの場合分けぐらいでもうかなりタイプミスやロジックのミスなどでうまく動かすのが難しくなります。

計算量的な話をすると、2回同じコードを書いたら関数化することでO(log2 n)の記述量に抑えられます。もしバグがあっても、関数化しておけば1ヶ所直すだけで関係するすべての箇所のバグが直るので、開発効率もよくなります。

2.副作用をできるだけなくす

例えば戻り値がない、何かをする関数は副作用のある関数です。

具体的には、標準出力に「おはよう」と出力する関数は副作用のある関数ですし、グローバル変数を書き換える関数も副作用のある関数です。

なぜなら、おはようを出力する関数を2回呼び出したらおはようが2回表示され、3回呼び出したら3回表示されます。これは何度呼び出しても違う結果になります。

また、グローバル変数を書き換える関数は、その前後でグローバル変数を参照している部分に影響を与えます。

理想的には、関数は何度呼び出しても同じ結果を返すように設計すべきです。 ライブラリの設計上戻り値のない関数は避けられないことも多いですが、自分でコードを書く範囲では、戻り値のある関数を書くようにすべきです。

副作用については、色々なパターンがあるのでここで解説しただけでは充分でないですが、色々と調べてみてください。

3.テストコードを書く

リファクタリング、副作用の無いコードに続き、3番目に重要なことを聞かれたら、テストコードを書くことを管理人は推奨します。

実際の開発の現場では、使っているライブラリのAPIなどが変わることが多々あります。

APIの変更や、自前部分の機能の追加変更削除に伴って既存のコードが動かなくなることがあります。

数万行規模のコードになってくると、テストコードを書いていなければ、コードやAPIの変更時にどこが動かなくなったのか特定するのが大変になります。

また、2が大事な理由にもなってくるのですが、副作用のあるコードはテストを書くのを難しくします。

例えば午前はおはよう、午後はこんにちはという文字列をかえすコードがあったとして、もし関数内で日付を取得しているとすると午前中はパス、午後は失敗するテストコードになってしまう可能性がでてきます。

オブジェクト指向言語ならば、例えば日付オブジェクトを引数にすることで副作用がなくなり、テスト時に午前の日付を生成したものと午後の日付を生成したものでテストコードをかけば、うまいことテストコードを書くことができます。

まとめ

管理人が一番重要だと思うことは「2回以上同じコードを書いたら関数化して1つにまとめる」です。 今回紹介したこと以外にもカプセル化などのインタフェース設計やモジュール化、プログラムを疎結合にすることや、その他のリファクタリングなど色々と大事なことはありますが、まず一つ覚えるとしたら上記のものをオススメします。

特にバックエンドでの話ですが、フロントエンドでも利用するプログラミング言語によっては使える技術なのでぜひ挑戦してみてください。