0

I have an aggregate root that needs to be in valid state in order to be used in the system properly. However, the process of building the aggregate is long enough for users to be distracted. Sometimes, all user wants is to configure some part of this big aggregate and then save his work and go home, and tomorrow he will finish aggregate construction.

How can I do this? My PM enforced that we allow aggregates to have invalid state, and then we will check IsValid boolean right before we use it.

I personally went another path: I used Builder pattern for building my aggregate and now I'm planning to persist the builder itself as some intermediary state.

Ivan Zyranau
  • 879
  • 2
  • 14
  • 33
  • It's highly possible that your object is not really a right aggregate (from the business point of view), since it's so complicated. I would try to split it into smaller parts. – Mike Wojtyna Apr 11 '17 at 23:51
  • I'm not going to add an answer as the ones by plalx and VoiceOfUnreason cover your options. I will add that you could go with more of a "tell-don't-ask" approach in that ARs should be processing *commands* through its methods. You could add that `Activate()` method that will place your aggregate into a usable state after checking invariants. Any other actions on the AR when not in a valid state will throw exceptions or revert the AR into an `Inactive/Draft` state. – Eben Roux Apr 12 '17 at 11:00
  • You could use a Saga to support this process. A saga would keep track of the state until you have everything you need to create a valid AR. – Jeff Dobson Apr 29 '17 at 14:05

2 Answers2

0

I have an aggregate root that needs to be in valid state in order to be used in the system properly. However, the process of building the aggregate is long enough for users to be distracted. Sometimes, all user wants is to configure some part of this big aggregate and then save his work and go home, and tomorrow he will finish aggregate construction.

How can I do this?

You have two aggregates -- one is the "configuration" that the users can edit at their own pace. The other is the live running instance built from a copy of the configuration, but only if that configuration satisfies the invariant of the running instance.

Community
  • 1
  • 1
VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91
  • So I have two absolutely the same aggregates (could be inherited), just one without validation and the other with validation? And I guess I can then persist them in the same table with a dedicated column for "isConfiguration" or "isWIP" tag set (prototype pattern)? By the way, there can be a situation where the "running" aggregate should be edited again (in fact, this is frequent). Then it can become invalid again. – Ivan Zyranau Apr 11 '17 at 18:12
  • 1
    why not just introduce a concept of your aggregate being "activated". this way it only needs to be in a specific valid state when it is activated / used. – Marco Apr 11 '17 at 18:26
  • The "configuration" aggregate could be in fact a CRUD entity. – Constantin Galbenu Apr 11 '17 at 19:42
0

By the way, there can be a situation where the "running" aggregate should be edited again (in fact, this is frequent). Then it can become invalid again.

You have two obvious options here:

  • Model every undergoing creation/change process as a different aggregate (perhaps even in a different Bounded Context -- could be CRUD). That allows you to free your main aggregate from contextual validation.

  • Use the same aggregate instance, but in different states. For instance, you may have some fields as Optional<T> which could be empty when the aggregate is in the draft state, but can't when it is published. The state pattern could possibly be useful here.

plalx
  • 42,889
  • 6
  • 74
  • 90