OOP: Inverse of Aggregation? - oop

In OOP when a class forms a HAS-A relationship with another class, it's called an Aggregation, a simple example of that is below where a Car has an Engine but an engine can exist without a car:
class Engine {
start() {
console.log('Engine started');
}
}
class Car {
engine: Engine;
constructor(engine: Engine) {
this.engine = engine;
}
}
Question:
If i had to do the inverse of Aggregation such that i could answer a query Give me all the cars associated with this Engine, what is that called in OOP?

The aggregation (or composition, or association) is a concept: it allows to say that A has a B. You can invert the composition (B has an A) but the concept itself has no "inverse". Or it would be: A does not have B !

has-a as a static relationship gets translated to Aggregation. In a typical Object oriented modeling, after identifying the static relationship between two entities, next question we ask is which is more frequent direction in which we will be raising the queries.
In your example it is one-to-one relationship between objects (vehicle has only one engine and engine is mounted on only one vehicle at given moment).
If most of the time the query is getMeThisVehiclesEngine() (container to contained), then Vehicle holds the reference of engine, if the query is opposite (I think this is kind of your inverse) like getMeTheVehicleWhichIsHoldingThisEngine() (content to container. Here container and content terms are from the domain perspective), then engine will hold the reference of vehicle, and I would call it association. If we need bidirectional navigation, both objects keep each others reference. (In general we avoid bidirectional relationship). with one to one relationship, its not that obvious, but imagine an example of shared aggregation with has-a relationship between Athletics Team and member-student. member-students can be part of different teams simultaneously. From team to student-member I would call it as aggregation and Team will hold collection of Students. From Student-member to Team I would call it association (Student is associated with Athletics Team) and Student will hold either simple reference of Athletics team, or collection of Teams, if Student can be member of multiple teams simultaneously.

Related

How would you decouple a scenario of lessons and students?

Assume you are making a software that manages classes and students.
I'd assume you would have an administrator class, lesson class, and student class.
The administrator class can have various functions such as "get the list of all available lessons" or "get the list of all lessons that a student is enrolled in".
Here's the tricky part.
A lesson can have many students while a student can have many lessons.
Here are some implementations I have thought of:
Lesson class contains list of students and student class contains list of lessons:
Pro: Straightforward, Con: Coupled
Lesson class contains list of students and in order to do "get all lessons a student is enrolled in" the administrator class would first get all lessons and then filter lessons containing that student.
Pro: Not coupled, Con: Inefficient computing
In the administrator class, have the following fields :
HashMap<Lesson, [Student]>
HashMap<Student, [Lesson]>
Pro: Not coupled, Con: Messy
None of them seem satisfying to me. Can I get some feedback on this dilemma? What is the typically accepted design pattern?
I wouldn't have the complete Student object inside Lesson objects and vice versa.
Lesson class contains a Set of studentIds of the subscribed students
Student class contains a Set of lessonIds in which they are subscribed to.
Your Administrator class can use these Ids to map, filter, retrieve lessons, students and their relationships.
Edit:
I have to say, that in a real life scenario where your data would be persisted for example in a relational database, you should have a table Students, a table Lessons and a table StudentsLessons with studentId and lessonId as foreign keys.
This is how I would go about it considering the fact that in future I might need to persist them in the DB.
The relationship between student and lesson is many-to-many and hence you need to setup bi-directional
or unidirectional relationship with these two classes.
Bi-directional - List of lessons in Student class and vice versa
Unidirectional - Either list of lessons in Student or list of
students in Lesson class
For example sake, I am setting unidirectional relationship
class Student {
private List<Lesson> lessions;
// other attributes
}
class Lesson {
// Lesson attributes
}
The Administrator class you are talking about is actually a good candidate for service class because it's providing services
such as "get the list of all available lessons"
For Lesson related queries, I'll create LessonService
class LessonService {
// Get the list of all available lessons
List<Lesson> findAllLessons() {...}
// Get all lessons a student is enrolled in
List<Lession> findAllLessons(Student student) {...}
}
and finally, there would a repository/dao layer that will abstract underlying database.
Your repository could be a simple collection based in-memory or represent the actual database.

difference between association and aggregation

