From my understanding of the DDD concepts, all application functionalities related to an entity should be placed into that entity.
For example: a UserEntity should have register() for the registration functionality.
However, this does not make sense for a large application where there is a huge number of functionalities. This would mean that one UserEntity class will be HUGE since it must have at least one method for each functionality.
I would think the better way is to abstract register() into its own entity: a RegFuncEntity.
This means each functionality (e.g. registration, login, search users, view membership, pay bills, etc) is abstracted into its own entity. The UserEntity still has methods, but only those related to the User basic functions (e.g. updateAddress(), updateFirstName(), updateSSN(), validate(), etc). The reRegFuncEntity can use UserEntity (i.e. a functionality entity can use this "core" entities).
My question is: is this design anemic and/or still follow DDD?
Domain Driven Design provides you a great tool known as bounded context. Your user will do different things in different bounded contexts. For instance: the User in the User Management BC will have login(), changePassword() and User entity will probably be the Aggregate Root.
In another BC, say Order, the User entity will provide other functionalities, and in this BC, User could not be the aggregate root (indeed, I'll tell you more: it could be a value object).
Then, you will have a one User entity for each BC. In DDD the same word could have different meanings (and behaviour) in different context (this is known as Ubiquitous language). The usual example in DDD is the Order entity: this means something to forward for the carrier, something to bill for the administrative and so on.
UL is even useful to spot different bounded context, if domain experts use the same word to talk about different things you've probably spotted a new BC.
Another tip of UL is: talk the language of domain experts: than don't use UserEntityfor users, but simply User, non programmer staff will have difficult to catch the meaning of entity.
After this process, if you have some functionality shared among multiple bounded context, you can look at a Shared Kernel.
Related
Assuming everyone has the rights to do the CRUD operations (everyone is an admin type user). I have displayed CRUD operations the user can perform in the Domain diagram however, it's become quite messy. I am curious if it's acceptable to do the alternative approach shown in the images below instead since the multiplicative relationships remain the same for each action (create,edit,delete)
Seperated CRUD
Alternative approach? (create, edit, delete)
In short
If it becomes messy, it probably lacks of separation of concerns, or represents associations that are not really needed.
More explanations
Are the associations needed?
An association between User and Xxx implies a semantic relationship between the two classes. This means that instances of the classes are linked and not just for the time of an operations. So x would be able to find the User(s) that updated it, and u would know the Xxx instances that it updated. This kind of association can make sense if you want some audit trails, but this seems not to be your purpose here.
In other words, the fact that a User may perform some operations that CRUD instances of Xxx is not sufficient for justifying an association.
If they are needed, do they represent what you think?
Now it appears that your associations are can ..., i.e. some kind of authorisation scheme. Your diagram tells that each user would need to know in advance all the Xxx that it could update. This is a heavy burden. It would also imply that a user needs to know all the Xxx it can create; before they are even created? This looks somewhat inconsistent.
Modeling an authorisation scheme
If you'd wand to design an authorisation system, you'd probably not link users directly to the object, but use some intermediary mechanisms:
To express that a user can create new projects, you'd probably have some authorisation object that tells the caracteristics of projects that can be created.
To express that a user can edit, update, delete projcts, you could have a direct association like you envisaged, if some admin would maintain such authorisations.
But probably you would have some authorisation object that would tell what a user can do (e.g. a user "role"/"profile") and what category of projects.
Equally probable is that there are some rules that govern CRUD authorisations (e.g. a user having the role "edit" can edit the project he/she is assigned to, but not the others). Making use of such rules instead of explicitly designing (redundant) authorisations could then save you a lot of unnecessary extra associations (and extra constraints to keep the authorisations consistent with the rules).
Separation of concerns
And to keep things continue to be messy, you should consider:
having a separate diagram in your model for the authorisation concept
use some common CRUD interface: the users would then be associated with the CRUD interface without having to replicate everything for every possible class.
The main issue with both of your class models is a confusion between the type/instance levels. Your "can create/edit/delete" authorization relationships do not hold between a specific user and a specific object (an instance of Company, Project or Ticket), but rather between a specific user and a sepcific object type (Company, Project or Ticket), so it's not an ordinary association between two ordinary object types.
If you want to describe/define such authorization relationships with a class model, you would need to define a meta-class like ObjectType and express that your object types (Company, Project or Ticket) are instances of it.
i'm trying to apply the domain driven design in a little project
i want to separate the authentication of rest of the users logic,
i'm using a value object for the id (userID) in the beginning i have the userID in the same level(package) of the users but I realize when i separate bounded context for authentication and user, they share a common value object for the userID, so my question is where supose that i have to put the common or share value objects? is correct if i created a packages called commons?
It is recommended to not share models between bounded contexts, however, you can share IDs and even simple Value objects (like Money).
The general rule is that you may share anything that is immutable or that changes very infrequently and IDs rarely change structure (here immutability refers to the source code and value immutability).
Packages called "common" usually refers to reusable concepts that you use in your projects, so that you don't have to code them in every project. There it's usual to put base abstract objects and interfaces, for entities, value objects, etc.
But it's not your case about userId. What you are saying is to put userId in a "shared kernel" model. It is an option, but usually it is not recommended.
From my point of view:
The auth BC has the concepts id,login,password,role,etc.
The user BC has concepts like name,surname,address,age,etc, but it also has to have the id, that it gets from auth BC.
From what I know, you have 2 options:
(1) Authentication BC shares "id" concept explicitly, i.e. it has a shared kernel. So "id" concept would belong to user BC model too.
(2) Authentication BC is a generic BC. So you have to integrate the user BC with the auth BC to get the id from it.
First of all, I personally see this as an context mapping question at code level, where you are effectively looking to have a shared kernel between multiple bounded contexts.
This depends on the business really. You typically need to consider the following questions:
How do different teams responsible for each bounded context collaborate with each other? If it's 1 team maintaining all the related bounded contexts, it might be OK, but it's multiple teams have different objectives, it leads to the next point.
How do you plan to maintain this shared kernel over time? In general, this shared kernel will need to change to adapt to business changes.
For more detailed arguments, there are plenty of resources out there about context mapping, such as Vaughn Vernon's book "Implementing Domain Driven Design".
Generally in UML, you model roles as opposed to people however if there is a use case to model people (along with their names, contact details, etc), is there a known way of depicting this?
For example do I create a superclass called "Person" and generalize the roles followed by a specialization of a real person?
I took a look at some of your other questions and now I realise I completely misunderstood and you're probably trying to model an organization and the people in it.
ArchiMate is a semantic layer on top of UML that is intended for architecture modelling. Real people get described in the business layer, as actors.
A business actor is defined as an organizational entity capable of (actively) performing behavior.
A business actor performs the behavior assigned to (one or more) business roles. Examples of business actors are humans, departments, and business units. A business actor may be assigned to one or more business roles. The name of a business actor should preferably be a noun.
Now generally the person fills a spot in the organization that in a couple years could be filled by another person. The structure / architecture of the organization would not change and as such the actor can be described by the name of their position, say, "Head of department" rather than by their name and phone number.
Still, I understand that it may be handy to have this sort of information available when you want to contact them.
UML-model-wise, I'd think that the actor Head of Department is a class, realizing a business role that's also a class, and that Joe with phonenumber 12345 is an object of that class.
But practically, I'd think this is too much detail for the level at which you're describing the organization. I'd suggest you stick a UML note on those few actors of key contacts whose names you think are worth mentioning in the diagram. But administrate the rest of them in a system that's more fit for this, like your company's ADS or Contacts in Microsoft Outlook.
How would you model in UML the following state of affairs:
A restaurant management system is used by waiters to keep track of
servings to tables. It is also used to keep track of which waiters
serve which tables.
This means that the concept of a waiter is both an actor (as
waiters are users of the system) and an entity object (because the
system keeps track of which waiter serves which tables).
Yet according to the UML a concept can't be both an entity and an
actor because by definition "An actor is an external entity that interacts with the system."
I could always use different names to separate these concepts but that
seems artificial.
What do you think?
The system's entity representing a waiter is not the same as the actual waiter who is an external agent acting on the system.
Either use different names, or put the actor and entity in separate namespaces or models.
Just because waiters use the system does not force you to name that actor as a 'waiter'. Think about other employees who might use the system in the same way, e.g. the host/hostess or a shift manager.
Actors who are using the system are usually fulfilling a role which can shared among different actors. You have to generalize the role the actor is playing. If any employee could participate in that use case, the role might be 'Employee'.
Even if you didn't take that approach, you still have other synonyms to distinguish between the entity and the actor. The actor may be 'waitstaff' and the entity could be 'server'. It is worth the time to come up with good names especially for frequently used terms. And if it comes down to it, forget what UML 'says' about using different names. People have been using bits and peices of UML since it came out, no one's going to shut you down if you decide to reuse a name.
What I would say is UML is trying to give you some good advice that if you are using the same name, it will cause problems later and is also an indication that there is more to the story.
When you are developing an architecture in OO/DDD style and modeling some domain entity e.g. Order entity you are putting whole logic related to order into Order entity.
But when the application becomes more complicated, Order entity collects more and more logic and this class becomes really huge.
Comparing with anemic model, yes its obviously an anti-pattern, but all that huge logic is separated in different services.
Is it ok to deal with huge domain entities or i understand something wrong?
When you are trying to create rich domain models, focus entities on identity and lifecyle, and thus try to avoid them becoming bloated with either properties or behavior.
Domain services potentially are a place to put behavior, but I tend to see a lot of domain service methods with behavior that would be better assigned to value objects, so I wouldn't start refactoring by moving the behavior to domain services. Domain services tend to work best as straightforward facades/adaptors in front of connections to things outside of the current domain model (i.e. masking infrastructure concerns).
You can also put behavior in Application services, but ask yourself whether that behavior belongs outside of the domain model or not. As a general rule, try to focus application services more on orchestration-style tasks that cross entities, domain services, repositories.
When you encounter a bloated entity then the first thing to do is look for sets of cohesive set of entity properties and related behavior, and make these implicit concepts explicit by extracting them into value objects. The entity can then delegate its behavior to these value objects.
Since we all tend to be more comfortable with entities, try to be more biased towards value objects so that you get the benefits of immutability, encapsulation and composability that value objects provide - moving you towards a more supple design.
Value objects enable you to incorporate a more functional style (eg. side-effect-free functions) into your domain model and thus free up your entities from having to deal with the complexity of adding complicated behavior to the burden of managing identity and lifecycle. See the pattern summaries for entities and value objects in Eric Evan's http://domainlanguage.com/ddd/patterns/ and the Blue Book for more details.
When you are developing an architecture in OO/DDD style and modeling
some domain entity e.g. Order entity you are putting whole logic
related to order into Order entity. But when the application becomes
more complicated, Order entity collects more and more logic and this
class becomes really huge.
Classes that have a tendency to become huge, are often the classes with overlapping responsibilities. Order is a typical example of a class that could have multiple responsibilities and that could play different roles in your application.
Given the context the Order appears in, it might be an Entity with mutable state (i.e. if you're managing Order's commercial condition, during a negotiation phase) but if you're application is managing logistics, an Order might play a different role: and an immutable Value Object might be the best implementation in the logistic context.
Comparing with anemic model, yes its
obviously an anti-pattern, but all that huge logic is separated in
different services.
...and separation is a good thing. :-)
I have got a feeling that the original model is probably data-centric and data serving different purposes (order creation, payment, order fulfillment, order delivery) is piled up in the same container (the Order class). Can't really say it from here, but it's a very frequent pattern. Not all of this data is useful for the same purpose at the same time.
Often, a bloated class like the one you're describing is a smell of a missing separation between Bounded Contexts, and/or an incomplete Aggregate separation within the same bounded context. I'd have a look to:
things that change together;
things that change for the same reason;
information needed to fulfill behavior;
and try to re-define aggregate boundaries accordingly. And also to:
different purposes for the application;
different stakeholders;
different implicit models/languages;
when it comes to discover the involved contexts.
In a large application you might have more than one model, thus leading to more than a single representation of a single domain concept, at least for concepts that are playing many roles.
This is complementary to Paul's approach.
It's fine to use services in DDD. You will commonly see services at the Domain, Application or Infrastructure layers.
Eric uses these guidelines in his book for spotting when to use services:
The operation relates to a domain concept that is not a natural part of an ENTITY or VALUE OBJECT.
The interface is defined in terms of other elements in the domain model
The operation is stateless