Object-Oriented Design – Saving Object via Its Own Method or Another Class?

designobject-oriented

If I want to save and retrieve an object, should I create another class to handle it, or would it better to do that in the class itself? Or maybe mixing both?

Which is recommended according to OOD paradigm?

For example

Class Student
{
    public string Name {set; get;}
    ....
    public bool Save()
    {
        SqlConnection con = ...
        // Save the class in the db
    }
    public bool Retrieve()
    {
         // search the db for the student and fill the attributes
    }
    public List<Student> RetrieveAllStudents()
    {
         // this is such a method I have most problem with it 
         // that an object returns an array of objects of its own class!
    }
}

Versus. (I know the following is recommended, however it seems to me a bit against the cohesion of Student class)

Class Student { /* */ }
Class DB {
  public bool AddStudent(Student s)
  {

  }
  public Student RetrieveStudent(Criteria)
  {
  } 
  public List<Student> RetrieveAllStudents()
  {
  }
}

How about mixing them?

   Class Student
    {
        public string Name {set; get;}
        ....
        public bool Save()
        {
            /// do some business logic!
            db.AddStudent(this);
        }
        public bool Retrieve()
        {
             // build the criteria 
             db.RetrieveStudent(criteria);
             // fill the attributes
        }
    }

Best Answer

Single Responsibility Principle, Separation of Concerns and Functional Cohesion. If you read up on these concepts, the answer you get is: Separate them.

A simple reason to separate the Student from the "DB" class (or StudentRepository, to follow more popular conventions) is to allow you to change your "business rules", present in the Student class, without affecting code that is responsible for persistence, and vice-versa.

This kind of separation is very important, not only between business rules and persistence, but between the many concerns of your system, to allow you to make changes with minimal impact in unrelated modules (minimal because sometimes it is unavoidable). It helps to build more robust systems, that are easier to maintain and are more reliable when there are constant changes.

By having business rules and persistence mixed together, either a single class as in your first example, or with DB as a dependency of Student, you're coupling two very different concerns. It may look like they belong together; they seem to be cohesive because they use the same data. But here's the thing: cohesion cannot be measured solely by the data that is shared among procedures, you must also consider the level of abstraction at which they exist. In fact, the ideal type of cohesion is described as:

Functional cohesion is when parts of a module are grouped because they all contribute to a single well-defined task of the module.

And clearly, performing validations about a Student while also persisting it do not form "a single well-defined task". So again, business rules and persistence mechanisms are two very different aspects of the system, which by many principles of good object oriented design, should be kept separate.

I recommend reading about Clean Architecture, watching this talks about Single Responsibility Principle (where a very similar example is used), and watching this talk about Clean Architecture as well. These concepts outline the reasons behind such separations.

Related Topic