I understand the difference between aggregation and composition but I am struggling a bit with association. My current understanding is that an association exists between classes when ‘they use each other’, for example, one object is passed to the other during a method call. See also:
http://www.codeproject.com/Articles/330447/Understanding-Association-Aggregation-and-Composit
Both objects exist independently and, in contrast to aggregation, no object is a container class of the other. Does this mean that both objects MUST have a copy of the other(s) (e.g. 1:m relationship) or how else is the association ‘stored’. Any feedback would be very much appreciated.
From the UML Superstructure 2.4.1:
An association declares that there can be links between instances of the associated types. A link is a tuple with one value for each end of the association, where each value is an instance of the type of the end. (UML Superstructure, Page 37)
Nothing more, nothing less. and very vague. Because of this, it is also very hard to understand. What I defined (In a course I teach) is a hierarchy of links from dependency to composition where:
Dependency from A to B means that A uses B but indirectly (say by receiving instances of it and forwarding them to other objects).
Association from A to B means that A uses B directly, (for example by calling methods)
Aggregation from A to B means that B is part of A (semantically) but B can be shared and if A is deleted, B is not deleted. Note that this says nothing about how the "is part" is implemented.
Composition from A to B is like Aggregation, where B cannot be shared and if A is deleted, all of its aggregates (Bs) are deleted also.
Aggregation is an Association relationship where the Association can be considered the containing class 'Owning' the contained class, and the lifetime of that relationship is not defined.
Association is an 'Has-A' relationship.
Example:-
public class Person
{
private final Name name;
private Address currentAddress;
//...
}
In this case, the Person Has-A name and Has-A Address, so there is an Association between Person and Name, and Person and Address.
An association describes a relationship between instances of one or more classes. In the words of the UML Reference Manual, "Associations are the glue that holds together a system."
Aggregation is a form of association in which there is a "whole-part" relationship. You may say that if a class Airplane has a class Engine then this forms a "whole-part" relationship.
Aggregation
Let's set the terms. The Aggregation is a metaterm in the UML standard, and means BOTH composition and shared aggregation, simply named shared. Too often it is named incorrectly "aggregation". It is BAD, for composition is an aggregation, too. As I understand, you meant you understand "shared aggregation and composition".
From UML standard:
Precise semantics of shared aggregation varies by application area and
modeler.
I haven't found a word about that aggregation supposed multiplicity, for example.
Association.
A definition from UML 3.4.1 standard:
An association describes a set of tuples whose values refer to typed
instances. An instance of an association is called a link. A link is a
tuple with one value for each end of the association, where each value
is an instance of the type of the end.
Aggregated relationship is a subclass of Association.
Association is based on relationship. IT is the glue for models.
But your feelings didn't lie - as the shared aggregation is not strictly defined, there is also NO any strictly defined boundary between Association and Aggregated association. Authors of tools and modellers have to set it themselves.
Association
It represents a relationship between two or more objects where all objects have their own lifecycle and there is no owner. The name of an association specifies the nature of relationship between objects. This is represented by a solid line.
Let’s take an example of relationship between Teacher and Student. Multiple students can associate with a single teacher and a single student can associate with multiple teachers. But there is no ownership between the objects and both have their own lifecycle. Both can be created and deleted independently.
Aggregation
It is a specialized form of Association where all object have their own lifecycle but there is ownership. This represents “whole-part or a-part-of” relationship. This is represented by a hollow diamond followed by a line.
Let’s take an example of relationship between Department and Teacher. A Teacher may belongs to multiple departments. Hence Teacher is a part of multiple departments. But if we delete a Department, Teacher Object will not destroy.
It depends on the context.
Association: A man drives a car, focus on the caller and callee relationship.
Aggregation: A man has a car, focus on the owner and member relationship.
Composition: A man has a mouth, focus on the owner & member but the owner consists of members, it means that they shared the same life cycle.
Feels like I'm speaking Chinglish.
Association
Association is a relationship where all objects have their own life-cycle and there is no owner. Let’s take the example of Teacher and Student. Multiple students can associate with a single teacher and a single student can associate with multiple teachers but there is no ownership between the objects and both have their own life-cycle. Both can create and delete independently.
Aggregation
the objects in Aggregation have their own life-cycle but there is ownership. Child object can not belong to another parent object. Let’s take an example of Department and teacher. A single teacher can not belongs to multiple departments, but if we delete the department teacher object will not destroy. We can think about the “has-a” relationship.
Composition
It is a strong type of Aggregation. Child object does not have their life-cycle and if parent object deletes all child object will also be deleted. Let’s take again an example of the relationship between House and rooms. House can contain multiple rooms there is no independent life of room and any room can not belongs to two different houses if we delete the house room will automatically delete.
An association between object types classifies relationships between objects of those types. For instance, the association Committee-has-ClubMember-as-chair, which is visualized as a connection line in the class diagram shown below, may classify the relationships FinanceCommittee-has-PeterMiller-as-chair, RecruitmentCommittee-has-SusanSmith-as-chair and AdvisoryCommittee-has-SarahAnderson-as-chair, where the objects PeterMiller, SusanSmith and SarahAnderson are of type ClubMember, and the objects FinanceCommittee, RecruitmentCommittee and AdvisoryCommittee are of type Committee.
See also my alternative CodeProject article.

