I've got a design problem, and I figure it's not something totally uncommon so there must be some good practices out there.

I have 2 domain entities: Process and Task. A Process is essentially a list of Tasks.

The functionality of a Process is to know what kinds of tasks it consists of (Task instances are created using a Factory when process enters 'Started' status), and to evaluate it's status based on the status of included Tasks.

A Task has a lot of functionality, but what the Process actually only needs from it is it's status, so I figured I should apply ISP here. For that purpose I created an interface TaskStatus, which is implemented in the base abstract Task class, and the Process holds a collection of TaskStatus objects.

Does it make sense up to this point?

Now the problem is that a different component, let's call it TaskProcessor, gets the list of Tasks from a Process, and needs a different kind of access to the Task objects.

How do I solve this? One way I figured out that would let me keep ISP is to move the list of Tasks out of the Process, into a global singleton TaskRepository. Both Process and TaskProcessor could query TaskRepository to get what they need without being dependent on any functionality they don't need.

I don't particularly like this solution because of 3 things: 1. Generally I think that the less global singletons the better 2. It moves the responsibility of holding a list of Tasks out of the Process, which might be a good thing from a SRP perspective, but I do believe that it actually belongs in the Process from a DDD perspective. 3. That's quite a lot of added complexity compared to just changing the type of the Task list in Process and being done with it.

  • You said a Process holds a list of associated Tasks. How does the Process distinguish between each task if it [the Process] only holds statuses? It seems like the TaskStatus interface should extend an Identifiable interface, that way the tasks containing only status up to this point also contain the ids of the tasks and those ids can then be used to fetch full fletched task models by the TaskProcessor. – Andy Sep 18 '18 at 8:09
  • The process doesn't actually need to distinguish between its tasks. Anyway, if I understand correctly, you do recommend a central repository where tasks are stored and can be accessed by the TaskProcessor using an ID? – Jacek Wojciechowski Sep 18 '18 at 8:35

If the job of a Process is to provide Tasks to a TaskProcessor so that it can do Task-specific things with them (as opposed to merely TaskStatus things), then it does need more than just the status, and it should hold Task objects, not TaskStatus references.

The question is whether it really is the job of a Process to feed data to a Processor, or whether the Processor should get its input from another place in the system - perhaps the same place the Process got it from.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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