タグ付けされた質問 「coupling」

9
1つのメソッドシグネチャを変更しましたが、現在25,000以上のエラーがあります。今何?
私は最近、非常に大きなアプリケーション(15M loc)で作業している新しい仕事を始めました。私の以前の仕事では、同様に大きなアプリケーションがありましたが、(良くも悪くも)OSGiを使用しました。これは、アプリケーションを独立して変更、コンパイル、デプロイできる多数のマイクロサービスに分割することを意味しました。新しいアプリケーションは、たった2つの.dllを備えた1つの大きなコードベースにすぎません。 ですから、このクラスのインターフェースを変更する必要があります。それが上司が私に要求したことだからです。彼らは当初、あまり一般化されていないいくつかの仮定でそれを書きました。しばらくの間、リファクタリングの問題は非常に密に結合されているため回避していました。インターフェイスを変更しましたが、現在25000以上のエラーがあります。エラーの一部は、「XYZPriceCalculator」のような重要な名前のクラスにあり、これは本当に壊れてはいけません。しかし、すべてのエラーが解決されるまで、アプリケーションを起動して動作するかどうかを確認することはできません。また、ユニットテストの多くは、そのインターフェイスを直接参照するか、そのインターフェイスを参照する基本クラスに結合されるため、それらを修正するだけでも非常に大きなタスクです。さらに、これらのすべてのピースがどのように組み合わされるかについては本当にわからないので、たとえ始めたとしても、物が壊れた場合にどのように見えるかはよくわかりません。 私は最後の仕事でこのような問題に本当に直面したことはありません。私は何をしますか?

11
カスケードリファクタリングを回避するにはどうすればよいですか?
プロジェクトがあります。このプロジェクトでは、機能を追加するためにリファクタリングしたいと考え、機能を追加するためにプロジェクトをリファクタリングしました。 問題は、作業を終えたときに、それに対応するためにインターフェイスを少し変更する必要があることが判明したことです。だから私は変更を加えました。そして、新しいクラスの観点から、現在のインターフェイスでは消費クラスを実装できないため、新しいインターフェイスも必要です。今では3か月後に、無数の事実上無関係な問題を修正する必要があり、1年前にロードマップされた問題、または問題がコンパイルされる前に修正できないと単純にリストされている問題の解決を検討しています再び。 この種のカスケードリファクタリングを今後回避するにはどうすればよいですか?これは、以前のクラスが互いに緊密に依存しすぎているという単なる症状ですか? 簡単な編集:この場合、リファクタリングは機能でした。これは、リファクタリングにより特定のコードの拡張性が向上し、一部の結合が減少したためです。これは、外部の開発者がより多くのことができることを意味し、それが私が提供したかった機能でした。したがって、元のリファクタリング自体は機能的な変更ではないはずです。 5日前に約束したより大きな編集: このリファクタリングを開始する前に、インターフェイスのあるシステムがありましたが、実装では、dynamic_cast出荷したすべての可能な実装を単純に確認しました。これは明らかに、インターフェイスから継承することはできなかったことを意味し、第2に、このインターフェイスを実装するための実装アクセス権を持たない人は不可能であることを意味しました。だから私はこの問題を修正し、誰でもそれを実装できるようにインターフェースを公開し、誰でもそれを実装できるようにし、インターフェースの実装が必要な契約全体であると判断しました。 私がこれをしたすべての場所を見つけて火で殺そうとしていたとき、特定の問題であることが判明した場所を1つ見つけました。それは、さまざまな派生クラスのすべての実装の詳細と、すでに実装されているが他のどこかより優れた複製機能に依存していました。代わりにパブリックインターフェイスの観点から実装し、その機能の既存の実装を再利用することもできます。正しく機能するには特定のコンテキストが必要であることを発見しました。おおまかに言って、呼び出し元の以前の実装はちょっと似ていました for(auto&& a : as) { f(a); } ただし、このコンテキストを取得するには、次のようなものに変更する必要がありました std::vector<Context> contexts; for(auto&& a : as) contexts.push_back(g(a)); do_thing_now_we_have_contexts(); for(auto&& con : contexts) f(con); これは、以前はの一部であったすべての操作についてf、一部はgコンテキストなしで動作する新しい関数の一部にする必要があり、一部は現在の遅延の一部で行う必要があることを意味しますf。しかし、すべてのメソッドf呼び出しがこのコンテキストを必要とするわけでも、必要とするわけでもありません。一部のメソッドは、別個の手段で取得する別個のコンテキストを必要とします。そのため、最終的にf呼び出しを行うすべて(大まかに言えば、ほぼすべて)について、必要なコンテキスト(ある場合)、取得元、および古いものからf新しいものへの分割方法を決定する必要がfありましたg。 そして、それが私が今いるところに行き着いた方法です。とにかく他の理由でこのリファクタリングが必要だったからです。

