❤️

汚いコードの害を伝えたいだとか

2024/09/19に公開

汚いコードはよくない

コードを書くと、コードは増える

プログラムは、ソースコードと呼ばれる文字列を記述する事で作成されます。このことを、単にプログラムを書く、コードを書く、などと言ったりします。

ほとんどの場合、プログラムを書くときには、その目的があります。
なにかの目的を達成するために、ソースコードと呼ばれる文字列を記述します。
この記述方法にはいろいろなものがあり、同じ目的を達成するにも無数の方法が存在します。
どの方法を選ぶかは作者に任されている、という言い方もできます。

ところで、ソースコードを記述していき、プログラムで実現できる事が細かくなるにつれて、文字の数はだんだんと増えていきます。

コードの増え方にもいろいろある

この文字が増えていく様子を比喩的に表現することを考えます。例えば書類を積み上げることや、積み木を積み上げるようなことで表現しましょう。文字の塊、積み木のようなものが、どんどんと積み上がっていく、というイメージです。

さきほど、同じ目的を達成するにも無数の方法が存在します と書きました。この方法には、例えばキッチリとした方法もあれば、乱雑な方法もあります。どちらも目的を達成できているとしても、直接的に目的を達成する以外の部分で微妙な差がある、というようなことです。

これを書類や積み木の積み上げで可視化すると、次のようなことになります。

常に同じ大きさの書類がきれいに積まれているのと、大小様々な書類が若干ぐちゃぐちゃしながら積まれているのと、というような見た目の違い。あるいは、積み木が整然とあまり隙間なく積まれているか、ぐらぐらして今にも崩れそうな感じで積まれているか、というような見た目の違い。
どちらの積み方も、今の時点で目的を達成していればそれで十分かもしれません。書類を保存するという事が目的であったとき、とりあえず書類がそこに存在していれば、最低限一旦はOKと言えるでしょう。
ただ、例えば書類を運ぶとなったら、ぐちゃぐちゃだと崩れてしまって運びにくいかもしれません。あるいは、今の積み木の上にさらに積み上げたいとなったら、ぐらぐらだと上に積み木を乗せられないかもしれません。

汚いコードはよくない

一般論として、新しい目的が発生したときに、今の状態から崩れにくい・積み上げやすい状態もあれば、崩れやすい・積み上げにくい状態もあります。 他に何の条件もなければ、崩れにくい・積み上げやすい状態をキープしておいた方が、新しい目的に対応しやすくてハッピーです。 これは、プログラム、ソースコードにも当てはまります。書類や積み木と比べて、視覚的な形ではわかりにくいケースもありますが、同じ目的に対して整然としたコード・乱雑なコードといったざっくりとした概念が存在して、バグを生みやすい・生みにくいという違いが生じます。バグを生みやすいのは当然良くないので、その意味で汚いコードは良くないです。

汚さ以外にも難しさの指標はあるし、レッテルを貼ってはいけない

コードを書く場合に難しいのは、「崩れにくい」と「積み上げやすい」が時に反する場合がある、という事です。「崩れにくい」というのは、なにか修正をした時に既存のプログラムが壊れないという概念だと思いますが、例えば文法によって安全な型が導入されていると、誤った代入などは生まれにくくなるでしょう。一方、複雑な型はしばしば型パズルなどと表現されるように、型によって改修がしにくくなるケースや、単純な修正の量としては増えてしまうケースもあります。これは「積み上げやすい」とは逆の状態を意味します。
あるいは、積み上げ方にもコツ(≒知識)があって、特定のコツを掴んでいる人にとっては積み上げやすいが、そうでない人にとってはとても積み上げにくい、といった場合が発生する事もあります。こうなると、もはや人によってあるべき状態が変わってしまい、ただでさえ可視化が難しいのに、何を目指すべきかがわからなくなってきます。極論では、単に自分の力不足で読めないコードに汚いコードとレッテルを貼る人もいたりして、そのようなあり方には逆に問題を感じます。

汚さとのトレードオフなどない、スポーツとのアナロジー

ただ、そうした難しい要素があるという前提で、それでも 良いコードを目指すべき です。
結果的に乱雑な状態になってしまう事は仕方ないとしても、意図的に書類を散乱させる人とは、その部分だけを見る限りでは、普通は一緒に仕事をしたくないですよね。もちろん、他にその人に良いところがあって、悪癖の一つという事であれば我慢することもあるでしょうが、一般論としては単純に書類を散乱させない仕事の仕方を覚えてもらった方が良いです。プログラミングもそうで、普通に良いコードを書く事を目指した方がいいです。十分な練習をした場合には、多くの局面で、良いコードを書く事とリリースまでのスピードはトレードオフの関係にはないです。単純に良いコードを目指した方が良いです。

