DRYおよびOODによるコードカップリングの導入


14

DRYとコードの結合に関するガイダンスを探しています。私は自分のコードを複製したくないし、無関係なモジュール間のコードの結合も嫌いです。そのため、複製が導入されてから1年後に同一の重複コードが見つかった場合、重複コードをリファクタリングします。しかし、現実の世界がはるかに予測不可能な状況を経験し、コードをリファクタリングした後、コードを再度フォークする必要がある状況が発生しています。

たとえば、ガソリン車、ガソリンSUV、電気自動車、電気SUVを処理するコードがあった場合、「コード」を「ガソリン」階層と「電気」階層にリファクタリングするとします。どちらも「車両」階層から派生しています。ここまでは順調ですね。そして、私の会社はハイブリッド車とハイブリッドセミを導入します。これには、元の階層自体に中核的な変更が必要になります。たぶん、ガソリンと電気階層の間の「組成」が必要になるでしょう。

上記のすべての製品に共通する変更を実装するのにかかる時間が長くなるため、明らかにコードの複製が悪いことです。しかし、一般的なコードをリファクタリングすると、製品固有のバリエーションを導入することも同様に難しくなり、バグを修正するためにコードの行を見つけなければならない場合に多くの「クラスジャンプ」が発生します。すべての子孫の間でトリガー回帰のバグをトリガーします。

DRYと不要なコードカップリングの最適なバランスをどのように実現しますか?


1
盲目的にルールに従うのではなく、最初に脳を動かすことは常に良いことです。
gnasher729

十分に公平-したがって、ルールではなくガイドラインです。
user2549686

DRY(または以前はOAOOと呼ばれていました)のWikiページを読みましたか?wiki.c2.com/?OnceAndOnlyOnceで、それに関する多くの最初の議論が行われました。(実際には、ワードは、パターンと実践に関する議論専用のWikiを発明しました。)
ヨルグWミットタグ

質問が重複しているように聞こえない場合でも、非常に関連する回答:softwareengineering.stackexchange.com/questions/300043/…–
ハルク

回答:


8

重複コードを「ガソリン」階層と「電気」階層にリファクタリングしたとしましょう。どちらも「車両」階層から派生しています。ここまでは順調ですね。

そして、私の会社はハイブリッド車とハイブリッドセミを導入します。これには、元の階層自体に中核的な変更が必要です。たぶん、ガソリンと電気階層の間の「組成」が必要になるでしょう

これが人々が相続よりも構成に向かっている主な理由の一つだと思います。

継承は、説明したような概念の変更がある場合、大規模な再構築を強制します。

再構築が「大きすぎる/難しい」場合、人々はそれを避けるために重複したコードを書きます。

コードを継承チェーンの上方に移動して複製をリモート化するのではなく、コードをヘルパークラスまたはサービスに移動し、必要に応じて構成の一部としてそのクラスを注入できます。

結果のデザインがOOPかどうかは議論の余地があります


1
継承は問題であり、DRYではないことを指摘した+1。コードを再利用する最も簡単な方法は、不要な依存関係を削除することです。多くの場合、継承を使用する場合、親クラス(およびその子孫)がすべて依存関係であるという事実を見逃します。依存関係を削減または排除した場合にのみ、実際に再利用可能なコードを取得できます。
グレッグブルクハート

3
結果のデザインがOOPかどうかは議論の余地があります」。すべてが議論の余地がある。質問は、理にかなった合理的な議論に開かれていますか?答えはいいえだ。あなたの最後の段落は、そうでなければ非常に良い答えを損なうと思います。
デビッドアルノ

@davidarnoは本当にあなたをフォローしてはいけません。タイトルのOODをObject Orientated Designと読みますか?だから、議論をトロールすることなく質問に取り組んでいます
ユアン

1
@ユアン:私はここでデイビッド・アルノと一緒です。「継承がなければOOPではない」という信念は誤りであることが 20年以上にわたってよく知られていると思います。
Doc Brown

これはまさに避けようとしていた議論の一種です。両側に意見があり、明確な答えはありません
ユアン

3

DRYの原則に従えば、それ以外の場合は無関係なモジュール間の結合を増やすことができます。特に大規模なソフトウェアシステムでは、これはDRYに従わない方がより良い代替策になる可能性がある状況につながる可能性があります。

