How should I use singleton in DDD? - domain-driven-design

I am implementing a school related app for the local government. I have classes and I want to count grade using the following formula: grade = acedemicYear - commencingYear + 1.
You can model this 2 ways:
both commencingYear and academicYear have a Year type and the acedemicYear year is some kind of singleton, so AcademicYear.getInstance() - this.commencingYear + 1
another solution that commencingYear has a type of AcademicYear, and I have a Calendar class, which gives me the current year, so Calendar.getAcademicYear() - this.commencingYear + 1
Still I don't feel these right. I am not sure whether I should inject the year into the model or it should be inside the model. Another problem that the academic year should be changed more or less manually, at least it starts every year on a different date. By increasing the academic year the grade > 8 means that the class is finished, so children from that class should not be on the current student list. What do you think, what is the best way to model this?

AcademicYear can of course be a value type like you've done. But isn't that over complicating things?
If you have an entity type which contains both commencingYear and academicYear you can easily control the value for those fields. Thus if someone tries to enter a date which is out of bounds you can just thrown an exception.
Regarding the calculation it sounds like business rules and therefore it should be wrapped within a method in the entity or in a domain service.
i.e. it's a rule, but a rule for a specific entity in the domain. thus it should not be wrapped in a static somewhere but implemented in the correct entity class.
Writing a more specific answer is hard as I have now knowledge about your domain or how you have implemented it.

Related

DDD value object composite identifier

