The job now is to fill out the persistence mechanisms relevant to KickoffCoordinator
s. You've seen a lot of this before, when we've persisted Task
s. A lot of the overall approach here is the same.
As you can see, I've made some changes to the initialization of KickoffCoordinator
and to the object itself. Here's one problem I faced here and have faced before: When one domain object refers to another, how do you represent the dependency at the object level? Here: should we have Task
be a field on KickoffCoordinator
?
If we don't do this, and instead just store the task's UUID, our KickoffCoordinator
domain object isn't as faithful to reality as we'd like it to be.
But if we do store the whole Task
on the coordinator, how do we handle the persistence of that task?
Task
with the coordinator, but we're already persisting it in its own repository. We could store the information in two places, but that raises a ton of problems (besides the wasted space, we have to worry about keeping the different representations in sync, which is the stuff of thick textbooks).Task
information with its coordinator and get rid of the other storage. But now we're coupling together both the actual persistence of those objects and the corresponding repositories. This is only appropriate if the objects are much more closely connected at the domain level thatn our coordinators and tasks are. (Think about how we'd store tasks that don't have corresponding coordinators; it could be done, but it would be a mess.)KickoffCoordinator
object. This is unwieldy and also couples together the functioning of the two repositories. (This is an important point: coupling and dependencies can occur even if the dependency isn't a matter of an explicit code import. If the actual functioning of a coordinator's repository depends on a task repository, or--worse--some specific task repository, our system is much less modular and harder to reason about than we want it to be.)Task
when the situation demands it. Here, it's the responsibility of the user of the coordinator to summon up the whole task if that's necessary. It is not required to do so.I chose the second-to-last option, storing just the UUID and accepting a slightly impoverished KickoffCoordinator
object. I think these situations are legitimately tricky to get right, but the more I think about it the more I'm happy with this one.
Whether I got this one right or wrong, the persistence and related testing is in place.
Here's the current commit in the veery/
repository.
Next post: Python task manager from scratch, part 41: Setting up event handling