Home > Uncategorized > Two powerful principles to improve the design

Two powerful principles to improve the design

Coupling is usually contrasted with cohesion. Low coupling often correlates with high cohesion, and vice versa.
Low coupling is often a sign of a well-structured computer system and a good design, and when combined with high cohesion, supports the general goals of high readability and maintainability.

The goal of this case study is to show the benefits of low coupling and high cohesion, and how it can be implemented with Java. The case study consists of designing an application that accesses a file in order to get data, processes it, and prints the result to an output file.

Solution without design:

For this first solution the design is ignored and only one class named DataProcessor is used to:

– Get data from file.
– Processing data.
– Print result.

And the main method invokes the methods of this class.

Drawback of this solution:

Low cohesion: DataProcessor class has many responsibilities so we can’t easily reuse algorithm in other application.
High coupling: the processing is high coupled with console and also with data provider.

Design refactoring:

– High Cohesion:
To improve cohesion each responsibility must be assigned to a different class so we need three classes:

FileProvider: To get data from File.
DataProcessing: To process data, and this class can use other classes to complete processing, but to simplify the design we consider that’s sufficient for our processing.
ResultReporting: To report result to file.

So each class has its own responsibility, here’s the advantages of this improvement:

– Easy to understand classes.
– Easy to maintain.
– Easy to reuse classes in other applications.

– Low coupling:
What happen if data exist in database not in file, in our last design our application is high coupled with file provider.

Using interfaces and abstract classes improve the low coupling, and the question is which type to use interface or abstract class?

Interface permit to define a contract without implementation, so no behavior logic exist for interfaces, however abstract classes let you define some default behaviors; and they force your subclasses to provide others.

Even you choose to use abstract class to define a default behavior, it’s better to provide also an interface, to dissociate between the contract and the behavior, this decoupling makes the code more flexible, and any changes in the behavior will not impact a lot of your code if you use interfaces.

Let’s add an interface that provides methods to get data from anywhere and for the case of file we need class that implement this interface.

And FileProvider inherit from IDataProvider to implement getData, and the same design can be used for DataProcessing and ReportResult.

Here’s the new collaboration between classes after refactoring:

– Class Factory:
In the latest design the creation of concrete instances of IDataProvider,IDataProcessing and IReportResult are created by Main method.

To improve the cohesion it’s better to assign this responsibility to a factory class so logic to instantiate a family of instances needed is isolated.

– Controller:
The orchestration between all classes is implemented in the main method.

To improve the cohesion let’s assign this responsibility to a Controller class, so we can use it in other applications.

The controller needs three classes to interact with them, controller could instantiate directly objects needed, but to improve low coupling, it’s better to give to the controller the objects needed.

For that two approaches could be used:

In house approach:

For this approach two main solutions exist:

– Add method named BindInstances(IDataProviderPtr,IDataProcesingPtr,IReportResultPtr).

– Use generics so the controller will be instantiated like that:
Controller<FileProvider,DataProcessor,ConsoleReport>

The difference between the two solutions is that for the first one each DataProvider must inherit from IDataProvider, and for the second one FileProvider need only the method GetData() even if it’s inherit from another class than IDataProvider.

The second choice is more decoupled than the first one, I don’t need to inherit from IDataProvider, and generics are a powerful tool to make the code more flexible.

Using DI frameworks aproach:

Another popular approach is to use a dependency injection framework like spring, guice or picocontainer to do the job.

Here’s the new collaboration between classes after refactoring:

Benefit of refactoring:

After refactoring using the two principles, this application became more flexible and we can use it for different scenario:
– Can get data from file,database,xml file,csv file,…
– Can process with many class not only one.
– Can report to console,file,….

Advertisements
Categories: Uncategorized
  1. Bhanu Prakash
    November 8, 2012 at 4:53 am

    “The difference between the two solutions is that for the first one each DataProvider must inherit from IDataProvider, and for the second one FileProvider need only the method GetData() even if it’s inherit from another class than IDataProvider.”

    Can you explain this in detail? I see that the first solution depends on Interfaces. However, second solution is now dependent completely on concrete class. Howz it helpful?

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: