Ehsan Ghanbari

Experience, DotNet, Solutions

YAGNI, Never Add Functionality Early

As a developer I always pretend that I know about principles, Rules, methods, KISS and YAGNI! But in some cases if you consider my codes you will find out that they are just some best bunch of code for giving an example as introduction dirty code for teaching YAGNI principle!

YAGNI is a principle of extreme programming that says "Never add functionality until deemed necessary". what I mostly make mistake is adding some extra functionality earlier and most of the time they never been used.

 

                                                                 Never Add Functionality Early

 

I think YAGNI is something more than coding correctly. Every aspect of task should be considered at the first and requirement must be analyzed. It seems that I'm not the only guys who write extra code! Only 10% of that extra stuff will ever get used, so you are wasting 90% of your time (I don’t remember where I've read this). Code should be ready for unexpected changes and open for modification but it DOES NOT mean to guess and implement the future of the product without any consideration, design, …

We Keep this at the forefront of our mind that practicing good architectures could be more vital on duplicating and guessing extra things. We must implement some generic and common operations of the application for once and cross cut it as we don't need to guess what else is required here or not.

So let's try to implement what we really need!

 



Open Closed Principle of Solid

Maybe you have heard this for times: "Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification."

it should be possible to extend the existing code with new functionality without any modification and without adding duplicate code or duplicate functionality. Take a look at this piece of code: 

  1.  public class ElementerySchool
  2.     {
  3.         public double Norm { get; set; }
  4.         public int Age { get; set; }
  5.         public bool Validate { get; set; }
  6.  
  7.     }
  8.  
  9.     public class HighSchool
  10.     {
  11.         public double Norm { get; set; }
  12.         public bool Validate { get; set; }
  13.     }
  14.  
  15.     public class LibraryValidation
  16.     {
  17.         public const double Norm = 17;
  18.         public const int Age = 8;
  19.        
  20.         private HighSchool _highSchool = new HighSchool();
  21.         private ElementerySchool _kindergarten = new ElementerySchool();
  22.  
  23.         public bool ValidateQualification(double norm, int? age)
  24.         {
  25.             if (norm < Norm)
  26.             {
  27.                 _highSchool.Validate = false;
  28.             }
  29.             if (age < Age && norm<Norm)
  30.             {
  31.                 _kindergarten.Validate = true;
  32.             }
  33.             return true;
  34.         }
  35.     }

 High school students with the limited norm of 17 are valid to be a library member but for kindergarten student, there are two rules: limited norm of 17 and limited age of 5!  Now after implementing this piece of code by applying OCP, it could be something like this (for keeping it simple I prefer to use property for validating the students, you know there are lots of good ways to do that)

  1.  public abstract class Student
  2.     {
  3.         public abstract double Norm { get; set; }
  4.     }
  5.  
  6.     public class HighSchool : Student
  7.     {
  8.         private double norm;
  9.         public override double Norm
  10.         {
  11.             get
  12.             {
  13.                 if (norm > 17) return norm;
  14.                 return norm;
  15.             }
  16.             set { norm = value; }
  17.         }
  18.     }
  19.  
  20.     public class ElementerySchool : Student
  21.     {
  22.         private int age;
  23.         private double norm;
  24.  
  25.         public override double Norm
  26.         {
  27.             get
  28.             {
  29.                 if (norm > 17)
  30.                 {
  31.                     return norm;
  32.                 }
  33.                 return 0; // other business
  34.             }
  35.             set
  36.             {
  37.                 norm = value;
  38.             }
  39.         }
  40.  
  41.         public int Age
  42.         {
  43.  
  44.             get
  45.             {
  46.                 if (age > 5)
  47.                     return age;
  48.                 return 0;// other business
  49.             }
  50.             set
  51.             {
  52.                 age = value;
  53.             }
  54.         }
  55.     }

As you can see, changing any part of this piece of code will influence other parts and rather than that each school has its own rules for validating the students. This properties are closed for modification but you can extend them by adding another businesses.



Dependency Inversion of SOLID principle

As you know, Dependency Inversion Principle is the last principle of SOLID. I talked about SOLID principle and fundamental in my previous post that was about SRP. Now I'm gonna to consider the dependency inversion of SOLID. Based on definition "High level modules should not depend upon low level module, both should be depend upon abstraction". Or in other definition "abstraction should not depend upon details, details should depend upon abstraction". When you have relationship between you classes in OPP, that relationship should be stated on terms of abstraction rather than concrete implementation. "The benefits of using loose coupling aren’t always instantly evident, but they become visible over time, as the complexity of a code grows." in concrete implementaion changes to one class will break the other class.

