最近、「ソフトウェア設計の哲学」を読み終えました。第 2 章では、ソフトウェアの複雑さのトピックが検討されています。
書籍「A Philosophy of Software Design」では、複雑さを実際的に次のように定義しています。
「複雑さとは、理解や変更を困難にするソフトウェア システムの構造に関連するものです。」
言い換えれば、複雑さにはさまざまな形があり、必ずしもパフォーマンスと関係があるわけではありません。コードはパフォーマンスが高くても複雑である可能性があります
この記事では、この本からいくつかの重要な定義と洞察を共有したいと思います。しかしその前に、おそらくあなたがすでに経験したことがある一般的な状況を想像してみましょう…
皆さんの多くがおそらく経験した、あるいはこれから経験するであろうホラーストーリーに飛び込んでみましょう。
それはシンプルな CRUD タスク管理アプリから始まりました。コードはクリーンでモジュール化されており、メンテナンスが簡単でした。開発チームは満足しており、システムは最初のクライアントに対して完璧に機能しました。
問題は、営業チームがカレンダーの統合、電子メール通知、優れたレポート生成機能を備えていると主張して、システムを大企業に販売したときに始まりました。販売が完了したため、これらの機能を迅速に実装する必要がありました。
カレンダーの統合: チームは Google カレンダーと Outlook を統合する必要がありました。さまざまな開発者がソリューションを実装したため、一貫性のないアプローチが発生しました。
メール通知: 次にメール通知が追加されました。ある開発者は特定のライブラリを使用し、別の開発者はカスタム ソリューションを作成しました。アプローチが混在しているため、コードがわかりにくくなっています。
レポート ジェネレーター: レポート ジェネレーターでは、開発者は PDF、Excel エクスポート、対話型ダッシュボードなどのさまざまなテクノロジを使用しました。統一されたアプローチの欠如により、メンテナンスは悪夢のようなものになりました。
複雑さの増大: 各機能は個別に迅速に開発されたため、機能間の依存関係が生じていました。開発者は、すべてを機能させるために「クイックフィックス」の作成を開始し、システムの複雑さと結合を増大させました。
ソフトウェア開発は単独で行われるわけではありません。さまざまな内的および外的要因が影響します。私たちは皆、このような状況にこれまでに経験したことがありますし、これからも同様です。
その後、問題が始まりました:
私たちが現在複雑なシステムを持っていることは明らかです。
ここで、この複雑さを「分析」して、簡単に特定して緩和できるようにしましょう。
「緩和」とは次のことを意味します:
「重度、深刻、または痛みを軽くする; 軽減する。」
コードには複雑さがつきものであることが多いと思います。本質的に複雑なものもあります。開発者としてのあなたの役割は、コンピューターが効率的に実行できるコードを作成するだけでなく、将来の開発者 (将来の自分自身を含む) が作業できるコードを作成することでもあります。
「複雑さを制御することは、コンピューター プログラミングの本質です。」
— ブライアン・カーニハン
前述の本の著者は、複雑さは通常 3 つの方法で現れると述べています。
一見単純な変更に多くの異なる場所での修正が必要な場合、変更の拡大が発生します。
たとえば、プロダクト所有者が「優先度」または「完了日」フィールドを要求し、エンティティが密結合している場合、いくつの変更を加える必要がありますか?
認知負荷とは、開発者がタスクを完了するために必要な知識と時間を指します。
次のシナリオを想像してください。新しい開発者がチームに加わり、レポート ジェネレーターのバグを修正するよう割り当てられました。このタスクを完了するには、開発者は次のことを行う必要がありました:
これは古典的な「推定不可能」シナリオであり、タスクに 1 ポイントまたは 8 ポイントがかかる可能性があります。D20 をロールして、それに応じて対応する方がよいでしょう。
未知の未知とは、自分が何を知らないのかが分からないことです。
これは複雑さの最悪の現れです。変更してはいけないものを変更してしまい、すべてが壊れてしまう可能性があるからです。
例: 開発者は、その関数に依存するレポート ジェネレーターに影響を与えることを知らずに、電子メール送信コードを変更して新しい通知を追加しました。これはクライアントに重大な問題を引き起こし、新たな複雑性の最悪の形態を例示しました。
ホラーストーリーと 3 つの主な症状を見たところで、複雑さの原因を見てみましょう。
依存関係はソフトウェアにとって不可欠であり、完全に排除することはできません。これらにより、システムのさまざまな部分が相互作用し、連携して機能することが可能になります。ただし、依存関係を適切に管理しないと、複雑さが大幅に増加する可能性があります。
コードを単独で理解または変更できない場合に依存関係が存在し、関連するコードの検討または変更が必要になります。
不明瞭さは、重要な情報が明らかでない場合に発生します。これにより、コードベースが理解しにくくなり、認知負荷が増大し、未知のリスクが増大する可能性があります。
不明瞭さは、重要な情報が明確ではないときに発生します。
段階的に行われるため、「今回だけなら問題ない」と考えてしまいがちです。しかし、蓄積されると、1 つまたは 2 つの依存関係を修正するだけでは大きな違いは生じません。
「ソフトウェア エンジニアリングではすべてがトレードオフです。」
— 著者は覚えていません
複雑さを回避する方法について、おそらくインターネットですでに見たルール、戦略、フレームワークをたくさん書くことができます: SOLID、デザイン パターン、YAGNI、KISS など。
ただし、これらすべてを 1 つの指針に統一することはできます (「The Pragmatic Programmer」で説明されているように): 「実装しているものは簡単に変更できますか?」 答えがノーの場合は、おそらく複雑さが増していると思われます。
コードを簡単に変更できるようにすることで、メンテナンスが簡素化され、開発者の認知的負荷が軽減され、システムの適応性が高まり、エラーが発生しにくくなります。
ありがとうございます!
以上がソフトウェアの複雑さとの終わりのない戦いの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。