Archive for May, 2013

Finding the way to Design Patterns : more SOLID

So continuing into the process of finding our way into design patterns from my last post , we will try and unfold SOLID a bit more. Some of the SOLID principle interpretations and applications can be very subjective and a matter of debate. How do you know the classes that you wrote have adhered to the Single Responsibility Principle ? Is there a way to determine ? What does Single Responsibility exactly mean?  How far do you try and take these things…blah ..blah.

There needs to be a balance in everything of course.One needs to find a mid way between over-engineering and under-engineering. We need to create small classes with very few cohesive/related functions without getting carried away by having so many classes that we cannot manage those either. At the same time , understanding exactly how to create classes with just one relevant behavior or few cohesive functions can get tricky. It’s important to ask the question while writing a class , what is it that will potentially change in this class later , that can be re-factored into a separate class , so minimal changes / or no changes need to be made to the existing implementation when the change needs to be made.

It’s important to ask the question while writing a class , what is it that will potentially change in this class later , that can be re-factored into a separate class , so minimal changes / or no changes need to be made to the existing implementation when the change needs to be made.

If we take the Logging example that we discussed in the previous post , we discussed three functions a logger can do. Initializing a medium to log , Formatting to the medium itself  and Writing to the medium . So, they all look like related functions don’t they ? So they all can go in one class , which is a violation of SRP . If we take one step further into re-factoring  perhaps it’s easy to recognize right away that there are different mediums to log , each requires a different method to write to itself. So we create separate classes for the medium . Yes , we applied SRP here.

What about formatting ?  Can formatting change ? Yes, it can . Say we need to add a new logging medium called Mobile Device. To the mobile device , you want to send text messages whenever severe conditions occur. Doesn’t the format of what goes into a database differ from a mobile device ?  Also , later down the line the potential users of our Logger may require that they want the format of the message a little different. Now if we did not separate the format function into it’s own class , we have it as part of the class that writes to the medium or worse as part of the Logger class. Logger class is actually our client facing class that the client would use to log messages . Just to change  formatting , we have to go and change this Logger class or the medium classes.

At this point we need to consider  whether it’s worth writing something like this:


   1:  interface IFormatter {
   2:   
   3:  public string Format( string message );
   4:   
   5:  }
   6:

and the logger could do something like this :


   1:  public class Logger{
   2:   
   3:  public Write( IFormatter formatter){}
   4:   
   5:  }
   6:

Or let’s go couple of steps further along these lines,


   1:  public interface ILogMedium{
   2:   
   3:  void Write(String Message);
   4:   
   5:  }
   6:

   1:  public class LogToDatabase : ILogMedium{
   2:   
   3:  public void Write(string message){
   4:   
   5:  // medium specific logging
   6:   
   7:  }
   8:   
   9:  }
  10:

   1:  public class Logger{
   2:   
   3:  ILogMedium _logTodb;
   4:   
   5:  IFormatter _formatter;
   6:   
   7:  public void Logger( ILogMedium logToMedium,  IFormatter formatter )
   8:   
   9:  {
  10:   
  11:  _logTodb = DBMediumProvider.Create(); // DBMediumProvider could be a creation class
  12:   
  13:  _formatter = DBFormatProvider.Create(); // DBFormatProvider could be a creation class
  14:   
  15:  }
  16:   
  17:  public Write(String message){
  18:   
  19:  _logTodb.Write( _formatter.Format(message) );
  20:   
  21:  }
  22:   
  23:  }
  24:

Please note : The code above is not a working solution. It is only like pseudo code to demonstrate the thought process .

The advantage of the above is we kept the formatter completely separate from the medium , as well as the Logger class. This allows us to plug in new mediums , formatters and configure them based on our needs. Also , if there are bugs it’s easier to fix a specific class as opposed to one big class which could potentially break other functions.

This brings us to the Open Closed principle , which is the next one and the ‘O’ in SOLID as we all know.

A consistent use of SRP can lead to OCP , which simply states: A class should be open for extension but closed for changes. This does not mean that classes should be completely sealed for change , it means that the class should be in a state where only bug fixes should be made and new functions should be added via new classes , minimizing implementation changes to the existing classes.

Words should not be taken literally here : once you wrote the class does not mean that it cannot be changed at all : however we should get to a point that , when behavior changes in predictable ways, you should not have to make several changes into a single class or several classes in the system. An ideal situation would be where you achieve the change by adding new class / code rather than changing existing code . For anyone who has been in programming for a few years supporting production systems , this will make a lot of logical sense.

