UMLでの構成と集約の違いを理解するのに苦労しました。誰かが私にそれらの良い比較とコントラストを提供してくれますか?また、それらの違いをコードで認識したり、短いソフトウェア/コードの例を見たりしたいと思っています。
編集:私が尋ねる理由の一部は、私たちが仕事で行っている逆の文書化活動のためです。コードを記述しましたが、戻ってコードのクラス図を作成する必要があります。関連付けを適切にキャプチャしたいだけです。
UMLでの構成と集約の違いを理解するのに苦労しました。誰かが私にそれらの良い比較とコントラストを提供してくれますか?また、それらの違いをコードで認識したり、短いソフトウェア/コードの例を見たりしたいと思っています。
編集:私が尋ねる理由の一部は、私たちが仕事で行っている逆の文書化活動のためです。コードを記述しましたが、戻ってコードのクラス図を作成する必要があります。関連付けを適切にキャプチャしたいだけです。
回答:
集約と構成の違いは、コンテキストによって異なります。
別の回答で言及されている車の例を見てみましょう。そうです、車の排気ガスは「それ自体」で立つことができるため、車との構成にはならない可能性がありますが、それはアプリケーションによって異なります。スタンドアロンの自動車の排気ガスを実際に処理する必要があるアプリケーション(自動車店の管理アプリケーション?)を作成する場合は、集約が最適です。しかし、これが単純なレーシングゲームであり、車の排気ガスが車の一部としてのみ機能する場合は、まあ、構図は非常にうまくいきます。
チェス盤?同じ問題。チェスの駒は、特定のアプリケーションでのみ、チェス盤なしでは存在しません。他のもの(おもちゃメーカーのそれのような)では、チェスの駒は確かにチェス盤にはなりません。
構成/集約をお気に入りのプログラミング言語にマッピングしようとすると、事態はさらに悪化します。一部の言語では違いがわかりやすい場合がありますが(単純な場合は「参照による」と「値による」)、他の言語ではまったく存在しない場合があります。
そして最後のアドバイスは?この問題に時間をかけすぎないでください。それは価値がありません。この区別は実際にはほとんど役に立ちません(完全に明確な「構成」があっても、キャッシングなどの技術的な理由により、それを集約として実装したい場合があります)。
経験則として:
class Person {
private Heart heart;
private List<Hand> hands;
}
class City {
private List<Tree> trees;
private List<Car> cars
}
コンポジション(Person、Heart、Hand)では、Personが破壊されるとすぐに「サブオブジェクト」(Heart、Hand)が破壊されます。
集約(City、Tree、Car)では、Cityが破棄されても「サブオブジェクト」(Tree、Car)は破棄されません。
要するに、構成は相互の存在に重点を置いており、総計では、この特性は必要ありません。
構成と集約は、関連のタイプです。それらは非常に密接に関連しており、プログラミングに関しては、2つの間に大きな違いはないようです。これら2つの違いをJavaコード例で説明しようと思います
集約:オブジェクトは他の外部に存在し、外部で作成されるため、(たとえば)引数としてコンストラクターに渡されます。例:人-車。車は異なるコンテキストで作成され、個人のプロパティになります。
// code example for Aggregation:
// reference existing HttpListener and RequestProcessor
public class WebServer {
private HttpListener listener;
private RequestProcessor processor;
public WebServer(HttpListener listener, RequestProcessor processor) {
this.listener = listener;
this.processor = processor;
}
}
構成:オブジェクトは、他の一部として存在するか、他のオブジェクトの内部でのみ意味があります。例:人々–心。ハートを作って人に渡すのではありません。代わりに、人間が作成されたときに心が作成されます。
// code example for composition:
// create own HttpListener and RequestProcessor
public class WebServer {
private HttpListener listener;
private RequestProcessor processor;
public WebServer() {
this.listener = new HttpListener(80);
this.processor = new RequestProcessor(“/www/root”);
}
}
ここでは、集計と構成の違いの例を使用して説明します
私が学んだ例は手への指でした。あなたの手は指で構成されています。それを所有しています。手が死ぬと指が死ぬ。指を「集約」することはできません。余分な指をつかんで、自由に手に付けたり外したりすることはできません。
別のポスターが言ったように、ここでの値は、設計の観点から、オブジェクトの寿命に関連していることがよくあります。あなたには顧客がいて、彼らはアカウントを持っているとしましょう。そのアカウントは、顧客の「構成された」オブジェクトです(少なくとも、私が考えることができるほとんどのコンテキストでは)。顧客を削除すると、アカウント自体に価値がないため、アカウントも削除されます。オブジェクトの作成では、多くの場合その逆が当てはまります。アカウントは顧客のコンテキストでのみ意味があるため、顧客の作成の一部としてアカウントの作成を行う必要があります(または、遅延して作成する場合は、一部の顧客トランザクションの一部になります)。
どのオブジェクトが他のオブジェクトを所有(構成)するのか、他のオブジェクトを参照(集約)するだけのオブジェクトを考えるのは、設計に役立ちます。オブジェクトの作成/クリーンアップ/更新の責任がどこにあるかを判断するのに役立ちます。
コードに関しては、多くの場合、わかりにくいです。コード内のほとんどすべてがオブジェクト参照であるため、参照されたオブジェクトが構成(所有)されているのか集約されているのかが明確でない場合があります。
部分全体 - 関連付けの概念の集約と構成の違いについて、どれほど混乱があるかは驚くべきことです。。主な問題は、(エキスパートソフトウェア開発者やUMLの作成者の間でさえ)構成の概念が全体とその部分の間のライフサイクル依存関係を意味し、全体がなければ部分が存在できないという誤解が広まっていることです。しかし、この見解では、パーツを切り離すことができ、全体が破壊されても存続できる共有不可能なパーツとの一部全体の関連付けの事例もあるという事実を無視しています。
UML仕様書では、「構成」という用語の定義は常に共有できない部分を意味していましたが、「構成」の定義的な特性が何であるか、および単なるオプションの特性であるものは明確ではありませんでした。新しいバージョン(2015年時点)でも、UML 2.5は、「構成」という用語の定義を改善しようとした後も、あいまいなままであり、非全体との部分全体の関連付けをモデル化する方法のガイダンスを提供しませんパーツを取り外すことができず、全体と一緒に破壊される場合とは対照的に、パーツを取り外し、全体の破壊に耐えることができる共有可能パーツ。彼らが言うには
複合オブジェクトが削除されると、オブジェクトであるそのすべてのパーツインスタンスも一緒に削除されます。
しかし同時に彼らはまた言います
部品オブジェクトは、複合オブジェクトが削除される前に複合オブジェクトから削除される場合があるため、複合オブジェクトの一部としては削除されません。
この混乱は、コンポーネントとコンポジットの間のライフサイクルの依存関係を考慮していないUML定義の不完全性を示しています。したがって、コンポーネントをコンポジットから切り離せないため、コンポジットを破棄するたびに破棄する必要がある<< 分離不可能な >>コンポジションのUMLステレオタイプを導入することで、UML定義をどのように拡張できるかを理解することが重要です。
Martin Fowler氏が説明している、組成物を特徴付けるための主な問題は、「オブジェクトは一つだけの組成の関係の一部とすることができる」ということです。これは、Geert Bellekensによる優れたブログ投稿UML構成vs集約vs関連付けでも説明されています。コンポジションのこの定義的な特性(排他的または共有不可のパーツを持つため)に加えて、コンポジットには、コンポジットとそのコンポーネントの間のライフサイクル依存性が伴う場合があります。実際、このような依存関係には次の2種類があります。
Person
との間の構成によって例示されHeart
ます。心臓は、その所有者が死亡したときに破壊されるか、別の人に移植されます。Person
との間の構成Brain
です。要約すると、ライフサイクルの依存関係は、構成の特定のケースにのみ適用されますが、一般的には適用されないため、定義上の特性ではありません。
UML仕様には、「複合インスタンスが削除される前に複合インスタンスからパーツが削除される可能性があるため、複合インスタンスの一部として削除されない」と記載されています。Car
- Engine
構成の例では、次の図に示すように、車が破壊される前にエンジンを車から取り外すことができ、その場合、エンジンは破壊されずに再利用できます。これは、構成線の複合側のゼロまたは1つの多重度によって暗示されます。
コンポジット側のコンポジションの関連端の多重度は、コンポーネントに必須のコンポジットがある(コンポジットにアタッチする必要がある)かどうかに応じて、1または0..1のいずれかです。コンポーネントが分離不可能である場合、これは必須のコンポジットがあることを意味します。
集約は、全体の一部を他の全体と共有できる部分全体の関係の意図された意味との関連付けのもう1つの特別な形式です。たとえば、コースは学位プログラムの一部であり、コースは2つ以上の学位プログラム間で共有できるため(たとえば、工学学位はCを共有できます)、次の図に示すように、クラスDegreeProgram
との間の集約をモデル化Course
できます。コンピュータサイエンスの学位を取得したプログラミングコース)。
ただし、共有可能な部分を含む集計の概念は実際にはあまり意味がないため、実装に影響を与えないため、多くの開発者はクラス図で白いひし形を使用せず、単純な関連付けをモデル化します代わりに。UML仕様には、「共有集約の正確なセマンティクスは、アプリケーション領域とモデラーによって異なります」とあります。
全体の側でのアグリゲーションのアソシエーションエンドの多重度は、任意の数(*)にすることができます。これは、一部が任意の数の全体に属している、または共有されているためです。
コード用語では、コンポジションは通常、含まれているオブジェクトがコンポーネントのインスタンスを作成する責任があることを示唆しています*。そして、含まれているオブジェクトは、それへの長期の参照のみを保持します。したがって、親オブジェクトが逆参照されてガベージコレクションされると、子もそうなります。
このコード...
Class Order
private Collection<LineItem> items;
...
void addOrderLine(Item sku, int quantity){
items.add(new LineItem(sku, quantity));
}
}
LineItemはOrderのコンポーネントであることを示唆しています-LineItemsはそれらを含む注文以外には存在しません。ただし、Itemオブジェクトは注文どおりに作成されません。これらは必要に応じて渡され、ショップに注文がない場合でも存在し続けます。コンポーネントではなく、関連付けられています。
* nbコンテナはコンポーネントのインスタンス化を担当しますが、実際にはnew ...()自体を呼び出さない場合があります-これはJavaであり、通常、最初に実行するファクトリが1つまたは2つあります。
他の回答で提供されている概念図は役に立ちますが、私が役に立ったと思った別のポイントを共有したいと思います。
コード生成、ソースコード、またはリレーショナルデータベースのDDLのために、UMLからいくつかのメリットを得ました。そこで、私はコードを使用して、テーブルにnull不可の外部キー(データベース内)とnull不可の「親」(およびしばしば「最終」)オブジェクトがあることを示すために構成を使用しました。レコードまたはオブジェクトを、親オブジェクトに関連付けられていない「孤児」として存在できるようにしたり、別の親オブジェクトによって「採用」したりする場合に、集計を使用します。
つまり、モデルのコードを記述するときに必要になる可能性があるいくつかの追加の制約を示すために、構成表記法を省略表現として使用しました。
私が好む例: 構成: 水は池の一部です。(池は水の構成要素です。) 集合: 池にはアヒルと魚がいます(池はアヒルと魚を集約しています)
ご覧のとおり、「part-of」と「has」を太字にしています。これらの2つのフレーズは通常、クラス間に存在する接続の種類を示すことができるためです。
しかし、他の人が指摘したように、接続がコンポジションであるか集約であるかは、多くの場合アプリケーションに依存します。
集計リレーションとコンポジットリレーションを区別するのは難しいので、いくつか例を挙げます。ここには家と部屋があります。ここにはコンポジットリレーションがあり、部屋は家の一部であり、ルームライフが始まりました。ハウスライフとウィルは、ハウスライフが終わったときに終わり、部屋は家の一部です。国や首都、本やページなどの構成について話します。総計の関係の例として、チームとプレーヤーを取り上げます。プレーヤーはチームなしで存在でき、チームはプレーヤーのグループであり、プレーヤーのライフはチームライフの前に開始できます。プログラミングについて話せば、プレーヤーを作成でき、その後チームを作成します。しかし作曲の場合は、家の中に部屋を作成します。合成---->合成|合成。集約------->グループ| 素子
条件を設定しましょう。集約はUML標準のメタタームであり、単にsharedという名前の構成と共有集約の両方を意味します。多くの場合、誤って「集計」と呼ばれます。構成も集合体なので悪いです。私が理解しているように、あなたは「共有」という意味です。
UML標準からさらに:
composite-プロパティが複合的に集約されていることを示します。つまり、複合オブジェクトは、構成されたオブジェクト(パーツ)の存在と格納に責任を持ちます。
したがって、大学とカテドラルの関連付けは構成です。大学外にはカテーテルが存在しないためです(IMHO)
共有集約の正確なセマンティクスは、アプリケーション領域とモデラーによって異なります。
つまり、自分または他の誰かのいくつかの原則に従っているだけの場合は、他のすべての関連付けを共有集約として描画できます。また、見てここに。