Home > CodeProject > Learn design patterns from real projects : JBoss case study (Part 2).

Learn design patterns from real projects : JBoss case study (Part 2).

In the previous article we dicovered 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 in to a lot of detailed specifics.
  • An interface enforce low coupling between components, what’s make 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.


from t in Types where t.IsInterface select t

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 explain better this problem let’s take the following example:

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


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

}

The Class C instead of referencing the interface IA, it 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 use 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 this kind of mistakes using CQLinq, the idea is to search all methods invoked from a concrete class reference instead of the interface one.


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 }

As we can observe many methods are concerned, maybe we can do 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 define 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

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

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.

As we can observe no dependency exist between the consumer and the interface, the consumer know 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 decouple 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 use this pattern:

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

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

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 use xercesImpl jar, let’s search for all classes using it.

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

only few classes use directly xrecessimpl, each one act 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 master 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.

Categories: CodeProject
  1. No comments yet.
  1. No trackbacks yet.

Leave a comment