Learning&Practicing Domain Driven Design, Looking for some guidance - c#
I am currently working towards learning "Domain Driven Design".
I'm wondering how someone would design these entities. I simplified the object model as it would take to long to explain the "REAL" application to highlight the area of the domain I'm having trouble with.
So a CustomerInfo aggregate contains a list of Entries. It's this "Entry" object I'm having trouble designing.
//Lets call the CustomerInfo the Aggregate Root
public class CustomerInfo {
/* Other properties removed, to simplify question */
public List<Entry> Entries { get; set; }
}
The Entry object "can" be described by a few different lists of entities. The caveat here is the "Entry" can "ONLY" be described by one of these lists. In my domain it does not make sense for an entry to have a list of Widgets AND a list of ThisThings.
To complicate things.
The entities Trinket, ThatThing, ThisThing and TheOtherThing all have the same properties, but in the context of this domain their meaning is very different.
This is my current domain model. Which I do not like as I have all this validation to make sure only one of the lists are populated by the user
public class Entry
{
public Guid EntryId { get; set; }
/* Other properties removed, to simplify question */
public List<Widget> Widget { get; set; }
public List<Trinket> Trinkets { get; set; }
public List<ThatThing> ThatThings { get; set; }
public List<ThisThing> ThisThings { get; set; }
public List<TheOtherThing> TheOtherThings { get; set; }
}
public class Widget
{
public Guid Widgetid { get; private set; }
public string Name { get; private set; }
public int Size { get; set; }
public string Color { get; set; }
}
public class Trinket
{
public Guid Trinketid { get; private set; }
public decimal Cost { get; private set; }
public Construction Construction { get; private set; }
}
public class ThatThing
{
public Guid ThatThingid { get; private set; }
public decimal Cost { get; private set; }
public Construction Construction { get; private set; }
}
public class ThisThing
{
public Guid ThisThingid { get; private set; }
public decimal Cost { get; private set; }
public Construction Construction { get; private set; }
}
public class TheOtherThing
{
public Guid TheOtherThingId { get; private set; }
public string Name { get; private set; }
public Construction Construction { get; private set; }
}
public class Construction : ValueObject<Construction>
{
public int Size { get; private set; }
public string Weight { get; private set; }
public string Unit { get; private set; }
public string Form { get; private set; }
}
What I'm struggling with is how to model this "Entry" entity properly.
1) Should I keep as designed and just rely on this crazy validation.
2) Should I be creating a polymorphic model to handle these?
public interface IWidget{
public Guid Widgetid { get; set; }
}
public interface IDifferentWidget:IWidget
{
public decimal Cost { get; set; }
public Construction Construction { get; set; }
}
public class Widget:IWidget
{
public Guid WidgetId { get; private set; }
public string Name { get; private set; }
public int Size { get; set; }
public string Color { get; set; }
}
public class Trinket : IDifferentWidget
{
public Guid WidgetId { get; private set; }
public decimal Cost { get; private set; }
public Construction Construction { get; private set; }
}
public class ThatThing : IDifferentWidget
{
public Guid WidgetId { get; private set; }
public decimal Cost { get; private set; }
public Construction Construction { get; private set; }
}
public class ThisThing : IDifferentWidget
{
public Guid WidgetId { get; private set; }
public decimal Cost { get; private set; }
public Construction Construction { get; private set; }
}
public class TheOtherThing : IDifferentWidget
{
public Guid WidgetId { get; private set; }
public decimal Cost { get; private set; }
public Construction Construction { get; private set; }
}
Then the Entry entity would look like, but does not prevent a ThisThing and ThatThing being added to the same Entry List.
public class Entry
{
public Guid EntryId { get; set; }
/* Other properties removed, to simplify question */
public List<IWidget> Widgets { get; set; }
}
3) Should I create different Entry entities entirely like WidgetEntry, ThisThingEntry with a common interface so the Aggregate Root would look like so:
//Lets call the CustomerInfo the Aggregate Root
public class CustomerInfo {
/* Other properties removed, to simplify question */
public List<IEntry> Entries { get; set; }
}
Considering the different options I've contemplated,the only solution that tackles this domain constraint "Entry" can "ONLY" be described by one of these lists is #3
Any guidance would be greatly appreciated, apologizes for the long winded question!
/*******************************REVISED DOMAIN DESIGN ***********************/
I still believe an CustomerInfo should be the aggregate because in my domain it makes sense to describe the CustomerInfo by the various entries users add to it to build a "CustomerInfo" entity.
//Lets call the CustomerInfo the Aggregate Root
public class CustomerInfo {
public Guid CustomerId { get; private set; }
private List<Entry> _entries;
public IEnumerable<Entry> Entries => _entries;
private CustomerInfo(Guid customerId /* Other properties removed, to
simplify question */){ }
public CustomerInfo Create(/* Other properties removed, to simplify
question */) {
return new CustomerInfo(Guid.NewGuid());
}
/*This is how the entity will control the state of the various lists of
entities that describe it.*/
public Entry UpdateEntry(/* Parameters removed for simplicity */) {
}
public Entry AddEntry(/* Parameters removed for simplicity */) {
}
public Entry RemoveEntry(/* Parameters removed for simplicity */) {
}
}
public class Entry {
public Guid EntryId { get; set; }
/* Other properties removed, to simplify question */
private List<Widget> _widgets;
public IEnumerable<Widget> Widgets => _widgets;
private List<Trinket> _trinkets;
public IEnumerable<Trinket> Trinkets => _trinkets;
private List<ThatThing> _thatThing;
public IEnumerable<ThatThing> ThatThings => _thatThing;
private List<ThisThing> _thisThings;
public IEnumerable<ThisThing> ThisThings => _thisThings;
private List<TheOtherThing> _theOtherThing;
public IEnumerable<TheOtherThing> TheOtherThings => _theOtherThing;
private Entry(guid EntryId /*This constructor will take more parameters,
it's simplified for my question*/) { }
//Create a new instance of a Entry entity
public Entry Create(/* Parameters removed for simplicity */) {
return new Entry(Guid.NewGuid());
}
//This is how the entity will control the state of the various lists of
entities that describe it.
public Widget UpdateWidget() {
}
public Widget AddWidget() {
}
public Widget RemoveWidget() {
}
private bool CanAddAWidget() {
/* Logic to prevent a widget from being add if any of the other
lists have items*/
}
public ThisThing UpdateThisThing()
{
}
public ThisThing AddThisThing()
{
}
public ThisThing RemoveThisThing()
{
}
private bool CanAddAThisThing()
{
/* Logic to prevent a widget from being add if any of the other lists
have items*/
}
}
The problem is that you haven't designed a proper Aggregate root - a tactical Domain driven design pattern.
In your case, Entry should be an Aggregate root that ensures its own invariants. The invariant that I've identified is that Entry should not have only one kind of Thing added to its internal list. So, your code should reflect that invariant.
That being said, the Entry should have an private list of things, implemented as separate lists or just one mixed list, depending on the list/lists usage. That will prevent the client code to add items to the list without any verification. Then the Aggregate should have a addThing public method (replace that name with a more proper name from your Ubiquitous language). This method must verify the said invariant and reject any duplicates.
To use or not an abstraction depends not on DDD but on the usage of the Things. Ask yourself: does this abstraction help me to follow the OOP principles (see SOLID)? In your case is not clear because I don't know how you use those things inside the Aggregate or in the client code.
The short answer is that you can't abstract away your question like this. For example what makes a Widget and a ThisThing so simmilar that they can be listed together but a ThatThing can't be?
Just consider it like this
class Dog: IMamal {
}
class Cat: IMamal {
}
interface IMamal : IAnimal {
}
class Chicken : IAnimal {
}
Here i found that Dogs and Cats are simmilar in that if i talk about animals that i would refer to those kind of animals as mamals.
So talk to your domain expert and try to figure out what certain groups of things are called. That way you can define an interface that groups certain things together but not others
If you can't find a way why they belong together in by talking to your domain expert then it's a good bet they should be 2 separate lists.
Polimorphism should really only follow if your domain really describes it that way. If i take my animal example a Mamal might have a Walk() method and a Bird might have a Fly() method and a Hop() method (if a birt doesn't fly)
There might not be polymorphic Move() method since no biologist would describe that an animal moves, they always refer to it as either walking or flying (just for the sake of argument here, it should be the domain expert who describes entities as all having a "Name" and not the programmer who sees that "Name" "Label" and "Description" are the same kind of fields. (As Mike pointed out conincidental coheision is the thing to avoid here)
Related
Combine two classes from a table per hierarchy inheritance structure in Entity Framework
We're are using the table per hierarchy inheritance technique with Entity Framework. I'll take the example classes from this page as the basic classes: Table per Hierarchy Inheritance - The Model. Please don't take the class names and properties as set. I didn't want to expose anything critical. This question is just about the structure. public class Contract { public int ContractId { get; set; } public DateTime StartDate { get; set; } public int Months { get; set;} public decimal Charge { get; set; } } public class MobileContract : Contract { public string MobileNumber { get; set; } } public class TvContract : Contract { public PackageType PackageType { get; set; } } public class BroadBandContract : Contract { public int DownloadSpeed { get; set; } } public enum PackageType { S, M, L, XL } Now, in our case we have the situation that there is a contract that can be both, a TvContract and a BroadBandContract, e.g. a MultiContract. We don't know how to deal with this since we cannot inherit from two classes. If we query the DbSet<TvContract> or DbSet<BroadBandContract> from the we also want to get the MultiContracts. Does someone have an idea how to deal with this scenario?
I see our current class structure is of inheritance. While to me it looks like composition. A contract may contain different subcontracts and once the contract expires, subcontracts too expire. However, subcontracts are of different types and that is what you could use for your advantage. You may also see a requirement where someone would add or remove the packages they have thus contract type is not really static. I would design to handle that. I would have also preferred an end date or Months individually on SubContract allowing for variable start and end dates for SubContract obejcts. I would redesign the classes like this and then only query Contract potentially with SubContract based filters. public class Contract { public int ContractId { get; set; } public DateTime StartDate { get; set; } public int Months { get; set; } public decimal Charge { get; set; } public bool IsMultiContract { get { return SubContracts.GroupBy(x => x.ContractType).Count() > 0; } } /// <summary> /// Optional unique check for subcontract types may be added /// </summary> public List<SubContract> SubContracts { get; set; } } public enum ContractType { Broadband, Mobile, TV } public class SubContract { public ContractType ContractType { get; set; } } public class MobileContract : SubContract { public string MobileNumber { get; set; } } public class TvContract : SubContract { public PackageType PackageType { get; set; } } public class BroadBandContract : SubContract { public int DownloadSpeed { get; set; } } public enum PackageType { S, M, L, XL }
Implementing Generic Interfaces for collections of widgets?
We're attempting to build a somewhat basic reporting system for our analytics team to use. It's our third or fourth iteration of the same system, but we're doing a consolidation and rewrite of a large portion of the backend logic to make generating reports easier going forward. One issue we're having is forming the interfaces that will be implemented by our reporting widgets in order to push them through to our ViewComponents. An example of a couple widgets may look something like the following: public interface IWidget<T> { WidgetType WidgetType { get; set; } string WidgetName { get; set; } T ViewModel { get; set; } } public class ChartWidget : IWidget<Chart> { public WidgetType WidgetType { get; private set; } public string WidgetName { get; set; } public Chart ViewModel { get; set; } public ChartWidget() { WidgetType = WidgetType.Chart; } } public class HeadlineBarWidget : IWidget<HeadlineBarData> { public WidgetType WidgetType { get; private set; } public string WidgetName { get; set; } public HeadlineBarData ViewModel { get; set; } public ChartWidget() { WidgetType = WidgetType.HeadlineBar; } } But the report will contain a collection of widgets, and that collection will need to be iterated over in the View in order to fetch the proper ViewComponents and supply them with the matching model that they expect. Unfortunately, it appears most collection types need to ensure type safety, and I need a way to make this a bit better. As it stands now, our IWidget object defines ViewModel as an object, and I don't think this is a good practice.
Grouping Variables For Better Organization [closed]
Closed. This question is opinion-based. It is not currently accepting answers. Want to improve this question? Update the question so it can be answered with facts and citations by editing this post. Closed 5 years ago. Improve this question My question has sort of already been asked here: How to build a group of constant variables in c# But I feel as though it is not quite asking the same thing. I will try to explain, please hear me out. Suppose for a moment that you had to represent attributes for a player, such as Strength, Agility, Stamina, etc. But at the same time you also wanted to list other attributes which were not directly related to the same group. Aside from Primary Attributes you could have Probabilistic Attributes, such as Accuracy, Evasion, and Critical Strike. As well as Logistical Attributes, like: Movement, Initiative, and Jump. Naturally, these Attributes serve different purposes, and thus, should be grouped seperately(Or at least in my mind they should). I could implement this using multiple classes: namespace Example { public class PrimaryAttributes { public int Strength { get; set; } public int Agility { get; set; } public int Stamina { get; set; } public int Intellect { get; set; } public int Willpower { get; set; } public int Spirit { get; set; } public PrimaryAttributes() { // Do stuff here } // Do more stuff here } } Continued... namespace Example { public class ProbabilisticAttributes { public int Accuracy { get; set; } public int Evasion { get; set; } public int CriticalStrike { get; set; } public ProbabilisticAttributes() { // Do stuff here } // Do more stuff here } } Continued... namespace Example { public class LogisticalAttributes { public int Movement { get; set; } public int Initiative { get; set; } public int Jump { get; set; } public LogisticalAttributes() { // Do stuff here } // Do more stuff here } } And then host them all in a single class, like this: namespace Example { public class Statistics { public PrimaryAttributes PrimaryAttributes { get; set; } public ProbabilisticAttributes ProbabilisticAttributes { get; set; } public LogisticalAttributes LogisticalAttributes { get; set; } public LogisticalAttributes() { PrimaryAttributes = new PrimaryAttributes(); ProbabilisticAttributes = new ProbabilisticAttributes(); LogisticalAttributes = new LogisticalAttributes(); } // Do more stuff here } } That would achieve the effect of being able to call something along the lines of "stats.PrimaryAttributes.Strength", which is clean and organized. However, I would prefer to not do this. I would like to host all the variables within the same class without having to use other classes. So what's the catch? I still want to be able to organize them behind an extended scope, or I guess what could be called a namespace; a sort of divider, if you will. I don't think anything like this exists within the C# language...or any language for that matter. But I want to know how close I can get to replicating this behavior. Here is an example of what I am looking for (not real C#, just an example). namespace Example { public class Attributes { group PrimaryAttributes // Imaginary "group" keyword. { int Strength { get; set; } int Agility { get; set; } int Stamina { get; set; } int Intellect { get; set; } int Wisdom { get; set; } int Spirit { get; set; } } group ProbabilisticAttributes // Imaginary "group" keyword. { int Evasion { get; set; } int Accuracy { get; set; } int CriticalStrike { get; set; } } group LogisticalAttributes // Imaginary "group" keyword. { int Movement { get; set; } int Initiative { get; set; } int Jump { get; set; } } public Attributes() { // Don't have to declare or initialize anything. } public int ReturnSomethingAmazing() { return this.PrimaryAttributes.Strength * this.PrimaryAttributes.Agility; // Notice the group accessor usage. } // Do more stuff here } } I hope you can see what I am talking about now. I want to be able to "scope" variables, but without the use of separate classes. I have also taken the liberty of thinking about how this could be parsed at compile time. Essentially, the group scopes would just be inlined, so myClassInstance.PrimaryAttributes.Strength , would be minimalized to myClassInstance.Strength. The scope doesn't actually exist, it's only there for the programmer to better facilitate organization, without expending more objects in memory at runtime. To end this, I wanted to summarize two questions. Is this in any way possible using current C#? and Do you think this would be a good suggestion to recommend to Microsoft for an addition to the C# programming language?
With this kind of questions, the only answer possible is an expression of an opinion. Sometimes people think differently, sometimes they don't, so please bear with me. OOP gets hard and confusing sometimes but here is how I think about it and what I would've done. Also, I understand that you want to do it without "separate classes" and what I will suggest is exactly the opposite. But I believe doing it using separate abstracts is where you "find The Force, Luke". First, let's create an enum to simplify the grouping (and de-grouping when we access the properties in the future): public enum AttributeCategory { Primary, Probabilistic, Logistical } Now, the concept of an attribute is a very good candidate for an interface. Let's create it and create an associated abstract to reduce and simplify the code (yeah, excessive use of interfaces, but who cares :D ): public interface IAttribute { string AttributeName { get; } AttributeCategory Category { get; } int Value { get; } } public abstract class AttributeBase : IAttribute { protected virtual string AttributeName { get; } protected virtual AttributeCategory Category { get; } protected virtual int Value { get; } } // Note: one might want to implement a generic type for value, something like AttributeBase<T> {... T Value { get; } } Now let's define a couple of additional abstracts, you'll see why I prefer doing it this way a tiny bit later: public abstract class PrimaryAttribute : AttributeBase { protected override sealed AttributeCategory Category { get; } = AttributeCategory.Primary; } public abstract class ProbabilisticAttribute : AttributeBase { protected override sealed AttributeCategory Category { get; } = AttributeCategory.Probabilistic; } public abstract class LogisticalAttribute : AttributeBase { protected override sealed AttributeCategory Category { get; } = AttributeCategory.Logistical; } OK, now we can implement actual attributes: public sealed class Strength : PrimaryAttribute { protected override string AttributeName => "Strength"; } public sealed class Stamina : PrimaryAttribute { protected override string AttributeName => "Stamina"; } public sealed class Accuracy : ProbabilisticAttribute { protected override string AttributeName => "Accuracy"; } public sealed class Initiative : LogisticalAttribute { protected override string AttributeName => "Initiative"; } With the "mess" I've described above we now can create a class that describes the collection of these attributes: public abstract class AttributeCollectionBase { protected virtual List<IAttribute> Attributes { get; } = new List<IAttribute>(); protected virtual IEnumerable<IAttribute> Get(AttributeCategory category) { return Attributes.Where(a => a.Category == category); } protected AttributeCollectionBase() { // Yup, we'll need this one place with the constructor that lists the "default" attributes... Might be for the best, though. Attributes.Add(new Strength()); Attributes.Add(new Stamina()); Attributes.Add(new Accuracy()); Attributes.Add(new Initiative()); } } Finally, we can create an implementation of this attribute collection: public sealed class AttributeCollection : AttributeCollectionBase { //... We don't need anything here to start. Maybe add something specific. } public class SomeCharacter { //... public AttributeCollection Attributes { get; } } var someCharacter = new SomeCharacter(); Now, why go through all this pain? Well, now if anything needs to be implemented for, let's say, probabilistic attributes (some generic calculation) - one modification needed, in the abstract class (new virtual method). Any change needed for all the attributes? One piece of code to adjust - AttributeBase. Ever need to separate some default attributes (let's say for a different class of characters) - just another AttributeCollectionBase implementation is needed, for example, KnightAttributeCollection. And, finally, you achieve the "get the attribute by type" implementation like this: someCharacter.Attributes.Get(AttributeCategory.Logistical); Nevertheless, this is my personal way I'm sharing and it might seem/be sub-optimal or less than understandable and it doesn't mean anything more than the fact that "it always depends".
This is a way I just came up with, not sure if it's worth it but you may like it: public class Attributes { // PrimaryAttributes public class PrimaryAttr { public int Strength { get; set; } public int Agility { get; set; } public int Stamina { get; set; } public int Intellect { get; set; } public int Wisdom { get; set; } public int Spirit { get; set; } } private PrimaryAttr _primaryAttr; public PrimaryAttr PrimaryAttributes { get { if (this._primaryAttr == null) this._primaryAttr = new PrimaryAttr(); return this._primaryAttr; } } // ProbabilisticAttributes public class ProbabilisticAttr { public int Evasion { get; set; } public int Accuracy { get; set; } public int CriticalStrike { get; set; } } private ProbabilisticAttr _probabilisticAttr; public ProbabilisticAttr ProbabilisticAttributes { get { if (this._probabilisticAttr == null) this._probabilisticAttr = new ProbabilisticAttr(); return this._probabilisticAttr; } } // LogisticalAttributes public class LogisticalAttr { public int Movement { get; set; } public int Initiative { get; set; } public int Jump { get; set; } } private LogisticalAttr _logisticalAttr; public LogisticalAttr LogisticalAttributes { get { if (this._logisticalAttr == null) this._logisticalAttr = new LogisticalAttr(); return this._logisticalAttr; } } // Rest of the implementation public Attributes() { // Don't have to declare or initialize anything. } public int ReturnSomethingAmazing() { return this.PrimaryAttributes.Strength * this.PrimaryAttributes.Agility; // Notice the group accessor usage. } // Do more stuff here }
Creating Objects where multiple objects have the same properties
My program is starting to get pretty big. and i have found that its starting to do the same thing in multiple area's. Im trying to figure out how i can make it more efficient. So i have an object that looks like this public class TreeViewNode { public TreeViewNode() { Children = new ObservableCollection<TreeViewNode>(); } public String Name { get; set; } public string Description { get; set; } public ObservableCollection<TreeViewNode> Children { get; set; } } i also have another object that looks like this; public class ComputerObject { public String Name { get; set; } public Int32 UUID { get; set; } public DateTime Created { get; set; } public ObservableCollection<Object> Children { get; set; } } Both these items need to have some of the same properties.. at the moment they both have the Children Property and the Name Property. but they both need to have some other common properties added to them. so i have tried something like this. public class BaseObject { public String Name { get; set; } public ObservableCollection<Object> Children { get; set; } public string Description { get; set; } public BaseObject() { Children = new ObservableCollection<object>(); } } public class ComputerObject: BaseObject { public Int32 UUID { get; set; } public DateTime Created { get; set; } } public class TreeViewNode: BaseObject { public String IconPath { get; set; } } Now this is just a cut down version of what i am implementing, i have alot of objects that share the same properties. and some that dont and mix and match. and i cannot figure out the best implimentation for this. My Objects are becoming very cluttered, and when i rename a property i find that i have to rename it in several area's and this isnt the way its ment to be. can someone please advise how i would implement multiple objects that share the same property names?
In my opinion you should not let classes inherit from one baseclass when these childclasses are not related to each other (like #Sriram Sakthivel asked Animal < Dog,Cat) just to share the same properties. You should determine which classes are related (cat, dog are animals; car, motorcycle are vehicles) and then create baseclasses based on these "groupings".
I would look into decorator pattern. In short, you dont share common properties via inheritance. You make classes that contain common properties, and use these classes as properties in your end classes. EDIT: Example is actually just a standard composition, it should work nevertheless E.G. public class Decorator1 { public String Name { get; set; } public ObservableCollection<Object> Children { get; set; } public string Description { get; set; } } public class Decorator2 { public long Id { get; set; } } public class ClassA { public Decorator1 TreeNodeImpl; } public class ClassB { public Decorator1 TreeNodeImpl; public Decorator2 LongIdImpl; }
Recursive objects causing stackoverflow on StackService.Redis client method Store()
I have two POCO classes (Account and Invoice) and as you can see (below are mockups of these classes) they are recursive. When I pass in an invoice object with the account property set and then try to store it using the redis client it causes a stackoverlow due to recursion. Below is an example of how I'm making the call. CachingService.Store<Invoice>(invoiceObj); public class CachingService { // .... public static void Store<T>(T obj) { using (var client = _redisClientsManager.GetClient()) { var typedClient = client.GetTypedClient<T>(); typedClient.Store(obj); } } } Example of my POCO classes: public class Account { public string Name { set; get; } public bool IsActive { set; get; } public virtual ICollection<Invoice> Invoices { set; get; } } public class Invoice { public bool IsPaid { set; get; } public DateTime? LastSent { set; get; } public int AccountId { set; get; } public virtual Account Account { set; get; } }
Most serializers (ServiceStack included) does not support cyclical references. This is a major anti-pattern when designing DTOs. To resolve this, you want to tell ServiceStack.Text's serializers to ignore that property for Serialization which you can do using the [IgnoreDataMember] property or changing it so it's not a public property or change it into a method.