3

The domain is more or less straightforward — I have an article (or rather several types of articles) that I want to edit and publish. Published article is exposed through an API to public. The thing I have a problem with is further editing of a published article. Versioning, revisions, etc. are irrelevant at the moment. I just need to model this process:

  • Author/editor creates an article (we have a new article)
  • Author edits it and saves it (the article's data is updated)
  • Author publishes it (the article becomes available to public)
  • Author edits the article again and saves (the published version doesn't change, what happens to the article?)

I'm not putting it as a "state change" in my description as it might bring up the state pattern sooner than it's needed. I tried approaching the problem in the following ways:

  1. Article as an aggregate through which the current version and the published version can be accessed. But it seems weird as it basically references it's own versions
  2. Split the problem into two context (editing and publishing) and create a new PublishedArticle entity when the article is published but it doesn't really model the real situation. No domain expert will say "We create a published article from this article"
  3. I looked into state pattern but got lost trying to understand how to actually use it in my concrete example.

DBs/languages are irrelevant. I will gladly see anything helpful, be it a link for further research or a piece of code in any language. Thank you

3 Answers 3

3

So the answer is "go listen to your domain experts", and probe very carefully when they seem to be using the same word for two different ideas with different life cycles.

No domain expert will say "We create a published article from this article"

True, but you may hear them say we published this draft; or we published this submission (not the same thing). Or that a revision was published (also not the same thing).

Article as an aggregate through which the current version and the published version can be accessed. But it seems weird as it basically references it's own versions

Not really that weird -- think source control; we have a document history, and tags that tell us which item in that history is the current development snapshot, and which was used for the nightly build, and which was used for the latest release....

Split the problem into two context (editing and publishing)

Maybe - two contexts (in the sense of bounded contexts from the blue book) usually means different audiences that use the same language with different semantics. If "editors" mean one thing when they say "article", and publishers mean a different thing, then two different contexts can help with that.

But if the editors and the publishers share the same vocabulary, then you might be looking for two different aggregates.

I looked into state pattern but got lost trying to understand how to actually use it in my concrete example.

State pattern works really well for processes; the trick is that the process instance, and the document going through the process, are different things. One keeps track of the work done (state machine) and one is the work (document).

Still curious about the state pattern. Can you elaborate on how it can possibly look in my scenario, please?

Processes tend to go well with "event sourcing" -- the current state of a process is just a fold of the events that have happened so far.

DraftCreated
DraftModified
DraftSubmitted
SubmissionRejected
DraftModified
DraftSubmitted
SubmissionApproved
ArticlePublished
ArticleRetracted
...

So imagine a state machine; you start in a Begin state, and each time you see that something has happened, you notify your machine instance of the event, and it calculates the next state.

Metaphorically, we have a piece of paper (the article) inside an envelope (the process). Every time somebody does something to the document, they write what they did on the envelope. You could imagine this envelope moving from one inbox to the next.

The current state is fundamentally the bit that answers questions; given what has happened so far, what things can happen next? who are we waiting on? how long did it take? how much should the author be paid? and so on

A very different set of questions from those you would ask the document: what's your title? how long are you? what reading level are you? and so on.

1
  • Thank you, that's super helpful. And yeah, I think I used the word context in a wrong way. I'll try to push the aggregates approach further and will also have a chat with the domain "domain experts". Still curious about the state pattern. Can you elaborate on how it can possibly look in my scenario, please? May 10, 2017 at 22:06
0

I've done it this way:

  • Article.Save - creates a new article with a new version number and specified content

  • Publication?.Publish(article) - adds/updates a PublishedArticleVersionNumber with the version number specified

  • Article.Load(versionId)- Returns the selected/latest version of the article for editing.

This is super flexible, because you never delete an article and separate the Publishing from the creation and editing.

However, it does eat a lot of disk space unless you do something clever about storing all those revisions. You can save deltas, use Event Sourcing, or just delete old versions. Easiest option, buy bigger harddisks

3
  • Thanks you. My problem is more about modelling it on the domain level. Persistence layer is a lesser problem than the actual domain logic. I wouldn't want to have the saving/publishing logic as an infrastructural solution as it would couple it quite a bit. May 10, 2017 at 22:01
  • Once you introduce the concept of an immutable Article and a separate PublishedArticleId there is no domain logic to speak of
    – Ewan
    May 10, 2017 at 22:10
  • re: "something clever about storing", I've seen systems like this built that just use git under the hood, and make use of its native cleverness.
    – Paul
    May 11, 2017 at 12:08
0

To add to the other good answers here, and to be a bit more meta, we should (be able to) do our domain designs directly in domain terms that client is familiar with, and without any reference to implementation patterns like state pattern.

The state pattern may indeed apply during coding, but that's premature to consider at this point.

A domain design need to capture the entities and their relationships, which will be driven by what your users need to talk about and to accomplish over time.

In DDD one of the first things you want to do is establish common vocabulary between the users within the domain. This common vocabulary is the built into the entities and relationships. Eventually that vocabulary gets built into capabilities and behaviors, via code. When we get to code, behavioral software patterns apply (e.g. state pattern).


I like @VoiceOfUnreason's teasing out of the terms draft and publication beyond the overloaded term article.


I would think that you might also be concerned about having a stable article identity, or having explicit relationships between drafts, such that a series of drafts would support changing the title in addition to other content. Something to ask your domain experts about.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.