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