Take a look at this implementation:

  1.    public class OrderRepository
  2.     {
  3.         public void Add()
  4.         {
  5.             //Add Order
  6.         }
  7.      }
  8.  
  9.     public class OrderService
  10.     {
  11.         private readonly  OrderRepository _orderRepository;
  12.     
  13.         public OrderService()
  14.         {
  15.             _orderRepository = new OrderRepository();
  16.         }
  17.  
  18.         public void CreateOrder()
  19.         {
  20.             _orderRepository.Add();
  21.         }
  22.      }

 

I just create an instance of the OrderRepository inside the OrderService to use the add method. As you know every changes in OrderRepository will destroy the OrderService class and we should modify the OrderService class every times. Now notice about this implementation:

 

  1.     public interface  IOrderRepository
  2.     {
  3.         void Add();
  4.     }
  5.  
  6.     public class OrderRepository :IOrderRepository
  7.     {
  8.         public void Add()
  9.         {
  10.             throw new NotImplementedException();
  11.         }
  12.     }
  13.  
  14.    public class OrderService
  15.     {
  16.         private readonly IOrderRepository _orderRepository;
  17.  
  18.         public OrderService(IOrderRepository orderRepository)
  19.         {
  20.             _orderRepository = orderRepository;
  21.         }
  22.     
  23.         public void CreateOrder()
  24.         {
  25.             _orderRepository.Add();
  26.         }
  27.     }

 

I just added an interface, but if you take a deeper look at OrderService,it doesn't have any concrete instantiating of OrderRepository and every change in IOrderRepository should be implemented in OrderRepository and OrderService just talks to IOrderService. (Don't call use we'll call you!). I also used constructor injection that you can read more about that here.

 

You can read more about DIP

  1. http://www.codeproject.com/Articles/495019/Dependency-Inversion-Principle-and-the-Dependency
  2. http://lostechies.com/derickbailey/2011/09/22/dependency-injection-is-not-the-same-as-the-dependency-inversion-principle/



Single Responsibility of Solid Principle

SOLID stands for five basic principles of Object Oriented programming to create a system that is easy to maintainable and  extensible. The principles of SOLID are guidelines to create refactored and clean code understandable by other developers. Here are the five principles of OOP:

 

Single responsibility principle

Open-Close Principle

Liskov Substitution Principl

Interface segregation principle

Dependency inversion principle

 

In this post I'm going to dig in Single responsibility principle.

                                                     "there should never be more than one reason for a class to change."

The single responsibility principle states that every class should have a single responsibility, and that responsibility should be entirely encapsulated by the class. Single Responsibility principle says that every object should have a single responsibility, if a class has more than one responsibility these responsibilities become coupled and cannot be executed independently.

When a class has more than one responsibility, there are also more triggers and reasons to change that class. If a class has more than one responsibility, then the responsibilities become coupled. Also when a responsibility is divided over more than one class, all classes part of that responsibility have to changed. "Always try to give every class its own and unique responsibility. It would be a bad design to couple two things that change for different reasons at different times." What's important is that responsibilities are separated by abstraction and therefore can be implemented by different consumers of that interface.

 

Take a look at this sample code:

 

  1.    public interface IUser
  2.     {
  3.         string FirstName { get; set; }
  4.         string LastName { get; set; }
  5.     }
  6.  
  7.     public class DisplayUsers
  8.     {
  9.         private IUser _user;
  10.  
  11.         public DisplayUsers(IUser user)
  12.         {
  13.             _user = user;
  14.         }
  15.  
  16.         public string Display()
  17.         {
  18.             return String.Format("{1}, {0}", _user.FirstName, _user.LastName);
  19.         }
  20.  
  21.         public static string Display(IUser user)
  22.         {
  23.             var displayUsers = new DisplayUsers(user);
  24.             return displayUsers.Display();
  25.         }
  26.     }
  27.  
  28.     public class Customer : IUser
  29.     {
  30.         public string FirstName { get; set; }
  31.         public string LastName { get; set; }
  32.         public string Email { get; set; }
  33.     }

 

You can see that every class and interface just could be changed for one reason,for example DisplayUsers class just Displays the users. Let's assume that you are going to implement banking, based on SRP you have to create another interface

  1.     public interface IBanking 
  2.     {
  3.         void Deposit(Guid accountNo, decimal amount);
  4.         void Withdraw(decimal amount);
  5.     }
  6.    

And implement the Banking class like this

  1.      public class Bank
  2.      {
  3.         public static decimal Balance { get; set; }
  4.  
  5.         public void Deposit(Guid accountNo, decimal amount)
  6.         {
  7.             //Do the operation
  8.             Balance += amount;
  9.             // Save the changes
  10.         }
  11.  
  12.         public void Withdraw(decimal amount)
  13.         {
  14.             //Do the operation
  15.             Balance += amount;
  16.             // Save the changes
  17.         }
  18.     }
 

