I have these classes:
public class Area{
...
private List<WorkSpace> _workspace;
public IReadOnlyCollection<WorkSpace> workspace;
}
and
public class WorkSpace{
...
private List<WorkSpaceReservation> _workspaceReservation;
public IReadOnlyCollection<WorkSpaceReservation> workspaceReservation;
}
and
public class WorkSpaceReservation{
...
}
Area is the aggregate root.
Now I want to add WorkSpaceReservation to WorkSpaceReservation list. Is it possible in DDD context and rules to define a method in workspace like this:
public void AddWorkSpaceReservation(WorkSpaceReservation w){
_workspaceReservation.Add(w);
}
Or we should add this method in aggregate root?
If for isolation, we should add it in aggregate root how can I access to _workspaceReservation from aggregate root?
There are arguments to avoid having the method in the Workspace but as you mentioned add it in the Area.
Having mutations in the aggregate root allows to implement invariants (validation) that can take into account the state of the entire aggregate, instead of just the single entity.
But doing it or not could not have a big impact depending what you need to do, more important is that also if the method is on the Workspace you don't allow the Workspace itself to be persisted, but only the aggregate root can be.
To solve the issue of the _workspaceReservation field I think you have to do something with the access modifiers (maybe having it internal?), but don't know much of C#
Related
I am new to DDD and I am designing a roommate matching system. One of my Aggregate Roots is a "Profile"
public class Profile
{
...
public Traits Traits { get; private set; }
public Traits Preferences { get; private set; }
...
}
As you can see a profile has a relationship to two entities of type Traits, "Traits" is the users own traits such as the max rent they can contribute, weather they smoke or not etc. and "Preferences" is the same type of info but it represents what they are looking for in a roomate.
I am struggling to understand how to best enforce an invariant like the following example "A profile cannot prefer a roommate who contributes more rent then they do themselves."
If I add a method to profile ChangeMaxRent() like such
public class Profile
{
...
public Traits Traits { get; private set; }
public Traits Preferences { get; private set; }
...
public void ChangeMaxRent(int newMaxRent)
{
//enforce variant here
Traits.SetMaxRent(newMaxRent);
}
}
Then a consumer could just circumvent this by accessing the Traits property directly like so
profile.traits.SetMaxRent(x)
The only way to avoid this is to make the getter for Traits and Preferences private so that a consumer cannot directly access it;
but this would cause a lot of code to be written in the Profile class since I would now need a getter for every property of Trait and Preference
I am struggling to see a clear path forward here, any help would be greatly appreciated.
Generally, you should follow Law of Demeter while designing your aggregates.
Try to avoid sharing mutable objects (e.g entities). This rule prevents reference leaks, making your domain much more secure. Otherwise, as you said, anyone can avoid your aggregate methods and do whatever they want with your entities.
If you really want to use your Traits entity data you could return a copy of an object or other read-only representation. Yep, this add you some additional work, but this way you can avoid a big headache in the future.
Here are a few different ways to achieve entity encapsulation within an aggregate in .NET:
Create the aggregate in a separate project. Define what can be accessed from the outside as public and the rest as internal. In your example, Profile.Traits getter would be public, but Traits.SetMaxRent would be internal.
Define the aggregate root's entities as nested classes of the root. Define what can be accessed only from the root as private. If the file grows, you can define the nested classes in separate files by using partial classes, so you'd have a Profile.cs file and a Profile.Traits.cs file.
Hide the entity reference (make Traits property getter private) and expose its properties (when necessary) directly from the root. You can expose TraitsMaxRent or TraitsInformation. Although Traits.SetMaxRent is public, nobody will be able to get a reference to the actual Traits object.
My personal preference is number 2. I find 1 overkill and 3 requires more code unless you can avoid mapping most of the entities' properties.
I did my best with the title. What I am trying to accomplish is tiered modularity with dependency injection. Whether or not this design pattern is good is a question for another forum.
Because I am using dependency injection, I have interface/implementation pairs. This is the top-level inteface:
public interface IConfiguration<T> where T : ConfigData
{
T GetConfig();
}
Where ConfigData is a simple class that exposes get/set properties like LogLevel and Environment.
There is a base implementation of the interface:
public abstract class ConfigurationBase<T> : IConfiguration
{
protected ConfigData Config { get; set; }
public T GetConfig()
{
return Config as T;
}
}
Now for the dependency injection part of this! I have several interface/implementation pairs that hierarchically inherit from one another. Furthermore, their protected Config property also exposes more properties in each subsequent child class. Here are my interface/implementation signatures:
public interface IGeneralConfiguration : IConfiguration<GeneralConfigData>
public class GeneralConfiguration : ConfigurationBase<GeneralConfigData>, IGeneralConfiguration
public interface ILoginConfiguration : IConfiguration<LoginConfigData>, IGeneralConfiguration
public class LoginConfiguration : ConfigurationBase<LoginConfigData>, ILoginConfiguration
public interface IAppConfiguration : IConfiguration<AppConfigData>, ILoginConfiguration
public class AppConfiguration : ConfigurationBase<AppConfigData>, IAppConfiguration
Note that the inheritance scheme for the config data element is ConfigData → GeneralConfigData → LoginConfigData → AppConfigData. The config data element just exposes more properties specific to login/the application etc. (like Username or StartUri) in each child.
Now, I can use this configuration concept across all my modules. As far as dependency injection goes, resolving IGeneralConfiguration, ILoginConfiguration or IAppConfiguration will yield the exact same instance. However, now general modules only need to resolve IGeneralConfiguration, modules specific to login will only need to resolve ILoginConfiguration, and app-specific modules can resolve IAppConfiugration, all so that they can access parts of their config data specific to the concern they are trying to handle. This modularity allows me to create smaller side-apps that reuse modules from the main application without having to do a lot of custom coding (for example, I can reuse the login module without the need for referencing app-specific modules) as long as I slightly alter my dependency registration.
If you are still with me up to this point, the only problem with this model is that in all of my sub classes (that inherit from ConfigurationBase<T>), they all need the ConfigData() implementation from the interface above them. This means that class LoginConfiguration needs a method definition for public GeneralConfigData GetConfig(), and class AppConfiguration needs a method defintion for both public GeneralConfigData GetConfig() as well as LoginConfigData GetConfig().
So fine. I do that. Now, in my application-specific modules, I get a compiler error. Up in my class field definitions, I have private IAppConfiguration _appConfiguration;. Later in a method, I make a reference to it:
var element = _appConfiguration.GetConfig().AppSpecificConfigElement;
The compiler is confused, saying
the call is ambiguous between the following or properties 'IConfiguration.GetConfig()' and 'IConfiguration.GetConfig()'
Why doesn't the compiler see that the type is IAppConfiguration and define the call to GetConfig() to the AppConfiguration's GetConfig() (where T is defined as AppConfigData)?
Is there an obvious way to disambiguate the call to GetConfig() using my scheme?
If I understand correctly then what you just did is that you have two methods that have same signature except for the return value which cannot be resolved automatically. Compiler doesn't (and cannot) traverse all subclasses derived from ConfigData to determine that AppSpecificConfigElement belongs to AppConfiguration and pick overload based on that - even if it did you can have multiple classes that have AppSpecificConfigElement property so it won't be much wiser. You need to help compiler understand what you need, either by typing _appConfiguration to proper type or using typed descendant of ConfigData instead of var in your statement first and then get property.
In both cases I think you seriously over-engineered and I would suggest to step back and reconsider your approach. As #zaitsman said these objects should be POCOs and have different loader (DB, filesystem, ...) implementing simple Load/Save interface that can be then passed to DI based on context.
I have a Order entity.
public class Order{
public string OrderNumber{get;set;}
public string CreateDate{get;set;}
......
}
Now, I want to add a getxxx method to it.
public class Order{
public string OrderNumber{get;set;}
public string CreateDate{get;set;}
......
public Order GetOrderDetail(string orderNumber){
.....
}
}
But I do not want to instantiate it every time. So, I want to add static to this method.
Whether this is in compliance with the DDD specification?
There's no reason to have static methods in domain objects except the occasional helper (construction method, property that returns a remarkable specific instance of a Value Object, etc).
If you feel you need it, it's probably a smell that the method is trying to reach for data that is not encapsulated in the entity. It will most likely try to get it from an external source outside the Domain layer and from a tightly coupled dependency, which is problematic in terms of design and testability.
Whether this is in compliance with the DDD specification?
No, it is not.
In DDD we have Repositories that load Aggregate roots, so, considering that Order is an Aggregate root, then you will have to create another class, OrderRepository that has the responsability to load an Order from persistence:
public class OrderRepository{
// ......
public Order loadOrderById(string orderId){
// .....
}
}
P.S. I don't use C#, I hope that this is correct.
In your case the answer is NO.
Reason:
You wont be able to access the non-static public properties of Order class in GetOrderDetail(string orderNumber) method. More likely you will use or prefered to use Dependency Injection
for your Data Access Layer and that DAL object will be a private instance field which wont be accecible in static method.
As the comment from Evk suggests that you wont be able to unit test it.
Here is more information on static methods When to use static classes in C#
So in a way I need a setter or a method that is only available to one (or a few more) classes. As far as I know this is common in some other languages as friend classes. I tried to simplify the example below. It's not the real case, and it's a bit more complicated. But I have to make sure that two properties in two different classes keep in sync. I.e. I'm using Entity Framework, and these properties are being synced to the Database.
public class UserGroup
{
List<GroupMember> _Members;
int _AcceptedMemberCount; // this is being synced to the database on save for performance reasons.
public void Join(User user)
{
var member = GetOrCreateMember( user );
member.State = MemberState.Accepted;
UpdateAcceptedMemberCount();
}
public void Ban(User user)
{
var member = GetOrCreateMember( user );
member.JoinState = MemberState.Banned;
UpdateAcceptedMemberCount();
}
private GroupMember GetOrCreateMember(User user)
{
// Creates a GroupMember from User,
// and add it to _Members if it doesn't exist.
}
private void UpdateAcceptedMemberCount()
{
_AcceptedMemberCount = _Members.Where(m => m.State == MemberState.Accepted).Count();
}
}
public class GroupMember
{
public MemberState State { get; internal set; }
}
Alternatives that I know
Using internal
disadvantage is that the property is still available to all the other classes in the same assembly. I.e. I have an assembly with my business models and entities. Making a separate assembly would complicate the code, especially when you're using Entity Framework, and need to start splitting the entities over multiple assemblies.
Adding a SetState(UserGroup userGroup) to GroupMember
... that does some extra manual checking if the UserGroup has done it's work. Like checking if the User has been added as a GroupMember to _Members. Feels really ugly, and more code to maintain that could get out of sync and break down in the future.
Using nested classes (See: https://stackoverflow.com/a/10507130/647845)
Does not really work well with Entity Framework.
Makes the code more verbose (always adding the parent class as a prefix when working with a GroupMember).
GroupMember is an important standalone class in this application. Hiding it behind a parent class for just this reason feels bad.
Has limited use, because every class can only have one hierarchy of outer classes.
Document it in the method summary, and ignore it
And just hope that everyone reads it, and never starts fiddling with the State of a GroupMember manually. The disadvantages of that are probably clear :)
Question
I can't imagine this is a really weird example, and lots of applications must have the same problems. What is the best practice here? How is this commonly solved?
Thanks in advance,
If it's acceptable for other classes to modify GroupMember.State, then you could use events to let the UserGroup monitor whenever a state has changed: when State changes, it raises an event and the UserGroup class listens to it.
If only the UserGroup should be allowed to set state, or if at least any state change should pass by user group, then one thing you could do is move the actual storage of the State property away from GroupMember and into UserGroup:
public class UserGroup
{
List<MemberState> _MemberStates;
...
}
This would require each GroupMember to store the UserGroup it belongs to, so this will only work if each group member is part of only one usergroup. If this is the case then GroupMember will look something like:
public class GroupMember
{
private UserGroup _Parent;
public GroupMember(UserGroup parent)
{
_Parent = parent;
}
public MemberState State { get {return _Parent.GetState(this);} }
// Where GetState is a function that returns the state from _MemberState
...
}
Of course, this does create a strong coupling between the two (together they work to provide two sides of the same public interface) and only works if each GroupMember always has exactly one UserGroup.
Now, if each group member can be part of multiple groups, then the above won't work, but guessing from your example this isn't the case here (because friend wouldn't solve this), so I'll not go into possible solutions.
After thinking about it some, it really comes down to your exact requirements and design choices. It's impossible to give a one-size-fits-all answer, but maybe I managed to inspire you to find a good choice for your project.
Suppose I've two settings (for sake of simplicity) that alters behaviour of my types in a reusable library.
I can define a configuration class:
class Config {
public bool Behaviour1 { get; set; }
public bool Behaviour2 { get; set; }
}
Than if I do such thing I must propagate the instance from the composition root (no matter if handled with IoC) to the whole hierarchy.
The code will be invaded by an horde of conditional statements, reducing readability, maintainability and extensibility.
Would not be better to define two behavioural types?
public class Behaviour1 : IBehaviour1 {}
public class Behaviour2 : IBehaviour2 {}
Remove global dependency the other types have from Config. Than each class that need a behaviour will depends on IBehaviourX and its factory will inject a proper concrete on the basis of Config type.
In this way only few top level types will depends on Config and behaviour of assigning behaviour (pardon the pun) will not propagate to the whole hierarchy.
I'm interested on your solutions in such case.
I would say that you're on the right track with implementing your behaviors as classes/interfaces rather than handling differences with conditionals and the like.
You might want to have a look at the Strategy Pattern as your current idea seems to be heading in that direction. And using IoC your idea should work just fine as is and it's probably what I would settle for.
you may think about the Creation Method design pattern .
Having to change the behavior of the class based upon the configuration parameters will present the problem because then your class will violate SRP rule clearly , create sub classes and use virtual /override methods to get desired behavior related to the configuration the and use Creation Method patten to get the correct object