Encapsulation aggregation / composition

Wikipedia article on encapsulation states:

"Encapsulation also protects the integrity of the component by preventing users from setting internal component data to an invalid or inconsistent state."

I started a discussion about encapsulation in a forum where I asked if objects should always be cloned inside setters and / or getters in order to keep the above encapsulation rule. I decided that if you want objects inside the main object not to be tampered with outside the main object, you should always clone it.

One of the panellists argued that you should make a distinction between aggregation and composition in this question. Basically, I think it is like this:

  • If you want to return an object that is part of the composition (such as a Point of Rectangle), clone it.
  • If you want to return an object that is part of an aggregation (for example, User as part of a UserManager), just return it without breaking the link.

It made sense to me too. But now I'm a little confused. And I would like to receive your opinion on this matter.

Strictly speaking, does encapsulation always mandate cloning?

PS: I am programming in PHP where resource management might be a little more relevant as it is a scripting language.

+2


source to share


2 answers


Strictly speaking, does encapsulation always mandate cloning?

No, it is not.

The person you mention is probably confusing protecting the state of an object with protecting the implementation details of an object.

Remember this: Encapsulation is a way to increase flexibility our code. A well-encapsulated class can change its implementation without affecting its clients . This is the essence of encapsulation.

Suppose the following class:

class PayRoll {
   private List<Employee> employees;

   public void addEmployee(Employee employee) {
       this.employees.add(employee);
   }
   public List<Employee> getEmployees() {
       return this.employees;
   }
}

      

This class now has low encapsulation. You can say that the getEmployees method breaks the encapsulation because by returning a List type you can no longer change this implementation detail without affecting the clients of that class. I couldn't change it, for example for a collection of maps, without affecting the client code.

By cloning the state of your object, you are potentially changing the expected client behavior. This is a malicious way of interpreting encapsulation.



public List<Employee> getEmployees() {
    return this.employees.clone();
}

      

We can say that the above code improves encapsulation in the sense that addEmployee is now the only place from which to change the inner list. So if I have a design solution to add new Employee elements at the head of the list instead of the tail. I can make this modification:

public void addEmployee(Employee employee) {
    this.employees.insert(employee);  //note "insert" is used instead of "add"
}

      

However, this is a small increment of encapsulation for a great price. Your customers have the impression that they have access to employees when in reality they only have a copy. So if I want to update the phone number of employee John Doe, I might mistakenly access the Employee object, expecting the changes to be reflected the next time they call PayRoll.getEmployees to users.

A higher encapsulation implementation would do something like this:

class PayRoll {
   private List<Employee> employees;

   public void addEmployee(Employee employee) {
       this.employees.add(employee);
   }
   public Employee getEmployee(int position) {
       return this.employees.get(position);
   }
   public int count() {
       return this.employees.size();
   }
}

      

Now, if I want to change the Map List, I can do it freely. Also, I am not breaking the behavior that customers are likely to expect: changing the Employee object from PayRoll does not lose those changes.

I don't want to spread too much, but let me know if it's clear or not. I would be happy to move on to a more detailed example.

+3


source


No, encapsulation simply requires the ability to manage state by creating a single point of access to that state.

For example, if you have a field in a class that you want to encapsulate, you can create a public method that will be the only access point to get the value that the field contains. Encapsulation is simply the process of creating a single access point in this field.



If you want to change the way this value is returned (cloning, etc.), you can do so, since you know that you are controlling one pass in that field.

0


source







All Articles