I was trying to understand DDD value objects and entities, and have a minor doubt in that. I've read in a lot of articles that value objects does not have identity. I wanted clarity on whether that the identity referred here is a single attribute or a any composite attributes.
Lets say I have an inventory management service which has a business transaction called "Inventory Adjustment", what it does is simply adjusts the quantity of items at your warehouse. You can create an adjustment with multiple line items, each line item will have an ItemID and Quantity fields.
Note: Lets assume that an item can occur only once in an adjustment, meaning an adjustment cannot have multiple line items with same Item ID.
The user can edit an adjustment line item, delete line items and add new line items as well.
In this context, is adjustmentLineItem a value object OR an entity inside adjustment root aggregate?
The confusion I have is when we say VOs should not have an identity, does that mean it should not have an ID field or a composite identity as well. Because in my case, I would not need an ID field for the line item object, the AdjustmentID + ItemID serves as an identifier for me.
Also, is it fine to have the parent entity identifier inside a VO (like adjustmentID)?
Not related to this context, in general what is the reason why VOs should not have identities?
NOTE: I am relatively new to DDD and my understandings might be wrong.
There's a difference between identifier and identity.
An identifier is a value that identify something, is what an entity use to track its identity.
The identity instead is what tells you that an entity is different from another one, you can use a number to do it (like in case of sql db sequences) or some UUID, or basically use a value that acts as an identifier
Difference between value objects and entities reside in the identity of the latter.
If we have an entity, let's say a Person, and we do a change (mutate) to it (eg. change name), it still remain the same entity (a person changing name still remain the same person). That is not true for value objects, if we have an Address and we change its street it is a different Address.
When we reify this abstraction into code, we need something to track the identity of an entity, to be able to check and confront it with another one. In these cases we add a value in the entity that acts as an identifier, something that we know will stay the same for the entire lifecycle of the entity.
So the identifier can be seen as a value and it can be treat as such.
Then going back to the questions:
It seems to me that in your case the InventoryAdjustment is the entity (it has its own identity), and it contains the list of AdjustmentLineItem that could be seen as a value, containing the ItemId that is also a value.
AdjustmentLineItem is a VO itself
Code to work with things not having an identity is simpler as they can easily be immutable, avoiding a lot of issues (you can look for the immutability topic to understand them, or there's this famous talk about Values)
A final note about this rule:
Lets assume that an item can occur only once in an adjustment
This enforce the fact that the InventoryAdjustment is an entity, and this rule is one of its invariants.
The InventoryAdjustment has a value in it being a List<AdjustmentLineItem>, and could check the rule when someone try to mutate it. When doing domain models, the access for editing purposes to the state of the entity should be disallowed, no setter methods and make impossible for external code of the InventoryAdjustment to do things like:
inventoryAdjustment.getAdjustmentLineItemList().add(anAdjustmentLineItem)
but rather expose methods to do mutation, and internally check invariants:
inventoryAdjustment.addAdjustmentLineItem(anAdjustmentLineItem)

Always valid domain model entails prefixing a bunch of Value Objects. Doesn't that break the ubiquitous language?

The principle of always valid domain model dictates that value object and entities should be self validating to never be in an invalid state.
This requires creating some kind of wrapper, sometimes, for primitive values. However it seem to me that this might break the ubiquitous language.
For instance say I have 2 entities: Hotel and House. Each of those entities has images associated with it which respect the following rules:
Hotels must have at least 5 images and no more than 20
Houses must have at least 1 image and no more than 10
This to me entails the following classes
class House {
HouseImages images;
// ...
}
class Hotel {
HotelImages images;
}
class HouseImages {
final List<Image> images;
HouseImages(this.images) : assert(images.length >= 1),
assert(images.length <= 10);
}
class HotelImages {
final List<Image> images;
HotelImages(this.images) : assert(images.length >= 5),
assert(images.length <= 20);
}
Doesn't that break the ubiquitous languages a bit ? It just feels a bit off to have all those classes that are essentially prefixed (HotelName vs HouseName, HotelImages vs HouseImages, and so on). In other words, my value object folder that once consisted of x, y, z, where x, y and z where also documented in a lexicon document, now has house_x, hotel_x, house_y, hotel_y, house_z, hotel_z and it doesn't look quite as english as it was when it was x, y, z.
Is this common or is there something I misunderstood here maybe ? I do like the assurance it gives though, and it actually caught some bugs too.
There is some reasoning you can apply that usually helps me when deciding to introduce a value object or not. There are two very good blog articles concerning this topic I would like to recommend:
https://enterprisecraftsmanship.com/posts/value-objects-when-to-create-one/
https://enterprisecraftsmanship.com/posts/collections-primitive-obsession/
I would like to address your concrete example based on the heuristics taken from the mentioned article:
Are there more than one primitive values that encapsulate a concept, i.e. things that always belong together?
For instance, a Coordinate value object would contain Latitude and Longitude, it would not make sense to have different places of your application knowing that these need to be instantiated and validated together as a whole. A Money value object with an amount and a currency identifier would be another example. On the other hand I would usually not have a separate value object for the amount field as the Money object would already take care of making sure it is a reasonable value (e.g. positive value).
Is there complexity and logic (like validation) that is worth being hidden behind a value object?
For instance, your HotelImages value object that defines a specific collection type caught my attention. If HotelImages would not be used in different spots and the logic is rather simple as in your sample I would not mind adding such a collection type but rather do the validation inside the Hotel entity. Otherwise you would blow up your application with custom value objects for basically everything.
On the other hand, if there was some concept like an image collection which has its meaning in the business domain and a set of business rules and if that type is used in different places, for instance, having a ImageCollection value object that is used by both Hotel and House it could make sense to have such a value object.
I would apply the same thinking concerning your question for HouseName and HotelName. If these have no special meaning and complexity outside of the Hotel and House entity but are just seen as some simple properties of those entities in my opinion having value objects for these would be an overkill. Having something like BuildingName with a set of rules what this name has to follow or if it even is consisting of several primitive values then it would make sense again to use a value object.
This relates to the third point:
Is there actual behaviour duplication that could be avoided with a value object?
Coming from the last point thinking of actual duplication (not code duplication but behaviour duplication) that can be avoided with extracting things into a custom value object can also make sense. But in this case you always have to be careful not to fall into the trap of incidental duplication, see also [here].1
Does your overall project complexity justify the additional work?
This needs to be answered from your side of course but I think it's good to always consider if the benefits outweigh the costs. If you have a simple CRUD like application that is not expected to change a lot and will not be long lived all the mentioned heuristics also have to be used with the project complexity in mind.

How to append parameter to existing parameters list from previous context in Dialogflow?

I'm building a chatbot that asks users for symptoms, one at a time.
There is a single entity #symptom, which is a list. I'd like to figure out how to append each new symptom into the symptoms parameter list from existing contexts.
For example,
Bot: Please type in your 1st symptom.
User: Cough
symptoms = ['cough']
Bot: Please type in your 2nd symptom.
Fever: Fever
symptoms = ['cough', 'fever']
Bot: Please type in your 3rd symptom.
User: Breathlessness
symptoms = ['cough', 'fever']
How do I go about building such a flow?
(N.B. I know I can simply have one intent that asks user to type out all the symptoms in one line, but I'd prefer for the symptoms to be asked one by one so I can ensure data cleansing before inserting the symptom into the list)
This too is more of a design issue:) You can roughly achieve what you have described with Follow-up intents and contexts, but a better way would be to more clearly separate the intent and parameter matching from any kind of further backend processing.
You should, if you haven't already, define your symptom entity as a Developer mapping entity. This gives you the option to map an arbitrary number of synonyms to one reference value:
reference value: fever
synonyms: fever, feverishness, high temperature, febricity, febrility
The user can now enter any of the synonyms, you will always get the reference value as the parameter (and list of these values if the parameter is a list). The reference value doesn't even have to be a normal word, it can be any unique identifier (e.g. a primary key from database of symptoms). It is only matched if it itself is included in the list of synonyms.
This structure would ensure that you will always get a parameter from a clearly defined set of values, even if the actual user input has a much greater variability. Any further processing of these parameters should be part of your backend code and not be tied to the Dialogflow agent. Ideally you would think of the reference values as the API between the user input and you backend business logic.

Should equals() method of value objects strive to return true by using transformations of attributes?

Assume we have a value object Duration (with attributes numberOfUnits, unit). Would it be a good idea to treat these objects as equal (for example, overriding Object.equals()) if they have the same duration but different units? Should 1 min be equal to 60 sec.
There are many contradicting examples. With java's BigDecimal compareTo() == 0 does not imply equals() == true (new BigDecimal("0").equals(new BigDecimal("0.0")) returns false). But Duration.ofHours(24).equals(Duration.ofDays(1)) returns true.
That's an unfortunately complicated question.
The simple answer is no: the important goal of value objects is to correctly model queries in your domain.
If it happens that equals in your domain has nice properties, then you should model them and everything is awesome. But if you are modeling something weird then getting it right trumps following the rules everywhere else.
Complications appear when your implementation language introduces contracts for equals that don't match the meaning in your domain. Likely, you will need to invent a different spelling for the domain meaning.
In Java, there are a number of examples where equals doesn't work as you would expect, because the hashCode contract prohibits it.
Well... I upvoted #jonrsharpe comment because without knowing the context it is almost impossible to give you an answer.
An example of what #jonrsharpe means could be that if in your domain you are using Duration VO to compare users input (who choose numberOfUnits and unit in a UI) it is obvious that Duration in minutes is not equal to Duration in seconds even if 1 min = 60 sec because you want to know if the users inputs the same things, and in this case they not.
Now, assuming that you will use Duration just for other things in which the format does not matter and ever means the same thing for domain rules (i.e. outdate something):
Why do you need Duration.unit attribute if it gives you nothing of value in your domain?
Why can not you just work with one unit type internally?
If it is just because different inputs/outputs in your system you should transform it to your internal/external(UI, REST API, etc) representation before apply rules, persist the VO (if needed) and/or showing it in a UI. So, separate input/output concerns from your domain. Maybe Duration (with unit attribue) is not a VO is just part of your ViewModel.

To Have An ID or Not To Have An ID - Regarding Value Object

Let's say two domain objects: Product and ProductVariety (with data such as color, size etc). The relationship between these two is one-to-many. Conceptually saying in the domain driven design, the ProductVariaty should be a value object, which is not the same object once its data is changed. From the implementation point of view, however, it is better to have some sort identification for the ProductVariaty so that we know which ProductVariety is selected and so on. Is an only solution to convert it to an entity class?
The following is a code segment to illustrate this situation.
#Embeddable
class ProductVariety {...}
#Entity
class Product {
#ElementCollection
private Set<ProductVariety> varities;
...
}
Conceptually saying in the domain driven design, the ProductVariaty should be a value object, which is not the same object once its data is changed
That's not quite the right spelling. In almost all cases (many nines), Value Object should be immutable; its data never changes.
Is an only solution to convert it to an entity class?
"It depends".
There's nothing conceptually wrong with having an identifier be part of the immutable state of the object. For example, PANTONE 5395 C is an Identifier (value type) that is unique to a particular Color (value type).
However, for an identifier like PANTONE 5395 C to have value, it needs to be semantically stable. Changing the mapping of the identifier to the actual color spectrum elements destroys the meaning of previous messages about color. If the identifier is "wrong", then the proper thing to do is deprecate the identifier and nominate a replacement.
Put simply, you can't repaint the house by taking the label off the old paint can and putting it on a new one.
In that case, there's no great advantage to using the identifier vs the entire value object. But its not wrong to do so, either.
On the other hand, if you are really modeling a mapping, and you want to follow changes that happen over time -- that's pretty much the definition of an entity right there.
What it really depends on is "cost to the business". What are the trade offs involved, within the context of the problem you are trying to solve?
Note: if you really do find yourself in circumstances where you are considering something like this, be sure to document your cost benefit analysis, so that the next developer that comes along has a trail of breadcrumbs to work from.

Resources