Click here to Skip to main content
15,884,176 members
Articles / Programming Languages / Java

Learn Design Patterns from Real Projects: JBoss Case Study (Part 2)

Rate me:
Please Sign up or sign in to vote.
4.00/5 (1 vote)
9 Nov 2012CPOL5 min read 11.3K   3   1
Structural design patterns are design patterns that ease the design by identifying a simple way to realize relationships between entities

In the previous article, we discovered some creational patterns used by JBoss, let’s discover now some structural design patterns used by it.

Structural design patterns are design patterns that ease the design by identifying a simple way to realize relationships between entities. There’s a common point between the majority of these kind of patterns, it’s the notion of interface or abstraction, so before discussing about structural patterns used by JBoss, let’s discover the utility of using interfaces.

Here are three key benefits derived from using interfaces:

  • An interface provides a way to define a contract that promotes reuse. If an object implements an interface, then that object is to conform to a standard. An object that uses another object is called a consumer. An interface is a contract between an object and its consumer.
  • An interface also provides a level of abstraction that makes programs easier to understand. Interfaces allow developers to start talking about the general way that code behaves without having to get into a lot of detailed specifics.
  • An interface enforces low coupling between components, what makes it easy to protect the interface consumer from any implementation changes in the classes implementing the interfaces.

These benefits could explain why interfaces are used in many design patterns, JBoss defines many interfaces to specify contracts and to enforce low coupling. Let’s search for all interfaces defined by JBoss, for that, we use CQLinq to query the code base.

Java
from  t in Types where t.IsInterface select t

Image 1

If our primary goal is to enforce low coupling, there’s a common mistake when using interfaces that could kill the utility of using them. It’s the using of the concrete classes instead of interfaces, and to better explain this problem, let’s take the following example:

The class A implements the Interface IA that contains the calculate() method, the consumer class C is implemented like that:

Java
public class C
{
   ….

   public void calculate()
   {
     …..
     m_a.calculate();
     ….
    }
    A m_a;
}

The class C instead of referencing the interface IA, references the class A, in this case, we lose the low coupling benefit, and this implementation has two major drawbacks:

  • If we decide to use another implementation of IA, we must change the code of C class.
  • If some methods are added to A not existing in IA, and C uses them, we also lose the contract benefit of using interfaces.

C# introduced the explicit interface implementation capability to the language to ensure that a method from the IA will be never called from a reference to concrete classes, but only from a reference to the interface. This technique is very useful to protect developers from losing the benefit of using interfaces.

With JArchitect, we can check these kind of mistakes using CQLinq, the idea is to search all methods invoked from a concrete class reference instead of the interface one.

Java
from m in Methods  where m.NbMethodsCallingMe>0 && m.ParentType.IsClass
let interfaces= m.ParentType.InterfacesImplemented
from i in interfaces where i.Methods.Where(a=>a.Name==m.Name).Count()>0
select new { m,m.ParentType,i }

Image 2

As we can observe, many methods are concerned, maybe we can make some improvements and use interfaces instead of concrete classes.

After discovering the role of interfaces, let’s discuss some structural patterns used.

Bridge

The goal of the bridge pattern is to decouple an abstraction from its implementation so that the two can vary independently, as described before using interfaces permit to change the implementation without impacting the consumer, but what about protecting interface changes.

To understand better how the bridge works, let’s discuss a concrete example from JBoss implementation. JBoss defines the class InstantiateAction that needs to use a method from KernelBeanValidator interface, and instead of using this interface directly a bridge between the consumer and the interface is added, and as shows the following dependency graphs:

Image 3

The consumer uses the bridge instead of using the interface directly.

Image 4

The bridge uses the interface, so we can change the interface used by the bridge without impacting the consumer.

And to discover better this low coupling between the consumer and the interface used, the dependency matrix gives us a useful view.

Image 5

As we can observe, no dependency exists between the consumer and the interface, the consumer knows only the bridge interface, and the bridge knows only the interface and not concrete class implementing it.

For this reason, we can confirm that the Bridge decouples an abstraction from its implementation so that the two can vary independently.

Adapter

Here the definition of the adapter pattern from wikipedia:

“The adapter is a design pattern that translates one interface for a class into a compatible interface. An adapter allows classes to work together that normally could not because of incompatible interfaces, by providing its interface to clients while using the original interface. The adapter translates calls to its interface into calls to the original interface, and the amount of code necessary to do this is typically small.”

Here’s a scenario where JBoss uses this pattern:

The Instrumentor class needs to use the Instrumentation class from JDK, instead of using it directly, the Instrumentor uses the interface HotSwapper to enforce low coupling and to define a contract independently of the JDK.

Image 6

And to communicate with the instrumentation class, the InstrumentAdapter which implements the HotSwapper interface is added to invoke the instrumentation methods.

Image 7

The lesson that we can take from this pattern is the following:

“The contract is never dictated by the classes used, but by the specification”.

And if the interface does not match with the final implementation used, we can just add an adapter to communicate between the consumer and the adaptee classes.

Facade

A facade is an object that provides a simplified interface to a larger body of code, such as a class library. This pattern could be very useful to isolate the using of external libraries inside some classes, so changing these external libraries will impact only a few classes communicating directly with them.

For example, JBoss uses xercesImpl jar, let’s search for all classes using it.

Java
from t in Types where t.IsUsing ("xercesImpl")
select new { t, t.NbBCInstructions }

Image 8

Only few classes use xrecessimpl directly, each one acts as a facade for a part of the external jar, and changing xercesImpl with another jar will impact only these few classes.

Conclusion

Structural patterns are very useful to structure well the application, but to know which one to use, we have to know the motivations behind using them, and avoid using them because they are very popularized. A good designer is not the one using all the known design patterns, but who masters the motivations of using them. And to complement the understanding of GOF motivations, it’s recommended to discover GRASP principles, they focus more on motivations.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Comments and Discussions

 
QuestionAn Initiative :) Pin
Shabana Parveen25-Dec-12 18:40
professionalShabana Parveen25-Dec-12 18:40 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.