.NETアプリケーション間でコードを共有する最も効果的な方法は何ですか?


14

私たちの仕事には、多くの基本機能を共有するいくつかの異なる.netアプリケーションがあります。クリーンなn層アーキテクチャを使用してこれらのアプリケーションを構築しましたが、同じ機能を何度か再実装したことに気付いたその瞬間にヒットしました。これは明らかにDRYに違反するため、修正する必要があります。すでに一般的なグルーコード(IoCの配線、ログ、設定)にNugetを使用していますが、すべてのアプリケーション間でデータ層とビジネス層を共有したいと考えています。このアイデアは、UIが実際に必要なビジネスレイヤーの部分のみを処理するというものです。

これは最初は簡単な問題のように見えますが、進行中の開発には落とし穴があり、どのように進めればよいかわかりません。すべてを支配するために1つのビジネスレイヤーを作成するとします。簡潔にするために、「Foundation」と呼びます。Foundationを使用するためにアプリケーションを移植しましたが、すべてが素晴らしいものです。Foundationはnugetを介してライトUIレイヤーに配布されており、見栄えが良いです。しかし、その後、アプリケーションに機能を追加し始め、トラブルに直面します。

プロジェクトAに取り組んでおり、Foundationの変更を必要とする新しい機能を追加するとします。Foundation(Foundation-A)に変更を加え、不安定なパッケージとしてNugetフィードにプッシュします。プロジェクトAは最新のnugetパッケージを取得し、すべてが良好です。一方、別の開発者がプロ​​ジェクトBに取り組んでいます。彼はソース管理から最新のFoundationを取得しますが、安定したブランチから取得するため、プロジェクトAの変更はありません。彼は変更を加え、Foundation-Bを作成しました。そして、すべてが良いです。しかし、その後、実際にコードを共有できるFoundation-AとFoundation-Bの実装機能を発見したため、それらを組み合わせます。一方、Foundation-Cは独自の変更を加えてそこに浮上しています。最終的に、Foundation-Bの運用準備が整いました。しかし、その後、プロダクションA、B、

これはうまくいくように思えますが、異なるデータベーススキーマで作業し、FoundationリポジトリのさまざまなブランチとプロジェクトA、B、Cリポジトリ間ですべてを同期させることを心配しています。おそらく多くの手作業が必要になるようで、エラーの可能性が広がります。これを可能な限り自動化したいと思います。

使用しているスタックは次のとおりです。C#、継続的インテグレーションを備えたTFS、Nuget。当社のアプリケーションはすべて、さまざまな種類のASP.NETアプリケーションです。物事を簡単にする場合は、さまざまなSCMを検討します。

さまざまなソースコードブランチでNugetを正常に保つ方法を探しています。間違ったNugetパッケージを参照するため、誤って開発コードを本番環境にプッシュしたくありません。


また、これがこのような議論のための良いフォーラムではない場合、誰かがより良いものを提案できますか?
ジョシュ

回答:


9

Foundation(Foundation-A)に変更を加え、不安定なパッケージとしてNugetフィードにプッシュします。

ここから問題が始まります...それをしないでください。

Foundation v1.0への変更は、Foundationのすべての消費者にとって本質的に価値があるはずです。そうでなければ、Foundationに属しません。したがって、nugetパッケージを作成するときは、Foundationの公式の安定したバージョン(v1.1など)として実行するか、まったく実行しないでください。

プロジェクトBは通常どおりFoundationの拡張機能を構築する必要がありますが、安定したFoundation(v1.2)をnugetにプッシュする前に、トランクの変更(v1.1)にマージする必要があります(適切なソース管理方法)。

Foundationの拡張機能を使用できる他のプロジェクトでは、必要に応じてNuget参照をアップグレードしたり、必要に応じて古いバージョンを使用したりできます。

@Giedriusに同意します。これは、Foundationの分岐/マージが適切に処理されると、パッケージ管理の問題が意味をなさないという意味で、ソース管理/分岐の問題のように思えます。


はい、これは理にかなっています。問題は実際のアプリケーションにあります。Foundation for v1.1を更新するとき、開発中にプロジェクトBでこれらの変更を使用する必要があります。そのコードを共有している方法がnugetを使用している場合、オプションは次のとおりです。1)新しいnugetパッケージを公開するか、2)dllを手動でコピーします。これらのどちらも良い選択のようには見えません。
ジョシュ

これのいくつかは、効果的なテストスイートを使用することで軽減できますが、機能を追加する際には、まだやり直しが必要です。
ジョシュ

@Joshはい、Foundationへの更新は、Project Bがそれらを使用する方法とは無関係に完全でテスト可能である必要があります(共有ライブラリに移動するため)プロジェクトBでFoundation v.Nextをインポートして使用するのは、nugetで安定したパッケージになるまで行わないでください。それは少し規律がかかりますが、そうでなければそれを行うことの混乱よりもはるかに優れています。
エリックキング

1
私はあなたが言っていることを完全に理解していますが、それは非常に現実的ではないと思います。機能を開発すると、すべてのビジネスロジックとデータアクセスレイヤーを完全にテストした場合でも、運用環境にプッシュされる前に変更が行われます。ビジネスロジックに別のプロパティを追加する必要があるか、製品の所有者が変更または明確化を求めて戻ってきたのかもしれません。単純化する仮定の一部が間違っていたのかもしれません。これらは常に起こることです。ロックされたベースロジックのリリースに制限されている場合、実際には非常に制限されているようです。
ジョシュ

