普段思ったことや、雑記。

Menu & Search

クソコードとは何であるか

2020年11月21日

そういえば、クソなコードの存在について、ああ、これのことか…と思うことがこれまでに何度かあったが。
では、どうであればそれはクソなコードと言えるのか、真面目に考えたことがなかったので、自分なりに定義を考えてみた。なるべく、重症そうな順に列挙してみる。

クソコードの特徴

1. 関数の入出力の定義が不明

関数とは、ある処理内容を1つの手続きとしてまとめたものである。関数化をするプロセスとして、ある決まった処理内容をまとめるまでは何の問題もなく良いことであるが、何の値を入れると、何の値を出すのか、デバッグをしないと不明なまとめ方をされてしまうと、後任者は困ってしまうだけである。

これをノーヒントでデバッグしろとか言う奴は、基本的には自分のケツも自分で拭けない奴なんだな、と思うのみで、憐れみの対象である(※このような自負の高い開発者はまれに見る)。そんなものは自分でデバッグしろ、が言えるのは、少なくとも処理系のI/Oが担保されている状態であって、I/Oが不明なものは実装担当者の実力不足、もしくは怠慢でしかない(※日本のIT現場によくある、多重下請け構造などの開発を除く)。

2. 不適切な抽象化

抽象化とは、Web開発でいうメジャーな抽象化パターンだとORマッパーであろうか。ORマッパーは、データストアのリソースをプログラムのクラスやオブジェクト等にアサインし、SQLなどのデータベースに対する問い合わせを言語をダイレクトに記述することなく、抽象化機構から問い合わせをしよう、というものだ。

抽象化に成功すると、よく似た機能A, B, Cがあるとし、この3つが関連する箇所を抽象化した場合にソースコードの総量が減ったり、似たようなロジックがそこら中に散る、みたいな状況を避けられるため、成功時のメリットはプログラムの運用観点で恩恵が大きい。

一方で、抽象化に失敗すると、何をしているのかが一見してよく分からなくなる。抽象化しすぎた結果、抽象的過ぎてコレは何をしているのかすぐに分からねえ(具体的処理内容を追うのに時間を要する)…という事態に陥る。
経験上、OOP大好き人間が、アプリケーションで頻繁に使わざるおえないような、『オレオレ規定クラス』を実装したりで、それがそもそも分かりにくい、とか。あるいは、OOPにおいて継承を多用した結果、多くのコードで多重継承の様相となり、覚えゲーが発生してしまうことが起こりがちである(世の中には、OOPが大して好きではない人間もいるのを覚えておいて欲しいのだが…)。

あとは、またORマッパーの話に戻るが、あれもオブジェクト、これもオブジェクト、みんなオブジェクト!…みたいな、オブジェクトを愛してやまない人が、オブジェクトをやたら拡張してみたりして、気がついたらオブジェクトがだいぶ肥えている、というパターン。
しかし、この場合、たしかにオブジェクトは肥大化してしまってはいるものの、逆にオブジェクトを見ればそこに何か書いてある、ということから、読む立場になった場合には、前述のオレオレ基底クラスによる不適切な抽象化よりだいぶマシなほうかもしれない。

ところで、最近技術者の先輩に教えてもらった法則で、ヴォルトの法則というものがある。ハードウェアとソフトウェアが交差する話ではあるのだが、ハードウェアが高速化したとしても、ソフトウェアを抽象化しすぎたらかえって全体のパフォーマンスは悪くなるよね、という話である。抽象化をする、という作業は本人は、んん!!ぎもぢっぃい!!ことなのかもしないが、それはソフトウェアの処理速度低下にも貢献もしている可能性があるというのは、コンピュータと地球環境に優しい開発者としては覚えておきたいものだ。

3. プログラムのグローバルな名前空間において、関数や変数の宣言、参照を多用する

関数やクラスをファイルとして都度ロードしたくないだとか、思想的な理由なのか、良くわからないが、本来は常にメモリ上に存在し続けなくてもよい変数や関数、クラスのインスタンスなどが、やたらグローバルのスコープに滞留しまくる、という設計のことである。

これをやると、定常的に使用される主記憶の量が割増になってしまい、コンピュータ資源がもったいない(※例えば、ガベージコレクションが実装されている言語系では、データの内容にもよるが大量データ処理などで、一時的にメモリ総量が必要な処理がある場合に不利が発生しやすいだろう)。現代的なコンピュータの仕組みでは、CPUやメモリなどのマシンリソースを効率よく取り扱うような仕組みが実装されているのが、ノイマン型コンピュータのウリであるので、その機構を阻害してしまうような実装は好ましくない。

4. 実装担当者に内容を聞いても、正しい答えが返ってくることがないソースコード

実装担当者自体がバグであったという、まさかの真のラスボスがいた、というパターン。多重下請け構造の超大規模の、カオスな環境を除き、未熟な開発者が前任だとこれはあるため、その場合は例外である。

5. 過去のソースコードの残骸がコメントアウトされて残っている

使おうと思ったけど、使わなかった。でも、なんとなく残っているコメントのことである。コメントにTODOなど、適切なラベルであったり、経緯が分かる内容の記載があれば当然問題はないものである。

クソコードを増やさないためにできること

自分が書いたプログラムは、『バックグラウンドの異なる』開発者が見たときに時間をかけずに理解できるか、考えることだろうか。あとは、当然ながら、コンピュータ資源を必要以上に使用しない実装を心がけることか。

バックグラウンドの異なる、というのが特に重要で、最近は特にライブラリ・フレームワークを使用して開発、みたいなシーンは当然のようになっている。特にWeb開発の業界にいると、技術の流行り廃りが激しく、3年スパンくらいで技術のトレンドが変わってくる。

よって、一過性の流行りのフレームワークに則ったルールで語られても、それが特異な可能性もある。そういった意識付けがある開発者は全く問題ないが、一方でそうでない方も多い気がする。
選定フレームワークが抽象化に積極的なモノを選定していた場合、だいぶそのフレームワークの思想に毒されている可能性があるので、『流行っているフレームワーク・ライブラリだから大丈夫』という固定観念は一度捨て、自分なりの第三者に分かりやすいコードは何か、という尺度を持って開発に取り組みたいものである。

Article Tags
mmiyauchi

プログラムを書きながらTranceを聴くのが良いですね。みなさんも聴いたほうがいいですよ、Trance。EDMよりハードトランスでしょ。

Related article

Redux(react-redux)における適切な配列要素の更新

2021年8月23日…

CloudFlareの『SSL/TLS 暗号化モード(HTTPS通信設定)』を使用したとき、『ERR SSL VERSION OR CIPHER MISMATCH』のエラーでChromeで発生し、接続できない場合の対処

英語の記事は見当たっ…

Dart(Flutter)についての所見

Dart(Flutter)についての所見

第一印象では、クロス…

Discussion about this post

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

Type your search keyword, and press enter to search