Clean Architecture - How to handle usecase dependencies

Viewed 1269

I am refactoring one of my older applications around to using the concept of use cases "clean architecture". I am little confused on how to leverage the common data & entity validations

for e.g. There are 2 use cases

  • Allow admins to import a new workflow template
  • Allow admins to create new workflow template

The above use cases are called from the controllers.

In both the above cases, there are some common database level validations like:

  • Is there already a workflow with same name ?

To handle these validations, Do I make this as separate use-case like "checkIfWorkflowWithSameNameExists()" ?

If I make a separate use case, then what options are better to call these common validations

  1. Can one use case call another use case directly
export function importNewWorkflowTemplate(specs){

  const { workflowRepository  } = specs;

  const exists = checkIfWorkflowWithSameNameExists()
  if(exists){
    //return error
  }
  
  return new (payLoad) => {
    //logic
  }
}

  1. Should I be injecting the dependent use cases
export function importNewWorkflowTemplate(specs){

  const { workflowRepository, checkIfWorkflowWithSameNameExists  } = specs;

  return new (payLoad) => {
    //logic
  }
}

  1. Should the validation belong to outer layer like the controller?
1 Answers

What you describe - checkIfWorkflowWithSameNameExists() - is not a use case.

This is simply a method put on a domain service, such as a repository. This could be a repository method on your workflow repository such as hasWorkflowWithName(name). The repository represents a collection of aggregates and thus knows best if there is one with the same name already.

If there is more complex domain logic to check for an existing repository and then either perform some error handling or performing specific logic to create the logic you can also consider to encapsulate these steps inside a domain service method. In this case the workflow repository interface would be injected into the workflow domain service which would then again be injected into the use cases.

With that you could use the same domain service in both use cases and the use case are responsible to orchestrate the translation between the external commands and the domain service interface and the corresponding domain entities.

Related