Showing posts with label OOP. Show all posts
Showing posts with label OOP. Show all posts

Sunday, July 24, 2011

Open Closed Principle

Motivation

A very important consideration when building software is to write code to produce applications which can adapt when new needs or requirements change (.. which for sure they will ) without affecting the rest of the already implemented functionality. Usually, changes in existing code should be minimized since it is assumed that the existing code is already unit tested and that probably it took a long time to get it correct and bug free.

Definition

The open closed principle states that Classes should be open for extension, but closed for modification. The goal of this principle is to allow classes to be easily extended without modifying existing code. Therefore, obtaining designs that are resilient to change and flexible enough to take a new functionality to meet changing requirements.

Example without Open Closed Principle

Let’s say there is a banking application which allows customers to create different types of bank accounts. Below, you can see the class diagram of how this application might look like:

(Click on the image to expand it)

The Account class handles different transactions that a customer might execute depending on his type of account. For example, saving accounts holders allow only withdrawals until the balance is €0.00 but giro accounts provide a credit of €500.00. So the developer writes some code that determines the appropriate type of account and then goes about doing the withdrawals:

   public Account (String name, String type)
{
/* This code is NOT closed for modification
* if new Accounts are introduced or removed
* we have to get into this code and modify it
*
* Bad Times!! :( */

this.type = type;
this.name = name;

if(type.equals("Giro Account"))
withdrawGiroAccount(amount);
else if(type.equals("Saving Account"))
withdrawSavingAccount(amount);
else if(type.equals("Personal Account"))
withdrawPersonalAccount(amount);

}
When you write code like this, you are looking for trouble because you know when it comes time for changes or extensions, you will have to reopen this code and examine what needs to be added or deleted. Often, this kind of code ends up in several parts of the application making maintenance and updates more difficult and error prone.

Clearly, dealing with which concrete class is required is really messing up our Account class and preventing it from being closed for modification. But now that we know that we want the Account class to remain untouched it is time to apply the principle.

Example with Open Closed Principle

The class diagram below shows how this application will be design.

(Click on the image to expand it)

First, we have a client class which will be in charge to create accounts. For this example is just a simple Java class which makes instances of giro, saving or any other type added in the future.

public class AccountTest
{
public static void main(String args[])
{

AccountType giroAccount = new GiroAccount();
AccountType savingAccount = new SavingAccount();

Account account1 = new Account("Cipriano's Account", giroAccount);
Account account2 = new Account("Desiree's Account", savingAccount);

System.out.println("\nTransactions for Cipriano's account");

System.out.println(account1.deposit(1000));
System.out.println(account1.withdraw(4000));
System.out.println(account1.withdraw(3000));
System.out.println(account1.withdraw(1000));

System.out.println("\nTransactions for Desiree's account");
System.out.println(account2.deposit(3000));
System.out.println(account2.withdraw(2000));
System.out.println(account2.withdraw(2000)); }

}
}
We define our Account class, and a constructor which will receive as parameters the owner of the account and the AccountType. Notice that the correct transaction is executed by help of polymorphism since all the new type of accounts will be a subtype of AccountTypes. When we create Account objects in AccountTest we are passing a concrete reference of AccountType (i.e SavingAccount, GiroAccout, etc..) to Account therefore, it will know what kind of transaction execute.
public class Account  {

private AccountType account;
private float amount;

public Account (String name, AccountType type) {
this.account = type;
this.account.setName(name);
}

public String deposit(float amount){
return account.deposit(amount);
}
public String withdraw(float amount){
return account.withdraw(amount);
}
public void setAmount(float amount){
this.amount = amount;
}
public float getAmount(){
return account.getAmount();
}
public String toString(){
return account.getName() + " : " +
account.getAmount() + "€";
}
}
Now is time to define AccountType which will be an abstract superclass of all the new different types of required accounts. It will provide shared common design but it will delegate the withdrawal implementation to concrete classes. It is in here where we are able to create new functionality of accounts without breaking the existing Account implementation. Thus, we will be able to add as many account types with different kind of withdrawal behaviors without even touching the Account class achieving like that the what the Open Closed Principle states. Account will be closed but new types of account might be open to extension providing new implementations of the abstract String withdraw(float amount).
public abstract class AccountType
{
private float amount = 0;
private String name;

public AccountType(){}

public AccountType(String name){
this.name = name;
}

public void setName(String name) {
this.name = name;
}

public String getName(){
return this.name;
}

public void setAmount(float amount) {
this.amount = amount;
}

public float getAmount(){
return amount;
}

public String deposit(float amount){
float current = getAmount();
setAmount(current + amount);

String result = "deposited " + amount + "€" ;
result = result + " for " + getName();
result = result + "\ncurrent balance is: " +
getAmount() + "€";
return result;
}

public abstract String withdraw (float amount);

}

Finally we add our concrete account type classes with their respective withdraw implementations.