スポーツで、なにか新しい技術を覚える時のことを想像してみてください。例えばバットを振る練習をするとき、一番最初は変な振り方で、しかもゆっくりしか振れないかもしれません。この状態では、ボールにあたっても飛距離が出ないでしょう。プログラミングで言えば、ゆっくり汚いコードを書いている状態です。
でも、練習をしたら、だんだんとスイングは速くなり、飛距離も出るようになります。これは、速く良いコードを書いている状態でしょう。
ただ、難しいのが、もしプロの指導者に付かずに独学で練習をしたら、変なクセがついてしまうかもしれません。これは、速く良いコードを書いていると思い込んでいるが、実際には速く汚いコードを書いているという状態です。速さと良さのトレードオフではなくて、単に変なクセでそうなってしまっているだけです。つらい。
スポーツでは、独学で独自理論を組み立てているが実際にはあまりうまくいかない、みたいな姿を簡単に想像できますよね。プログラミングでも確実にそうです。運がよい人は独学でもうまく行きますが、確率的に多くの人は何かしら変なクセがつきます。こうした変なクセは、意図的に修正していかないと一生直りません。

汚さに悪意はないし、汚くてもコードは価値を生む

一方、よほど悪意を持った人でない限りは、意図的に汚いコードを書こうという人もいません。単純に良い習慣が身についていないだけで、悪意はなくても汚いコードになってしまう、という事はよくあります。個人的には、ほとんどがごく単純に知識の問題であると感じています。
そのようなとき、単純に目の前のコードと向き合ってさくっと修正して、繰り返さないようにする。それを繰り返すことで、いま汚いコードを書くのと同等以上の速さで良いコードが書けるようになり、仕事の精度は一層向上していきます。
実際には、そこまで仕事の精度が向上しなくても、ビジネス的に当たればなんとかなる事が多いです。汚いコードだからビジネスに価値がないなんて事はないし、汚いコードを使うと会社が潰れるという事もないし、むしろ汚いコードでビジネスが成立しているのであれば、コードを改善すればさらに事業自体を拡張するような伸び代があるかもしれず、それは素晴らしいことです。

コードを書くプロとして

ただ、職人的な意味でのプロとしては、ごくごく単純に汚いコードを書く習慣を直し続ける・改善し続ける事が大事であり、モラルであり、誇りなんじゃないかなと思います。汚いコードへのある種の忌避感は持ち、しかしそれによって人や過去を否定することはせず、淡々と向き合って改善し続ける。
そういう事なんじゃないかな、と思いました。

おまけ

以下はおまけです。

同じ目的を達成するにも無数の方法が存在します、という事について本文ではコードの汚さに関連する部分のみを取り上げましたが、プログラミングをする上では他にも考慮すべき事があります。
その例として、コードを実行するのに必要なメモリの量や、時間という事があります。プログラムは計算機で動くので、計算機のリソースをどれぐらい使うのか、メモリと時間の観点で見よう、という事ですね。これの一つの指標として概算レベルで役に立つのが、空間計算量や時間計算量のオーダーです。
自分がなにかを実装するときに、まず方法をいくつか挙げられるか。それらの方法について、メモリの量や時間がざっくりとどれぐらいになるか。コード自体の分量、難しさはどうなるか。さくっと検討して、あるいはもし必要なら実際に書いて試したうえで、最終的にどれにするかを決める。かつ、その結論を覚えてなじませるようにする。こういう事を繰り返すと、自然と汚くないコードになっていきます。
逆に言うと、なにかを実装する時に、ぱっと実装方法を思いつかないけどとにかく頑張って無理やり書いてみると、だいたい最初は汚いコードが出来上がります。それで終わりにしてしまうかどうか。
たしかに、ものすごく短期的に見れば、そうした検討過程を除いて取り敢えず書き上がったもので終わりにすると速くコードを書けるように見えます。しかし、検討を繰り返していくと、最初は時間がかかるとしても、だんだんと自分の選択する方法や出力が安定して、スッと洗練されたコードが出てくるようになり、やがて最初に汚いコードを書いていた以上の速度で短く良いコードを書けるようになります。コードを書いて終わりではなくて、コードを書いた事を経て、最終的にあるべき良いコードを学習して次に生かせるようにしていく、という事を常に継続的に行う事が必要です。

できないよりはできる方がいい、これはものすごく当たり前です。まずは目的を達成できる事が大事です。
しかし、仕事においては「ギリギリできる事」だけを背伸びしてやる、なんとかがんばって一つの結果にたどり着く、みたいな事だけではなくて、必要に応じて準備や練習もしたうえで「自然に出てくる選択肢たちから、特にフィットしたものを選んで安定的にやっていく」という感覚も必要です。医師が治療法を提案するとき、事前の知識が何もなくて、そこからがんばって背伸びしてひねり出したたった一つの治療法がうまくいくケースもありえると思いますが、普通に事前に十分な知識を持っていて、いくつかの治療法が考えられる中で検討して最適なものはかくかくしかじかの理由でこれ、という風に提案してもらった方が良いですよね。もちろん、検討にめちゃくちゃ時間をかけ過ぎるのは問題かもしれませんが、このような検討がうまくできない場合は、単純に知識不足を疑った方が良いように思います。
こうした知識を獲得するサイクルがうまくできているか否かが、最終的な出力が汚いコードになるか否かと関連しているように感じます。その辺も、汚いコードへの忌避感につながるのかもしれません。

一方、良いコードという概念は非常に難しいと思います。良いコードの考え方の参考になるかもしれない記事を貼っておきます。

https://zenn.dev/339/articles/83caa21b9ad736

https://zenn.dev/339/articles/e3c174fdcc083e

https://zenn.dev/339/articles/ecc4986473ca88

Discussion