6
「関数とデータ間の密結合」が悪いのはなぜですか?
この引用は、「Clojureの喜び」のp。32、しかし誰かが先週の夕食で私に同じことを言って、私はそれを他の場所でも聞いた: [A]オブジェクト指向プログラミングの欠点は、関数とデータの間の密結合です。 アプリケーションで不要な結合が悪い理由を理解しています。また、オブジェクト指向プログラミングであっても、可変状態と継承を避けるべきだと言っています。しかし、なぜクラスに関数を貼り付けるのが本質的に悪いのかはわかりません。 つまり、クラスに関数を追加すると、Gmailでメールにタグを付けたり、ファイルをフォルダーに貼り付けたりするように思えます。それはあなたが再びそれを見つけるのを助ける組織的なテクニックです。いくつかの基準を選択してから、同じようなものをまとめます。OOP以前は、プログラムはファイル内のメソッドのかなり大きな袋でした。つまり、関数をどこかに配置する必要があります。整理してみませんか? これが型に対するベール攻撃である場合、関数への入力および出力の型を制限することは間違っていると言うだけではありませんか?それに同意できるかどうかはわかりませんが、少なくともプロとコンタイプの安全性に関する議論には精通しています。これは、ほとんど別の懸念のように思えます。 確かに、時々それを間違え、機能を間違ったクラスに置きます。しかし、他の間違いと比較すると、これは非常に小さな不便さのようです。 そのため、Clojureには名前空間があります。OOPのクラスに関数を貼り付けることは、Clojureの名前空間に関数を貼り付けることとどのように異なりますか?クラスの関数は、必ずしもそのクラスのメンバーだけで動作するとは限らないことを忘れないでください。java.lang.StringBuilderを見てください。これは、すべての参照型で動作するか、オートボクシングを通じて、すべての型で動作します。 PSこの引用は、私が読んだことのない本を参照しています:Multiparadigm Programming in Leda:Timothy Budd、1995。

