From anemic domain to domain driven - c#

I was trying to find a clear and simple example of what an anemic domain really means. There is a lot of theory around, and also many well answered questions. Still, I could not get a clear picture about to what extent "anemic domain" meaning really goes. Therefore, I believe it would be simpler to see a dummy practical example of an anemic domain design and than ask you how could this be evolved to a domain driven one...
So, let's say we have a data entity of type TaskData:
public class TaskData
{
public Guid InternalId { get; set; }
public string Title { get; set; }
public string Details { get; set; }
public TaskState ExplicitState { get; set; }
public IEnumerable<TaskData> InnerTasks { get; set; }
}
And there is the need of an additional property called "ActualState", which is a computed state: if the Task has inner sub-tasks, the value strictly depends of the children, otherwise, the "ActualState" is equal to "ExplicitState"
If I write this logic in a separate service class (I call them "engines") we have:
internal class TaskStateCalculator
{
public TaskState GetState(TaskData taskData)
{
if (taskData.InnerTasks.Any())
{
if (taskData.InnerTasks.All(x => this.GetState(x) == TaskState.Done))
{
return TaskState.Done;
}
if (taskData.InnerTasks.Any(x => this.GetState(x) == TaskState.InProgress))
{
return TaskState.InProgress;
}
return TaskState.Default;
}
return taskData.ExplicitState;
}
}
The first question is:
Does the code above reflect an anemic domain design, even if the TaskStateCalculator service/engine is part of my Domain Layer?
If yes, in order to avoid it, we'll need to move the logic inside the TaskData class (and rename TaskData to Task). Am I right?
The second question is (actually a chain of them):
What if we have a more difficult situation? Let's say there is the need for a property called ComputeSomething inside Task entity, and the logic of this property needs to access the entire Task's repository. In this case, the Task class would have a dependency on TaskRepository. Would this be ok? How would EF construct an instance of such class? What is the alternative?

I was trying to find a clear and simple example of what an anemic domain really means
It's in fact really easy to go from an anemic domain model to a rich one.
Set all property setters to private and then add methods if you want to change state of a model.
Evaluate all Law of Demeter violations and add methods where suitable.
Eventually you will have a correct model.
In your case I would encapsulate that logic inside TaskData as your TaskStateCalculator violate Law of Demeter
public class TaskData
{
public Guid InternalId { get; private set; }
public string Title { get; private set; }
public string Details { get; private set; }
public TaskState ExplicitState { get; private set; }
public IEnumerable<TaskData> InnerTasks { get; private set; }
public TaskState GetState()
{
if (!InnerTasks.Any())
return ExplicitState;
if (InnerTasks.All(x => this.GetState(x) == TaskState.Done))
{
return TaskState.Done;
}
if (InnerTasks.Any(x => this.GetState(x) == TaskState.InProgress))
{
return TaskState.InProgress;
}
return TaskState.Default;
}
}
another thing is that I would probably not expose InnerTasks collection at all to the outside world (just have it as a member field). But it's hard to say as I do not know how the class is used in other scenarios.
Why private setters
Every time you have to change more than one property it's often better to describe the behavior with a method, as it's then impossible to forget to change all required properties. A method also describes better what you are trying to do than changing a set of properties.
Even if you just change a single property, that property can set the class in an invalid state as the change may not be compatible with the rest of the information in the class. Don't forget that encapsulation is one of the core principles in OOP

Related

DDD - How to enforce invariants on collections across aggregates