Understanding when to use inheritance to allow one class to use instances of another

When creating classes, is there a rule for when to use inheritance and when to import a new class, without inheritance, into another?
Here’s an example:
I make a class called Person, and then create lots of Person objects.
I then create a child class called House. Using inheritance and properties, all my Person objects can now have a House.
I then create a child class called Car so all my Person objects now have Houses and Cars.
and so on… and so on….
I now have this sequence of classes:
NSObject < Person < House < Car < new Class < another new Class, etc.
With the above scenario, my logic (I'm an Objective-C beginner) tells me I have two different ways of producing the same outcome:
As explained above, or
Create each class without inheritance and then import it into Person as an ivar – for example, an instance of House now becomes a type, and that is then imported into a Person object using properties.
Please excuse my lack of terminology and understanding. If required, I can upload a code example but it’s more of a general question on when and when not to use inheritance.
This question is not specific to Objective-C: the guideline for when to use inheritance is the same for all object-oriented languages, and it is based on substitutability, summarized by the Liskov Substitution Principle:
if S is a subtype of T, then objects of type T may be replaced with objects of type S
In other words, use inheritance only when you can say "{derived} is a {base}>"; when you model a "{owner} has a {something}", use composition
Student is a Person -- Inheritance
Car is a vehicle -- Inheritance
Person has a House -- Composition (ivar or property)
Car has a(n) Engine -- Composition (ivar or property)

Member "Is-A" Person or Person "Has-A" Enrollment

I am trynig to create a set of Models for our Enterprise App. It has never had them being tied very tightly to the Databases. At this point I am trynig to simply answer the "Is-A" or "Has-A" questions. I am basing this off the DB structure but I do not want to, neccesarily, be tied to that.
For starters I have the, very, obvious Person model with the typical "Has-A" Phone and Address. Almost everything works off of that Person model and is a "Has-A".
However, we have Members. In our DB/Current System a Member is a Person who has an Enrollment. To be specific an Enrollment of a certain type that is Dis-Enrolled(by Date).
On one hand I feel that Member would Inherit form Person as a "Is-A" relationship. However I am very new to this type of thing and I wonder if I am over thinking it. Does my Person "Has-A" Enrollment or does that imply something else?
It makes me wonder, if I do have a Member should I have different "Is-A" models for Pre-Enrollments, Enrollments, Former Enrollments? It seems that is more a question of State but again, I am new at this. If it is a question of state am I back to just having a Person model that "Has-A" Enrollment?
I understand this is, somewhat, opinion based and I welcome each persons opinion on this.
It makes more sense that Person be higher up in the heirarchy. From the group of all People, you have some members, some ex-members, and some members-to-be.
If you try to look at it the other way and say From the group of all Members, all are people...but some are Dis-Enrolled? It makes less sense that way since if they are Dis-Enrolled, then they are no longer members.
Unless being a Member and Enrollment are not connected (ie. if you can be dis-enrolled and still be a member).
Well, I'll try to answer you question though I don't fully understand what is "Enrollment" (I'm not native english speaker) I guess it some kind of Membership.
Suppose you will decide to use IS-A relationship, so you would end up with:
Member:Person, VIPMember:Member, ExMember:Member, etc. What would you do if you Person object changes to Member or anything else? You will have to convert you object to this type, create a Member object copy values from Person object... thats lots of boilerplate work.
If Object changes it Type after it's creation better use some property to distinguish it's type. Cosider Apple : Fruit (Apple is always Fruit, it can't become Tomato), and CanceledOrder : Order (Order can become CancledOrder so I would prefer Order.State). This is especially true for languages when once the object is created you can't change it's type (like C#).
As for your case from what I understood I would create:
public class Person
{
public IEnumerable<Membership> Memberships {get;}
public bool IsMember
{
get
{
return Memberships.Any();
//Or what ever logic you imply
}
}
}

DDD: subclasses & root entities

Let's say I have the typical entity Car
class Car : Entity
{
public double MaxSpeed { get; set; }
public Color Color { get; set; }
/* ... */
}
This entity, in my domain model, would be the root entity of an Aggregate.
Now let's say I specialize cars. I create a Ferrari, and the happy owners of Ferraris like to call them by a nickname:
class Ferrari : Car
{
public string Nickname { get; set; }
}
Let's say I have another entity, the Company entity. It would be the root entity of another Aggregate. There are many people working on a company, represented by the entity Person. Persons may have cars. But the President of a company is usually very rich and this kind of people, they have Ferraris:
class President : Person
{
public Ferrari Ferrari { get; set; }
}
In this situation, I have the entity President, who is inside the Company Aggregate, that is holding a reference to a Ferrari, an specialization of the root entity of another aggregate.
Is this correct in view of DDD? Can/should I consider the specialization of root entities themselves as root entities of the same aggregate? I mean, in the domain I described, is the entity Ferrari also the root entity of the Car Aggregate (since Ferrari is also a Car)?
Now let's say I have to persist this model to a Database. I think that my question does not depend on the OR/M framework I will use.
How should I build the table holding Cars? Should I build a single table Cars, with a "CarType" column (possible values: "Car", "Ferrari"), and a nullable Nickname column?
Or should I build a table for Cars and a table for Ferraris, the latter one having its PK a FK of Cars?
Thanks!
Generally when you cross root aggregate boundaries you only allow the reference to be of the ID of the other root aggregate. You then use that ID to look up the other aggregate in its repository.
So in your case you would want President to have a Car ID and if you ever needed to do something to the President's car you would use the Car ID to go to the repository to get the car. President would not have a reference to the Car itself.
Now about that Ferrari. It's kind of difficult to enforce that in standard DDD terminology. Normally you would put some validation on the assignment of a Car to a President. Or perhaps there is a CarBuyingService just for Presidents that makes sure you get it right. Normally in DDD specializations are not themselves root aggregates.
You shouldn't use inheritance to model your domain because you will soon run into trouble once model starts to get complex.
President is simply a role of the person and person can have multiple roles. Maybe president got just one role but that's simply accidental by choosing wrong example.
Ferrari shouldn't be inherited from car either. It's not obvious on Ferrari example, because they only do one type of cars but consider company making many types like vans, sedans, hatchbacks, trucks and so on. You will probably want to make classes for every type that will inherit from car class. And then what... are you going to make five Toyota classes that will inherit from each type? Such as...
Car -> Sedan -> ToyotaSedan
Car -> Truck -> ToyotaTruck
Car -> Hatchback -> ToyotaHatchback
That would be ridiculous.
Disclaimer: I know nothing about about cars. However...
Don't use inheritance to model your domain. Ever.
Try it without inheritance and it will also became obvious how to persist your domain.
I think you start losing a lot of the flexibility of the system by creating concrete types of these entities. The type of relationship that you are implying is something I generally hand with a "Type" entity. For example, you have a car. A Ferrari is a type of car. The two entities that are borne from that are a Car and a CarType.
The way that you are talking about doing it, you would have to add new entities every time a new type is introduced. If all that you are trying to capture is the "nickname" of the car, I would think that is just another piece of data, and not another entity. Unless you have different data (i.e. different property names) and/or behavior differences in Car entities for different types, you do not gain much with this approach. I would rather have repository methods like FindCarByType() and deal with one type of entity, to reduce risk.
I am by no means a DDD expert, and I am struggling with some concepts (or more like struggling with the multiple interpretations of some concepts). I am finding that there is not a 100% pure implementation, and that there are nuances to each implementation that I have seen.
Edit Follows
I see that I misread part of what you had written. I see that nickname is not for all vehicles, but just for Ferrari : Car. I think that the answer is really "it depends". How much domain specialization do you have in the rest of your model? Having a nickname might be prevalent amongst Ferrari entities, but is it exclusive? It isn't only about the actual data, but the requirements. Basically it comes down to how much specialization your are expecting in these entities.