When we search for design pattern articles, we find essentially documentation concerning "Gang of Four" patterns, they are very useful and contribute to well design application.
But when I discovered GRASP principles, I advice anyone interested to improve his skills design to look at these principles, it gives a design fundamental rules.
In this article, we will discover some GRASP principles used by Spring, and the advantages of using them.
Spring is one of the most popular application development frameworks for enterprise Java.
The Spring Framework does not impose any specific programming model, it has become popular in the Java community as an alternative to, replacement for, or even addition to the Enterprise JavaBean (EJB) model.
Spring makes things easy for software designers, it gives them a good basis to have well designed projects. but what about Spring itself, it's well designed also? To try answering this question, let's X-Ray some Spring jars with JavaDepend and discover some designs facts.
Spring Design Analysis
After analysis, here's the dependency graph between all jars analyzed:
And the Matrix view give us more details about the dependency weight between these jars.
Low coupling is desirable because a change in one area of an application will require less changes throughout the entire application. In the long run, this could alleviate a lot of time, effort, and cost associated with modifying and adding new features to an application.
Using interfaces and abstract classes can improve the low coupling and we can evaluate the abstractness of a defined module by the following metric:
A = Na / Nc
* A = abstractness of a module
Zero is a completely concrete module. One is a completely abstract module.
* Na = number of abstract classes in the module.
* Nc = number of concrete classes in the module.
Here's the abstractness of all Spring jars analyzed:
Let's discover all interfaces of jars analyzed, for that we execute the following request:
SELECT TYPES WHERE IsInterface
And to have a better idea of Spring interfaces, the treemap view give us an alternative way to see visually the code elements concerned by a request.
Having a lot of interfaces is not sufficient to be sure that low coupling is enforced, the question is these interfaces are used? For that, let's search for the most used types inside Spring:
All most used types are Class utilities, exceptions or interfaces, and when it concerns a logic layer, the interface is used.
With a good abstractness ratio, and many interfaces used, we can say that Spring enforces low coupling, that makes it very flexible.
When we use interfaces, one interesting question is: who is responsible for creating concrete implementations? Spring provides a good solution using dependency injection, but it's not the way used inside Spring itself.
Spring use Factories to do this job, and as you can see it contains many factory classes:
The single responsibility principle states that a class should have one, and only one, reason to change. Such a class is said to be cohesive. A high LCOM value generally pinpoints a poorly cohesive class. There are several LCOM metrics. The LCOM takes its values in the range [0-1]. The LCOMHS (HS stands for Henderson-Sellers) takes its values in the range [0-2]. Note that the LCOMHS metric is often considered as more efficient to detect non-cohesive types.
LCOMHS value higher than 1 should be considered alarming.
SELECT TYPES WHERE LCOMHS > 0.95 AND NbFields > 10 AND NbMethods >10
Only 4 classes are considered as not cohesive.
Information Expert is a principle used to determine where to delegate responsibilities. These responsibilities include methods, computed fields and so on.
Using the principle of Information Expert, a general approach to assigning responsibilities is to look at a given responsibility, determine the information needed to fulfill it, and then determine where that information is stored.
The Eferent Coupling metric can be an interesting metric to evaluate if some types are more responsibilities, and if they are candidate to be refactored.
The Efferent Coupling for a particular type is the number of types it directly depends on.
SELECT TYPES WHERE TypeCe > 50
These types have a high efferent coupling, and maybe they are candidate to refactoring.
According to Polymorphism, responsibility of defining the variation of behaviors based on type is assigned to the types for which this variation happens. This is achieved using polymorphic operations.
Let's search for all polymorph methods, for that we can execute the following CQL request:
SELECT METHODS WHERE NbOverloads>1
treemap view gives us a good idea of using polymorphism inside Spring:
The Protected Variations pattern protects elements from the variations on other elements (objects, systems, subsystems) by wrapping the focus of instability with an interface and using polymorphism to create various implementations of this interface.
The “Abstractness vs Instability” graph can be useful to detect projects that will be difficult to change.
This following post describes the utility of this graph and how to exploit it to improve the design.
Almost all jars are inside the green zone, it's a good point when changes are needed for maintenance or evolution.
Spring uses all GRASP principles, that makes it simple to understand and maintain, and developers can learn many things when discovering and analyzing Spring source code.
So give a look inside the source and enjoy with all design best practices implemented.
- 17th November, 2011: Initial post