I'm a bit confused about where to place the CreateTreatmentPlanUseCase and CreateTreatmentPlanController. Should they be in the interface adapters layer or in the frameworks/ infrastructure layer?
It's recommended to place them in the infrastructure layer. Since you're working with JavaScript, specifically TypeScript, you can create a js module to set up the use cases. This module can then import the necessary use case definition module(s).
For example, you can create a module called usecases.js
, or usecases.ts
in your case. Within this module, you'll import the required modules like this:
import { CreateTreatmentPlanUseCase } from 'CreateTreatmentPlanUseCase'
import { PatientRepositoryImpl } from 'PatientRepositoryImpl'
import { TreatmentPlanRepositoryImpl } from 'TreatmentPlanRepositoryImpl'
Then, you can set up your use case like so:
const patientRepository = new PatientRepositoryImpl();
const treatmentRepository = new TreatmentPlanRepositoryImpl();
export const createTreatmentPlanUseCase = new CreateTreatmentPlanUseCase(
patientRepository,
treatmentRepository
);
Once you have a module for the setup, you can import it in your controller module:
import { createTreatmentPlanUseCase } from 'usecases'
You may organize your modules differently, but the main concept remains the same. It's common practice to separate the setup from the definition in JavaScript for better code organization and maintainability.
EDIT
Currently, my use-cases are in the application layer and controllers in the adapters layer. I am also creating repository implementations in the adapters layer. Is this the right approach or should the repository implementations go in the infrastructure/database layer?
It's acceptable to have them in the adapter layer. However, instead of creating a directory named adapters
and placing all controllers and repositories there, consider creating separate directories for controllers
and repositories
. A more organized approach would be to create feature-specific directories with modules named repository.ts
, controller.ts
, and usecase.ts
.
+- package.json
|
+- treatments
|
+- create
|
+- usecase.ts
|
+- repository.ts
|
+- controller.ts
This structure provides better clarity and focuses on features rather than technical details like the adapters layer.
Should I have a controllers directory with a folder per use-case, import the repos there, construct the use case, and pass that to the controller?
That approach is fine, especially if your controllers are use-case oriented. It promotes encapsulation, as other modules won't be able to access the use cases unless explicitly exported. It aligns with the concept of package by feature, as discussed in the clean architecture principles.
In a similar scenario, your directory structure could look like this:
+- package.json
|
+- treatments
|
+- create.ts // use cases, repositories, controllers, etc.
EDIT
If I adopt the package by feature approach and need to reference PatientRepository, is it okay to import the interface from the Patient directory/package?
While you can do this, it's often beneficial to follow the interface segregation principle and create repositories that are feature-driven. For instance, if you have a use case called CreateTreatmentPlanUseCase
, consider creating a repository named CreateTreatmentPlanRepository
specific to that use case. This approach may lead to some duplicated code but results in decoupled and more focused use case repositories.
Alternatively, you can create a common repository module shared by multiple use case repositories. This ensures that common methods are explicitly defined and prevents accidental changes that only apply to one use case. Ultimately, it's your decision to choose the best approach and be willing to refactor when necessary.