Pretend I have entities A, B, C, D. They each have a structure as follows
public class A{
public IEnumerable<B> Bs {get;}
public IEnumerable<C> Cs {get;}
public IEnumerable<D> Ds {get;}
}
public class B{
public IEnumerable<B> Bs {get;}
public IEnumerable<D> Ds {get;}
}
public class C{
public IEnumerable<B> Bs {get;}
public IEnumerable<C> Cs {get;}
}
public class D { }
(Imagine this is a bit like a windows folder structure but more complex)
But there is a set of 5+ functions relevant to any class that holds entities (e.g. functions to search the structure). Instead of rewriting these functions we introduce a class:
public class BHolder : ValueObject {
public IEnumerable<B> Bs {get;}
... 5+ DIFFERENT FUNCTIONS HERE
//(example of a write below) (might include validation logic later)
public BHolder AddB(B toBeAdded) => new BHolder(Bs.Concat(new[] {toBeAdded});
}
Now class A has a BHolder, CHolder, and DHolder (and so on for B, C, and D).
From my understanding of DDD, BHolder is not an Entity and therefore MUST be a ValueObject. I've heard the best practice is for these ValueObjects to be immutable. But that means for every "Write" inside of A, B, and C I now need to wrap them as follows:
public class A{
public BHolder BHolder {get;}
....
//"wrapping function" below
public void AddB(B toBeAdded) => BHolder = BHolder.Add(toBeAdded);
}
But as the class grows, we start to get to the stage where there are 15+ "wrapping functions" that are essentially just empty code.
If I make the BHolder mutable, I don't need to worry about these wrapping functions. But every time in the past I've thought making a ValueObject mutable was a good idea I've been proven wrong. (In this case the only thing I can think of is that these "wrapping functions" enforce invariants specific to A holding Bs (which there are none)).
So my question is, is it okay to make BHolder mutable? Or is there a better way that I'm not seeing?