Let's say we sell cars, customizable cars.
A customer chooses a CarModel and then starts configuring the CarModel. In our shop, she can only choose the color of the Steeringwheel.
Some CarModels can have more types of SteeringWheels than others.
Therefore, we have a Catalog which contains CarModels and SteeringWheels.
A customer can create a CarConfiguration. She chooses the model and then from the available steering wheels for that model she chooses the color steering wheel she likes.
class Catalog
{
public IReadonlyCollection<int> CarModels { get; }
public IReadonlyCollection<int> SteeringWheels { get; }
public void RemoveSteeringWheel(int steeringWheelId)
{
...
}
}
class SteeringWheel : AggregateRoot
{
public int Id { get; }
public string Color { get; }
public decimal Price { get; set; }
}
class CarModel : AggregateRoot
{
public int Id { get; }
public decimal Price { get; set; }
public IReadonlyCollection<int> SteeringWheels { get; }
public void AddSteeringWheel(int steeringWheelId)
{
...
}
public CarOrder CreateCarOrder(int steeringWheelId)
{
return new CarOrder(...);
}
}
class CarOrder : AggregateRoot
{
public int Id { get; set; }
public CarConfiguration CarConfiguration { get; set; }
}
class CarConfiguration : ValueObject
{
public int CarModelId { get; set; }
public int SteeringWheelId { get; set; }
}
For this to work there is an invariant that the available steering wheels for a car model must always be present in the catalog. To enforce this invariant, we must guard (at least) two methods:
AddSteeringWheel on CarModel; we can only add a SteeringWheel if it is available in the Catalog
RemoveSteeringWheel on Catalog; we can only remove a SteeringWheel if it is not configured on any CarModel.
How to enforce this invariant? CarModel does not know about the SteeringWheel collection on Catalog and Catalog doesn't know anything about CarModel's steering wheels either.
We could introduce a domain service and inject repositories into that. That service would be able to access the data from both aggregates and be able to enforce the invariants.
Other options are to create navigation properties and configure the ORM (Entity Framework Core in my case) to explicitly load those relations.
And probably many more, which I can't think of right now…
What are the most elegant/pure-ddd/best practice options to achieve this?
How to enforce invariants on collections across aggregates
Fundamentally, what you have here is an analysis conflict. When you distribute information, you give up the ability to enforce a combined invariant.
For example:
For this to work there is an invariant that the available steering wheels for a car model must always be present in the catalog
So what is supposed to happen when one person is updating a CarConfiguration concurrently with another person modifying the catalog? What is supposed to happen with all of the existing configurations after the catalog is changed?
In many cases, the answer is "those activities are both to be permitted, and we will clean up the discrepancy later"; ie we'll attempt to detect the problem later, and raise an exception report if we find anything.
(If that answer isn't satisfactory, then you need to go back into your original decision to split the information into multiple aggregates, and review that design).
Pat Helland has a lot of useful material here:
2009 Building on Quicksand
2010 Memories Guesses and Apologies
2015 Immutability Changes Everything
In effect, your local calculation include stale (and possibly outdated) information from somewhere else, and you encode into your logic your real concerns about that.
Well first of all, it might be that CarModel knows something of SteeringWheels, as I assume that if you add a SteeringWheel with a Price, the Price of CarModel changes?!
So there probably should be a Value Object or Entity as part of the CarModel aggregate that represents that.
Furthermore, I think you need a command handler, that knows of both, and decides if the provided SteeringWheel is valid, before trying to add that to the CarModel, that on its own has to decide if adding the SteeringWheel is allowed, trusting the command handler that the reference of the SteeringWheel is valid.
Invariants between aggregates can't be transitionally consistent, only eventually. So when you add a steering wheel to your carModel, you raise an event saying steeringWheelUsedbyCarModelEvent, you catch that event in Domain event handler and update the steering wheel. Steering Wheel aggregate holds an id(or collection if can be used by multiple car configurations) of the carmodel it is assigned to.

How to notify all guard methods when global changes

Often in my applications built with Caliburn Micro I have a need to store some global data; this could be app specific config, authentication properties, etc. I generally put them in a class called "Session" and inject that via constructor injection so that every view model has a reference to a single instance of Session.
I found a case where I wanted a guard method on two different view models to be linked to a Session variable; the issue is guard methods are generally notified of changes in the setter of the changed variable. Since it's a global, it doesn't know what depends on it. (It occurs to me that this pattern of variables being aware of what guard is hooked into them is bad, but when it's all in the same ViewModel it doesn't matter much.)
I could throw an event, but that's messy and a lot of work for something that should be simple.
I could try to identify every spot where it may have been updated and manually notify, but that's error prone.
public class MyViewModel: Screen{
public MyViewModel(SessionInfo session){
Session = session;
}
public CanTakeAction { get { return !string.isNullOrWhitespace(Session.SomeProperty); } }
}
public class SessionInfo {
public SessionInfo(){}
public string SomeProperty { get; set; }
// this is where I would normally notify a guard method, but this is not going to work
NotifyOfPropertyChange(() => CanTakeAction); // except it doesn't know about CanTakeAction
}
One possible solution would be to introduce a base ViewModel, which has the guard methods (virtual). For Example,
public class ViewModelBase:Screen
{
private SessionInfo _sessionInfo;
public ViewModelBase(SessionInfo sessionInfo)
{
_sessionInfo = sessionInfo;
}
public void NotifyGuardMethods()
{
NotifyOfPropertyChange(nameof(CanTakeAction));
}
public virtual bool CanTakeAction { get; set; } = false;
}
For all the ViewModels that needs to be notified by the change in Session, you could now derieve from the ViewModelBase.
public class ShellViewModel:ViewModelBase
{
public override bool CanTakeAction { get=>//its own logic; set=>//its own logic; };
}
You could now introduce Events to the ViewModelBase, which could use the NotifyGuardMethods defined in the base class to notify all other view models. This ensures the messsy Events part would be restricted to one class alone (base view model).

where to put the checking function for the model (asp.net mvc5)

i know the model should not have any logic , but i don't know where is the good place to put the checking or the update function for a particular model
ex.
public class GuestBook
{
public int money { get; set; }
[Required]
public string name { get; set; }
[Required]
public string email { get; set; }
public DateTime content { get; set; }
public bool rich()
{
if (this.money <3000)
return false;
else
return true;
}
public void earn(GuestBook b)
{
this.money += b.money;
}
}
the function rich() and earn() is only use for this module(GuestBook)
if i didn't put it in this module , then where i should put?
Following good OOP design principles, the only way to really protect your classes' invariants (and not have a maintainability nightmare) is by not allowing them to be changed by anyone other than the class. Typically this is done by NOT exposing public setter methods (public auto properties are evil), making your fields readonly (wherever possible), and initializing them from the constructor.
The whole point of having classes is to group data with behavior. A simple data structure containing ints and strings is not a class in the OOP sense, it's just a struct.
In some cases you are stuck with an even more evil ORM that FORCES you to make all properties public. This is not an issue with Entity Framework (and some others too) though, EF can magically reflect in and access private setters if needed, you just gotta make sure there's also a private default constructor.
According to your class rich method is validating and earn method is applying business logic. You can create AdditionalMetadataAttribute for rich method logic that can fire on ModelState.IsValid and for earn method you need to create BO class that apply your all business logic.
here a link for AdditionalMetadataAttribute

WCF Service-Consumer Syncrohnisation

I am trying to synchronise changes to a DataContract between my service and it's consumers. I am having trouble designing a maintainable way of informing of property changes.
For example, I want to keep the below synchronised:
[DataContract]
public class MyObject
{
[DataMember]
public Guid Id { get; private set; } = Guid.NewGuid();
[DataMember]
public int Foo { get; set; }
[DataMember]
public string Bar { get; set; }
}
My original approach was to use an event which took a property name and an object, as such:
public delegate void PropertyChangedEventHandler(Guid id, string propertyName, object value);
The service & consumers could then subscribe to the property changes:
myObject.PropertyChanged += MyObjectPropertyChanged;
// MyObject would raise the property change inside of the property set.
private void MyObjectPropertyChanged(Guid id, string propertyName, object value)
{
// Depending on which end is listening the service can send
// the change to the consumer or vica versa
}
I have encountered an issue using this method as the serializer could not determine how to serialize object.
I now don't know how to handle informing of changes. I can see two approaches but I am hoping for a better solution.
I could inform the consumer/service that a change has been made. It can then request from the service/consumer for the changed MyObject. I see this being a problem if more than one consumer changes the same object at the same time (as the service is concurrency is set to multiple). It could result in one consumer's changes being lost.
The second approach is to create an EventArgs, which mirrors the properties of the MyObject and you access the property based on the property name passed with the EventArgs and synchronise the local copy. This would allow two consumers to change different properties without fear of either being lost. However this feels like a lot of repeated code. A lot of unused data is also passed around as MyObject grows. Admitidly there is room for reflection in regards to reading and setting the appropriate property.
For example:
public class MyObjectPropertyChangedEventArgs : EventArgs
{
public Guid Id { get; set; }
public string PropertyName { get; set; }
// Then one of the relative property below would be set to the new value
public int Foo { get; set; }
public string Bar { get; set; }
}
I don't see this being an uncommon use case and was hoping for some insight into how this is usually done?
As far as service is concerned, why do not you leverage of CallbackContract in order to notify client that some changes occured?
On client side in turn DataContract can implement INotifyPropertyChanged interface and whenever change to any property takes place then you call service.

Which of these is the better architecture/design approach?

Objective
To write a effecient Active Directory library to ease the work of technicals who are responsible to create access models into the domain controller's Active Directory. This library must allow the following:
Basic operations: Add, Modify, Delete, List entries;
An entry may either be an organizational unit, group or user (no further need required as of now);
I thought about having a class which would represent the domain with which we want to work with.
public class Domain {
public Domain(string root) {
Root = root;
Entries = new Dictionary<string, IDirectoryEntry>();
}
public string Root { get; private set; }
public Dictionary<string, IDirectoryEntry> Entries { get; private set; }
}
Then, I have used dependency injection to enforce the belonging constraint to a domain of an entry. For example:
public abstract class DirectoryEntry : IDirectoryEntry {
public DirectoryEntry(Domain domain, string name) {
Domain = domain;
Name = name;
Domain.Entries.Add(name, this);
}
public Domain { get; private set; }
public Name { get; set; }
}
public class OrganizationalUnit : DirectoryEntry {
public OrganizationalUnit(Domain domain, string name)
: base(domain, name) {
}
}
public class Group : DirectoryEntry {
public Group(Domain domain, string name)
: base(domain, name) {
}
}
Now, notice that I add the entry using Domain.Entries.Add() to the given domain upon instantiation of an IDirectoryEntry interface.
Questions
Is this a good practice, if I don't want the user to change the Domain property of any IDirectoryEntry instances?
Would it be preferable to simply let this Domain.Entries.Add() line go away, and have a method within my Domain class that would add an entry to the domain?
Code Sample for question #2
public class Domain {
//See above for other members.
public void AddEntry<T>(T entry) {
Entries.Add(entry.Name, entry);
}
}
What is, according to you, the best architecture in this situation?Both seem to be good enough to be considered, so I'm a bit confused about it wanting the easiest possible way for the library end-users.
Have you looked at .NET 3.5/4's System.DirectoryServices.AccountManagement namespace? It provides much of the functionality you require in a more unified and .NET friendly interface. I personally have written a library with similar requirements to yours, using a combination of both.
Overall, I think your design looks good, but I don't know enough about your problem domain to know if you'll be painting yourself into a corner so to speak.
Specifically, to Question 1, I think that will work; however, anyone with a reference to an instance of Domain could remove any given Entry.
To Question 2, that is very likely how I would implement it myself, unless I had a compelling reason not to.

Categories