for learning purposes I'm trying to build a rest api with some DDD principles. After reading a lot, some things are not quite clear to me.
Before I ask the questions I will show the domain model and an example use case.
Domain model
TagAR
- id
- workspace_id // Reference to WorkspaceAR
- name
WorkspaceAR
- id
- name
- tags // List of Tag ids. Reference to TagAR
ProjectAR
- id
- workspace_id // Reference to WorkspaceAR
- name
- description
- tags // List of Tag ids. Reference to TagAR
NoteAR
- id
- workspace_id // Reference to WorkspaceAR
- name
- tags // List of Tag ids. Reference to TagAR
Some business rules:
- A Workspace can have multiple Projects and Notes
- Projects and Notes can have multiple Tags
- A Tag belongs to a Workspace
Example use case: Add new Project to Workspace (command)
CreateProjectDto:
workspace_id: int
name: string
description: string
tagNames: string[]
class ProjectCommandService(projectRepo, tagRepo, worksapceRepo):
function CreateProjectUseCase(dto: CreateProjectDto):
workspace = workspaceRepo.FindById(dto.workspace_id)
if workspace is None:
return Error
tagIds = []
for tagName in dto.tagNames:
tag = tagRepo.FindByName(tagName)
if tag is None:
tag = tagRepo.Create(dto.workspace_id, tagName)
tagIds.Append(tag.id)
project = NewProject(dto)
project.AddTags(tagIds)
projectRepo.Create(project)
return project.id
1. A transaction shouldn't modify multiple aggregates but what about creating them? In this case I'm referring to the tags that should have been created if one or more are not existing.
In my first domain model iteration the Tag was an Entity inside the ProjectAR but other AR's are also using Tags. Since there shouldn't be shared entities I made the TagAR and every other AR just store the IDs for reference.
In my head there is a conflict. Tag should be an own AR AND only one AR should be modified within one transaction. What is the solution here?
2. An AR should reflect the transaction/ use cases. So here are two more use cases:
a: UpdateProjectDetailsUseCase Description: Update properties (name, description, ...). Not the tags.
b: AddTagToProject/ RemoveTagFromProject Description: Add/ Remove Tags from Project.
There will be the same use cases for NoteAR.
Should I build separate ARs for this? Because each use case doesn't need the whole ProjectAR (invariations). And if so do I have 2 ARs (ProjectDetailAR, ProjectTagAR) or 3 ARs (ProjectDetailAR for update, ProjectTagAR for tagging, ProjectAR for creation)?
If I split the AR, I would create smaller ones which is a goal of AR design. And if I hat ProjectDetailAR and ProjectTagAR the use cases could run in parallel and there wouldn't be a conflict.
3. The tag-check-and-create-routine will be the same in the CreateNoteUseCase. Should it be extracted and if so where should the logic live? Or is it too much abstraction?
I couldn't find any example DDD projects that rely on a tagging system. If anyone knows some or other resources I would appreciate some links.
Thanks in advance