web-dev-qa-db-ja.com

継承による下流の問題を防ぐ方法

これをStack Overflowから移動しましたが、ここが推奨される場所でした。これは、重複の可能性があるとマークされています 継承よりも構成のメリットについての質問 。私はその質問をしているのではなく、私たちが持っているコードを前提として開発を管理するための戦略を探しています。

質問のコンテキストは、Qtを使用してC++で記述された一連のアプリケーションです。私たちは疑似アジャイルな方法で作業します。つまり、2週間のスプリントがありますが、頻繁なリリースはありません。

これらはすべてテーマのバリエーションですが、それぞれがその前のテーマを変更します。

これは理想的なシナリオではありませんが、私が作業しなければならないものです。

したがって、アプリケーションAはAlibを使用します。アプリケーションBはBlibとAlibを使用します。 Blibのほとんどのクラスは、Alibのクラスの子孫です。同様に、アプリケーションCはAlib BlibおよびClibを使用します。これらは主にBlibからサブクラス化されますが、時々Alibからもサブクラス化されます。

私たちはCVSを使用しており、MSVCプロジェクトが正しくマージされないため、ビルドを分岐するのはかなり面倒です。

現在起こっていることは、Alibに取り組んでいる開発者が、レビューの戦略や開発に関するルールを採用しない限り、BlibとClibの両方で予期しない問題を引き起こす可能性があることです。

私たちは多くの時間的プレッシャーにさらされており、現在コードを再編成する時間がないので、現在のフレームワーク内で実行できることを探しています。

Gitを使用している場合は、各開発者のコ​​ードを分岐する方が簡単ですが、今のところ、まだそこにはありません(パイプラインにあります)。

私は、ALibの機能を(追加するのではなく)変更するすべての新しい開発にその動作をサブクラス化するよう要求するという方針に沿って考えています。

私が読んだ他のオプションには、「頻繁に失敗する」、つまりAlibの内容のコミット/変更について率直であり、BlibとClibが頻繁にレビューされ、変更に対応できることを確認します。

これと同様に、頻繁なコードレビュー(1人の開発者(私)は3つのライブラリすべてについて十分な知識を持っているため、潜在的なダウンストリームの影響を早期に発見できるはずです)は、コミット前またはコミット後の問題を引き起こします。

編集:幅広い解決策をありがとう、私はこれらのいくつかを回答としてマークできるといいのですが、John W'usの回答で行ってきました。彼は3番目のポイントで私のジレンマをかなり明確に述べています-各libにいくつかの分離を持ちながら、自分自身の繰り返しを減らす(つまり、DRYに違反しない)ようにします。最終的にはコードのリファクタリングが必要ですが、より多くの(一部の!)単体テストで、壊れたコードを強調表示する必要があります。私たちが抱えていた1つの問題は、Alibの開発者がBlibとClibに影響する変更を確認し、BlibとClibの開発者が正しく理解していない方法で変更を加えることです。したがって、コードを閉じたままにする(拡張するが変更しない)ルールも非常に適切です。

7
mike

あなたのための3つのオプション

オープン/クローズの原則に従う

コードとプロセス管理の観点から、チーム全体で Open/Closed Principle を遵守する同意を得ることは、問題の解決に役立つはずです。

すべての人にこの原則を厳密に守らせることができれば、それで十分でしょう。

自動化された単体テストによる継続的な統合ビルド

自動化された 継続的なビルドプロセス を開発し、ALib、BLib、およびCLibのいずれかが変更されるたびにビルドされるようにします。

ビルドの一部として実行される 自動ユニットテスト のスイートを開発します。テストのいずれかが失敗した場合、ビルドは失敗するはずです。

ビルドを壊した人を誰もが恥ずかしく思う。

代わりにインターフェースを使用してください

自分で解決できず、ALibを常に変更できるようにする必要がある場合は、実装の継承から離れて、次のように interface inheritance に厳密に従う必要があります。

  1. 新しいlibを開発し、それをILibと呼びます。このライブラリには、実装コードが含まれておらず、インターフェース定義のみが含まれている必要があります。
  2. ALib、BLib、およびCLib間の継承関係を削除する
  3. ALib-> ILib、BLib-> ILib、およびCLib-> ILib間のインターフェース関係を追加します
  4. ILibをフリーズ

このようにして、ALibの実装変更がBLibおよびCLibに与える影響はありません。

欠点は、多くのコードを複製してしまう可能性があることです。つまり、違反 [〜#〜] dry [〜#〜] です。

3
John Wu

私が恐れている銀の弾丸を見つけることはほとんどありません。 fragile base class 問題のすべての症状があります。

短期的には、CIを構築して実行し、できるだけ広い範囲でテストカバレッジを取得することに、できる限りの努力を注ぎます。そうすれば、少なくとも問題を解消できなくても軽減できます。

調査できる構造的なアイデアの1つは、アプリケーションAがAlibを直接使用せず、A'libのサブクラスを使用することです。 OOP純粋ではないかもしれませんが、アプリAに必要な機能が実際にBとCには必要ない場合は、A'libに配置して脆弱性の一部を軽減できます。

幸運を。私はあなたの立場に立っており、それは最も楽しい経験ではありませんでした。

2
Alex

alibに取り組んでいる開発者は、BlibとClibの両方で予期しない問題を引き起こす可能性があります

Alibの自動テストがないか、少なすぎたり、他のライブラリの数が少なすぎたりします。開発者がAlibで上位互換性があると期待する何かを変更した場合、テストは既存の機能が壊れないことを確認する必要があります。変更が意図的に互換性がない場合は、予期された一連のテストのみが失敗します。

それがあなたが取り組むべきことです-テストを使って手動のレビュープロセスの大部分を自動化します。

1
Doc Brown