Let's say that we are working on some kind of school management system and we want to drop (remove) a course from a particular student during the enrollment process. We might have an enrollment entity that might look something like this:
class Enrollment(Entity): def __init__(self, course, student, *args, **kwargs): super().__init__(*args, **kwargs) self.course = course self.student = student def drop(self): # Some code pass
The use case that is responsible for performing the "drop" operation could look something like the following:
class DropCourse(UseCase): def __init__(self, enrollment_gateway): self.enrollment_gateway = enrollment_gateway def execute(self, request): enrollment = self.enrollment_gateway.get_by_id(request.enrollment_id) if not enrollment: raise EnrollmentNotFoundError enrollment.drop() # Source of my question
In this example, I'm calling the drop method of the enrollment entity, but I'm having difficulty deciding how to go about executing the logic that will perform this action. I have thought of three possible solutions to this.
One solution is to pass the 'CourseDropper' object to the constructor of the enrollment entity. When the drop method of the entity is called, use the course_dropper object to do the work. The problem I see with this solution is that over time, the constructor of the entity might grow if I add more and more dependencies to it that perform similar operations.
Another solution can be to add a "CourseDropper" object to the constructor of the use case, that has a method called 'drop_enrollment' that takes an enrollment as an argument. This object could then use whatever database we happen to be using and mark the enrollment as 'dropped'.
The third solution, which is the one I'm currently leaning towards, is to pass the 'CourseDropper' object to the drop method of the entity from the use case itself. It would be really easy to implement, because all the entity has to do is call the drop method of the course dropper and pass itself in as an argument.
I'm not sure if the last solution violates any of the clean architecture or SOLID principles. Which of these solution would be better in terms of design and architecture?