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

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?

  • seems to me that enrolement shouldn't have the drop method at all. put that logic in DropCourse.Execute – Ewan Apr 11 at 18:28
  • Are you referring to the second solution I suggested? – Enrique Apr 11 at 22:17
  • possibly, seems a bit close to the data layer to me, but along those lines in anycase – Ewan Apr 12 at 10:01
  • Thank you for the feedback. – Enrique Apr 12 at 16:17

Your Answer

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

Browse other questions tagged or ask your own question.