0

A Network is composed of Nodes that are connected with Fibers. The Network is responsible for making sure that:

  1. both ends of any fiber are connected to a Node;
  2. that no two ends are connected to the same Node;
  3. that no two nodes can be in the same (x, y) location;
  4. a network has a limit of 10 nodes and 10 fibers.

Both the Network, the Node and the Fiber are information-rich (they have a name, a date when they were deployed, etc), and it looks to me as if Network is an Aggregate Root (as its the container of both Nodes and Fibers and forces invariants between them).

I'm at this point also sure that Node and Fiber are entities, and that they are also probably Aggregate Roots.

One possible implementation of the Network class might be as follows:

class Network {
  private final NetworkId id;
  private String name;
  private Location location;
  ...
  private final Map<FiberId, Fiber> fibers = new HashMap<FiberId, Fiber>();
  private final Map<NodeId, Fiber> nodes = new HashMap<NodeId, Node>();
}

which poses a big problem if my use case is just to edit the location or the name of the Network. In that case I just don't care about fibers and nodes and realistically, it is expected them to be quite possible for their numbers to be on the order of 10k-100k nodes/fibers! How should I approach this issue? Should I separate the definition of a Network (containing fibers and nodes and their invariants) from the rest of the fields?

I've always thought of Aggregate Roots as Entities that have a set of invariants to hold over its attributes, in contrast with Entities that just don't care abouts the state of their attributes (for instance, a Person defined with a name and age wouldn't probably need to have any kind of checking for invalid combinations of name and age).

Following this philosophy, I generally tend to decide whether some domain concept is either a Value, Entity, Value or Event and then if it's an Entity, if it's an Aggregate Root. Is my assumption flawed?

Thanks

devoured elysium
  • 101,373
  • 131
  • 340
  • 557
  • I don't agree with the way you tell Aggregate Roots from Entities. There are not only Aggregate level invariants but also object level invariants, even in simple Entities or even Value Objects. We do care about the state of their attributes, which according to some DDD schools of thought, must always stay consistent. See http://codebetter.com/gregyoung/2009/05/22/always-valid/ – guillaume31 Apr 18 '14 at 15:15

2 Answers2

3

First of all, don't waste time thinking which is an entity or value objects. Technical details like this come up by themselves. The important thing is to model correctly the concepts. So, what does the domain understand by Network? Is it the container of Nodes or Fibes or itself a logical unit?

Can you have a network without any Node or Fibe? Can an empty Network exists in the domain? Does the Network contains Node and Fibe or the Node and Fibe are organized (grouped by) in a Network? You have to determine if a collection of Node or Fibe really define a network i.e you simply can't have a valid Network concept without those concepts.

Also it does matter the bounded context, the Network concept is specific to one context, it might look a bit different in other context. There is no one single Model valid everywhere. So, in what context are you defining the Network? You need to define only things relevant to THAT context not everything that might be part of Network at some point.

Don't do DDD as a recipe, looking for technical patterns to identify an aggregate root (AR). Do it organically, just try to design the model according to the specific domain context. You'll know when something is an AR not only an entity.

As a thumb rule, an AR is not a container it's still a domain concept which happens to act as a facade for other related concepts.

MikeSW
  • 16,140
  • 3
  • 39
  • 53
  • "what does the domain understand by Network? Is it the container of Nodes or Fibes or itself a logical unit?" From my perspective a network is a container, yes. I didn't get what you mean by a "logical unit". – devoured elysium Apr 17 '14 at 00:29
  • "Can you have a network without any Node or Fibe? Can an empty Network exists in the domain?" Yes. An analogy would be having a Photoshop project without any text or pictures in it, I'd say. It's still a photoshop project. – devoured elysium Apr 17 '14 at 00:30
  • "You have to determine if a collection of Node or Fibe really define a network i.e you simply can't have a valid Network concept without those concepts." A network is really just a bunch of fibers and nodes, plus a couple of restrictions over how nodes and fibers can interact. I don't believe there's a way out of it. – devoured elysium Apr 17 '14 at 00:32
  • I edited the OP and added another constraint. Although your posts' theory is interesting, I'm left wondering how would one go about implementing it in code.. Could you be so kind as to make a sketch of how to go about it? From my perspective, there is no way around the fact that I will have in some place a container of both fibers and nodes, and that that container should have the rules/restrictions regarding how fibers and nodes are allowed to interact (that's what a network is). – devoured elysium Apr 17 '14 at 00:35
  • From an utilitarian point of view, I could maybe separate the container part of a Network from the other general attributes (maybe create a NetworkProperties class? I really don't like the idea..), thus freeing myself from having to load all nodes and fibers every time I want to change a simple attribute such as "name" or "author" from the network. – devoured elysium Apr 17 '14 at 00:37
  • 1
    A Fibe and Node container is usually called a Repository. Maybe you want to have Network simply defined as the concept and to enforce the business rules for Fibe and Node. Have the the relevant Network behaviour take a repository for Node and Fibe as dependency and enforce the constraints. Or put that enforcing in a service. I don't know enough of the Domain to come up with something more concrete. However, I don't think is a concern of the Network to act as a container for other concepts. – MikeSW Apr 17 '14 at 00:53
1

What about delegate the invariant protection to smaller aggregate root?

1.both ends of any fiber are connected to a Node;
2.that no two ends are connected to the same Node;

I think these two could be protected by Fiber. While this one below is kind of tricky, a simple solution is to use database constraint on the location.

3.that no two nodes can be in the same (x, y) location.

Then the network is just an aggregate root with identity and some information.

Yugang Zhou
  • 7,123
  • 6
  • 32
  • 60
  • Yes, I concur with 1) and 2) and that's actually how I was doing it. But I'm still at a loss with the Network and the (x, y) location of nodes. Could you please be more explicit on how would you actually model the Network class? Would Network still need to contain all the nodes and all the fibers? – devoured elysium Apr 15 '14 at 02:23
  • I would probably not model Network as a container since Fiber and Node could protect the invariants themselves. Fiber and Node have NetworkId to maintain their relationships. The only issue is that using database unique constraint makes rule 3 implicit. – Yugang Zhou Apr 15 '14 at 02:30
  • But should my domain code assume a database will have that implicit constraint? – devoured elysium Apr 17 '14 at 00:23
  • I would let the database does what it is good at especially when there is no database portable requirement. Would you check is an identity duplicate in your code :) I think declaring the NodeRepository throws an DuplicateLocationException is just enough. – Yugang Zhou Apr 17 '14 at 01:04
  • How to deal with a "a network has a limit of 10 nodes and 10 fibers." constraint, for instance? Wouldn't that obligue you to have the nodes and fibers in Network? – devoured elysium Apr 17 '14 at 01:14
  • @devouredelysium What about let a domain service return a Specification object contains Nodes and Fibers of a given Network(delegate aggregate retrieving to NodeRepository and FiberRepository). Let the specification check the invariant. – Yugang Zhou Apr 17 '14 at 01:41