削除しやすいコードを書く
- すべてのコード行には保守コストが伴う。コードの再利用は変更を難しくする。
- API の利用者が多いほど、変更時に書き直さなければならないコードも増える。
- コードの依存関係を管理することは、大規模システムにおける重要な問題である。
0段階: コードを書かない
- コード行数は、それ自体では多くの情報を与えない。
- 書かなかったコードは、削除するのが最も簡単なコードである。
1段階: コードをコピペする
- 再利用可能なコードは、後から実例を通じてより簡単に書ける。
- コードのコピペは、依存関係を避けて柔軟性を得るための方法である。
2段階: コードをコピペしない
- コードが十分にコピペされたなら、関数として切り出すタイミングである。
util ディレクトリを作り、さまざまなユーティリティを別ファイルに置いておくのがよい。
3段階: さらに多くのボイラープレートを書く
- ボイラープレートはコードのコピペに似ているが、それぞれ異なる場所でコードを変更する。
- ボイラープレートは依存関係を減らし、柔軟性を提供する。
4段階: ボイラープレートを書かない
- ボイラープレートが多すぎるなら、ポリシー、ワークフロー、状態についての見解を持つライブラリでラップすべきである。
requests と urllib3 の関係がよい例である。
5段階: 大きな塊のコードを書く
- ビジネスロジックは、終わりのない例外ケースと速くて汚いハックによって特徴づけられる。
- 大きなミスを削除するほうが、小さなミスをいくつも削除するより簡単である。
6段階: コードを断片に分ける
- 大きな塊のコードは保守コストが大きい。
- コードの責務を分離し、変更可能性を考慮してモジュールを設計すべきである。
7段階: 書き続ける
- 新しいアイデアを試せるよう、既存コードとは独立して新しいコードを書けるようにすべきである。
- フィーチャーフラグは、後で気が変わっても対応できる方法である。
GN⁺のまとめ
- この記事は、コードを書く際に削除しやすいコードを作る方法について説明している。
- コードの依存関係を減らし、柔軟性を高め、保守コストを下げることが核心である。
- 類似した機能を持つプロジェクトとしては
requests と urllib3 がある。
- この記事は、ソフトウェア開発者にコード管理と保守の重要性を改めて気づかせてくれる。
1件のコメント
Hacker Newsの意見
「Simple is robust」という言葉が気に入った。システムの複雑さが少ないほど、変更しやすいという意味だ。将来に向けた計画は、拡張可能なコードよりも直感的なコードで立てるべきだ。たとえば、状況が要求したときだけ抽象化し、単純な重複を許容し、初期段階ではモノリスを使い、水平スケーリングよりも垂直スケーリングを優先する。複数の 0→1 システムを構築する中で、こうした共通点を見いだした。
テストや可観測性への言及がないのは驚きだ。テストには保守コストがかかるが、コードを削除するときに問題が起こるリスクを減らしてくれる。外部の呼び出し元にサービスを公開する場合は、一部の呼び出しを廃止予定としてマークし、それでもまだ呼ばれているかを観測する強力な方法が必要だ。最近、GraphQL リゾルバを半自動で削除したが、使用頻度のメトリクスによって削除できないリゾルバを把握した。GraphQL には廃止予定アノテーションがあるが、サービス側では特別な扱いをしていなかった。可観測性を追加して、廃止予定の関数が呼び出されたかどうかのフラグを立て、十分に長い期間プロダクションで動かしたあとで、外部公開されたコードを安全に削除できる。
「削除のための設計」を推したくなる。昔は、あらゆる状況を計画し、あらゆる要件を満たす作品を作れると思っていたが、将来のニーズを予測するのは難しい。いつか自分が作ったものは誰かにとって不要になり、その人がそれを取り壊すのが正当化される日が来る。だから、取り除きやすく作ることに力を注ぐべきだ。これはしばしば結合を減らすことにつながるが、何でもメタ構成可能なフレームワークに分解したがる若い開発者の発想とは違う。論理的に理解しやすいなら、密結合のほうが良いこともある。
コードを削除しやすく書くには、依存関係を避けるために重複させ、管理のために重複させないことだ。コードを層に分け、実装は簡単だが使うには不便な部分の上に、シンプルな API を構築するべきだ。コードを分離し、書くのが難しい部分と変更されやすい部分を、残りのコードから互いに切り離すべきだ。すべての選択をハードコードせず、実行時にいくつか変更できるようにしておくべきだ。個人的な経験では、削除しやすいコードは階層化・モジュール化されていて、拡張もしやすい。
計算物理学の学生たちには、最高の計算とは気にかける必要のない計算だといつも言ってきた。
個人的には、コードをビジネスロジックと実際の実装に分けている。ビジネスロジックはその性質上、重複していてもよいが、技術的な詳細が過度に重複してはいけない。ビジネスロジックを直接扱わず、アプリケーション非依存に保っている限り、ビジネスロジックは好きなだけ混沌としていて構わない。問題が起きてうまくいかない場合でも、実装全体を削除するという選択肢があり、それを修正したり、実際の仕様を実装から探し出したりすることを強いられない。
最初の段落には明らかな誤りがある。コード再利用の問題は、後で気が変わったときの妨げになるという点だ、という主張だ。これは一般には誤りだ。考えを変えたとき、コードが 10 か所にコピー&ペーストされていたら、10 か所を変更しなければならない。一方で、コードが関数になっていれば 1 回変更するだけで済む。10 回の呼び出しのうち 1 つだけ変えてはいけないとしても、なおコピー&ペーストはできるし、関数をより汎用的にすることもできる。道を渡るときに周囲を見ないのと同じで、コピー&ペーストはほとんど常に悪い考えだ。
悪いコードは削除しにくいからこそ長く残る、という見事な相関がある。
ソフトウェアはできるだけ素の状態で使い、深いカスタマイズをしないほうがいい、という意味なのだろうか。