Simplicityの重要性: 捨てることの難しさ

Oct 9, 2024

It is better to do the right thing wrong than the wrong thing right.

間違ったことを正しく行うよりも、正しいことを間違って行う方が良い。

(引用元:https://thesystemsthinker.com/transforming-the-systems-movement/)

はじめに

プロダクト開発において、Simplicity(シンプリシティ)は非常に重要な要素です。

ラッセル・エイコフ曰く、間違ったことを正しく行うよりも、正しいことを間違って行う方が良いとされています。これは人々が間違っていることをより正確に行えば行うほど、より間違った方向に進んでしまうということを意味しています。


多くの人が、「この機能は複雑そうだけど導入すればきっとうまく行きそう」「新しい機能を追加すれば複雑にはなるけどなんか良くなりそう」といった形で目の前に掲げられた目標を正しく作業することに没頭し、結果としてプロダクトが複雑化してしまったという経験があるのではないでしょうか?


一度複雑になってしまったプロダクトから複雑性を取り除くことは非常に難しく、またプロダクトが成長するにつれてより簡素化することが難しくなります。

この記事では、Simplicityの重要性と、Simplicityを保つことの難しさについて考察します。

Simplicityとはなにか

Simplicity

1. the fact that something is easy to understand or do何かが理解しやすい、または行いやすいという事実2. the fact that something is ordinary, traditional, or natural, and not complicated何かが普通、伝統的、または自然であり、複雑でないという事実3. the fact that something is plain and has no decoration何かが平凡で装飾がないという事実

(出典:Oxford Learner's Dictionaries)

プロダクト開発における複雑になりがちな課題

以下にあげるものはプロダクト開発において複雑になりがちな課題のほんの一部であり、Simplicityを保つ為に意識しなくてはいけない点は多岐にわたります。

不必要なステップや操作の追加

顧客がサービス上で目的を達成するために、不必要なステップや操作を要求すべきではありません。

顧客体験の視点から見て無駄な手順を排除することはサービス利用を促進すための重要な要素です。また、システム開発の観点でも無駄なステップや条件分岐が増えることは、開発速度を遅くし、メンテナンスコストを増やす要因となります。

複雑な契約体系

顧客向けの契約やプランの分岐が最小限であり、理解しやすい形であるべきです。

契約体系が複雑な場合、顧客がサービスを利用する際に混乱を招くだけでなく、サポートやカスタマーサクセスの負担も増えてしまいます。また、契約ごとに制約条件やフック処理を入れるなど、システム開発の観点からも複雑さが増す要因となります。

複雑な条件

機能を利用するための条件は最小限であるべきです。

ある機能を利用するためにはAとBという条件が必要である、というように複数の制約条件を組み合わせたビジネスロジックの設計がしばしば行われます。

条件が多くなると、システム全体のメンテナンスコストが増え、顧客や運用者にとっても理解しづらく、運用が困難になるリスクがあります。

不必要な機能追加

価値を提供するために、真の必要性がない機能や仕様を追加すべきではありません。

機能追加が多い場合、それぞれの機能に対してテストやメンテナンスが必要になります。また、追加した機能は将来的に削除が難しくなり、システムの複雑さが減りにくくなります。

限られた顧客への対応

特定の顧客のために過度なカスタマイズや条件分岐を追加すべきではありません。

特定の顧客に対応するためのカスタマイズが多い場合、それぞれのカスタマイズに対してテストやメンテナンスが必要になります。

過度な技術採用

使用するライブラリやフレームワークが多すぎたり、過度に大きなものを導入すべきではありません。

ライブラリやフレームワークが多すぎる場合、長期的にそれらをメンテナンスすることが非常に困難になります。使用する技術が過度に大きなものの場合、不要な機能や実装が増え、システム全体が不必要に複雑化することもあります。

重複コード

同じ機能を実現するためのコードが重複せず十分に再利用すべきです。

重複コードが多い場合、同じ機能に対して複数の修正が必要になります。

未来に対する過度な対応

不確定な未来の要件を見越して、過度な抽象化や拡張性の追加をすべきではありません。

過度な抽象化や拡張性を持たせることは、開発速度を遅くし、メンテナンスコストを増やす要因となります。

過度なインフラストラクチャ

機能を実現するためのインフラストラクチャが過度に提供されるべきではありません。

インフラストラクチャが過度に提供されている場合、金銭的なメンテナンスコストが増えるだけでなく、開発速度も遅くなります。

捨てることの難しさ

捨てることは作ることよりもはるかに難しいです。

感情的な愛着

時間をかけて築き上げたコードや、長年使用してきた運用プロセスに愛着が湧くことで、それを捨てることに抵抗感が生じることがあります。しかし、Simplicityの重要性で述べた通り、複雑さはプロダクトの価値を最大化する上での障壁となります。

私の経験から述べると、そのような理由で残しておいたものの多くは、将来的にも障壁となったままずっと放置されることが多いです。

将来への過度な期待

いつか必要になるかもしれない」という考えは不要な機能を捨てられない原因となります。

しかしほとんどの場合、その「いつか」は訪れることはありません。たとえ必要になったとしても、その時には別のより良い方法が見つかることが多いです。

顧客離れへの恐れ

特定の顧客のニーズに対応するために追加した機能を削除することは、顧客離れのリスクを伴います。

しかし、プロダクトの価値は、限定された顧客のニーズに応えることではなく、より多くの顧客のニーズに応える機能を提供することであるべきです。

複雑で難解なコード

複雑なビジネスロジックや、理解しにくいコードが残っていると、それを削除することが非常に難しくなります。

とくに、テストのないコードや、他のコードと密結合しているコードは、削除することが難しくなります。

最後に

私もしばしば、シンプルでないビジネスロジックを設計したり、複雑な仕様をシステムに組み込んだり、感情的に複雑さを残してしまうことがあります。

しかし、一度複雑になってしまったプロダクトから複雑性を取り除くこと痛みを伴います。可能な限り最初の段階から、不要なものを捨ててSimplicityを保ち続けることが重要です。

迷ったときはシンプルな方を選択しましょう。