コンテンツにスキップ

「カレーを作るな、カレールーを入れた煮込みを作れ」:超新人エンジニア向け 抽象化と命名の話

チェック

  • [ ] 本文を確認した
  • [ ] 概要を確認した
  • [ ] タグを確認した
  • [ ] inbox/ 直下へ移行した

概要

新人向けに、抽象化と命名を「カレーを作る」ではなく「カレールーを入れた煮込み料理を作る」と考える比喩で説明する記事。 特定用途に密着した名前や処理は再利用しづらく、変更時に修正箇所が増える。 一方で抽象化しすぎると意味が曖昧になるため、操作と対象を適切に分ける命名が重要。

本文

問題のコード

新人コードでよくある例として、カレー専用の処理が挙げられている。

function makeCurry() {
  cutCarrot();
  cutPotato();
  fryMeat();
  addWater();
  boil();
  addCurryRou();
  boilMore();
}

一見わかりやすいが、カレー専用すぎて他に使えない。

発想を変える

人間は「カレーを作る」と考える。 しかしプログラムでは、「材料を切って煮込んで、最後に味付けする処理」と捉える。

つまり、カレーを作るのではなく、「カレールーを入れた煮込み料理」を作っていると考える。 そうすると、カレー、シチュー、ポトフ、トマト煮込みに共通する部分を切り出せる。

抽象化したコード

記事では、煮込み料理を作る処理として抽象化している。

function cookNikomi($zairyoList, $ajitsuke) {
    $kitta = kiru($zairyoList);
    $nikonda = nikomu($kitta);
    return ajitsuke($nikonda, $ajitsuke);
}

この形なら、味付けを引数で変えられる。 カレー専用ではなく、シチューやポトフにも使える。

命名の考え方

悪い命名は、対象が特定のものに依存しすぎる。

makeCurry($zairyoList);
cutCarrot();

よい命名は、操作を表し、対象は引数で変える。

cookNikomi($zairyoList);
kiru($carrot);

「ニンジンを切る」ではなく、「材料をカットする。何を切るかは引数次第」と捉える。

抽象化しない失敗としすぎる失敗

抽象化しないと、似た処理が増える。

makeCurry();
makeStew();
makeHayashiRice();

共通する改善を入れるとき、すべての関数を直す必要が出る。

一方で、抽象化しすぎると何をしているか分からない。

processZairyo($zairyoList);
cookingProcess($zairyoList);
makeMeal();

広すぎる名前は、処理の中身を想像しにくい。 切る、炒める、煮込むのように、意味のある操作単位で名前をつける。

要点

  • 「何を作るか」ではなく「どんな操作をしているか」を見ると抽象化しやすい。
  • 対象を名前に埋め込みすぎると、再利用できず変更に弱くなる。
  • 抽象化しすぎると、今度は処理の意味が見えなくなる。
  • 良い命名は、操作を表し、具体的な対象は引数やデータで受け取る。

タグ

abstraction #naming #beginner #programming #software-design