Tuesday, 23 June 2015

Encapsulation

Encapsulation
Encapsulate - "To enclose or be enclosed in or as if in a capsule". [the free dictionary]

In software
Encapsulation is the practice of having classes/objects not expose their data but expose methods to act upon the data. It also relates to how we choose to put methods and data into classes (Putting data with the relevant methods that use it).

There are many ways we can choose to decompose systems into objects but encapsulation is an effective way of making systems easier to understand and maintain. By restricting access to data we can change the internals of a class/module without requiring changes in the code that uses that class/module.

Example
I have a class “Person”
 public class Person  
 {  
   public string FirstName { get; set; }  
   public string LastName { get; set; }  
 }  

Now take the following method:

 public string FullName(Person person)  
 {  
        return person.FirstName + person.LastName;  
 }  

If this method is not in the Person class the class must expose the firstname and lastname data for this method to work. So any other piece of code then has access to firstname and lastname and can use it. This means that if at a later point you decide to store the person’s name as just a fullname string you must change code that is outside of the person class. If this method is part of the person class you only have to update the person class and as long as its public interface is well designed and not affected by the change you should not have to change any other classes.

Design
By carefully thinking about how we compose our classes we can hide the details (implementation) from the outside world, this can be a massive advantage when maintaining large systems as we can completely rewrite the internals of a class and have it not affect the rest of the system. When classes are encapsulated well it can lead to a better conceptual model (set of classes that represent the system), and often a better set of abstractions making the system easier to code against.

How to achieve 
You can use Getters and Setters to make it easier to encapsulate data, in .net an auto property can achieve this quickly. This will let you change the data later and still use the same property. Generally I would prefer using methods to act upon a class though.

Put methods in the same class as the data they are operating on, this should help achieve cohesion and make modification easier later.

Avoid
Classes exposing their data and their internal workings, this can even include the way you design your methods. Sometimes you can encapsulate how the object works by avoiding sharing of implementation details. For example return amount of fuel as a percentage left rather than gallons.

Having your method access and change data within another object (see if you can move the method to within the other object, where hopefully it will make more sense)

Scope
Spend time thinking about anything that is not private, is there a way you could increase encapsulation by reducing the amount of data shared. Is your publicly accessible interface clean and free of clues as to how the object is implemented.

Also be wary of protected members, it can seem natural for inherited objects to have access to data but this can lead to problems refactoring later. Loose coupling between inheritance trees is hard to achieve but important to consider.

Benefits of encapsulation
  • Increase cohesion (Relation of data/methods within a class, high cohesion is good!)
  • Decrease coupling (High coupling of classes can make them hard to reuse, replace and test)
  • Better separation of concerns (when classes are highly cohesive a class is more likely to only focus upon itself)
  • Easier to reuse (A loosely coupled class will be easier to reuse in other places)
  • Easer to make changes (Only changes to the public interface require changes in other places)
  • Reduces complexity (By only requiring you to think about one class at a time)
Disadvantages of encapsulation
  • Can require more code (Boiler plate, getters/setters etc.)
Inheritance and encapsulation
Inheritance can be seen to be breaking encapsulation as you are exposing the workings of the class to the class that is sub classing. Over use of inheritance where it is not required will often lead to the breaking of encapsulation. So we should favor composition (Containing another object) over inheritance as a mechanism for code reuse.