2
数か月間これを行ってきたので、これは基本的に私たちが決めたものです。私は正式なプロセスを持つことをあまりにも心配していたと思います。実際に作業を開始すると、事態は非常にスムーズに進みました。ご意見ありがとうございます。
ジョシュ14年

4

重複コードをより抽象的な方法で適用可能な関数にリファクタリングし、独自のライブラリまたはフレームワークに配置します。疎結合でアーキテクチャに依存しないようにします。問題は発生しません。インスピレーションが必要な場合は、.NETフレームワークが、インターフェイス、ジェネリック、およびなどのソフトウェアパターンなどを使用して概念を抽象化する方法を学習してくださいDispose()

また、すべての重複コードが実際に重複しているわけではないことに注意してください。その一部は、グルーコードまたはアーキテクチャを維持するために必要なコードであるため、あまりにも乾燥していることに執着しないでください。


たぶん、私は自分の質問に答えられるほど明確ではなかったでしょう。これは次に来るものについてです。すべて完了しました。今度は、異なるプロジェクト間でコードを効果的に共有する必要があります。誰かが「そのためにナゲットを使うだけだ」と言って、詳細に出会って問題にぶつかるまで、それは素晴らしいことです-異なるブランチやアプリケーションからの異なる変更を同期する方法など。
ジョシュ

まあ、私はエリック・キングに同意します。基盤コードは、不安定なバージョンではなく、安定したバージョンとしてプッシュする必要があります。重要なのは、安定したAPIを維持することです。基盤メソッドのシグネチャが変更されないことがわかっている場合、基盤にメソッドを安全にプッシュし、後で何も壊さずにリファクタリングできます。
ロバートハーベイ

4

コードの再利用

コードの再利用には、長年にわたって支持されてきたいくつかのアプローチがありました。各アプローチには場所があり、さらに重要なことには問題がありますが、.NETでコードを再利用する実行可能な方法は次のとおりです。

  1. 共通ライブラリ。複数の場所で必要なコードは共通ライブラリに配置され、コードベースの他のすべての部分はこのコードへの単一の参照を持ちます。原則的な欠点は、多くの無関係な関数を含むこのライブラリに依存して、プロジェクトの大部分が終わることです。これは品質保証の観点からは悪い考えです。

  2. 共通ソースコード。複数の場所で必要なコードは一度書き込まれ、共通のディレクトリ構造のソースファイルに配置されます。このコードを必要とするすべてのプロジェクトには、ソースファイルの1つとしてこのファイルが含まれます。これにより、コードの再利用が可能になり、1回だけ書き込みを行う利点が多くなります。しかしながら。その欠点は、プロジェクトのさまざまな部分をこのコードのさまざまなバージョンでコンパイルできるようになることです。これにより、品質保証によって検出および特定するのが非常に難しい微妙な欠陥が生じる可能性があります。

  3. サービス。共通コードはサービスとして実装され、他の側面からアクセスできます。これには、デプロイメントに単一のサービスが存在するという利点があり、依存関係が回避されます。ただし、遅延と障害が発生します。この種のアプローチは、高可用性とフォールトトレランスがすでに理解および管理されている大規模な分散製品でうまく機能します。

NuGETの管理

ここには、もっと興味深い問題があります。複数の構成の管理。ここでの私のアドバイスは、異なるコードバージョンではなく、構成ファイルで多様な顧客ベースを管理することです。管理する構成データの少なくとも3つの層があります。顧客には決して見えない基本(内部)製品構成。顧客が変更する可能性のあるデフォルトの構成オプションと、顧客が変更した構成オプションの最終層。これらの異なる層を分離することにより、顧客の構成を破壊することなくアップグレードを展開できます。


1

問題は、nuget / source control / branchingにあるのではなく、コードの接着に陥るものにあると思います。

Robertにはいい答えがあります。全体像を見るために、これらの一般的なユーティリティが各プロジェクトにもたらす依存関係について考えることをお勧めします。

http://ayende.com/blog/3986/let-us-burn-all-those-pesky-util-common-libraries http://blog.jordanterrell.com/post/CommonUtility-Libraries-Dead.aspx

あなたが持っている地獄を避けるための最良の方法は、グルーコードをオープンソースにすることです。このようにして、ビジネスロジックが公開されないため、具体的なプロジェクトの依存関係がグルーコードに滑り込まないように気を付け始めます。それは、社外でも誰でも再利用できるほど抽象的です。コードで十分です-コミュニティの意見も得られます。


グルーコードの管理については話していない。既に解決策があり、うまく機能している。ビジネスロジックの共有について話をしている。たとえば、アプリケーションは組織や人の管理を扱っている。人を作成すると、人の作成方法に関連する多数のビジネスルールがあります。何度も作成するのではなく、オブジェクトの作成から永続化までをすべて処理する1つのパッケージが必要です。人々を作成する必要があります
ジョシュ

0

解決策は簡単です。そのための個別のプロジェクトを作成し、それを個別の要件として管理します。独自の要件、テスト、規則、文書化、計画、人などです。問題を引き起こす前に最初に評価されます。

またはそれ以上:組織内で「オープンソース」にします。したがって、誰でもコードを変更できますが、完全なコミット権を持つのは選択した少数の人だけです。そして、それらの人々は品質と正しい機能を保証する責任があります。

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