web-dev-qa-db-ja.com

オープンソースライブラリ間でコードを共有するためのベストプラクティス

私はAndroidライブラリをかなりの数の人が使用しています。ライブラリAと呼びましょう。

2つ目のライブラリであるライブラリBを構築しています。

2つのライブラリーは概念的に関連しており、同じドメインのさまざまな問題を解決します。 2つのライブラリは一緒に使用される可能性がありますが、必須ではありません。

問題:ライブラリAには、ライブラリBで再利用したいクラスとインターフェースがいくつか含まれています。

これを行う方法に関するベストプラクティスはありますか?私がこの問題に遭遇したのはこれが初めてであり、他の人々が使用するライブラリーであるため、より意味のあるソリューションを実装したいと考えています。

私は3つのアプローチを見ることができます:

  1. ライブラリAからライブラリBに、再利用するインターフェイスとクラスをコピーして貼り付けます。
  2. ライブラリAをライブラリBにインポートします。
  3. ライブラリAから、再利用するインターフェイスとクラスを取り出し、それらを新しいCOREライブラリに公開して、ライブラリAとライブラリBの両方にCOREライブラリをインポートします。

検討していない可能なアプローチは他にもありますか?

私がこの解決策で見ることができる問題:

  1. これはより悪い解決策です。 DRYの原則には従いません。最も重要なのは、両方のライブラリのユーザーがcom.libraryA.Interface1およびcom.libraryB.Interface1。これは、ライブラリAとBの間の素敵な相互作用を可能にしません。
  2. ライブラリBは、必要のない一連のコードをインポートします。最も重要なことは、AからBへの共有インターフェースのため、ライブラリBのユーザーは常にライブラリAをインポートする必要があるということです。
  3. これは最もエレガントなソリューションのようですが、この状況でバージョン管理をどのように処理する必要がありますか?ライブラリA、B、およびCOREは常に同じバージョン番号を持つ必要がありますか?そうでない場合、A、B、COREに異なるバージョン番号を付けるのは理にかなっていますか? COREの変更はAとBの両方に影響し、3つすべてにバージョンバンプが必要です。 AとBの変更は分離されます。

まだ見られない問題はありますか?

3番目のオプションが正しいかどうかは、状況によって異なります。基本的な質問は、Aに現在2つのものが含まれていて、実際にはかなり離れており、それぞれが別個のエンティティとして役立つかどうかです。

たとえば、Aを2つに分割し、AとBの両方をクライアントとするコアがある場合、コアはC、D、Eをサポートする上で優れた機能を果たす可能性がありますか?

または、AがコアとAプライムに分割された場合、基本的には中央で分割される単一のものになり、おそらくC、D、またはEはコアとAプライムの両方の部分を使用する必要があります?

それを決定したら、結論はおそらくかなり明白になります:Aが実際に(現在)同じライブラリに存在する2つの別々のことを表し、それらを分離すると、それ自体でよりきれいに使用できるコアが得られます、次に先に進み、それらを分離します。

一方、AのほぼすべてのクライアントがAの提供するものの80%(または何でも)を使用する可能性が高いが、それぞれが異なる80%を使用する場合、全体としてそのままにしておくのが理にかなっています。 。

バージョン管理について:Aを1つにしたままにするか、Aを2つに分割するかにかかわらず、ほぼ同じ問題が発生します。つまり、ライブラリに(少なくとも)Aに依存するライブラリが1つあります。

かなり一般的な戦略の1つは、バージョン管理を2つのカテゴリに分けることです。マイナーな変更はバグ修正などですが、文書化された動作のみに依存するクライアントの場合、新しいバージョンのライブラリが古いバージョンの代わりとして機能する必要があります。つまり、バグを修正して機能を追加できますが、文書化された動作に重要な変更を加えることはできません。

文書化された動作に変更を加えた場合、それはメジャーバージョンの変更になります。クライアントが変更を認識している必要があります。

したがって、Aを半分に分割するかどうかに関係なく、Bは別のものに依存しています。マイナーバージョンの場合、一部のクライアントは1.1以降に依存しており、別のクライアントは1.2以降に依存している可能性があります(ただし、どちらの場合も、「または新しい」には1.xのみが含まれ、一部の2.xは含まれません)。

それらのすべてに同じバージョン番号を使用することは、明らかに異なるライブラリがいくつかある場合にほとんどの利点ですが、(何らかの理由で)十分に頻繁に一緒に使用され、ユーザーがそれらを一緒に追跡しやすくなるため、 AとBの両方を使用している場合、3つのバージョン番号を追跡する必要はありません。

4
Jerry Coffin

明白で正しい解決策は(2)です。BをAのクライアントにします。

確かに、Bは必要以上にインポートしますが、これは99%のライブラリクライアントの場合です。ライブラリAの内部をよく理解しているため、誤解されているだけで、通常よりも非効率に気づいています。作業の分割の利点は、この概念的な非効率性をはるかに上回ります。

6
Kilian Foth