There is a great example here that you can use it, thanks for reading!

 



Interface Segregation principle (ISP)

"no client should be forced to depend on methods it does not use." Interface segregation is a Simple but useful patterns of SOLID principle , in other words interface segregation is just about splitting an interface to several interfaces to make it simple working with classes those are going to implement the members.

Example

Suppose this interface :

  1.     public interface IAccountService
  2.     {
  3.         void CreateBankAccount();
  4.         void DeleteBankAccount(Guid accountId);
  5.         void GetAllBankAccounts();
  6.         void GetAccountInfo(Guid accountId);
  7.      } 

and AccountService class

  1.     public class AccountService  :IAccountService
  2.     {
  3.         public void CreateBankAccount()
  4.         {
  5.             throw new NotImplementedException();
  6.         }
  7.         public void DeleteBankAccount(Guid accountId)
  8.         {
  9.             throw new NotImplementedException();
  10.         }
  11.         public void GetAllBankAccounts()
  12.         {
  13.             throw new NotImplementedException();
  14.         }
  15.         public void GetAccountInfo(Guid accountId)
  16.         {
  17.             throw new NotImplementedException();
  18.         }
  19.     }

Account service class is one that admin uses it to access all the implemented method , now we need a UserService for users of the banking system to able to create account , delete account , get account information , to do this we implement the IAccountService to this service too , like this :

  1.     public class UserService : IAccountService
  2.     {
  3.         public void CreateBankAccount()
  4.         {
  5.             throw new NotImplementedException();
  6.         }
  7.         public void DeleteBankAccount(Guid accountId)
  8.         {
  9.             throw new NotImplementedException();
  10.         }
  11.         public Ilist<Account> GetAllBankAccounts()
  12.         {
  13.             throw new NotImplementedException();
  14.         }
  15.         public Account GetAccountInfo(Guid accountId)
  16.         {
  17.             throw new NotImplementedException();
  18.         }
  19.     }

All of the IAccountService members are necessary for UserService but  GetAllBankAccounts() , because users of a bank couldn’t access to all account of the system! We can let the unnecessary members as  Not Implemented but It's so hideous , isn't it !? To solve this it's better to use Interface segregation pattern , simply add a new interface and change the IAccountService like this :

  1.    public interface IAccountService
  2.     {
  3.          IList<Account> GetAllBankAccounts();
  4.     }
  1.     public interface IUserService
  2.     {
  3.         void CreateBankAccount();
  4.         void DeleteBankAccount(Guid accountId);
  5.         Account GetAccountInfo(Guid accountId);
  6.     }

And now implement both IAccountService and IUserService for AccountService

  1.     public class AccountService  :IAccountService , IUserService
  2.     {
  3.         public IList<Account> GetAllBankAccounts()
  4.         {
  5.             throw new NotImplementedException();
  6.         }
  7.         public void CreateBankAccount()
  8.         {
  9.             throw new NotImplementedException();
  10.         }
  11.         public void DeleteBankAccount(Guid accountId)
  12.         {
  13.             throw new NotImplementedException();
  14.         }
  15.         public Account GetAccountInfo(Guid accountId)
  16.         {
  17.             throw new NotImplementedException();
  18.         }
  19.     }

And implement the IUserService members for UserService :

  1.     public class UserService : IUserService
  2.     {
  3.         public void CreateBankAccount()
  4.         {
  5.             throw new NotImplementedException();
  6.         }
  7.         public void DeleteBankAccount(Guid accountId)
  8.         {
  9.             throw new NotImplementedException();
  10.         }
  11.         public Account GetAccountInfo(Guid accountId)
  12.         {
  13.             throw new NotImplementedException();
  14.         }
  15.     }

Now Every service class implements the needed members ,right ? If you take a closer look to this simple example rather than making the code more readable by using ISP, it is like the real world or business functionality, my mean every user is able to create , delete and get the account information and admin could see the list of all accounts rather than what Users could do .



About Me

Ehsan Ghanbari

Hi! my name is Ehsan. I'm a developer, passionate technologist, and fan of clean code. I'm interested in enterprise and large-scale applications architecture and design patterns. I spend a lot of time on software architecture. Since 2008, I've been as a developer for different companies and organizations and I've been focusing on Microsoft ecosystem all the time. During the past years, Read More

Post Tags
Pending Blog Posts
using Elmah in asp.net MVC4
Using FluentSecurity in MVC
Strategic design
Factory Pattern
time out pattern in ajax
Redis as a cache server
How to use PagedList In asp.net MVC
Multiple submit buttons in asp.net MVC
Domain driven design VS model driven architecture
What's the DDD-lite?