How do I avoid duplicate code with similar classes, same methods with different property names

119 Views Asked by At

Here's a very basic example of what I'm talking about. We have Student, Enrollment, and Club, along with StudentEnrollment and StudentClub representing many-to-many relationships between Students->Enrollment and Students->Club. I am using EFCore for the data model, if that helps.

One basic method of both of these class would be adding a student to an enrollment, or a club, if they are not already a part of that respective object (see StudentEnrollment.AddStudent and StudentClub.AddStudent). The methods are pretty much functionality identical, but the name of the class and the name of the properties you need to compare are different.

Is there a way to create a shared method/class/inheritance/interface/generic/SOMETHING that can be written just once, and used by both classes, despite the different property/class names?

Basic example code (with some pseudocode):

public class Student
    {
        public int StudentId { get; set; }
        public string Name { get; set; }
    }

    public class Enrollment 
    {
        public int EnrollmentId { get; set; }
        public string EnrollmentName { get; set; }
    }

    public class StudentEnrollment
    { 
        public int EnrollmentId { get; set; }
        public int StudentId { get; set; }

        public void AddStudent(Student student, Enrollment enrollment)
        {
    //pseudocode
            if (!exists (Where(enrollment.EnrollmentId == this.EnrollmentId && student.StudentId == this.StudentId)))
            {
                // add student enrollment
            }
        }
    }

    public class Club
    {
        public int ClubId { get; set; }
        public string ClubName {get; set;}
    }

    public class StudentClub
    {
        public int ClubId { get; set; }
        public int StudentId { get; set; }

        public void AddStudent(Student student, Club club)
        {
    //pseudocode
            if (!exists (Where(club.ClubId == this.ClubId && student.StudentId == this.StudentId)))
            {
                // add student club
            }
        }
    }

I don't think inheritance works, nor an interface. Maybe a generic, I'm not very good in that space? Something else?

1

There are 1 best solutions below

4
Flydog57 On

The question to ask when considering inheritance is whether there is an "is-a" relationship between two classes.

It's pretty obvious that a StudentClub is not a StudentEnrollment (since enrollment here is class enrollment), nor, vice versa.

Is there a common concept that they are both is-a of? You might consider having a StudentGrouping a common (likely abstract) base class (or perhaps having an IStudentGrouping interface that they both inherit from).

The concept of a StudentGrouping seems way too abstract to spend inheritance on. Is there any reason why you might consider, say, a collection of polymorphic StudentGrouping instances on your code.

You might might be able to make a case for both classes implementing an IStudentGrouping interface (implementing ICollection<Student>), which would give a clear indication that both are collections of students (and allow use of the Collection Initialization Pattern).

That said, I don't know if that gives you much benefit compared to making both classes simply implement ICollection<Student>. I suggest just going with that.