残念ながら、あなたの例はこれを実証するのにあまり適していません-そこに記載されている問題は、継承の誤った準最適な使用法における古典的なエラーが原因です。ただし、私が上で書いた内容については、共通のコードを共通の基本クラスにリファクタリングするか、ヘルパークラス(構成)にリファクタリングするかは問題ではありません。どちらの場合も、共通のコードをライブラリLに配置し、以前は無関係だった2つのプログラムAとBからそのライブラリを参照することが強制される場合があります。

AとBは以前は完全に無関係であり、バージョン管理、リリース、および独立してデプロイできると仮定します。ただし、共通のコードを共有ライブラリLに入れると、Aの新しい要件によりLに変更が加えられ、Bに変更が生じる可能性があります。そのため、追加のテストが必要になり、おそらくBの新しいリリースとデプロイサイクルが必要になります。

それでは、DRYの原則を放棄したくない場合、この状況にどのように対処できますか?さて、これにアプローチするためのいくつかのよく知られた戦術があります:

  1. A、B、およびLを同じ製品の一部として保持し、1つの共通バージョン番号、共通のビルド、リリース、および展開プロセス、高度な自動化

  2. または、マイナーバージョン番号(互換性のない変更なし)とメジャーバージョン番号(おそらく重大な変更を含む)を使用して、Lを単独で製品にし、AとBがそれぞれLの異なるバージョン行を参照できるようにします。

  3. Lをできるだけソリッドにし、後方互換性に注意してください。L内のモジュールを変更せずに再利用(OCP)できるほど、重大な変更が発生する可能性は低くなります。「SOLID」の他の原則は、その目標をサポートするのに役立ちます。

  4. 特にLおよびAおよびBに対して自動テストを使用します。

  5. Lに何を入力するかに注意してください。システム内の1箇所にのみ存在するビジネスロジックは、良い候補です。「似ている」だけで、将来異なる可能性のあるものは、悪い候補です。

AとBが異なる無関係なチームによって開発、保守、および進化される場合、DRYの原則はそれほど重要ではなくなります-DRYは保守性と進化性に関するものですが、2つの異なるチームに個別の保守作業を提供させることは、製品を結ぶよりも効果的です少しの再利用のために一緒に。

結局、それはトレードオフです。大規模なシステムでDRYの原則に従う場合は、堅牢で再利用可能なコンポーネントの作成により多くの労力を費やす必要があります。通常は予想以上です。それが価値があるときとそうでないとき、あなたはあなたの判断を信頼しなければなりません。


1

DRYはさらに別の構造的ルールです。つまり、極端に考えても、無視するのと同じくらい悪いことです。構造的な考え方から抜け出すための比phorです。

あなたの双子が大好きです。クローンを殺します。

キーボード入力を避けるために盲目的にコピーアンドペーストすると、クローンを作成します。確かに彼らはあなたが望むことをしますが、今ではその振る舞いの変更はとても高価なのであなたを圧迫します。

責任が異なるために同じコードで同じ動作を再現すると、今では同じニーズが発生しますが、異なる変更が発生する可能性があります。

あなたは彼らのDNA(コード)を好きなだけスキャンできます。クローンと双子を区別するのは、あなたがそれらを見るだけであるかどうかを判断するのが難しいです。必要なのは、彼らが住んでいる背景を理解することです。なぜ生まれたのか。彼らの究極の運命はどうなるでしょう。

ABC社で働いているとしましょう。3人の会社幹部、A、B、Cによって運営されています。全員がソフトウェア製品の作成を望んでいますが、それぞれに独自の部門があります。彼らは皆、あなたが小さく始めたいと思っています。今のところ、簡単なメッセージを出力するだけです。あなたは「Hello World」と書きます。

嫌いだ、会社名をそこに入れてほしい。

Bはそれを愛し、そのままにして、会社名をスプラッシュスクリーンに追加してほしいと考えています。

Cは電卓が欲しいだけで、メッセージはあなたが始めるための単なる方法であると考えました。

あなたが確信していることの一つは、これらの人たちはこのプロジェクトが何であるかについて非常に異なる考えを持っていることです。時々彼らは同意するでしょう。時には彼らはあなたをさまざまな方向に引き寄せます。

コードを独立して変化させる機能を作成しているためにコードを複製すると、双子が作成されます。入力が苦痛でコピーアンドペーストが簡単なためコードを複製すると、邪悪なクローンが作成されます。

A、B、およびCは、コードが提供する必要がある異なるマスターです。長い間、1行のコードで複数のマスターにサービスを提供することはできません。


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