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

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
}
}
}

Related

Extend the school timetable example (quarkus guide)

I want to extend the timetable example of the quarkus guide with the entity student. Each student grades all courses (eg. 1-6, more is better). Each student can visit all courses. I am looking for a student - course - allocation, so that the global sum of grades is maximal.
Can I do this with only 1 PlanningEntity or must I have 2?
Is there a trick to add a PlanningVariable List<Student> to Lesson?
I 'd argue this is a different planning problem, with a different Solver configuration (so a different #PlanningSolution and #PlanningEntity class) but which can reuse problem fact classes (Room, Timeslot, etc).
In practice, I'd remove the #PlanningEntity annotation (and the #PlanningVariable annotations) from the Lesson class, because the lesson to room/timeslot assignments will be part of the input, not part of the planning optimization. I am not sure if you even need room/timeslot information at all.
We don't support lists of planning variable (#PlanningVariableCollection) yet and I doubt it would be a good fit here because the order of the students in the list doesn't matter. A set might, but we don't support that either yet. It is being worked on. In any case, there's a much simpler solution:
Create a planning entity StudentToCourseAssignment class. Follow the docs chapter 22 domain modeling guide to decide if the planning variable is on the student field xor the course field.
Also replace the TimeTable class accordingly.

How to model a domain object that can be of several types (in several states)?

Example : Having a human that can own 1 or more pets of different types (cat, dog, elephant, seal etc) .
I would think of making an aggregate that would have Human as root (that holds petCollection as reference to Pet) and another aggregate that would have Pet as root (with cat, dog, elephant, eagle as children for this aggregate) .
The problem is that each pet type can have different behaviour (example : a seal can swin() but it won't fly() / an eagle can fly() but it won't swim() ) . So a state or strategy pattern does not seem right . How can a human tell a pet object to run() if it doesn't know it's type ? Using the state/strategy pattern, the objects need to have similar behaviour . Doing an if/else (for the case of polymorphism to check the object type) check again , doesn't seem a proper design .
How should i design this domain or what patterns can help me here ?
Generally speaking, if something (only/always) is something, you should use Inheritance.
If something does something, you should use an Interface.
If something plays the role of something (e.g. a Legal Party plays the role of a Customer and/or a Supplier) you should use Composition.
So Seal inherits Animal and implements Swim, Bark
and
Dog inherits Animal and implements Run, Bark
If you want your animals to swim, then either iterate them checking if they implement Swim and then call swim(), or filter the collection prior to iterating through it to get the animals that implement Swim.
Aggregate roots and inheritance is not a very good idea typically.
You probably want to avoid one Aggregate to have a collection of other Aggregates.
The idea of the Aggregate (well, one of them) is that it represents transaction boundary, therefore there, ideally, should be no need in this structure.
It is normal, however, when one Aggregate has a collection of other Aggregates IDs.
I'm not sure there's anything really architecture or DDD related here. It's just basic OO (polymorphism).
If your starting point is a single pet and you want to trigger a behavior particular to its species, no secret - the caller has to know which subtype the pet is and reference the object with its real subtype, not Pet.
If your starting point is a Human and you want to call some behavior across all or part of its pets, you need to reason about something more abstract. If I understand the domain well, something like "an action that a human can tell an animal to perform".
Once you've found the proper name for that, create an abstract method with that name on Pet and have every subclass of Pet implement it in its own way. Then, thanks to polymorphism, you can tell a collection of pets to do it regardless of whether they are cats, dogs, or elephants.

Is it acceptable to have multiple aggregation that can theoretically be inconsistent?

