この記事は Zenn に投稿した記事 の転載です。
はじめに
初めての投稿です。
未経験からエンジニアを始めて1年が経ちました。
さて、
エンジニアになり、プログラミングを学び始めると、どこかで一度は耳にする言葉があります。
「コードは短い方(簡潔な方)が良い」
本当でしょうか。私はこの間、自分の書いたコードと模範解答っぽいコードを並べて、この言葉を疑うことになりました。
題材は、よくあるマッチ棒の問題です。
マッチ棒の正方形問題
マッチ棒で正方形を横に並べて作ります。
1個目の正方形には4本必要で、2個目からは辺を1つ共有できるので3本ずつ足せばいい。「正方形をn個作るのにマッチ棒は何本必要か?」という問題です。
_ _ _
|_|_|_| ← 正方形3個 = 4 + 3 + 3 = 10本
私の頭に浮かんだのは、式というより動作でした。4本で1つ目の正方形を作って、3本ずつ足していく——その手の動きがそのままコードになりました。
~①思考のコード化~
function countMatchsticks(squareCount) {
const FIRST_SQUARE = 4; // 最初の正方形は4本
const STICKS_TO_ADD = 3; // 2個目以降は3本ずつ足す
let total = FIRST_SQUARE;
for (let i = 0; i < squareCount - 1; i++) {
total += STICKS_TO_ADD;
}
return total;
}
先述した「1個目の正方形には4本必要で、2個目からは辺を1つ共有できるので3本ずつ」を、まさに動作の単位でコードにしていますよね。
一方で、この問題にはもっと短い書き方があります。
~②短い書き方~
function countMatchsticks(squareCount) {
return 3 * squareCount + 1;
}
どちらも同じ答えを返します。では、どっちで書くべきなのでしょうか。
2つのコードを読んだとき、頭の中で起きたこと
正直に白状します。
長い方のコードは、読んだ瞬間にマッチ棒が見えました。4本で正方形を作って、3本ずつ足していくあの動作が、コードの上にそのまま乗っている。だから読んだだけで正しさが分かった。
短い方は違いました。3 * squareCount + 1 を見ても、マッチ棒は浮かばなかった。ではどうやって「これも正しい」と納得したかというと——同じ数字を入れて試したんです。n=1なら4、n=2なら7、n=3なら10……よし、合ってる。
ここに大事な非対称があります。
- ①思考のコード化:読めば分かる
- ②短い書き方:検算しないと信じられない
短いコードは、正しさの確認という労働を、読む側に外注しているのです。
変数名を付けてみると、残酷な差が出る
この差をもっとはっきり見る実験があります。
両方のコードに、意味のある名前を付けてみることです。
長い方は簡単でした。FIRST_SQUARE(最初の正方形は4本)、STICKS_TO_ADD(2個目以降は3本)。コメントを全部消しても、変数名だけでマッチ棒の世界が語れています。
では短い方は?
3 はまだ「1個あたり3本」と名付けられます。でも + 1 に付けられる名前がないんです。マッチ棒の正方形の世界に「1本」という実体は存在しません。「1本」は工程だからです。
あの +1 は、4本の正方形を「3本 + 1本」に分解した計算の残滓でしかない。
つまり短いコードは、変数名で意図を表現しようとした瞬間に破綻します。意図がもうコードの中に残っていない証拠です。
では「短いは正義」は完全に間違いなのか?
ここで面白いのは、数学の世界だと結論が逆転することです。
数学なら間違いなく、展開し切った 3n + 1 の方が良い。
なぜ正解が逆転するのか。
数学の 3n + 1 は、そもそも命題を立てて、論法を使って証明した結果として出てくるものです。「なぜこうなるか」という物語は、式の外側——証明の過程——に保管されている。だから式自体は限界まで削ぎ落として美しくしていい。物語は別の場所にちゃんとあるからです。
コーディングはそうじゃない。
たとえば、
半年後にこのコードを初めて開いた同僚(あるいは未来の自分)が読めるのは、コードとそれに付随するドキュメント、あとコメントくらいです。
証明ノートは添付されていない。だから物語(=設計者の意図)は、コードの中に残すしかない。
-
4 + (n-1)*3は、証明を式の中に畳み込んだ形 -
3n + 1は、証明を捨てた形
「短いコードが正義」という思い込みの正体は、物語を外部に持てる数学の美学を、物語を内部に持つしかないコードの世界に、そのまま輸入してしまったものだったのです。
結論:どっちで書くべきか
ここまで物語肯定主義のように話してきましたが、一度フラットに考え直します。
「短い=正義」でも「長い=丁寧」でもありません。問うべきはこれです。
「このコードを次に読む人に、何を伝えたいか」
動作の物語を伝えたい場面なら、手順が見える形で。答えだけで十分な場面(証明済みと共有されている、あるいはコメントやテストが物語を別途保管している)なら、短い形で。
初学者のうちは、自分の書いた「長いけど動作が見えるコード」を恥じる必要はまったくない、というのが今回の私の結論です。
おまけ:この話の続き
今回の話は、突き詰めると「意図をコードに残すか、消すか」という選択の話です。
では逆に、意図をわざと消したい場面があるとしたら・・?——実はあるんです。
難読化やセキュリティの世界。
その話はまた別の記事で。