5
定数をどこに置くべきか、そしてその理由は?
私たちの大部分が大規模なアプリケーションでは、通常、「定数」の場所はわずかしかありません。 GUIおよび内部定数(タブページのタイトル、グループボックスのタイトル、計算係数、列挙)の1つのクラス データベースのテーブルと列用の1つのクラス(この部分は生成されたコードです)およびそれらの読み取り可能な名前(手動で割り当てられた) アプリケーションメッセージ(ロギング、メッセージボックスなど)の1つのクラス 定数は通常、これらのクラスの異なる構造体に分けられます。C ++アプリケーションでは、定数は.hファイルでのみ定義され、値は.cppファイルで割り当てられます。 利点の1つは、すべての文字列などが1つの中央の場所にあり、何かを変更する必要があるときに誰もがどこにあるかを知っていることです。 これは特に、プロジェクトマネージャーが人々が行き来する際に好むように思われるものであり、このようにして誰もがアプリケーションの構造を掘り下げることなく、このような些細なことを変更できます。 また、同様のグループボックス/タブページなどのタイトルを一度に簡単に変更できます。別の側面は、そのクラスを印刷して、キャプションが直感的であるか、ユーザーへのメッセージが詳細すぎるか、混乱しすぎていないかなどを確認できる非プログラマーに渡すことができることです。 ただし、いくつかの欠点があります。 すべての単一クラスは、定数クラスに密接に結合されています 定数の追加/削除/名前の変更/移動には、アプリケーションの少なくとも90%の再コンパイルが必要です(注:少なくともC ++の場合、値の変更は行われません)。1500クラスのC ++プロジェクトの1つでは、これは約7分間のコンパイル時間(プリコンパイル済みヘッダーを使用し、ヘッダーなしでは約50分)に加えて、特定の静的ライブラリに対する約10分間のリンクを意味します。 Visual Studio Compilerを使用して速度が最適化されたリリースをビルドするには、最大3時間かかります。膨大なクラス関係がソースであるかどうかはわかりませんが、そうであるかもしれません。 何かを非常に迅速にテストしたいので、そのテスト(そしておそらくその後のすべてのテスト)だけで15分待ちたくないので、一時的に直接コードに文字列をハードコーディングすることになります。「後で修正します」という考え方に何が起こるかは誰もが知っています。 別のプロジェクトでクラスを再利用するのは必ずしも簡単ではありません(主に他の密結合によるものですが、定数の処理はそれを容易にするものではありません)。 そのような定数をどこに保存しますか?また、プロジェクトマネージャーに、上記の利点に適合するより優れた概念があることを納得させるために、どのような議論を提起しますか? C ++固有の回答または独立した回答をお気軽にお寄せください。 PS:私はこの質問が一種の主観的なものであることを知っていますが、正直に言って、この種の質問についてこのサイトよりも良い場所を知りません。 このプロジェクトの更新 コンパイル時間に関するニュースがあります 。Calebとgbjbaanbの投稿に続いて、時間があるときに定数ファイルをいくつかの他のファイルに分割しました。私は最終的にプロジェクトをいくつかのライブラリに分割しましたが、これは今でははるかに簡単になりました。これをリリースモードでコンパイルすると、データベース定義(テーブル、列名など-8000を超えるシンボル)を含む自動生成ファイルと特定のハッシュを構築することにより、リリースモードで膨大なコンパイル時間が発生することがわかりました。 DB定数を含むライブラリのMSVCオプティマイザーを非アクティブ化すると、リリースモードでのプロジェクト(複数のアプリケーション)の合計コンパイル時間を最大8時間から1時間未満に短縮できるようになりました。 MSVCがこれらのファイルを最適化するのにこれほど苦労する理由はまだわかりませんが、今のところ、ナイトリービルドのみに依存する必要がないため、この変更により大きなプレッシャーが軽減されます。 その事実、およびより緊密でない結合、より良い再利用性などのその他の利点も、「定数」の分割に時間を費やすことは、結局のところそれほど悪い考えではないことを示しました;-) Update2 この質問にはまだ注目が集まっ ているので、ここ数年私がやってきたことは次のとおりです。 関連するスコープにすべての定数、変数などを正確に配置します。単一のメソッドでのみ定数を使用する場合、そのメソッドで定義することは問題ありません。単一のクラスに興味がある場合は、そのクラスのプライベート実装の詳細として残します。同じことが名前空間、モジュール、プロジェクト、会社の範囲にも当てはまります。ヘルパー関数などにも同じパターンを使用します。(パブリックフレームワークを開発する場合、これは100%適用されない場合があります。) これにより、再利用性、テスト容易性、および保守性が向上し、コンパイル時間(少なくともC ++)が少なくなるだけでなく、バ​​グ修正にかかる時間が短縮され、新しい機能を実際に開発する時間が増えます。同時に、より多くのコードをより簡単に再利用できるため、これらの機能の開発は高速になります。これは、中央定数ファイルが持つ利点よりも重要です。 詳細を知りたい場合は、特にインターフェイス分離の原則と単一責任の原則をご覧ください。 あなたが同意する場合、この更新は基本的に彼が言ったことに対するより一般的な見解なので、カレブの答えに賛成です。