Whatever we discussed above with Logger example with reference to SRP will apply to OCP as well , because OCP can be achieved by applying SRP consistently. So had we written the formatting in the Logger or the individual medium classes we would not be able to add new formatters or change existing formatting without changing the Logger or the mediums classes , plus mix and match formatting with mediums . The way we achieved OCP with Logger example is we gave the Logger a Single Responsibility of writing to the medium. We gave the Medium classes a Single Responsibility of initializing / creating the medium and specifically write to that medium as well. And then OCP came into effect when we made it possible for new formatters to be added to the system by simply implementing the interface IFormatter and adding that class to the system as a plugin. So , when a user wants to use the new Formatter , she can do it through the configuration system and that formatter will get automatically used which needs to be implemented through some creation classes of course , which is a separate topic – an example is Factory Method pattern.

Several design patterns use the SRP and OCP , and following the above two will put you in the mode of clean and efficient code . Some popular patterns like Strategy , Factory are all based on OCP . We will continue with this discussion in the next post , happy programming !

Few references :

Wikipedia definition Open-Closed

Interesting read on OCP by Jon Skeet

, , , , ,

6 Comments

Finding the way to Design Patterns : SOLID

In my previous post on design patterns I discussed about why it’s a challenge for developers / organizations to adopt patterns as part of their development practices. I also had suggested that a dedicated effort to re-factor code should be made continuously as part of software life cycle especially in the early to mid-stages of development. Having said that, how do you go about re-factoring? How do some of the object oriented principles and design patterns help with re-factoring? So, if re factoring is important, the object oriented mechanisms that allow and facilitate this are important as well. In conclusion the learning needs to happen, slowly and steadily – as a result it will start becoming a habit to incorporate some of these patterns related principles.

I guess the challenge is where do you begin? There is a ton of information on the web, it’s all too overwhelming, scattered and fragmented. You need a have a structure and if you just pick up the Gang of Four book (our bible for design patterns), it can seem rather academic and intimidating for the first timer, abstract as well. The book of course is great, however it’s hard to jump into patterns pragmatically just by reading it.

As in my previous post in my concluding paragraph I had said that getting familiar with SOLID principles developed by Robert. C. Martin is great way to get started with principles that will lead the way towards patterns programming later.  Before expanding upon technically on what SOLID is about, I would like to discuss its importance in the whole OO programming space. If you come from a OO language background like Java, C++, C# etc. you already are familiar with Encapsulation, Inheritance, Polymorphism as foundational principles of OO and they are a daily part of your programming life. SOLID takes it one step further, lays out 5 principles that you can apply to re-factor and improve the code making it maintainable, reusable and efficient.

So when you start applying SOLID, you basically are applying some of the fundamental principles on which Design Patterns are developed. SOLID stands for Single Responsibility, Open-Closed principle, Lishkov Substitution principle, Interface Segregation and Dependency Inversion.

If you just take the first two: Single Responsibility and Open-Closed principle, just there you will improve the structure and quality of your classes.

Single Responsibility states: a class should have only a single responsibility.

Say, you are writing a Log class whose job is simply to write messages to different logging mediums. However you also gave it the responsibility of formatting the messages for these mediums, because it’s part of logging function. In addition, you gave it the responsibility of initializing and choosing the medium to log into, for ex: Event logs, Database, Log files etc. So now the Logger class has multiple reasons to change – one is, Write to the log medium, another is formatting the message: perhaps different mediums require different formatting and on top of that initializing the medium . So your class has now grown into one giant monolithic program that has multiple reasons to change – formatting for each medium, initializing the medium and logging to the medium. So if you need to change only one aspect : say change the formatting messages in database , you have to change that class and the rest of the code could possibly break because you needed to make changes for one aspect. We come across situations like this all the time in production code where we change one thing and potentially something else breaks , without us intending it . This sort of programming makes the code not only fragile, but totally un-pluggable.

Ideally in this situation, the Logger class should just take on the responsibility of writing to the medium being free of what medium it is writing to and what formatting that particular medium needs. Although it seems like they are all related functions , they merit to become individual classes based on their specific function and behavior. More so, ideally you should write an interface that can be implemented to write to different log mediums.

public interface ILog
{
void Write(String Message);
}

As you see , when you just take this one principle and follow it while writing the code you will see that you have written classes that are light weight and each is meant to do one particular job – this makes the design pluggable , reusable and efficient  . You can create classes that are specific to a medium – so adding mediums for logging becomes easy later. Also if there is a change required in it , say how you format the message for that medium, you change only the corresponding medium or the formatting class, avoiding the risk of the rest of the code breaking due to the one change you made in one big class.

As you go further and start applying one by one each principle you will see that certain patterns are shaping up, and possibly they can be applied to common scenarios. I guess I will stop here for now, and conclude that the first step is definitely to understand SOLID and start applying it in your programming life seriously.

Below is a great Video on Single Responsibility Principle by Robert C. Martin himself to learn more on it and get started :

We will discuss more on the rest of the SOLID in the upcoming post …until then happy programming.

,

15 Comments