DPJF is a tool for detecting occurrences of design patterns (DP) in Java programs. The acronym DPJF stands for Detection of Patterns by Joining Forces, reflecting that the unusually good results of DPJF are achieved by a novel combination of various well-known static analysis techniques (forces).
The first public release of DPJF detects the following similarity groups (that is, sets of structurally similar patterns):
- Forwarders include the patterns in which a method forwards its invocation to an object of a supertype or a sibling type. This similarity group includes the Decorator, Proxy and Chain of Responsibility (CoR) patterns.
- Decouplers include the patterns that propagate information in systems where objects are involved in conceptual dependency relation and the 'master' object is decoupled from dependent objects. This similarity group includes the following patterns: Observer, Composite, Bridge, State, Strategy.
The main highlight of DPJF is that it surpasses other known DP detection tools in detection quality (Precision and Recall), even on programs containing highly unusual pattern implementations or many structurally similar patterns that are easily confused by other tools.
|DPJF makes no mistakes: 100% precision||DPJF finds more: Up to 3 times higher recall for proxies|
|In both diagrams, the last column shows the median of the measured values|
Moreover, DPJF is one of the fastest existing tools. The table below compares its query times (running on JTransformer 2.9.3 and SWI-Prolog >= 5.11.29) to the performance of other tested DP detection tools.
|Red color indicates the fastest tool on a particular benchmark. Bombs indicate tool crashes.|
Note that after its initial start, DPJF does not need to re-parse projects. If the project is changed at run-time, the JTransformer factbase (→ implementation) is updated instantly with unnoticeable delays. So DPJF will actually incur only the pure query time in all but its very first run during an Eclipse session. To the best of our knowledge, none of the other existing tools supports incremental update of their internal representation. They all need to re-parse the entire project for each new analysis, incurring on each run much higher costs than the those shown above.
Like other tools, DPJF can help in understanding the structure of yet unknown applications. However, DPJF can also assist in application development, paving the way for applications of DPD beyond program comprehension. Its high query speed enables rerunning design pattern detectors automatically after every update of a file in the Eclipse IDE. Therefore, it can be used as a permanent advisor that hints at wrong, incomplete or unrecommended implementations of a design pattern. For instance, it detects Singletons whose constructor is public (as the one from JHotDraw 6 shown in the screenshot below). Such problems are instantly displayed in the editors of affected classes. Going even one step further, DPJF even provides automatic “quick fixes” that let programmers fix detected problems at the expense of a mouse click. Thus DPJF serves as an “intelligent advisor” who not only advises, but also does some work for you!
DPJF can detect patterns in any Java project. It was tested on JHotDraw 5.1, JHotDraw 6.0, Java IO 1.4, AWT 1.14, ArgoUML 0.18 and Eclipse Team Core (from Eclipse 3.6.0). The factbases for these repositories come with our installation packages.
The right-hand-side table shows some relevant size indicators for each project. Comparison of project sizes to the measured detection speed (above) reveals the good scalability of DPJF.
DPJF is based on the JTransformer analysis and transformation engine. JTransformer parses the source and byte code of a Java program, creating a database of Prolog facts (called a factbase) that describes the program elements and their relationships.
DPJF consists of several detection modules (DMs). Each DM is responsible for detecting a set of structurally similar patterns (a similarity group). A DM consists of a structural submodule and a behavioral submodule implemented as Prolog queries that analyse the factbase created by JTransformer. The structural submodule identifies candidates for a given similarity group by applying very efficient structural analyses. The behavioral submodule distinguishes the candidates within the same similarity group, classifying them properly or rejecting them.
This architectural decision has allowed us to implement DPJF in very short time and achieve very good performance results by profiting from advances of the underlying infrastructures (JTransformer and SWI-Prolog).
For instance, JTransformer has always provided extremely high query speed but taking advantage of its potential required very deep optimization knowledge that complicated the implementation of efficient detectors. Since the introduction of dynamic multi-argument indexing in SWI-Prolog 5.11.29 even naively written queries can run at very high speed, making it easy for interested developers to extend DPJF by new pattern detection modules.