3
依存性注入はどのように結合を増加させますか?
依存性注入に関するウィキペディアのページの短所セクションには、次のことが記載されています。 依存性注入は、サブシステムのユーザーにそのサブシステムのニーズを提供するように要求することにより、結合を増加させます。 依存性注入に対する記事へのリンク付き。 依存性注入により、クラスは具体的な実装の代わりにインターフェースを使用します。その結果、結合が減少するはずです。 私は何が欠けていますか?依存性注入はどのようにクラス間の結合を増加させますか?

3
Pyqt / QtアプリのロジックからUIを適切に分離する方法は?
私は過去にこの主題について多くのことを読み、ボブおじさんのこのような興味深い講演をいくつか見てきました。それでも、デスクトップアプリケーションを適切に設計し、UI側の責任とロジック側の責任を区別することは常に非常に難しいと感じています。 優れた実践の非常に短い要約は、このようなものです。UIから切り離したロジックを設計する必要があります。これにより、どの種類のバックエンド/ UIフレームワークに関係なく(理論的に)ライブラリを使用できるようになります。これが意味することは、基本的にUIは可能な限りダミーであるべきであり、重い処理はロジック側で行われるべきだということです。別の言い方をすれば、文字通り、コンソールアプリケーション、Webアプリケーション、またはデスクトップアプリケーションで素敵なライブラリを使用できます。 また、ボブおじさんは、どのテクノロジーを使用するとさまざまなメリットが得られるか(良いインターフェース)を議論することを提案します。 ですから、この質問は非常に広範な質問であり、インターネット全体で何度も議論されてきました。そこで、何か良いものを得るために、pyqtでMCVを使用しようとする非常に小さなダミーの例を投稿します。 import sys import os import random from PyQt5 import QtWidgets from PyQt5 import QtGui from PyQt5 import QtCore random.seed(1) class Model(QtCore.QObject): item_added = QtCore.pyqtSignal(int) item_removed = QtCore.pyqtSignal(int) def __init__(self): super().__init__() self.items = {} def add_item(self): guid = random.randint(0, 10000) new_item = { "pos": [random.randint(50, 100), …
20 design  python  mvc  gui  coupling 

5
なぜ型がそのビルダーと結合されるのでしょうか?
私は最近、Code Reviewで私のJavaの回答を削除しました。 private Person(PersonBuilder builder) { やめる。赤旗。PersonBuilderはPersonを構築します。それは人について知っています。PersonクラスはPersonBuilderについて何も知らないはずです-それは単なる不変の型です。ここで、Aに依存するBに依存するAに依存する循環カップリングを作成しました。 Personはパラメータを取得するだけです。構築せずにPersonを作成するクライアントは、それを実行できる必要があります。 私は下票で平手打ちされ、それを(引用して)赤旗と言った、なぜ?ここでの実装は、Joshua Blochが彼の「Effective Java」本(アイテム#2)で示したものと同じ形をしています。 したがって、Javaでビルダーパターンを実装する正しい方法は、ビルダーをネスト型にし(これはこの質問の目的ではありません)、製品を作成することです(ビルドされているオブジェクトのクラス)このように、ビルダーに依存します: private StreetMap(Builder builder) { // Required parameters origin = builder.origin; destination = builder.destination; // Optional parameters waterColor = builder.waterColor; landColor = builder.landColor; highTrafficColor = builder.highTrafficColor; mediumTrafficColor = builder.mediumTrafficColor; lowTrafficColor = builder.lowTrafficColor; } https://en.wikipedia.org/wiki/Builder_pattern#Java_example 同じBuilderパターンの同じWikipediaページには、C#の実装が大きく異なります(そして、はるかに柔軟です)。 //Represents a product created …

4
イベント駆動型プログラミング:いつ価値があるのか​​?
わかりました、この質問のタイトルは、イベントベースのプログラミングをいつ使用する必要があるかとほぼ同じです。しかし、上記の質問の答えは、私が直面している特定のケースでイベントを使用すべきかどうかを決定するのに役立ちませんでした。 私は小さなアプリケーションを開発しています。それはシンプルなアプリであり、その機能の大部分は基本的なCRUDです。 特定のイベント(特定のデータを変更する場合)で、アプリケーションはそのデータのローカルコピーをファイルに書き込む必要があります。これを実装する最善の方法についてはわかりません。できます: データが変更されたときにイベントを起動し、そのようなイベントに応答をバインド(ファイルを生成)します。または、オブザーバーパターンを実装します。それは不必要な複雑さのようです。 データを変更するコードからファイル生成コードを直接呼び出します。はるかに単純ですが、依存関係をこのように設定するのは間違っているようです。つまり、アプリのコア機能(データを変更するコード)をその追加の特典(バックアップファイルを生成するコード)に結合するのは間違っているようです。ただし、このアプリは、そのカップリングが問題を引き起こすポイントまで進化しないことを知っています。 この場合の最善のアプローチは何ですか?

3
デカップリングはRESTのDRYに勝りますか?
既存のJava APIのほとんどの機能を公開するREST APIを構築しています。両方のAPIは、組織内で使用するためのものです。外部で使用するために設計する必要はありません。私は両方のAPIに影響を及ぼしていますが、REST APIを実装しています。Java APIは引き続きローカルアプリケーションに使用されます(「非推奨」ではありません)が、重要な新規開発にはREST APIが使用されます。 Java APIクラスの一部は単なるデータです(プロパティ、ゲッター、セッターを持つBean)。そして少なくともこれらのいくつかは、REST APIを介して(何らかの形で)データ(XMLまたはJSONにマーシャリングされる)として送信するのに意味があります。たとえば、サーバーマシンに関する情報を格納するクラス。これらのデータクラスについて、次の選択に直面しています。 元のJavaクラス(またはサブクラス)をREST APIで直接公開する、または REST API専用の新しいデータ転送クラス(DTOパターン)を作成しますか? いずれにせよ、RESTデータ転送クラスがあります。問題は、オリジナルに注釈を付けるか、新しいものを作成するか(オリジナルのコピーに近い場合があります)です。他の選択肢もありますが、主にこれら2つに焦点を当てます。 #1の引数: DRY(繰り返さないでください) 実装が速い REST APIのアップグレードが簡単 #2の引数: REST APIをJava APIとは別にバージョン管理する必要がある場合はどうなりますか?(これは多少可能性があります。) プロパティの削除、動作の追加、クラス階層の変更など、Javaデータクラスに大幅な変更があった場合はどうなりますか?(これも多少可能性があります。) 要するに、DRY(#1)とデカップリング(#2)の間のトレードオフのように思えます。 #1から始めて、その後#2に移って問題が発生した場合は、必要なことを証明できないものを構築しないというアジャイルガイドラインに従っています。これは悪い考えですか。とにかくそこに行き着くかもしれないと思うなら、私は#2から始めるべきですか? 私のリストに欠けている主要な議論/結果はありますか?
19 java  api  rest  coupling  dry 

8
文字列との結合はクラスメソッドよりも「緩い」のでしょうか?
Swingを使用して、Javaで学校グループプロジェクトを始めています。これは、データベースデスクトップアプリの簡単なGUIです。 教授は去年のプロジェクトのコードを教えてくれたので、彼がどのように仕事をしているかを見ることができました。私の最初の印象は、コードが本来あるべきよりもはるかに複雑であるということですが、プログラマーは、自分が書いただけではないコードを見るとき、これをよく考えると思います。 私は彼のシステムが良いか悪いかの理由を見つけたいと思っています。(私は教授に尋ねたが、彼は後でなぜそれが良いのかを見るだろうと言ったが、それは私を満足させない。) 基本的に、彼の永続可能なオブジェクト、モデル(ビジネスロジック)、およびビュー間のカップリングを避けるために、すべては文字列で行われます。データベースに格納される永続オブジェクトは文字列のハッシュテーブルであり、モデルとビューは互いにサブスクライブし、サブスクライブする「イベント」に文字列キーを提供します。 イベントがトリガーされると、ビューまたはモデルは、そのイベントの処理を決定するすべてのサブスクライバーに文字列を送信します。たとえば、ビューアクションリスナメソッドの1つ(これは永続オブジェクトにbicycleMakeFieldを設定するだけだと思います): else if(evt.getSource() == bicycleMakeField) { myRegistry.updateSubscribers("BicycleMake", bicycleMakeField.getText()); } その呼び出しは、最終的にVehicleモデルのこのメソッドに到達します。 public void stateChangeRequest(String key, Object value) { ... bunch of else ifs ... else if (key.equals("BicycleMake") == true) { ... do stuff ... 教授は、このような方法は、ビューでビジネスロジックオブジェクトのメソッドを単純に呼び出すよりも、拡張性と保守性が高いと言います。彼は、ビューとモデルがお互いの存在を知らないので、ビューとモデルの間に結合がないと言います。 ビューとモデルが機能するには同じ文字列を使用する必要があるため、これはより悪い種類のカップリングだと思います。ビューまたはモデルを削除するか、文字列にタイプミスをすると、コンパイルエラーは発生しません。また、コードが必要以上に長くなります。 私は彼とこれについて議論したいが、彼は彼の業界経験を使って、私、経験の浅い学生がするかもしれない議論に反論する。私が見逃している彼のアプローチにはいくつかの利点がありますか? 明確にするために、ビューをモデルに明らかに結合させることで、上記のアプローチを比較したいと思います。たとえば、車両モデルオブジェクトをビューに渡し、車両の「メイク」を変更するには、次のようにします。 vehicle.make = bicycleMakeField.getText(); これにより、車両のメーカーを1か所で設定するために現在使用されている15行のコードが、読み取り可能な1行のコードに削減されます。(そして、この種の操作はアプリ全体で何百回も行われるため、読みやすさと安全性にとって大きな勝利になると思います。) 更新 私のチームリーダーと私は、静的型付けを使用してフレームワークを望みどおりに再構築し、教授に通知し、最終的に彼にデモを提供しました。彼は私たちに助けを求めない限り、そして私たちのチームの残りの部分を最新に保つことができる限り、私たちのフレームワークを使用するのに十分寛大です-これは私たちにとって公平に思えます。
18 java  coupling 

6
オブジェクト指向設計における疎結合
私はGRASPを学ぼうとしていますが、これは低結合について説明されています(ここ3ページにあります)。 クラスのメソッドaddTrackについて考えてみましょうAlbum。2つの可能なメソッドは次のとおりです。 addTrack( Track t ) そして addTrack( int no, String title, double duration ) どの方法で結合が減少しますか?Albumクラスを使用するクラスはTrackクラスを知る必要がないので、2番目のものはそうします。一般に、メソッドへのパラメーターは、java。*パッケージの基本型(int、char ...)およびクラスを使用する必要があります。 私はこれに反対する傾向があります。私はさまざまな理由addTrack(Track t)よりも優れていると信じていますaddTrack(int no, String title, double duration): メソッドのパラメーターはできるだけ少ないほうが常に良いです(Uncle BobのClean Codeによれば、なしまたは1つ、できれば2、場合によっては3、特別な場合は3、3つ以上はリファクタリングが必要です-これらはもちろん推奨ルールではありません) 。 場合addTrackのインタフェースの方法であり、要件がいることを必要とするTrackより多くの情報(たとえば年またはジャンル)を持っている必要があり、インターフェイスを変更する必要があるので、この方法は、別のパラメータがサポートする必要があること。 カプセル化が壊れています。addTrackがインターフェイス内にある場合、の内部を知らないはずTrackです。 実際には、多くのパラメーターを使用して、2番目の方法でより結合されています。仮定noから変更するパラメータニーズをintへlong以上があるのでMAX_INT、トラック(または何らかの理由で)。Trackメソッドとメソッドの両方を変更する必要がありますが、メソッドaddTrack(Track track)のみTrackが変更される場合は変更します。 4つの引数はすべて実際には相互に関連しており、それらの一部は他からの結果です。 どのアプローチが良いですか?

5
結合を増加させずにDRYを適用することは可能ですか?
関数Fを実装するソフトウェアモジュールAがあるとします。別のモジュールBは、F 'と同じ関数を実装します。 重複するコードを取り除くには、いくつかの方法があります。 AにBのF 'を使用させます。 BにAのFを使用させます。 Fを独自のモジュールCに入れ、AとBの両方に使用させます。 これらのオプションはすべて、モジュール間に追加の依存関係を生成します。カップリングを増加させる代わりに、DRY原則を適用します。 私が見る限り、DRYを適用すると、カップリングは常に増加するか、リースでより高いレベルに移動します。ソフトウェア設計の最も基本的な2つの原則の間には矛盾があるようです。 (実際、そのような競合があることは驚くことではありません。これはおそらく、優れたソフトウェア設計をそれほど難しくしていることです。これらの競合は通常、入門書では扱われていません。 編集(明確化のため):FとF 'の等価性は単なる偶然ではないと思います。Fを変更する必要がある場合、F 'も同様に変更する必要があります。

3
DRYおよびOODによるコードカップリングの導入
DRYとコードの結合に関するガイダンスを探しています。私は自分のコードを複製したくないし、無関係なモジュール間のコードの結合も嫌いです。そのため、複製が導入されてから1年後に同一の重複コードが見つかった場合、重複コードをリファクタリングします。しかし、現実の世界がはるかに予測不可能な状況を経験し、コードをリファクタリングした後、コードを再度フォークする必要がある状況が発生しています。 たとえば、ガソリン車、ガソリンSUV、電気自動車、電気SUVを処理するコードがあった場合、「コード」を「ガソリン」階層と「電気」階層にリファクタリングするとします。どちらも「車両」階層から派生しています。ここまでは順調ですね。そして、私の会社はハイブリッド車とハイブリッドセミを導入します。これには、元の階層自体に中核的な変更が必要になります。たぶん、ガソリンと電気階層の間の「組成」が必要になるでしょう。 上記のすべての製品に共通する変更を実装するのにかかる時間が長くなるため、明らかにコードの複製が悪いことです。しかし、一般的なコードをリファクタリングすると、製品固有のバリエーションを導入することも同様に難しくなり、バグを修正するためにコードの行を見つけなければならない場合に多くの「クラスジャンプ」が発生します。すべての子孫の間でトリガー回帰のバグをトリガーします。 DRYと不要なコードカップリングの最適なバランスをどのように実現しますか?
14 design  dry  coupling 

3
実装の詳細に結合しない単体テストの動作
彼の講演TDDでは、それがすべてうまくいかなかったので、Ian CooperはTDDのユニットテストの背後にあるケントベックの当初の意図をプッシュし(特にクラスのメソッドではなく、動作をテストするため)、テストを実装に結合しないように主張しています。 save X to some data source典型的なサービスとリポジトリのセットを備えたシステムのような動作の場合、テストを実装の詳細に結合することなく、特定のメソッドの呼び出しなど、リポジトリを介してサービスレベルで一部のデータの保存を単体テストする方法)?この種のカップリングを避けることは、実際には努力する価値がない/何らかの形で悪いですか?

5
依存性注入を使用して一時的な結合を回避する方法
Serviceコンストラクタを介して依存関係を受け取るが、使用する前にカスタムデータ(コンテキスト)で初期化する必要があると仮定します。 public interface IService { void Initialize(Context context); void DoSomething(); void DoOtherThing(); } public class Service : IService { private readonly object dependency1; private readonly object dependency2; private readonly object dependency3; public Service( object dependency1, object dependency2, object dependency3) { this.dependency1 = dependency1 ?? throw new ArgumentNullException(nameof(dependency1)); this.dependency2 = dependency2 …

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