The Dependency Inversion Principle (DIP)

The last of SOLID principles about OOD is known as Dependency Inversion Principle (DIP).

This principle says that:

 

High-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend upon details. Details should depend upon abstractions.

 

This principle, with the OCP principle already discussed, are intended to make software application loosely coupled. This feature is achieved by removing as much as possible dependencies between higher level modules (those usually more general) and the low-level modules (those usually more specific). In fact, usually in conventional application architecture, the high level modules use the functionality exposed by low-level modules using direct references to the latter, thus creating a strong coupling between them.

This coupling results in any change of low-level modules, also lead inevitably change of high-level, and this situation is certainly not desirable.

So instead of depending directly on low-level modules, the high-level modules should depend on abstractions, such as interfaces or abstract classes. In this way if you change some details behind those abstractions the high level modules remain unchanged as they depend on abstractions (interfaces).

The term “inversion”means that by applying this principle the direction of the dependency is reversed because the high-level modules do not depend on low-level modules buy they depend on abstractions, as well as the implementation details.

Moreover, as the abstractions raise a “wall” between the different levels, any changes can not propagate everywhere, but there are only confined within the module to which these changes belong logically.

The latter is a fundamental prerequisite so that software applications are easily maintainable.

You can find an implementation of DIP in Dependency Injection Pattern or in the Inversion of Control.

In fact there is some confusion around these terms and many people use them interchangeably, both refer to the principle or  refer to patterns, but the fact remains that the inversion of control or dependency injection is an implementation of DIP.

Just to add to the confusion  the Hollywood Principle is just another way of calling the Inversion Of Control.

The Interface Segregation Principle (ISP)

The Interface Segregation Principle (ISP) is another principle about OOD.

It simply states that:

“CLIENTS SHOULD NOT BE FORCED TO DEPEND UPON INTERFACES
THAT THEY DON’T USE”

If we return back to the first OOD principle, the Single Responsibility Principle, it can be said that this principle should also apply to interfaces or to abstract class, in addition to the concrete classes.

Therefore, one interface should mean one responsibility, without creating the so-called “fat interfaces”, i.e. interfaces that contain too many methods/properties that relate to more than 1 responsibility.

To find an example of violation of this principle does not need to go too far, just peek inside the .Net framework itself .

If we take a look inside the abstract class MembershipProvider, which is the class which all providers, default and custom,  inherit from, we’ll be looking at 28 abstract methods, which must be provide an implementation in case of creation of custom membership provider.

  public abstract void Initialize(string name,
      NameValueCollection config)
  public abstract string ApplicationName { get; set; }
  public abstract bool EnablePasswordReset { get; }
  public abstract bool EnablePasswordRetrieval { get; }
  public abstract bool RequiresQuestionAndAnswer { get; }
  public abstract bool RequiresUniqueEmail { get; }
  public abstract int MaxInvalidPasswordAttempts { get; }
  public abstract int PasswordAttemptWindow { get; }
  public abstract MembershipPasswordFormat PasswordFormat { get; }
  public abstract int MinRequiredNonAlphanumericCharacters { get; }
  public abstract int MinRequiredPasswordLength { get; }
  public abstract string PasswordStrengthRegularExpression { get; }
  public abstract bool ChangePassword(string username,
      string oldPwd, string newPwd)
  public abstract bool ChangePasswordQuestionAndAnswer(
      string username, string password, string newPwdQuestion,
      string newPwdAnswer)
  public abstract MembershipUser CreateUser(string username,
      string password, string email, string passwordQuestion,
      string passwordAnswer, bool isApproved, object
      providerUserKey, out MembershipCreateStatus status)
  public abstract bool DeleteUser(string username,
      bool deleteAllRelatedData)
  public abstract MembershipUserCollection GetAllUsers(int  
     pageIndex,
     int pageSize, out int totalRecords)
  public abstract int GetNumberOfUsersOnline()
  public abstract string GetPassword(string username, string answer)
  public abstract MembershipUser GetUser(string username,
      bool userIsOnline)
  public abstract MembershipUser GetUser(object providerUserKey,
      bool userIsOnline)
  public abstract bool UnlockUser(string username)
  public abstract string GetUserNameByEmail(string email)
  public abstract string ResetPassword(string username,
      string answer)
  public abstract void UpdateUser(MembershipUser user)
  public abstract bool ValidateUser(string username,
      string password)
  public abstract MembershipUserCollection FindUsersByName(
      string usernameToMatch, int pageIndex, int pageSize,
      out int totalRecords)

This methods has to do with authentication, persistence, retrieve of user based on various criteria, password management, and so on.

All these abstract methods must be implemented even if the client code that uses the feature is only interested in some of these aspects mentioned above.

In this way, the methods that you do not care end up being defined as follows:

public override int GetNumberOfUsersOnline()
{
    throw new NotImplementedException();
}

This approach has several problems, including:

  • Indirect and especially useless  coupling between clients that use the functionality. If additional functionality is required, all clients must be modified, even those not interested in new features;
  • Clients are misled because some methods explicitly raise an exception;
  • Code maintenance is more difficult;

The Liskov Substitution Principle (LSP)

The Liskov Substitution Principle (LSP) is another principle  that has to do with software design and namely with inheritance.

This principle takes its name from Barbara Liskov, U.S. scientist in computer science.

This principle simply states that

“CLASSES THAT USE REFERENCES TO BASE CLASSES MUST BE  ABLE TO USE OBJECTS OF DERIVED CLASSES WITHOUT KNOWING IT”

In other words, if we have a class (say Class C)  that use a reference to a base class inside (Class B), then Class C MUST be able to use a reference with ANY derivate class of Class B (present and future), without knowing it and especially without changing the logical behaviour.