I have a question about the modelling of classes and the underlying database design.
Simply put, the situation is as follows: at the moment we have Positions and Accounts objects and tables and the relationship between them is that a Position 'has an' Account (an Account can have multiple Positions). This is simple aggregation and is handled in the DB by the Position table holding an Account ID as a foreign key.
We now need to extend this 'downwards' with Trades and Portfolios. One or more Trades make up a Position (but a Trade is not a Position in itself) and one or more Portfolios make up an Account (but a Portfolio is not an Account in itself). Trades are associated with Portfolios just like Positions are associated with Accounts ('has a'). Note that it is still possible to have a Position without Trades and an Account without Portfolios (i.e. it is not mandatory to have all the existing objects broken down in subcomponents).
My first idea was to go simply for the following (the first two classes already exist):
class Account;
class Position {
Account account;
}
class Portfolio {
Account account;
}
class Trade {
Position position;
Portfolio portfolio;
}
I think the (potential) problem is clear: starting from Trade, you might end up in different Accounts depending if you take the Position route or the Portfolio route. Of course this is never supposed to happen and the code that creates and stores the objects should never be able create such an inconsistency. I wonder though whether the fact that it is theoretically possible to have an inconsistent database implies a flawed design?
Looking forward to your feedback.
The design is not flawed just because there are two ways to get from class A to class D, one way over B and one over C. Such "squares" will appear often in OOP class models, sometimes not so obvious, especially if more classes lie in the paths. But as Dan mentioned, always the business semantics determine if such a square must commute or not (in the mathematic sense).
Personally I draw a = sign inside such a square in the UML diagram to indicate that it must commute. Also I note the precise formula in an UML comment, in my example it would be
For every object a of class A: a.B.D = a.C.D
If such a predicate holds, then you have basically two options:
Trust all programmers to not break the rule in any code, since it is very well documented
Implement some error handling (like Dan and algirdas mentioned) or, if you don't want to have such code in your model, create a Checker controller, which checks all conditions in a given model instance.

Setting up a "to-many" relationship value dependency for a transient Core Data attribute

I've got a relatively complicated Core Data relationship structure and I'm trying to figure out how to set up value dependencies (or observations) across various to-many relationships. Let me start out with some basic info. I've got a classroom with students, assignments, and grades (students X assignments). For simplicity's sake, we don't really have to focus much on the assignments yet.
StudentObj <--->> ScoreObj <<---> AssignmentObj
Each ScoreObj has a to-one relation with the StudentObj and the AssignmentObj.
ScoreObj has real attributes for the numerical grade, the turnInDate, and notes.
AssignmentObj.scores is the set of Score objects for that assignment (N = all students).
AssignmentObj has real attributes for name, dueDate, curveFunction, gradeWeight, and maxPoints.
StudentObj.scores is the set of Score objects for that student (N = all assignments).
StudentObj also has real attributes like name, studentID, email, etc.
StudentObj has a transient (calculated, not stored) attribute called gradeTotal.
This last item, gradeTotal, is the real pickle. it calculates the student's overall semester grade using the scores (ScoreObj) from all their assignments, their associated assignment gradeWeights, curves, and maxPoints, and various other things.
This gradeTotal value is displayed in a table column, along with all the students and their individual assignment grades. Determining the value of gradeTotal is a relatively expensive operation, particularly with a large class, therefore I want to run it only when necessary. For simplicity's sake, I'm not storing that gradeTotal value in the core data model. I don't mind caching it somewhere, but I'm having a bitch of a time determining where and how to best update that cache.
I need to run that calculation for each student whenever any value changes that affects their gradeTotal. If this were a simple to-one relationship, I know I could use something like keyPathsForValuesAffectingGradeTotal ... but it's more like a many-to-one-to-many relationship. Does anyone know of an elegant (and KVC correct) solution? I guess I could tear through all those score and assignment objects and tell them to register their students as observers. But this seems like a blunt force approach.
I just postet a project on github which probably solves part of the problem with observings
http://github.com/mbrugger/CoreDataDependentProperties
A more detailed description of the project can be found there.
-(NSArray*) keyPathsForValuesAffecting would not have solved your problem as this only works across to-one relations
In addition you should not make the dependent attribute transient, as it makes your context "dirty" (unsaved changes) already after recalculating all values after loading

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.