ソフトウェアエンジニアの福井です。
前職含めて様々なオーバーエンジニアリングを目の当たりにし、また自身で設計実装してきました。
オーバーエンジニアリングにはオーバースペックな技術やテクニックを使うことや、誤ったビジネス戦略からくる過剰な仕様を満たすこと、善意によるニーズを超えた機能拡張などのケースがあります。
今回オーバーエンジニアリングというワードを、"将来を見越しすぎた設計をすること"にフォーカスし、色んな観点から考えます。
最初に将来を見越しすぎた設計の具体例があると以降の説明がしやすいため、まず具体例をいくつかあげます。
オーバーエンジニアリングのパターンと具体例
抽象化、汎用化、共通化を目的とした結果、オーバーエンジニアリングになってしまうケースがあります。これらのパターンについて解説します。
抽象化
具体例
ある為替レート取得API xxから別のAPI yyに乗り換えるかもしれないので、xxとyyを抽象化した"為替取得クライアント"という層を独自実装する。結果として、- 抽象化層の存在でコードの見通しが悪くなる
- 実際に乗り換えたとしても正しく抽象化できておらず、結局抽象化層に手が入る
考察
抽象化層は変更コストを下げる一方で、抽象化層自体が負担になります。実際の乗り換えが強く想定されない限りは、この例では為替レート取得API xxのためだけの実装をすべきでしょう。
汎用化
具体例
利用側都合のプライベートAPIを将来他の箇所からも使われることを期待し、汎用的なエンドポイント名と作りにする。結果として、考察
コードが再利用可能であればあるほど、使いづらいものになると言われますが、APIレベルでも同じことが言えるでしょう。
共通化
具体例
初めてある計算ロジックを開発したが、他の箇所で使われることを期待しAPI化する。結果として、- 結局どこからも使われず、APIの開発運用コストだけが残る
考察
重複箇所が3回出てきたら共通化する、という経験則が適用できるでしょう。ただ偶発的な重複かの見極めは必要です。
なぜオーバーエンジニアリングは悪いのか
プロダクト、サービスのデリバリーコストが上がり、品質が悪くなる
プロダクト、サービスの設計がシンプルでない分、理解しにくくなります。そのため開発量が多くなるのに加え、開発に時間がかかり、バグの温床にもなります。その見越しすぎた将来が来たとしても、当初の設計が最適とは限らない
当初の設計が将来の業界トレンドや新技術を踏まえて最適とは限りません。見越しすぎた設計が将来固定化され、変更を阻害する場合もあります。未知の未知に対応できない
既知の未知を見越して設計できても、結局未知の未知を見越せません。極端な例だと、コストをかけてオーバーエンジニアリングする -> コロナ禍 -> 業績悪化 -> コストカットのためサービス廃止、と、かけたコストが無駄になる例も考えられます。
なぜオーバーエンジニアリングしてしまうのか
個人の経験不足やビジネス<技術寄りのマインド、ビジネスの理解不足が原因とよく言われます。他にもプロダクトを将来スケールさせる熱意から、オーバーエンジニアリングしてしまうケースもあります(ビジネスの理解不足に入るかもしれませんが)。
では将来を見越した設計は全て悪いのか
そんなことはありません。
プライベートネットワークのCIDR設計やコアデータのDBテーブル設計などの戻りにくいところは、ある程度将来を見越して設計することに価値はありますし、これはオーバーエンジニアリングではありません。
他にも例えばGoogleが公開するAPI設計パターンで、リストを返すパブリックAPIは最初からページ分割サポートを推奨しています。 *1
では見越しすぎた将来が実際に来たらどうするか
その時に設計含めたリファクタリングをする他ないでしょう。ただ設計レベルからリファクタリングするのはコードレベルのリファクタリングに比べてコストが大きいため、腰は重くなります。それでも結果としてオーバーエンジニアリングするよりはコストの期待値は低いでしょう。
リファクタリングのタイミング
『マイクロサービスアーキテクチャ 第2版』*2で、UIごとに1つのBFFを追加するとコード重複の懸念があるという文脈で、重複箇所が3回出てきたら抽象化を作成する経験則が優れているという記載があります。これは他の設計レベルのリファクタリングでも適用できると思います。例えば実装時に設計の歪さを数回感じたら、そのタイミングでリファクタリングする、などです。
オーバーエンジニアリングかどうかの議論の落とし所
元の設計から変更できるかを含めて、特に大きな問題がなければ基本的に元の設計のまま進めるのが良いかもしれません。
『ソフトウェアアーキテクチャの基礎』*3でJavaベースのプロジェクトでScalaを使いたがる"Scala愛好家"の話があります。この話は将来を見越す関係なく特定の技術が使いたい人の例ですが、最終的にはビジネスとのトレードオフでScala愛好家本人も納得した形でScala導入を断念し、本人はプロジェクトに大きな貢献をした、という話です。ただ現実のオーバーエンジニアリングかどうかの議論は、このようにうまくいくことは少ないと思います。
自身がオーバーエンジニアリングしないためには
自身で設計したプロダクト、サービスに中長期で携わり、将来を見越しすぎた設計の問題を自身で実感するのが一番効果的だと思います。そうすることで匙加減がわかってくるでしょう。ただ自身の設計を振り返ったり、問題を見つけることが前提あります。
今回、将来を見越しすぎた設計について、具体例をあげつつ色んな観点から考えました。オーバーエンジニアリングに立ち向かう人の思考の材料になれば幸いです。
*2:Sam Newman (2022, November 30). マイクロサービスアーキテクチャ 第2版. 株式会社オライリー・ジャパン
*3:Mark Richards, Neal Ford (2022, March 4). ソフトウェアアーキテクチャの基礎. 株式会社オライリー・ジャパン