web-dev-qa-db-ja.com

YAGNIとSRPの間に競合はありますか?

私の仕事は、コードの品質を改善する責任があります。この責任を果たすために、私はプログラムを開発者とペアにし、設計原則と設計パターンに関するセッションを実施することがよくあります。開発者が単一責任原則またはYAGNIに違反する必要があると言った開発者に驚いた。

単一の責任の原則は、すべてのクラスまたはモジュールに変更する理由が1つあるべきであると述べています。わかりやすくするために再説明します。モジュールは1人のアクターに対してのみ責任を負う必要があります。

私の理解では、単一責任の原則に従う理由は次のとおりです。クラスが2つのアクターを担当する場合、1つのアクターがそのクラスの変更を推進する場合、他のアクターの要件を意図せず変更する可能性があります。

[〜#〜] yagni [〜#〜]あなたの頭字語は必要ありません。極端なプログラミングの原則は、動作する可能性のある最も単純なことを行うと述べています。不必要なモジュール化を削除してコードを単純化するために、YAGNIに頼ることがよくありました。

SRPとYAGNIの競合:システムにワークフローが実装されていました。また、ワークフローの使用状況に関するデータを収集する必要がありました。ワークフローで使用されるパラメーターのパーセンテージ分布について調べる必要がありました。データ収集は他のクラスで行う必要があり(オブザーバーまたはデコレーターパターンを使用できる可能性があります)、ワークフローが実装されているクラスではなく、両方の要件がシステムの異なるアクターによって駆動されることを説明しました。ワークフローはエンドユーザーにサービスを提供し、データコレクションは製品管理にサービスを提供します。

私の同僚は、ワークフローが実装されているクラスのパラメーターを直接ログに記録したいと考えていました。これは、これを機能させるために行う最も簡単なことだと私に言った。

このシナリオでは、SRPに従う必要があると確信しています。また、ワークフローに変更があった場合、誤ってデータ収集を変更する可能性が低いため、SRP(2つのクラスで実装)に従っています。また、データ収集に変更があった場合、ワークフローを誤って変更する可能性も低くなります。しかし、ワークフローやデータ収集で起こりうる変更について説明すると、彼は「あなたはそれを必要としない」と言っています。

これをどのように説明できるかについての提案はありますか?

11

YAGNIは、後で到着する可能性がある架空の要件のコード変更に労力を費やすことを避け、代わりに、現在の要件に焦点を当てることを意味します。ただし、これは機能要件に限定されるものではありません。「使い捨て」ソフトウェアを作成しない限り、コードを読みやすく、理解しやすく、進化可能に保つという非機能要件が常に存在します。そして、責任を分離することは、その目標を達成するための主要なツールの1つです。

したがって、私はこのような状況でのYAGNIの原則を、SRPのメリットが見えるようになる前に責任を分離しないようにするための推奨として解釈します、実際にはコードが複雑になるとすぐに。そして、それは通常、1つのクラスで異なるビジネス要件を実装しようとすると、非常に迅速に発生します。

このロギング要件を追加するために、ワークフローが実装されている「クラス」に2つまたは3つの小さな拡張を作成する必要がある場合は、それを許容します。しかし、それから私の痛みのレベルにおそらく到達し、私は考え始めます "一体、このロギングメカニズム、または少なくともワークフロークラスからのデータコレクションをより適切な場所にリファクタリングできますか?"

だからあなたの開発者に伝える代わりに:

  • "念のため、最初から別のデータ収集クラスを作成してください"(これにより、リクエストがYAGNIの反論になりやすくなります)、

それらを教えてください:

  • "異なる責任が明らかになるとすぐに別のデータ収集クラスにリファクタリングし、コードをより明確にするのに役立ちます"

これは、将来の未知の要件ではなく、コードを理解しやすい状態に保つための要件nowにSRPを適用する必要がある根拠になるはずです。

もちろん、コードが複雑であると認識されるしきい値、およびこれを修正するためにSRPをいつ適用できるかは、開発者ごとに異なる可能性がありますが、それはチームが見つけなければならないバランスであり、どこに コードレビューのみ助けることができます

31
Doc Brown

原則に厳密に従うべきではありません。

経験を通じて得られた知識を説明するためにあります。彼らの目標は、ソフトウェア開発のさまざまな側面について洞察を与えることです。彼らが時々互いに反抗することは驚くことではありません。

私は本当に好きです この中の記事 これは次のピラミッドを示します:

enter image description here

ピラミッドの背後にある考え方は、上位層を犠牲にして下位層を弱体化してはならないということです。

まず第一に、このイメージは絶対的だとは思わないでください。盲目的にそれに従うべきではありません。ただし、基本的に、いくつかの原則が他の原則よりも重要であることが合理的であると述べています。おそらく、ソリューションを機能させることが最優先事項であるべきです。

あなたのSRP対YAGNIの質問のレンズでは、私は自分自身に尋ねます:

  • ソリューションは現在機能していますか?それとも、適切な機能を正しくする前にそれを改善しようとしていますか?
  • SRPはコードを改善しますか?早すぎるものをオーバーエンジニアリング/一般化していませんか?

「Rubyでの実用的なオブジェクト指向設計」の著者であるSandi Metzからの本当に良い講演 が非常に良い点に触れています。

複製は間違った抽象化よりはるかに安価です

おそらく、今すぐ抽象化を開発すると、間違った方法で抽象化する可能性があります。


ボトムライン

最終的には、アプリケーションのコンテキストを考慮して、原則を適用する必要があります。確かに、SRPがあなたの状況に適したガイドとなるケースかもしれません。または... SRPを使用すると、現時点ではそれを過剰設計する可能性があり、YAGNIを使用する方が適しています。

主な見解はおそらくはい、信仰に従っていると原則が互いに矛盾することが一般的であり、これは問題ではありません。すべて順調。

どちらかと言えば、最初に実用的なソリューションを実装し(つまり、ソリューションの1つを選択してそれを実行する)、それから生じる影響に適応して、ソフトウェアを有機的に構築することをお勧めします。

11
Albuquerque

単一の責任原則では、すべてのクラスまたはモジュールに変更する理由が1つあるべきであると述べています。わかりやすくするために再説明します。 モジュールは1つだけの俳優に責任があります。

私はこの声明に同意しません。つまり、従うのは良いルールではないと思います。そして、ボブおじさんが非常によく似た、あるいは同じことを言っていることは知っています。

これについて少し考えてみましょう。 add()subtract()を持つ単純なAmountクラスがあるとします。ある「俳優」がadd()ともう1つのsubtract()だけを必要とする場合はどうでしょうか。このクラスを分割する必要がありますか?それにより、コードの保守性が向上しますか?私はあなたがそうするだろうと主張することはないと思います。

それはすべてに依存し、常に判断力を行使する必要があると言う前に、ルールが単純なケースにさえ適用されない場合、ルールは良いルールではないと思います。

質問への回答:確かにそうです。可能であれば、データコレクションを実際のワークフロー実装から分離することも試みます。たとえば、Workflowがインターフェイスであり、データコレクションのすべてのデータがパラメーターを介して利用できる場合、データを収集して呼び出しを委任する実装を作成します。

ただし、収集が必要なワークフローの内部データがあり、それがパブリックパラメーターでは利用できない場合、データコレクションを実装自体に配置しても問題はありません。この場合、実際の実装の実装に実際に関心があるためです。動作。

だから、あなたもまだ私を納得させることができませんでした:)

2