Re: Aggregate for transactional consistency
Michael Rempel <[email protected]>
| Newsgroups | gmane.comp.programming.domain-driven-design |
|---|---|
| Message-ID | <CAN2bj2CsAmLX_xrcr-pmHZwn_3FMvMaZ5_kSW2YmQAUDE8Ht6A@mail.gmail.com> |
I might also add that a BC is hard to define because it is a fine boundary. Think of painters painting a picture, the fine lines that define edges are finish detail. Similarly I think you need to model well past the bounded context boundary before you can define clear fine lines. In implementation this boundary becomes vital, but in design it needs to be ignored until the model is clear. And this is my biggest battle with inexperienced teams. They always want to just code the core that is easy to define, ignoring boundary problems. Or they just want to do it monolithicly and have the usual huge problems later on. If you think modeling in terms that include deep filtering, with the CQRS pattern you are likely to push some of the filter into the database where it belongs. I wont argue the point, either you see it or you will ignore me until you see it. That is why I model infrastructure as more of a whole. Sure I will chunk it up and use aggregates. But that isnt the core concern when modeling, especially early, but really always. Classic DDD doesnt show workflows or filters and I think considering both, or all three really, the best way to figure out both BCs and aggregates. Dont draw the lines until you see most of the picture. It is easy to draw the line when you have the picture almost done. On Wed, Jun 12, 2013 at 9:35 AM, Michael Rempel <[email protected]>wrote: > It never says so in the DDD book, but your data reads and writes should be > bite sized chunks. Not too big, and not too small. > > If you go back to a conventional programming mindset for a minute, you > would do validation and aggregation in screen chunks. I tend to create > manifests to make screens and use CQRS for commands/reads as separate items > but the manifest almost always includes a chunk that anticipates the result > for an update command. > > This is the backdrop that influences my domain decisions. The question I > want to always answer in roughly the right way is what validation > requirements are there for all the commands that I want to do against this > entity (using the term loosely here). When I know roughly what that is > going to be like, I have a better idea what to do with aggregates, roots > and so on. An aggregate root is a crude way of attempting to answer the > 'what is a bite sized chunk' question IMHO. > > Another concept not discussed much in DDD is security. The implicit > argument for DDD says that data is the most important thing, security and > workflows are secondary concerns. Sometimes this is what makes DDD hard to > do. In my estimation I want a balance between all three aspects. Data, > Workflows, and security are all co-influencers. And if you miss one aspect, > which is usually security, it becomes a perennial hack in your code. > > For my teams we have another name for security. It is renamed FILTERING > because the data filter aspect of security is far more pervasive and > influential in the systems I design, than is the question 'can I do this'. > In addition, filtering also has a push notification aspect to it, who needs > to know about this, and when? I follow the RACI pattern, responsible, > accountable, consulted, informed. Who needs to have each of those roles. > > responsible means the controller of permissions > accountable means the user of permissions > consulted means the in-process colaborators > informed means the post-process announcees > > When designing with DDD I have each of the 3 aspects of design, and each > of the RACI actors in mind. I then want to design infrastructure, not > functionality. I used to say design version 3 to build version 1, but that > isnt very clear. What I mean is design infrastructure for data, workflow, > and filtering so that the most difficult problems in the domain are solved, > and remain solved. This is a bit idealistic and the idea of capturing all > that up front is a bit of a nightmare for most people. Ambiguity is the > enemy. This is war. And in the heat of battle it is easy to loose sight of > the objective at times. But that is ok, because as an Architect we have > been through a few battles. > > So answering your question means it depends. What are the big chunks? > > In my world when we 'publish' the thing is immutable, and we want to be > able to take advantage of that fact by having an ID similar to a DOI that > we can pass around and reference from anywhere. When we do that we get rid > of all the work lint, and just produce the outcome. That might store in the > database in its original form, but it might also just become an > authoritative PDF. Of course you want to keep the artifacts of creation > around for versioning a new instance, a revision, another similar document > of some sort. But when the document prints it should render the database > version frozen, it should make objects immutable and so on in your code. > Which in my mind means they are some other kind of aggregate. > > > On Tue, Jun 11, 2013 at 2:48 PM, j88bradshaw88 <[email protected]>wrote: > >> ** >> >> >> I am developing a CMS type application and am looking to use some ddd >> tactical patterns. Here is the situation: >> >> The application deals with the authoring and publishing of items. >> >> Items are grouped together in a workflow group. Within that group, one >> item may be marked as 'Published', one item as 'Working' and any number as >> 'Archived'. >> >> A item can only be edited when it is in the 'Working' state. >> >> When a working item is published it replaces its corresponding published >> item (if there is one), which would be then marked as Archived. >> >> If no draft exists, a new working version may be created by copying the >> published version or any of the archived versions. >> >> The question is, following the guidance that Aggregates should >> encapsulate system invariants, should Workflow Group be an Aggregate root - >> encompassing all its items? >> >> My worry is that this would make quite a large aggregate, and it would >> stop items being globally accessible (i.e. all interaction would have to go >> through the Workflow Group AR). >> >> The alternative I see is to make Item an Aggregate Root, and then have a >> Domain Service deal with the transactions and invariants. For instance: >> >> PublishWorkingItem(int itemId) >> { >> Item workingItem = itemRepo.GetWorkingItem(itemId); >> Guid groupId = workingItem.GroupId; >> Item publishedItem = itemRepo.GetPublishedItemForGroup(groupId); >> if(publishedItem != null) >> { >> publisheditem.Archive(); >> } >> workingItem.Publish(); >> } >> >> To add to the complexity, there needs to be different types of Item(i.e. >> Artcile, etc.) so Item would be an abstract class that is derived from. >> >> >> > >