In my domain model diagram, I have a class Area that is defined by multiple sensors (eg:temperature sensors), but each sensor can be on one area at a time. As I can move the sensors, I can change the sensors to another area, and in the ultimate case delete the area (because an area needs sensors to exist).
Knowing, Area has already and attribute data:Data.
How can i keep track of previous Areas?
eg:
time=0 - Area A has sensors 1,2,3
time = 10- Area A has sensors 2,3
time =20- Area A has sensors 3
I want to be able to go to previous states of the instance, and check which sensors belonged to the area at a certain time t.
Current diagram:
You can use a qualified association with the timestamp as qualifier. This is shown with a small rectangle at the Area end of the association with the text t:Timestamp in it.
PS: In your diagram an Area can exist without Sensors, since the multiplicity is 0..*. You should change it to 1..* if you want this semantics.
The qualifier is an interesting approach. However, it requires to know the precise timestamp of the start of an Area assignment to access the current or an historically associated area. Moreover the history goes in both direction, unlike the qualifier which is inly at one end.
For these reasons the association class would be more suitable:
the association class keeps track of the history, with a begin and end date.
the association with the current period could simply have no end date. Since an association class has reference
semantic (and identity), you could change the end date of the current association, once it’s no longer the current one.
navigation in both direction can take into account the chronology.
The only challenge is to express
the multiplicity constraint at any given time, as the association would become many to many: it’ll be more difficult to tell that there is only one area for a sensor at any given time. Programmatically (for the implementation), it’ll not be a big deal to implement this. But expressing this in OCL, taking into account possibly overlapping intervals it’s more difficult. Fortunately, as qwerty_so indicates in the comments, it’s perfectly valid to express the constraint in plain english.
N.B. additional comparison of an association class and a qualified association for similar problems, here on SE.
Related
First, don't think i'm trying to get the job done by someone else, but i'm trying to design a class diagram for a domain model and something I do is probably wrong because I'm stuck, so I just want to get hints about what i'm not doing correctly to continue...
For example, the user needs to search products by categories from a product list. Each category may have subcategories which may have subcategories, etc.
The first diagram I made was this (simplified):
The user also needs to get a tree list of categories which have at least one product.
For example, if this is all the categories tree:
Music instruments
Wind
String
Guitars
Violins
Percussion
Books
Comics
Fiction
Romance
I can't return a tree of Category which have at least one product because I would also get all subCategories, but not each sub category has a product associated to it.
I also can't remove items from the Category.subCategories collection to keep only items which have associated products because it would alter the Category entity, which may be shared elsewhere, this is not what I want.
I thought of doing a copy, but than I would get 2 different instances of the same entity in the same context, isn't it a bad thing ?
So I redesigned to this:
Now I don't get a collection of child categories I don't want with each Category, I only know about its parent category, which is ok.
However, this creates a tree of categories which is navigable only from the bottom to the top, it makes no sense for the client of ProductList who will always need a top -> bottom navigation of categories.
As a solution I think of the diagram below, but i'm not sure it is very good because it kinda dupplicates things, also the CategoryTreeItem does not seems very meaningful in the domain language.
What am I doing wrong ?
This is rather an algorithmic question than a model question. Your first approach is totally ok, unless you were silent about constraints. So you can assign a category or a sub-category to any product. If you assign a sub-category, this means as per this model, the product will also have the parent category. To make it clear I would attach a constraint that tells that a product needs to be assigned to the most finest know category grain. E.g. the guitar products would be assigned to the Guitar category. As more strange instrument like the Stick would get the Strings category (which not would mean its a guitar and a violin but just in the higher category.
Now when you will implement Category you might think of a method to return a collection of assignedInstruments() which for Guitar would return Fender, Alhambra, etc. You might augment this assignedInstruments(levelUp:BOOL) to get also those instruments of the category above.
Generally you must be clear about what the category assignment basically means. If you change the assignment the product will end up in another list.
It depends on the purpose of the diagram. Do you apply a certain software development method that defines the purpose of this diagram in a certain context and the intended readers audience?
Because you talk about a 'domain model', I guess your goal is to provide a kind of conceptual model, i.e. a model of the concepts needed to communicate the application's functionality to end users, testers etc. In that case, the first and the second diagram are both valid, but without the operations (FilterByCategory and GetCategories), because these are not relevant for that audience. The fact that the GUI only displays a subset of the full category tree is usually not expressed in a UML diagram, but in plain text.
On the other hand, if your intention is to provide a technical design for developers, then the third diagram is valid. The developers probably need a class to persist categories in the database ('Category') and a separate class to supply categories to the GUI ('CategoryTreeItem'). You are right that this distinction is not meaningful in the domain language, but in a technical design, it is common to have such additional classes. Please check with the developers if your model is compatible with the programming language and libraries/frameworks they use.
One final remark:
In the first diagram, you specified multiplicity=1 on the parent side. This would mean that every Category has a parent, which is obviously not true. The second diagram has the correct multiplicity: 0..1. The third diagram has an incorrect multiplicity=1 on the composition of CategoryTreeItem.
From my perspective your design is overly complex.
Crafting a domain model around querying needs is usually the wrong approach. Domain models are most useful to express domain behaviors. In other words, to process commands and protect invariants within the correct boundaries.
If your Product Aggregate Root (AR) references a Category AR by id and this relationship is stored in a relationnal DB then you can easily fulfill any of the mentionned querying use cases with a simple DB query. You'd start by gathering a flat representation of the tree which could then be used to construct an in-memory tree.
These queries could be exposed through a ProductQueryService that is part of the application layer, not the domain as those aren't used to enforce domain rules or invariants: I assumed they are used to fullfil reporting or UI display needs. It is there you could have a concept such as ProductCategoryTreeItemDTO for the in-memory representation.
You are also using the wrong terms according to DDD tactical patterns in your diagrams which is very misleading. An AR is an Entity, but an Entity is not necessarily an AR. The Entity term is mostly used to refer to a concept that is uniquely identified within the boundary of it's AR only, but not globally.
CONTEXT: I have an abstract class Student. From this class I derive three concrete classes SchoolStudent, UnderGradStudent, PostGradStudent. I have another class Vehicle. A school student must NOT drive a vehicle however, an undergrad or a postgrad student may or may not drive a vehicle.But every vehicle must be driven by somebody hence the Vehicle class has a reference to a student.
PROBLEM: I have association between classes UnderGradStudent & Vehicle and another association between PostGradStudent & Vehicle. However, I am a little confused about the multiplicity.
As I understand the problem, the UML class diagram should look something like this:
However, I suspect the above diagram suggests that each Vehicle will have one UnderGradStudent as well as one PostGradStudent.
Is the above diagram correct as to what I want to model corresponding to the context?
As you've drawn this UML diagram, it implies (but does not say correctly) that a Vehicle must be driven by both one UnderGradStudent and one PostGradStudent. It also implies that an UnderGradStudent can drive any number of Vehicles and a PostGradStudent can drive any number of Vehicles (at the same time). I don't think that's what you intended. The reason I say "implies" is that you have overlaid two associations on one end. Last I checked, that is invalid UML.
I think you wanted to say that a Vehicle may be driven by up to one Undergrad Student or Postgrad Student. To say that, I recommend the following model:
What this says is:
A valid instance of Student must be one of School Student, Undergrad Student, or Postgrad Student (and not multiply classified)
A valid instance of Allowed Driver must be one of Undergrad Student or Postgrad Student (and not multiply classified)
A Vehicle can be driven by up to one Allowed Driver (at a time)
An Allowed Driver drives up to one Vehicle (at a time)
This describes a valid situation at any point in time, which is really useful. Think of it as a way to evaluate the validity of any frame in a movie.
If you need to record all the drivers of every vehicle ever, you would need to make many changes. A Person actually plays the role of a Student (among other roles, usually), and that role can change over time. You would need to record the start and end time of every role change and the start and end time of every driver / vehicle change. Think of this as recording all the frames in a movie, but without the ability to express the validity of any given frame in the movie. You lose that ability when you relax multiplicities.
You can get the benefits of the "single frame" and the "whole movie" approach by combining all of the associations I mentioned.
Your problem will easily be solved by using a 0..1 multiplicity near the *Student classes from the Vehicle. This will tell the reader that both are allowed to have a related optional vehicle. To avoid both using the same car you need to attach a constraint like this:
Alternatively you can do it the following way:
I'm not good in writing OCL but you could formalize the constraint as well.
We want to model a warehouse application. Let us assume we identified the following real world objects:
Articles(the things stored in the warehouse)
Palettes (where the Articles are on)
Compartments (the places in the racks where the palettes are stored in)
There are the following constraints:
A palette is in exactly one compartment
A compartment can hold zero or one palette
For the start we have one operation:
Move (moves a palette from its current compartment to another).
Of course this is very simplified.
How should this be modelled?
Stockitem could be a value object I think. One solution would be to model the whole warehouse as an aggregate with palette and compartment entities. The move operation could be implemented without any problems in this case regarding its constraints (invariants). But this approach has obvious drawbacks. The Event log for this aggregate will grow infinitely. Two move operations could not be executed in parallel because of the aggregate versioning and so on. And from a ddd point of view, it feels not right for me.
Another approach would be to make each palette and each compartment its own aggregate. But how would the move operation be implemented then?
Problem 1 : Who loads referenced aggregates?
I think it should stick to the palette. The palette could reference the compartment it is in (its an aggregat). But how is this reference implemented (CQRS/ES)? The Comandhandler of the move command obviously will load the palette aggregate from the palette repository and call the move method on it. Who loads the referenced compartment? And who loads the compartment it should be moved to? I read that aggregates should not access repositories. Should the commandhandler load both compartments? Should the compartments be given to the move method as parameters? Or should the commandhandler set the current compartment to the palette and give the target compartment as a parameter?
Problem 2 & 3 : Constraints and bidirectional association between aggregates
What about the constraints? To check if the target compartment is empty, the compartment needs to know the palette that is stored in it. This would be a bidirectional association that should be avoided. And because they are different aggregates, they could not be updated in the same transaction. Has the palette to fire a domain event to inform the compartment that it will move to it? Has it to be implemented as a saga with undo action? What if two moves conflict, one wins, but the loosing palette could not be moved back, because the old compartment is filled up in the meantime?
This all seems very complicated to me regarding the really simple problem.
In the books and the examples it seems all so clear. But if I try to use it, I seem to do it wrong.
Could somebody guide me in the right direction please?
Problem 1
I think you need to do some transactional analysis in addition to the business analysis here.
If your domain is highly collaborative (which is what DDD is recommended for), how often do moves to a given compartment happen ? Would it be feasible contention-wise for the Move operation to happen under a transaction that spans across the 2 Compartment aggregates (source and target) ? Or would eventual consistency suffice, where the source Compartment would signal the world via an event that the Palette has left it, and the target Compartment would somehow be informed later, in an asynchronous way, that the Palette is joining it ?
A palette floating "in limbo" for a small amount of time can be perfectly acceptable, that's something you need to ask a domain expert about.
Problem 2
A bidirectional association is not the only solution. You could ask the PaletteRepository for all the Palettes that have CompartmentID X. Alternatively, Compartment could (should) have a list of Palette IDs, not a full reference to them.
Overall, I think you should look first if there's a business implication/answer to all the design questions you're asking yourself. The domain expert will usually have an educated opinion on whether eventual consistency is realistic or immediate consistency is required, what should happen in case of conflict, etc.
You should just start object modeling the behaviour, and don't think about aggregates and value objects at all. Once you've modeled the needed behaviour, you'll know what are the entities, aggregates, roots and value objects.
In the explanations by Vaughn Vernon he makes it clear that you need to work out the details of what you need before you can make these decisions.
After some confusion with mixing use case and class diagrams, managed to clear some doubts and come up with the following class diagram. Felt more comfy with this than use case. Hope am not wrong. Would like some feedback on any errors and improvements on it. Thank you.
Question:
A new library has books, videos, and CDs that it loans to its users. All library material
has a unique identification number and a title. In addition, books have one or more authors,
videos have one producer and one or more actors, while CDs have one or more artists.
The library maintains one or more copies of each library item (book, video or CD). Copies of all
library material can be loaned to users. Reference-only material can only be loaned for a
maximum of two hours and can’t be removed from the library. Other material can be loaned for
up to two weeks. For every loan, the library records the user, the loan date and time, and the
return date and time. For users, the library maintains their name, address and phone number.
Draw a class diagram for the description above.
Class Diagram: link to diagram
Don't use notes for multiplicities 1..*. Edit associations or their ends instead and write it there.
Write multiplicities on ends, not in the middle of the line.
Arrows should be subscribed by names of attributes.
Libraries can have many Videos, books, CD's and so on. So, there multiplicities should be in both ends.
No arrows on the line is the same as arrows on both ends. Check it on the right sides.
Write attributes inside blocks when they are of types not present on the diagram. If they are not, put their names on the opposite ends of the associations, near arrows.
You should use some empty diamonds on the left side.
You should decide the multiplicity of the producer.
Divide Title from Copy. And maybe, from Edition.
Don't mix plural and singular - hold to some system. I use plurals only for collections, but you needn't take it, of course. Plurals in class names are senseless - all classes apart from singletones have many instances.
You don't need toconnect library to CD and Video - they are merely subsets of Books. And books already are connected. The same with three lists in the Library block.
Loan should be connected to Book.
According to standards, loan() is a constructor of the class Loan. It can't be in another class.
I am creating a Class Diagram for a simple booking system for the theater. I would like to know if the diagram makes any sense and if anything needs to be changed (arrow directions) in order for it to be correct?
Thanks.
Image URL: http://i.stack.imgur.com/zWiGW.jpg
Here are some recommendations that you're free to incorporate or ignore as you see fit:
I don't agree with the relationship between Show and Venue. It seems more natural to have a Booking maintain the relationship between a Show and a Venue.
I don't see a Date for a Show anywhere. Did I miss it? That seems important.
Shows don't have Seats; a Venue has Seats.
A Ticket ought to entitle you to a Seat in a Venue on a particular date. I don't see that.
TicketType should be nothing but an enum.
Decompose User to have a Name, Address, and Credential classes. Separate the Credentials out from User.
A real payment system would need far more than what you have showing (e.g. CreditCard, etc.)
I think your model needs a lot of work.
In addition to what duffymo said, here are some generic observations not strictly related to this particular diagram but rather you modeling practices.
If an association is one way navigable then there is no need to name both ends. You have named both ends of all associations, but only navigable end needs a name.
Drop the 'can' from all association ends. In some cases there is a handy term, for example show can be hosted at a Venue. But in other cases it's perfectly fine and even common practice to name association ends same as the class at that end. (so name the Seat end simply Seats)
Avoid many to many relationships if you can. If you can't then look into adding an association class in between, it almost always makes sense.