Home > Projects Analysis > Inside Tapestry Core

Inside Tapestry Core

Tapestry is defined like that in Wikipedia:

“Apache Tapestry is a component-oriented Java web application framework to implement applications in accordance with the model-view-controller architectural pattern. Tapestry was created by Howard Lewis Ship independently, and was adopted by the Apache Software Foundation as a top-level project. Tapestry emphasizes simplicity, ease of use, and developer productivity. Tapestry adheres to the Convention over Configuration paradigm, eliminating almost all XML configuration. Tapestry uses a modular approach to web development, by having strong binding between user interface components (objects) on the web page and their corresponding Java classes.”

I already used Tapstry and I can confirm that’s very simple to use and it’s very elegant, but what about the inside of Tapestry, it’s also well designed and implemented?
This question is very important for each open source project, it gives the assurance that the evolution and maintenance of the project will be easy.

Let’s discover the inside of Tapestry Core by analyzing it by JArchitect.

Here’s the Tapestry general informations:

The first remark is that Tapestry core is well modularized using packages and also well commented.

Let’s go deep inside Tapestry and discover its  implementation and design.

Implementation

Number of line of code

Methods with many line of code are not easy to maintain and understand, let’s search for methods with more than 40 lines.

SELECT METHODS WHERE NbLinesOfCode > 40 ORDER BY NbLinesOfCode DESC

Only few methods have more than 40 lines, it makes the code more readable.

Cyclomatic complexity

Cyclomatic complexity is a popular procedural software metric equal to the number of decisions that can be taken in a procedure. Let’s execute the following CQL request to detect methods to refactor.

SELECT METHODS WHERE CyclomaticComplexity > 20 ORDER BY CyclomaticComplexity DESC

Only 4 methods can be considered as complex.

It’s a very good point when we want to understand source code, almost all methods have less than 40 lines of code, and a cyclomatic complexity less than 20.

Methods with many variables

Methods where NbVariables is higher than 8 are hard to understand and maintain. Methods where NbVariables is higher than 15 are extremely complex and should be split in smaller methods (except if they are automatically generated by a tool).

SELECT METHODS WHERE NbVariables > 15 ORDER BY NbVariables DESC

Only 4 methods has too many variables.

Types with many methods and fields

Let’s search for types with many methods, for that we can execute the following CQL request:

SELECT TYPES WHERE NbMethods > 30  ORDER BY NbMethods DESC

And we can do the same search for fields;

SELECT TYPES WHERE NbFields > 20  ORDER BY NbFields DESC

Few types have many fields and methods. And understanding type’s responsibilities and behavior became very easy.

DESIGN

Inheritance

Types with a big depth of inheritance are not easy to maintain, we have to avoid these kind of classes, and of course there are some cases where it’s not problematic.

Let’s search for classes where depth of inheritance is more than 5.

SELECT TYPES WHERE DepthOfInheritence >=5

Only exceptions classes are concerned, and in this case we can consider that it’s not a problem, exception classes don’t contains business logic, and maintain these classes will not be problematic.

Type cohesion

The single responsibility principle states that a class should have more than 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 
ORDER BY LCOMHS DESC

Only 6 types are considered as no cohesive.

Efferent coupling

The Efferent Coupling for a particular type is the number of types it directly depends on. Types where TypeCe > 50 are types that depends on too many other types. They are complex and have more than one responsibility. They are good candidate for refactoring. Let’s execute the following CQL request

SELECT TYPES WHERE TypeCe > 50  ORDER BY TypeCe DESC 

Another way to see the result is the treemap view, where every type, method and field are represented by  rectangles, and blue ones concern the result of our CQL request, so we can see visually the types concerned by the request.

In our case 4 types are concerned and we can see also their size, the size is proportional to line of code, but we can change it to other metrics.

Types most used

It’s very interesting to know which types are most used,for that we can use the TypeRank metric. TypeRank values are computed by applying the Google PageRank algorithm on the graph of types’ dependencies. A homothety of center 0.15 is applied to make it so that the average of TypeRank is 1. Types with high TypeRank should be more carefully tested because bugs in such types will likely be more catastrophic.

The interesting thing is that almost all types most used are interfaces, it’s a very good news for design, indeed using interfaces instead of concrete classes enforces low coupling and makes the code more flexible.

For example let’s search for Types used by PageImpl, the class implementing the tapestry web page.

SELECT TYPES WHERE IsDirectlyUsedBy 
"org.apache.tapestry5.internal.structure.PageImpl" AND !IsInTierJar

As you can see almost all types are interfaces, so we can change concrete implementations with few source code changes.

We can export result to dependency graph:

Or export it to Matrix view, to have more details about the weight of using these interfaces.

To enforce low coupling Tapestry use injection mechanism to bind with a concrete classes, and to see that let’s search for all fields using Inject annotation to bind with a concrete class.

SELECT FIELDS WHERE HasAnnotation "org.apache.tapestry5.ioc.annotations.Inject"

Many fields use this annotation to inject the concrete class, it make the design more flexible, and easy to understand.

Tapestry is a good framework to use for your J2EE projects, It’s very simple, and as developer you can use only POJO types without having complicated implementation, and it’s also well implemented and designed, and don’t hesitate to look inside the source code, it’s very easy to understand.

Advertisements
Categories: Projects Analysis
  1. October 25, 2011 at 10:00 pm

    Thanks for the analysis … I think Tapestry’s code base is a testament to the power and necessity of dependency injection on the Java platform. I think it’s interesting that the few rough edges your searches found where often a the edge of Tapestry, such as places where it needs to parse XML … or in generated code (from an ANTLR grammar).

    I’ve had quite a number of people contact me to say that they learned something new about coding from reading the Tapestry source; that’s high praise. I’m looking forward to a distant day where I can rework much of my logic around JDK closures as well.

  2. October 28, 2011 at 10:32 am

    “I’ve had quite a number of people contact me to say that they learned something new about coding from reading the Tapestry source”.

    I am definitely one of them. Even the author of http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882 will be amazed to see how tapestry code is a practical example of his book.

  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: