何を優先すべきか:YAGNIまたはGood Design?


76

YAGNIはどの時点で適切なコーディング慣行に優先する必要がありますか?私は職場でプロジェクトに取り組んでおり、同僚に良いコード標準をゆっくりと導入したいと思っています(現在は存在せず、すべてが韻や理由なしでハッキングされています)が、一連のクラスを作成した後(私たちはTDD、または悲しいことにどんな種類のユニットテストもしないでください)私は一歩後退し、YAGNIに違反していると思いました。なぜなら、これらのクラスのいくつかを拡張する必要がないことを確信して知っているからです。

具体的な例を次に示します。一連のストアドプロシージャをラップするデータアクセスレイヤーがあり、基本的なCRUD機能を備えた基本的なリポジトリスタイルのパターンを使用しています。すべてのリポジトリクラスに必要なメソッドがいくつかあるので、リポジトリ用の汎用インターフェイスを作成しましたIRepository。ただし、その後、各タイプのリポジトリ(例:)に「マーカー」インターフェース(つまり、新しい機能を追加しないインターフェースICustomerRepository)を作成し、具象クラスがそれを実装します。ファクトリー実装でも同じことを行い、ストアドプロシージャによって返されたDataReaders / DataSetsからビジネスオブジェクトを構築しました。リポジトリクラスの署名は次のようになります。

public class CustomerRepository : ICustomerRepository
{
    ICustomerFactory factory = null;

    public CustomerRepository() : this(new CustomerFactory() { }

    public CustomerRepository(ICustomerFactory factory) {
        this.factory = factory;
    }      

    public Customer Find(int customerID)
    {
        // data access stuff here
        return factory.Build(ds.Tables[0].Rows[0]);
    }
}

ここでの私の懸念は、YAGNIに違反しているということです。99%の確実性でCustomerFactory、このリポジトリに具体的なもの以外のものを提供する理由がないことを知っているからです。ユニットテストがないため、MockCustomerFactory同じようなものは必要ありません。また、非常に多くのインターフェイスがあると、同僚が混乱する可能性があります。一方、工場の具体的な実装を使用することは、デザインの匂いのようです。

適切なソフトウェア設計とソリューションのオーバーアーキテクトとの間で妥協する良い方法はありますか?すべての「単一実装インターフェース」が必要なのか、または、例えば、基本インターフェースと単一のコンクリートのみを使用して、良いデザインを少し犠牲にして、プログラミングを心配しないのか疑問に思っています。実装が使用される場合のインターフェース。


17
「ユニットテストがないため、MockXは不要です」と言うと、当然「IXは不要で、Xのみが必要」になります。ユニットテストがないという事実は、IXとMockXが必要であるという事実を強調しています。これらは、ユニットテストを行うのに役立つからです。テストを行わないという現実を受け入れないでください。それは一時的な問題として扱い、それは(おそらく長い間)改善されるでしょう。
アンソニーペグラム

10
それをGoogleに些細だにもかかわらず、「あなたがそれを必要とするつもりはない」ために、誰かがYAGNIが立っていることを言及する必要があります
thedaian

1
このような新しいクラスを作成する場合は、ユニットテストを追加する必要があると思います。同僚がそれらを実行しない場合でも。少なくとも後で、「見て!コードを壊したときにユニットテストがそれをキャッチした!ユニットテストの素晴らしさを見て!」と言うことができます。その場合、ここでモック可能にすることは価値があるかもしれません。(ただし、インターフェイスを定義せずにオブジェクトをモックできる場合は、それを好むでしょう)
ウィンストンイーバート

単体テストでモックフレームワークを作成(または使用)せざるを得ないので、ライブストアドプロシージャはヒットしませんか?それが私がテストを追加しない傾向がある主な理由です-私たちはそれぞれ、テストとコードの記述を行う本番データベースのローカルコピーを持っています。
ウェインモリナ

3
@Anthonyそして、モッキングは、それに伴う余分な複雑さのオーバーヘッドを常に正当化しますか?モッキングは優れたツールですが、その有用性もコストに対して重み付けする必要があり、場合によっては間接的な過剰によってスケールが逆になります。もちろん、余分な複雑さを支援するツールはありますが、複雑さを解消することはできません。「あらゆるコストでのテスト」を当然のように扱う傾向が高まっているようです。これは間違っていると思います。
コンラッドルドルフ

回答:


75

適切なソフトウェア設計とソリューションのオーバーアーキテクトとの間で妥協する良い方法はありますか?

ヤグニ。

良いデザインを少し犠牲にすることができました

誤った仮定。

そして、基本インターフェース、次に単一のコンクリート、

それは「犠牲」ではありません。それ良いデザインです。


72
完璧は、追加するものが他にないときではなく、奪うものが何もないときに達成されます。アントワーヌドサンテグジュペリ
ニュートピア

5
@Newtopian:人々は、Appleの最新製品に関するそれについて複雑な感情を持っています。:)
ロイティンカー

14
この種の答えには大きな問題があります。「YはYが言っているのでXは真実であり、Yはコミュニティに裏打ちされている」妥当な推論ですか?現実の誰かがYAGNIに対してった場合、あなたは彼にこの答えを議論として見せますか?
vemv

2
@vemv。ここの誰もYAGNIに対して暴言を言っています。S.Lottが言ったのは、2つの価値ある目標の間でOPが認識した矛盾は間違いだということでした。ところで、今日のソフトウェアの世界 YAGNIに反するアクティブな開発者を知っていますか?実際のプロジェクトに取り組んでいる場合、要件は絶えず変化しており、ユーザーとマネージャーは一般に、自分が何をしたいのか、それを自分の前に置くまで望んでいないことを知っています。必要なものを実装することはたくさんの仕事です-未来を予測しようとするコードを書くことによって、なぜ時間、エネルギー、そしてお金を浪費する(またはあなたの仕事を危険にさらす)のですか?
ベクトル

6
私のポイントはYAGNIではなく、回答の質です。特に誰かが暴言を言っているとは思わない、それは私の推論の一部だった。もう一度読んでください。
vemv

74

ほとんどの場合、必要のないコードを避けることで、設計が改善されます。最も保守可能で将来性のある設計とは、要件を満たす、最小限の適切な名前のシンプルなコードを使用する設計です。

最もシンプルなデザインは、最も進化しやすいものです。無駄な、過剰に設計された抽象化レイヤーのような保守性を損なうものは何もありません。


8
「YAGNIコードの回避」は、気が遠くなるほどあいまいです。それはあなたが必要としないコードかYAGNI原則に従うコードを意味するかもしれません。(Cf. 'KISSコード')
sehe

2
@sehe:「YAGNIの原則を順守している間は」完全にあいまいではありませんが、「あなたがコードを必要としない」とはどういう意味ですか必要ないの?
マイケルボルグワード

1
この回答を大きなフォントで印刷し、すべての建築の宇宙飛行士が読むことができる場所に掛けます。+1!
kirk.burleson

1
+1。いくつかの新しい機能をサポートおよび追加するために与えられた最初の企業プロジェクトを今でも覚えています。私が最初にしたことは機能を失うことなく、40,000行のプログラムから32,000行の無駄なコードを削除することでした。元のプログラマーはその後まもなく解雇されました。
EJブレナン

4
@vemv:「役に立たない」を「現在は使用されていないが、些細なことを除いて」、つまりYAGNIの場合と読みます。そして、「過剰設計」は「不良」よりもかなり具体的です。具体的には、「具体的な現在の要件ではなく、理論的概念または考えられる要件によって生じる複雑さ」を意味します。
マイケルボルグ

62

YAGNIとSOLID(またはその他の設計手法)は相互に排他的ではありません。しかし、それらは極に近い反対です。どちらかを100%遵守する必要はありませんが、ギブアンドテイクがあります。1つのクラスで使用される高度に抽象化されたパターンを1か所で見て、YAGNIと言って単純化すればするほど、デザインは固くなりません。逆も同様です。開発では何度も、設計が「信頼に基づいて」確実に実装されます。あなたはそれがどのように必要になるかわかりませんが、あなたはただ予感を持っています。これは真実かもしれません(そして、経験が増えるほど真実になる可能性が高くなります)が、平手打ちの「do it light」アプローチと同じくらい多くの技術的負債を負わせる可能性もあります。DILの「スパゲッティコード」コードベースの代わりに、「ラザニアコード」になる場合があります。非常に多くのレイヤーがあるため、メソッドや新しいデータフィールドを追加するだけで、サービスプロキシと実装が1つだけの疎結合の依存関係を数日かけて歩いていくプロセスになります。または、「ラビオリコード」で終わる可能性があります。これは、アーキテクチャ内で上下左右に移動することにより、それぞれ3行の50のメソッドを実行できるような小さなバイトサイズのチャンクです。

私は他の答えでそれを言ったが、ここにある:最初のパスで、それを動作させる。2番目のパスでは、エレガントにします。3番目のパスで、SOLIDにします。

その内訳:

最初にコード行を記述するとき、それは単に機能する必要があります。この時点で、あなたが知っているすべてのために、それは一度限りです。したがって、2と2を追加するための「アイボリータワー」アーキテクチャを構築するためのスタイルポイントを取得する必要はありません。

次回カーソルがそのコード行に入ると、最初に書いたときから仮説が反証されました。あなたはそのコードを再訪しています。おそらく、それを拡張したり、他の場所で使用したりするので、一度限りではありません。ここで、DRY(繰り返さないでください)などのいくつかの基本原則と、コード設計のためのその他の簡単なルールを実装する必要があります。繰り返しコードのメソッドやフォームループの抽出、一般的なリテラルや式の変数の抽出、コメントの追加などが可能ですが、全体的にコードは自己文書化する必要があります。これで、コードがきちんと結合されていても、コードはきちんと整理されており、コードを見ている人は、コードを1行ずつトレースするのではなく、コードを読むことであなたが何をしているのかを簡単に知ることができます。

カーソルがそのコードに入る3回目は、おそらく大したことではありません。再度拡張するか、コードベースの他の少なくとも3つの異なる場所で有用になります。この時点で、それはシステムのコアではないにしても重要な要素であり、そのように設計する必要があります。この時点で、通常、それがどのように使用されているかについての知識もあります。これにより、これらの使用法と新しい使用法を合理化するために設計を設計する方法に関して適切な設計決定を行うことができます。これで、SOLIDルールが方程式を入力するはずです。特定の目的を持つコードを含むクラスを抽出し、同様の目的または機能を持つクラスの共通インターフェースを定義し、クラス間に疎結合の依存関係を設定し、それらを簡単に追加、削除、または交換できるように依存関係を設計します。

この時点から、このコードをさらに拡張、再実装、または再利用する必要がある場合は、すべてがうまくパッケージ化され、「ブラックボックス」形式で抽象化されます。他の必要な場所にプラグインするか、インターフェイスの使用を変更せずに、インターフェイスの新しい実装としてテーマに新しいバリエーションを追加します。


2番目に素晴らしいです。
フィリップデュパノビッチ

2
はい。事前に再利用/拡張を設計するために使用していたとき、再利用または拡張したいときは、予想とは異なる方法になることがわかりました。特に未来に関しては、予測は困難です。したがって、私はあなたの3ストライクルールをサポートします-その時までに、あなたはそれがどのように再利用/拡張されるかについて合理的な考えを持っています。NB:例外は、それがどのようになるかを既に知っている場合です(たとえば、以前のプロジェクト、ドメインの知識、または既に指定されている)。
13

4番目のパスで、それをすばらしいものにします。
リチャードニールイラガン

@KeithS:ジョン・カーマックは似たようなことをしたようです。「Quake IIのソースコード... Quake 1、Quake World、およびQuakeGLを1つの美しいコードアーキテクチャに統合します。」fabiensanglard.net/quake2/index.php
13ren

+1私はあなたのルールに名前を付けると思います:「実用的なリファクタリング」:)
松o

31

それらのどちらの代わりに、私はWTSTWCDTUAWCROTを好みますか?

(私たちができる最も簡単なことは何ですか?それは便利で、木曜日にリリースできますか?)

私がやるべきことのリストにはもっと簡単な頭字語がありますが、それらは優先事項ではありません。


8
その頭字語はYAGNIの原則に違反しています:)
riwalk

2
私は必要な文字を正確に使用しました-それ以上でもそれ以下でもありません。そのように、私はモーツァルトのようなものです。うん。私は頭字語のモーツァルトです。
マイクシェリル 'キャットリコール'

4
モーツァルトが頭字語を作るのがひどいことは知りませんでした。SEサイトで毎日新しいことを学びます。:P
キャメロンMacFarland

3
@Mike Sherrill 'CatRecall':それをWTSTWCDTUWCROTAWBOF =「私たちができる最も簡単なことは何ですか?それは便利です、木曜日にリリースでき、金曜日に壊れることはありませんか?」;-)
ジョルジオ

1
@ Stargazer712 no :) POLAに違反しています。
v.oddou

25

YAGNIと優れたデザインは矛盾しません。YAGNIは、将来のニーズをサポートする(サポートしない)ものです。優れた設計とは、ソフトウェアが現在行っていることと、その方法を透明にすることです。

ファクトリーを導入すると、既存のコードが簡単になりますか?そうでない場合は、追加しないでください。テストが追加されている場合(テストを追加する場合など)、追加してください。

YAGNIは、将来の機能をサポートするために複雑さを追加しないことについてです。
グッドデザインとは、現在のすべての機能をサポートしながら複雑さを取り除くことです。


15

彼らは対立していません、あなたの目標は間違っています。

何を達成しようとしていますか?

質の高いソフトウェアを作成し、それを行うには、コードベースを小さく保ち、問題が発生しないようにします。

今、私たちは衝突に達しました。使用しないケースを作成しない場合、すべてのケースをどのようにカバーしますか?

問題は次のようになります。