It ‘s very easy to violate this principle when overriding virtual methods defined in a base class.

Let’s consider an example like this:

public class BaseClass
{
   protected double n1;
   protected double n2;
  
   public BaseClass(double a, double b)
   {
      this.n1 = a;
      this.n2 = b;
   }
  
   public virtual double Multiply()
   {
      return this.n1 * this.n2;
   }
}
 

This class simply accepts 2 double numbers by it’s constructor, and by a virtual method returns the two numbers multiplied together.

Now, let’s create a derived class like this:

public class DerivedClass : BaseClass
{
   const double COEFFICIENT = 1.1;

   public DerivedClass(double a, double b)
       : base(a, b) { }

   public override double Multiply()
   {
      return base.Multiply() * COEFFICIENT;
   }
}
 

This class is derived by the first one and simply overrides the virtual method “Multiply” defining another implementation of it where the result of the multiplication is further multiplied by a fixed coefficient.

Therefore, having a method that takes a reference to BaseClass, like this:

public double DoSomeWork(BaseClass b)
{
   return b.Multiply();
}

we can pass as a parameter any derived class, as in the example below:

BaseClass b = new BaseClass(-5, 20);
double result = DoSomeWork(b);
Console.WriteLine(result);

DerivedClass d= new DerivedClass(-5, 20);
double result2 = DoSomeWork(d);
Console.WriteLine(result2);
 

Very trivial, right ? And everything works fine.

But when you develop your derived class and specifically when the virtual method is redefined, you must pay attention to some situations that, if they occur, involving the violation of the Liskov substitution principle. Specifically, a general rule to keep in mind is that a derived class should *not* require additional conditions or either provide fewer conditions than those required by the base class.

For example, what would happen if you change the redefinition of the method Multiply in this way  ?

 public override double Multiply()
 {
   if (this.n1 < 0)
        throw new InvalidOperationException(
             "Number n1 cannot be negative");
 
    return base.Multiply() * COEFFICIENT;
 }
  

The overridden method adds an additional condition, namely that the parameter n1 cannot be negative by raising an exception, and then is demanding something more than its base class that takes two double numbers instead through its constructor, also providing negative numbers. This additional condition required makes the base class and derived class not interchangeable anymore and therefore the Liskov Substitution Principle is violated.

The LSP can be violated in different ways, but everyone has to do with inheritance. Therefore you must take extreme care when you redefine virtual methods.

The second Solid principle: OCP

In this post I will speak about the second principle of Object Oriented Design (OOD), i.e. the Open-Closed Principle (OCP). in addition to the first one (SRP)  which I have already spoken in my previous post.

This principle was coined by Bertrand Meyer, the same person who coined the term “design by contract”, to which I devoted an article that you can view on the  UgiDotNet site.

This principle simply states that software entities, i.e. class, “should be opened for extensions but closed for modifications“.

Now, what does it really means ?

We all know that code changes according to changing requirements. When we design a module software, we design it according to certain requirements valid at the time. When requirements change we should be able to extend that software module, i.e. add new features in addition to existing ones, and the latter should not be changed for any reason.

In other words, when we create a module with certain features, that module must be immutable, and immutable means stable.

This principle apparently shows a contradiction: how can something that is immutable be subject to extensions, and then ultimately to change?

The answer lies in the use of abstract classes or interfaces. In fact, you can see it from this point of view: an interface or an abstract class, once created and established the methods and properties with their signatures, must be unalterable, but you can create different concrete classes which implement that interfaces and abstract classes, and then different implementations, and then modify or extend their behavior leaving the contract intact.

In this way, the software module is closed for modifications (the interface doesn’t never change), but is also open for extensions as you can create different implementations.

This principle would imply another principle: it’s necessary to design on interface and not on concrete implementations, otherwise the OCP would inexorably violated.

The first Solid principle: SRP

Some of the principles about the object oriented programming (OOD) deal with design.

This design principles are known with the acronym of SOLID.

SOLID stands for:

(S)ingle Responsibility principle;
(O)pen closed principle;
(L)iskov substitution principle;
(I)nterface segregation principle;
(D)ipendency inversion principle

In my opinion, these principles are very important to understand if we are to achieve the greatest benefits of OOP.

In this post, I’ll speak about the first of these principles, i.e. the Single Responsibility Principle (SRP).
In future posts, I hope, I’ll speak about the others.

The SRP is perhaps the easiest to understand and the easier to violate.
This principle states that a class should have one and only one reason to change (responsibility).
One responsibility is associated with a potential reason for change the code of a class. So, if a class has more than 1 responsibility, also has more than 1 reason for change, and then the class violates the SRP.

For example, consider a interface like this, which is implemented by a hypothetical class that manages documents:

 public interface IDocument
 {
    Document LoadDocument(int id)
    void SaveDocument(Document document)
    decimal GetTotalDocument(int id);
}

What’s wrong with this simple code ?

Apparently nothing, but in terms of design this class violates the SRP, because the first two methods having to do with the persistence, while the third returns the result of a state variable according to a specific business rule, and then has to do with business rules. Thus, this hypothetical class may change if we change repository of persistence and /or if we change the business rules, and thus violates the SRP.

A better approach is to split this class into 2 separate classes, one for each responsibility, i.e.:

 public interface IDocumentPersistence
 {
     Document LoadDocument(int id)
     void SaveDocument(Document document)
 }
 
 public interface IDocumentRules
 {
     decimal GetTotalDocument(int id);
 }
 

The application of this principle maximizes the cohesion between the various parts of an application and minimizes the coupling between the same parts.

In the previous example the two interfaces are likely to be called from different parts of an application and are also subject to change for different reasons, so it is proper to keep them separate.