public class GiroAccount extends AccountType {

public static final float OVER_DRAFT_LIMIT = 5000f;

public GiroAccount() {
}

public GiroAccount(String name) {
super(name);
}

public String withdraw(float amount) {
float current = getAmount();
float withdrawal;

if (current - amount >= -OVER_DRAFT_LIMIT)
withdrawal = amount;
else
withdrawal = OVER_DRAFT_LIMIT + current;

setAmount(current - withdrawal);

String result = "withdrawn " + withdrawal + "€";
result = result + " from " + getName();
result = result + "\ncurrent balance is: " + getAmount() + "€";

return result;
}

@Override
public String toString() {
return "GiroAccount";
}
}
public class SavingAccount extends AccountType {

public SavingAccount(){}
public SavingAccount(String name){
super(name);
}

@Override
public String withdraw(float amount) {
float current = this.getAmount();
float withdrawal = 0;
String result="";
if(current - amount >= 0){
withdrawal = amount;
setAmount(current - withdrawal);
result = "withdrawn " + withdrawal + "€" ;
result = result + " from " + getName();
result = result + "\ncurrent balance is: " +
getAmount() + "€";
}
else
result = "Insuficient money available";

return result;
}

@Override
public String toString(){
return "SavingAccount";
}
}
Conclusion

The Open Closed Principle is a useful software design consideration when it comes to writing maintainable code and might be used to design applications in which requirements are likely to change. There are many design patterns that allow developers to write extendable code without changing existing implementation. For example the Factory pattern, the Decorator pattern or the Observer pattern.

Be careful when choosing the areas of code that need to be extended; making a flexible design sometimes involves additional complexities and effort. Applying the Open Closed Principle everywhere can lead to complex, hard to understand code.

Thursday, February 10, 2011

Object Oriented Programming - Initial Post

As many other people my first contact with programming was by far not an Object Oriented language. In my case my first programming tool was the well remembered “flowchart” (which by the way I think is a great tool to start..) After we developed some logic and understood the very basics of loops, processes and flows then we moved into what it was my first official language which was Pascal, a procedural programming language designed in the late 60's and initially thought as a language to teach students structured programming. As soon as I started loving Pascal and picturing myself as a successful skilled Pascal programmer (I was feeling very confident programming my first very basic console programs), somebody told me well guess what?? Pascal is so old and so useless that nobody uses it anymore other than teaching purposes. Of course I was shocked!! How come??? so now the language which for 6 “long” months I have learned with so much passion is useless??? well yes, said this person!! now what you have to learn is an Object Oriented Programming Language called Java!!

That day, I had the pleasure to meet the well old known programmer's friend called CHANGE. Which up to now always shows up, just as my first days with Pascal whenever I start feeling comfortable using a particular technology (languages, framework, APIs or whatever.. ). Therefore, after being witness of the radical changes that have occurred during the last years I've learned to appreciate the basics of programming and the importance to learn them well; because the basis of programming haven't changed much for 40 years.

As well after that day I heard for the first time the term Object Oriented Programming or OOP for short. To be honest at the beginning it was somehow confusing for me to fully understand it, I used to read about: encapsulation, abstract classes, polymorphism, interfaces, objects, inheritance, and many other terms that I was really not sure what their real purpose was.

The idea of this post is to give an introduction to OOP. In further posts I will be writing about its basic concepts and posting some code examples to exemplify the concepts discussed here. I will be using Java since it is a known programming language among software developers and the one I have more experience with. It is important to note that the topics discussed here are being thought in Java terms, so they might slightly differ from other OO languages. But first some history..

History

The terms “objects” and “oriented” seem to make first appearance at MIT during the late 50's and early 60's in different research projects taking place on this university at that time. However, it is considered to be SIMULA the first object oriented language. As its name suggests it was used to create simulations. Alan Kay, who was at the University of Utah at the time, liked what he saw in the SIMULA language. He had a vision of a personal computer that would provide graphics-oriented applications and he felt that a language like SIMULA would provide a good way for non-specialists to create these applications. He sold his vision to Xerox Parc and in the early 1970s, a team headed by Alan Kay at Xerox Parc created the first personal computer called the Dynabook. Smalltalk was the object-oriented language developed for programming the Dynabook. It was a simulation and graphics-oriented programming language. Smalltalk exists to this day although it is not widely used commercially.

The idea of object-oriented programming gained popularity in the 1970s and in the early 1980s Bjorn Stroustrup integrated object-oriented programming into the C language. The resulting language was called C++ and it became the first object-oriented language to be widely used commercially.

In the early 1990s a group at Sun led by James Gosling developed a C++ based language called Java which was originally designed for interactive television, but it was too advanced for the digital cable television industry at the time. This project was going nowhere until the group re-oriented its focus and marketed Java as a language for programming Internet applications. After that, the language has gained widespread popularity and nowadays is widely used and constantly new languages are being influenced by it (i.e. Python, PHP, C#, SCALA ). Since then Java hasn't stopped evolving and is one of the favorite languages used in the academia and the industry.

For the initial posts I will assume that the reader has never used an OOP language before so I will start defining the most very basic concepts. I think it is a good idea to do so because as I said I really believe that learning the basics and learn them well are going to really help to avoid misunderstandings that can later lead us to get lost on the topic and get frustrated. So having said that, if you are an experienced programmer definitely this will be old stuff for you. However, if you are not I will firstly cover what objects, classes, inheritance, interfaces and packages are. Having done that we will be ready to move to real code examples.