ここに画像の説明を入力してください (興味のある方、これは蒸発雲と呼ばれます

それで、これを駆動しているのは何ですか?

  1. 必要ないものが分からない
  2. 時間を無駄にしてコードを肥大化させたくない

これらのうちどれを解決できますか?まあ、それは時間を無駄にしたくないように見え、コードを肥大化させることは大きな目標であり、理にかなっています。最初のものはどうですか?コーディングする必要があるものを見つけることができますか?

私は仕事中のプロジェクトに取り組んでおり、同僚に良いコード標準をゆっくりと導入したいと思っています(現在は存在せず、すべてが韻や理由なくハッキングされています)。 YAGNIに違反していると思ったのは、これらのクラスの一部を拡張する必要がないことは確実にわかっているからです。

それをすべて言い直そう

  • コード標準なし
  • 進行中のプロジェクト計画はありません
  • カウボーイはどこでも独自のことをしています(そして、野生の西部で保安官を演奏しようとしています)、そうです。

適切なソフトウェア設計とソリューションのオーバーアーキテクトとの間で妥協する良い方法はありますか?

妥協する必要はありません。チームを管理する能力があり、プロジェクト全体のビジョンを持っている人が必要です。あなたは、あなたが必要としないものを投げ込むのではなく、あなたが必要としているものを計画できる人を必要としています。理由をお話しします、それはあなたのすべての中に誰も気の利いた計画がないからです。まったく別の問題を修正するためのコード標準を導入しようとしています。解決する必要がある主な問題は、明確なロードマップとプロジェクトです。それができたら、「コード標準はチームとしてこの目標をより効果的に達成するのに役立ちます」と言うことができます。これは絶対的な真実ですが、この質問の範囲外です。

これらのことを行えるプロジェクト/チームマネージャーを獲得してください。持っている場合は、地図を求めて、地図を持っていないというYAGNIの問題を説明する必要があります。彼らがひどく無能な場合は、自分で計画を書き、「私たちが必要なものについての私のレポートはここにあります。それを見直して、あなたの決定を知らせてください」と言ってください。


残念ながらありません。開発マネージャーは、標準/品質よりも迅速に物事を遂行することをより重視するか、クラスから直接返される生のDataSetを使用するなどの標準的なプラクティス、VB6スタイルのコーディング、およびすべてをコピーして貼り付けた重複したロジックを持つコードビハインドのすべてを行う以上。
ウェインモリナ

それは問題ありませんが、少し遅くなりますが、その心配に話をする必要があります。このYAGNI /役に立たないコードの問題が時間を浪費していることを説明し、ロードマップを提案し、ロードマップを彼に与え、それがより速く動作することを説明してください。彼が買収されたとき、開発の速度に対して貧弱な標準が持っている問題に直面し、より良いものを提案してください。彼らはプロジェクトの完了を望んでおり、物事を管理する方法がわからないだけで、あなたは彼を交換するか、彼を赤ちゃんにするか、または辞める必要があります。
シークレット

えーと..運転の目標は「良い、価値のある製品を持ちたい」と思いますか?
sehe

@seheそれは彼の決定ではありません:p。
シークレット

3
素晴らしい答え。彼は困難な戦いに直面しています。経営陣の賛同がなければ、それを成し遂げるのは難しいでしょう。そして、あなたはその質問が時期尚早であり、本当の問題に対処していないことは正しいです。
セススピアマン

10

ユニットテストでコードを拡張できるようにすることは、YAGNIでカバーされることありません。必要になるからです。ただし、CustomerFactoryは既にインターフェイスを継承しており、とにかくいつでもMockCustomerFactoryに交換できるため、単一実装インターフェイスへの設計変更が実際にコードのテスト容易性を向上させているとは確信していません。


1
グッドデザインとYAGNIの間の宇宙の戦いや恋愛についてだけでなく、実際の問題についての有益なコメントのために+1。
-psr

10

質問は誤ったジレンマを提示します。YAGNI原則の適切な適用は、無関係なことではありません。それは良いデザインの一つの側面です。SOLIDの各原則は、優れた設計の側面でもあります。どの分野でもすべての原則を常に完全に適用できるわけではありません。現実の問題はコードに多くの力をかけ、それらのいくつかは反対の方向に押し進めます。設計の原則はそれらすべてを説明する必要がありますが、すべての状況に適合する少数の原則はありません。

さて、それぞれの原則を見てみましょう。それらは時々異なる方向に引っ張ることがありますが、本質的に対立するものではないということを理解してください。

YAGNIは、開発者が特定の種類の手直しを回避するのを支援するために考案されました。これは、将来変化または必要になると思われるものについての仮定や予測に基づいて、誤った決定を早すぎるようにしないように導くことによって行われます。集合的な経験から、これを行うと、通常は間違っていることがわかります。たとえば、YAGNIは、現在複数の実装者が必要であることがわかっていない限り、再利用を目的としたインターフェースを作成しないように指示します。同様にYAGNIは、あなたが知っている限り、アプリケーションで単一のフォームを管理するために「ScreenManagerの」を作成していないと言うでしょう、今あなたが複数の画面を持ってしようとしていること。

多くの人が考えることとは反対に、SOLIDは再利用性、汎用性、または抽象化に関するものではありません。SOLIDは、その特定の変更が何であるかについては何も言わずに、変更備えたコードを書くのを支援することを目的としています。SOLIDの5つの原則は、過度に汎用的でなくても柔軟で、素朴でシンプルなコードを構築するための戦略を作成します。SOLIDコードを適切に適用すると、役割と境界が明確に定義された小規模で焦点の合ったクラスが生成されます。実際的な結果は、必要な要件の変更に対して、最小限のクラスに触れる必要があることです。同様に、コードを変更しても、他のクラスに至るまでの「リップル」は最小限に抑えられます。

状況の例を見て、YAGNIとSOLIDが何を言う必要があるか見てみましょう。すべてのリポジトリが外部からは同じように見えるという事実のため、共通のリポジトリインターフェイスを検討しています。しかし、一般的な汎用インターフェースの価値は、どのインターフェースが特に使用されているかを知る必要なく、実装者のいずれかを使用できることです。あなたのアプリのどこかにこれが必要または有用な場所がない限り、YAGNIはそれをしないと言います。

確認すべき5つの原則があります。Sは単一の責任です。これはインターフェースについては何も言っていませんが、具体的なクラスについては何かを言っているかもしれません。リポジトリの責任は、暗黙的なコンテキスト(CustomerRepositoryは暗黙的にCustomerエンティティのリポジトリです)から明示的な呼び出しに変換することですCustomerエンティティタイプを指定する汎用データアクセスAPI。

Oはオープンクローズです。これは主に継承に関するものです。共通の機能を実装する共通のベースからリポジトリを派生させようとした場合、または異なるリポジトリからさらに派生することが予想される場合に適用されます。しかし、あなたはそうではないので、そうではありません。

LはLiskov Subsututabilityです。これは、共通リポジトリインターフェイスを介してリポジトリを使用する場合に適用されます。インターフェイスと実装に制限を設けて、一貫性を確保し、さまざまな要素に対する特別な処理を回避します。その理由は、そのような特別な処理がインターフェースの目的を損なうためです。共通リポジトリインターフェイスを使用しないように警告する可能性があるため、この原則を検討することが役立つ場合があります。これはYAGNIのガイダンスと一致します。

私はインターフェイス分離です。これは、リポジトリに異なるクエリ操作を追加し始めた場合に適用されます。インターフェイスの分離は、クラスのメンバーを2つのサブセットに分割できる場合に適用されます。1つは特定のコンシューマーによって使用され、もう1つは他のコンシューマーによって使用されますが、両方のサブセットを使用するコンシューマーはほとんどありません。ガイダンスは、1つの一般的なインターフェイスではなく、2つの個別のインターフェイスを作成することです。あなたの場合、個々のインスタンスの取得と保存が、一般的なクエリを実行するのと同じコードによって消費される可能性は低いため、これらを2つのインターフェイスに分けることは有用です。

Dは依存性注入です。ここで、Sと同じポイントに戻ります。データアクセスAPIの消費を別のオブジェクトに分離した場合、この原則は、そのオブジェクトのインスタンスを単に更新するのではなく、作成時に渡す必要があることを示しています。リポジトリ。これにより、データアクセスコンポーネントのライフタイムを簡単に制御できるようになり、リポジトリ間で参照を共有できる可能性が開かれます。

アプリの開発のこの特定の段階では、SOLIDの原則のほとんどが必ずしも適用されるわけではないことに注意することが重要です。たとえば、データアクセスを分割する必要があるかどうかは、データアクセスの複雑さ、およびデータベースにアクセスせずにリポジトリロジックをテストするかどうかによって異なります。これはありそうもないと思われるので(残念ながら、私の意見では)、おそらく必要ではないでしょう。

そのため、すべてを検討した結果、YAGNIとSOLIDが実際に1つの共通の堅実で関連性の高いアドバイスを提供していることがわかりました。おそらく、共通の汎用リポジトリインターフェイスを作成する必要はないでしょう。

この慎重な考えはすべて、学習演習として非常に役立ちます。学習するのは時間がかかりますが、時間が経つにつれて直観が発達し、非常に速くなります。あなたは正しいことを知っているでしょうが、誰かがあなたに理由を説明するように頼まない限り、これらすべての言葉を考える必要はありません。


このページのほとんどの議論では、GRASPrinciplesの「低結合」と「高凝集性」という2つの大きな競争相手は除外されていると思います。コストのかかる設計上の決定は、「低結合」の原則に基づいています。低結合のためにSRP + ISP + DIPを「アクティブ化」するタイミングが好きです。例:1つのクラス-> MVCパターンの3つのクラス。またはさらに高価:.dll / .soモジュール/アセンブリに分割します。ビルドへの影響、プロジェクト、メイクリスト、ビルドサーバー、ソースバージョンのファイルの追加のために非常にコストがかかります
...-v.oddou

6

「良いデザイン」とは、役に立たない場合でも常に適用しなければならないある種のアイデア論と正式なルールに従うことを意味すると考えているようです。

IMOそれは悪いデザインです。YAGNIは優れたデザインのコンポーネントであり、矛盾することはありません。


2

あなたの例では、YAGNIが優先されるべきだと思います。後でインターフェースを追加する必要がある場合、それほど費用はかかりません。ちなみに、クラスごとに1つのインターフェイスがあり、それがまったく目的を果たさない場合、本当に良いデザインですか?

もう1つ考えて、必要なのはグッドデザインではなく、十分なデザインである場合があります。以下は、このトピックに関する非常に興味深い一連の投稿です。


最初と3番目のリンクは同じ場所に移動します。
デビッドソーンリー

2

一部の人々は、インターフェイス名はIで始まるべきではないと主張します。特に1つの理由は、特定の型がクラスであるかインターフェイスであるかという依存関係を実際にリークしていることです。

CustomerFactory最初にクラスになることを禁止し、後でインターフェイスに変更することを禁止しているのは、DefaultCustormerFactoryまたはによって実装されUberMegaHappyCustomerPowerFactory3000ますか?変更する必要があるのは、実装がインスタンス化される場所だけです。そして、あなたがより良くないデザインを持っているなら、これはせいぜい一握りの場所です。

リファクタリングは開発の一部です。単一のクラスごとにインターフェースとクラスを宣言し、少なくとも2つの場所ですべてのメソッド名を同時に変更するよりも、コードをほとんど持たず、リファクタリングしやすい方が良いです。

インターフェイスを使用する際の本当のポイントは、モジュール性を実現することです。これはおそらく、優れた設計の最も重要な柱です。ただし、モジュールは、外界からの分離によって定義されるだけでなく(外部の観点からそれを知覚する方法ですが)、内部の動作によっても同様に定義されることに注意してください。
私が指摘したいのは、本質的に一緒に属するものを切り離すことはあまり意味がないということです。ある意味では、カップごとに個別の棚がある食器棚を持っているようなものです。

重要なのは、大きくて複雑な問題をより小さく、より単純な副問題に考案することです。そして、さらに細分化することなく十分にシンプルになるポイントで停止する必要があります。そうしないと、実際にはより複雑になります。これはYAGNIの結果と見ることができます。そして、それは間違いなく良いデザインを意味します。

目標は、単一のリポジトリと単一のファクトリーでローカルの問題を何らかの形で解決することではありません。目標は、この決定がアプリケーションの他の部分に影響を与えないことです。それがモジュール性です。
同僚がモジュールを見て、一握りの自明な呼び出しでファサードを見て、自信を持って、彼らがそれらを使用できると確信し、すべての潜在的に洗練された内部配管を心配する必要はありません。


0

interface将来、複数の実装を予測して作成しています。I<class>コードベース内のすべてのクラスを持っているかもしれません。しないでください。

YAGNIに従って、単一の具象クラスを使用するだけです。テスト目的で「モック」オブジェクトが必要な場合は、元のクラスを2つの実装を持つ抽象クラスに変換します。1つは元の具象クラスで、もう1つはモック実装です。

明らかに、元のクラスのすべてのインスタンス化を更新して、新しい具象クラスをインスタンス化する必要があります。静的コンストラクターを事前に使用することで、これを回避できます。

YAGNIは、コードを書く必要がある前にコードを書かないように言っています。

優れたデザインは、抽象化を使用することを意味します。

両方持つことができます。クラスは抽象化です。


0

マーカーがインターフェイスする理由 「タグ付け」以外のことは何もしていないと思います。工場タイプごとに異なる「タグ」があるので、何がポイントですか?

インターフェースの目的は、クラスに「行動する」動作を与え、いわば「リポジトリ能力」を与えることです。したがって、すべての具象リポジトリタイプが同じIRepositoryのように動作する場合(すべてIRepositoryを実装する場合)、それらはすべて他のコードと同じ方法で、まったく同じコードで処理できます。この時点で、設計は拡張可能です。より具体的なリポジトリタイプを追加します。すべてが汎用IRepositoryとして処理されます。同じコードがすべての具体的なタイプを「汎用」リポジトリとして処理します。

インターフェースは、共通性に基づいて物事を処理するためのものです。ただし、カスタムマーカーインターフェイスはa)動作を追加しません。およびb)独自性の処理を強制します。

有用なインターフェースを設計する限り、具象クラスと1対1の相関を持つ特殊なクラス、タイプ、またはカスタムマーカーインターフェースを処理するための特殊なコードを記述する必要がないというOOの利点が得られます。それは無意味な冗長性です。

たとえば、多数の異なるクラスの強く型付けされたコレクションが必要な場合、マーカーインターフェイスが表示されます。コレクションでは、それらはすべて「ImarkerInterface」ですが、それらを引き出すと、それらを適切な型にキャストする必要があります。


0

今、漠然と合理的なICustomerRepositoryを書き留めることができますか?例えば、過去にあなたの顧客が常にPayPalを使用していた(本当にここに到達した、おそらく悪い例)?または、会社の誰もがアリババとの接続に熱中していますか?もしそうなら、より複雑なデザインを今すぐ使用して、上司に遠視されているように見えるかもしれません。:-)

そうでなければ、待ってください。1つまたは2つの実際の実装を行う前にインターフェイスで推測すると、通常は失敗します。言い換えると、一般化するいくつかの例ができるまで、派手なデザインパターンを一般化/抽象化/使用しないでください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.