This repository has been archived on 2022-12-20. You can view files and clone it, but cannot push or open issues or pull requests.
sdm01/report.tex

694 lines
32 KiB
TeX

% vim: set ts=2 sw=2 et tw=80:
\documentclass[11pt,a4paper]{scrartcl}
\usepackage[utf8]{inputenc}
\usepackage[margin=2.25cm]{geometry}
\usepackage{hyperref}
\usepackage{listings}
\usepackage{xcolor}
\usepackage{lmodern}
\usepackage{booktabs}
\usepackage{graphicx}
\usepackage{float}
\usepackage{tikz}
\usepackage{listings}
\usepackage{pgfplots}
\usepackage{subcaption}
\setlength{\parindent}{0cm}
\setlength{\parskip}{0.3em}
\hypersetup{pdfborder={0 0 0}}
\usepackage[nomessages]{fp}
\renewcommand*{\titlepagestyle}{empty}
\lstset{
basicstyle=\small\ttfamily,
%frame=shadowbox,
rulesepcolor=\color{black},
columns=fullflexible,
commentstyle=\color{gray},
keywordstyle=\color{blue},
mathescape=true,
aboveskip=1em,
captionpos=b,
abovecaptionskip=1em,
belowcaptionskip=1em
}
\title{Assginment 1 -- Software Design and Modelling}
\author{Volodymyr Karpenko \and Claudio Maggioni}
\begin{document}
\begin{titlepage}
\maketitle
\pagenumbering{roman}
\tableofcontents
\listoffigures
\lstlistoflistings
\end{titlepage}
\section{Project selection process}
\pagenumbering{arabic}
We have to choose a Java-based project on GitHub that follows the following
requirements:
\begin{itemize}
\item 100 or more stars;
\item 100 or more forks;
\item 10 or more open issues;
\item 50.000 or more lines of code.
\end{itemize}
Additionally, we added some less strict constraints that we thought would lead
to a more significant and influential analysis:
\begin{itemize}
\item There must be evidence that the project follows business-oriented
conventions. This excludes amateur or personal projects that might have
fewer design pattern applications due to their nature.
\item Repository data, documentation, and comments must be written in English.
Many repositories that are at the top of the search results provided by the
hard requirements are not in English, and this drastically hampers our
ability to understand the code;
\item The artifact the project produces must not rely on external components
and have a streamlined build process, with all code stored in a single
Maven/Gradle module. This improves our ability to tinker with the project
more quickly and the pattern detection process, which requires all
\textit{.class} files related to the project to be stored in a single
directory tree.
\end{itemize}
Additionally, instead of querying GitHub directly for projects, we decided to
see if libraries we knew already in our Java development career would match the
hard and soft requirements we set for ourselves.
Therefore, we considered the following GitHub repositories:
\begin{description}
\item[vavr-io/vavr] a Java library for functional programming, was discarded
as the project is less than 20.000 lines of code and does not meet the rigid
requirements;
\item[bitcoin4j/bitcoin4j] a Java implementation of the bitcoin protocol,
discarded as the project is distributed in several subprojects, and
therefore the build process is nontrivial;
\item[FasterXML/jackson-core] is the core ''module`` of a Java JSON
serialization and deserialization library. We chose this project because it
meets the selection criteria. It does not rely on external components for
its execution. Finally, the project structure uses a single Maven module for
its sources and is thus easy to analyze.
\end{description}
\subsection {The Jackson Core Project}
As mentioned, Jackson is a library that offers serialization and deserialization
capabilities in JSON format. It is highly extensible and customizable through a
robust but flexible API. The library is divided into what the Jackson developers
call “modules,” i.e., plug-ins that can augment the serialization and
deserialization process. Some modules, like the \textit{jackson-dataformat-xml}
module, target different encoding languages like XML.
The chosen repository contains only the \textit{core} module of Jackson. The
\textit{core} module implements the necessary library abstractions and
interfaces to allow other modules to be plugged-in. Additionally, the
\textit{core} module implements the tokenizer and low-level abstractions to work
with the JSON format. We will refer to this module as ``Jackson'' or ``Jackson
Core'' interchangeably throughout this report.
We choose to analyze version 2.13.4 of the module (i.e.\ the code under the
\textit{git} tag \textit{jackson-core-2.13.4}) because it is the latest stable
version available at the time of writing.
After verifying that the project meets the hard requirements related to GitHub
(more than 2000 stars, more than 600 forks, 35 open issues\footnote{as of
2022-10-19 (ISO 8601 date)}), we ensured that the project had enough lines of
code by using the cloc tool, which provided the following output shown in Figure
\ref{fig:cloc}. By looking at the results we can finally assert that the
project contains 58.787 non-blank lines of Java code and this satisfies all the
requirements.
\begin{figure}[h]
\centering
\begin{tabular}{lrrrr}
\toprule
Language & Files & Blank & Comment & Code \\
\midrule
HTML & 4,846 & 18,473 & 235,544 & 1,997,020\\
Java & 285 & 8,532 & 20,004 & 48,783\\
CSS & 3 & 18 & 69 & 990\\
Logos & 2 & 260 & 212 & 605\\
Bourne Shell & 3 & 35 & 62 & 223\\
XML & 7 & 5 & 1 & 179\\
DOS Batch & 1 & 35 & 0 & 153\\
Markdown & 3 & 58 & 0 & 125\\
Maven & 1 & 13 & 23 & 112\\
YAML & 3 & 1 & 5 & 71\\
JavaScript & 1 & 1 & 0 & 29\\
JSON & 1 & 0 & 0 & 10\\
Properties & 2 & 0 & 16 & 5\\
\midrule
Total & 5,158 & 27,431 & 255,936 & 2,048,305\\
\bottomrule
\end{tabular}
\caption{Output of the \textit{cloc} tool for the Jackson Core project at
revision \textit{jackson-core-3.13.4}.}
\label{fig:cloc}
\end{figure}
\section{Analysis Implementation}
The analysis is performed using the
\textit{Pattern4J}\footnote{\url{https://users.encs.concordia.ca/~nikolaos/pattern\_detection.html}}
developed at Concordia University. This program attempts to detect traditional
design patterns by scanning the bytecode (i.e.\ the \texttt{.class} files) of a
given project and by checking several heuristics. Due to the unceirtanty of this
process we double-check each instance of a pattern found to use our own
judgement and detect possible false positives.
Since the tool needs compiled \textit{.class} files to perform the analysis,
and since \textit{jackson-core} is a standard Maven project, we compile the
sources using the command \texttt{mvn clean compile}. The \textit{pom.xml} of
the library specifies Java 1.6 as a build target, which is not supported by JDK
17 or above. We used JDK 11 instead, as it is the most recent LTS version of the
JDK to still support this target.
An XML dump of the \textit{Pattern4J} analysis results is included in the
submission as the file \textit{analysis.xml}.
In the following sections each detection of the \textit{Pattern4J}
tool is reviewed to characterize if it is indeed not a false positive and if the
design pattern is varied in any way in its application. For the sake of brevity,
when referring to a class by its fully-qualified domain name the prefix
\textit{com.fasterxml.jackson.core} is omitted as all classes in the Jackson
core project reside in this package or in a sub-package of this package.
\section{\textit{Pattern4J} Accuracy and Quantitative Analysis}
As it would be very hard to check each class in the Jackson project for design
patterns manually to get a true number of false positives and false negatives,
we opt for a more statistical approach. We select 20 classes at random from the project
and we review the reported results for this subset. The classes were selected
from the \textit{target/classes} directory generated by Maven using the
following command:
\begin{verbatim}
find . -name '*.class' | shuf -n 20 | sed 's#\.class##;s#/#.#'
\end{verbatim}
The selected classes and the analysis results for both \textit{Pattern4J} and
our manual inspection are shown in Figure \ref{fig:conf}. Using those results,
we can say that \textit{Pattern4J} shows a false positive
rate\footnote{\url{https://en.wikipedia.org/wiki/False_positive_rate}} of 53.8\%, a
false negative rate of 11.1\%, and an accuracy of 75.0\%.
\begin{figure}[h]
\begin{subfigure}{\linewidth}
\resizebox{\textwidth}{!}{
\begin{tabular}{l|rrrr|p{7cm}}
\toprule
Class & \multicolumn{1}{p{1.5cm}}{True positives} &
\multicolumn{1}{p{1.5cm}}{False positives} &
\multicolumn{1}{p{1.6cm}}{False negatives} &
\multicolumn{1}{p{1.6cm}|}{True\ \ \ negatives} &
Notes\\
\midrule
util.DefaultPrettyPrinter\$Indenter & ~ & 1 & ~ & ~ & state and adapter, false positives \\
ObjectCodec & ~ & ~ & ~ & 1 & ~ \\
type.WritableTypeId & ~ & ~ & ~ & 1 & ~ \\
util.DefaultPrettyPrinter\$NopIndenter & 1 & ~ & ~ & ~ & variation of
singleton, true positive \\
json.PackageVersion & ~ & ~ & 1 & ~ & variation of singleton, false negative \\
io.UTF32Reader & ~ & ~ & ~ & 1 & ~ \\
io.NumberInput & ~ & ~ & ~ & 1 & ~ \\
json.JsonReadFeature & ~ & ~ & ~ & 1 & ~ \\
io.SerializedString & 1 & ~ & ~ & ~ & variation of singleton, true
positive \\
type.TypeReference & ~ & ~ & ~ & 1 & ~ \\
JsonPointer & ~ & 1 & ~ & ~ & singleton, false positive \\
json.UTF8DataInputJsonParser & ~ & ~ & ~ & 1 & ~ \\
format.InputAccessor\$Std & ~ & ~ & ~ & 1 & ~ \\
JsonStreamContext & 1 & ~ & ~ & ~ & template method (barely), true
positive \\
filter.TokenFilter & ~ & 0.5 & 0.5 & ~ & singleton, false positive;
strategy, false negative \\
util.VersionUtil & ~ & ~ & ~ & 1 & ~ \\
json.UTF8JsonGenerator & ~ & ~ & ~ & 1 & ~ \\
JsonParser\$Feature & ~ & ~ & ~ & 1 & ~ \\
exc.StreamReadException & ~ & ~ & ~ & 1 & ~ \\
util.JsonGeneratorDelegate & ~ & 1 & ~ & ~ & decorator, false positive
(a ``delegation'' instead, pattern not supported by \textit{Pattern4J}) \\
\midrule
Total & 3 & 3.5 & 1.5 & 12 & ~ \\
Percentage & 15.0\% & 17.5\% & 7.5\% & 60.0\% \\
\bottomrule
\end{tabular}
}
\caption{Table of classes analyzed manually against the \textit{Pattern4J}
tool results. Units are classes, the value $0.5$ represents a pattern inside
a class with two patterns.}
\label{fig:conf:tab}
\end{subfigure}
\begin{subfigure}{\linewidth}
\centering
\vspace{1cm}
\begin{tikzpicture}
\begin{axis}[
colormap={parula}{color=(white) rgb255=(90,96,191)},
xlabel=Pattern4J,
xlabel style={yshift=-40pt},
ylabel=Manual detection,
ylabel style={yshift=40pt},
xticklabels={Has pattern, No pattern},
xtick={0,...,1},
xtick style={draw=none},
yticklabels={Has pattern, No pattern},
ytick={0,...,1},
ytick style={draw=none},
enlargelimits=false,
colorbar,
xticklabel style={
rotate=45
},
nodes near coords={\pgfmathprintnumber\pgfplotspointmeta},
nodes near coords style={
yshift=-7pt
},
]
\addplot[
matrix plot,
mesh/cols=2,
point meta=explicit,draw=gray
] table [meta=C] {
x y C
0 0 3
1 0 1.5
0 1 3.5
1 1 12
};
\end{axis}
\end{tikzpicture}
\caption{Confusion matrix comparing the \textit{Pattern4J} detection results
with our manual interpretation of the classes. Units are classes, the value
$0.5$ represents a pattern inside a class with two patterns.}
\label{fig:conf:mat}
\end{subfigure}
\caption{Results of the statistical analysis on the effectiveness of the
\textit{Pattern4J} tool as a class-by-class table (Figure
\ref{fig:conf:tab}) and as a confusion matrix (Figure \ref{fig:conf:mat}).}
\label{fig:conf}
\end{figure}
Moreover, based on \textit{Pattern4J} complete analysis output, we are able to
report the overall findings, shown in Figure \ref{fig:ana}.
\begin{figure}[H]
\centering
\begin{tabular}{lrr}
\toprule
Design Pattern & Pattern Applications & Classes Covered \\
\midrule
Factory Method & 2 & 2 \\
Singleton & 13 & 13 \\
Adapter & 8 & 6 \\
Decorator & 2 & 2 \\
State & 5 & 3 \\
Bridge & 1 & 1 \\
Template Method & 7 & 7 \\
\midrule
Total & 38 & 34 \\
\bottomrule
\end{tabular}
\caption{Quantitative summary of \textit{Pattern4J} complete analysis output
for the Jackson core project.}
\label{fig:ana}
\end{figure}
\section{Structural Patterns}
\subsection{Singleton Pattern}
\textit{Pattern4J} found a lot of instances of the singleton pattern, namely 13.
However, some discussion is required to understand the ways the Jackson core
project applies this pattern, as the instances found are sometimes wildly
different from the standard application or outright false positives.
\begin{lstlisting}[caption=The \textit{sym.Name1}
class.,language=java,label=lst:name1]
public final class Name1 extends Name {
private final static Name1 EMPTY = new Name1("", 0, 0);
private final int q;
Name1(String name, int hash, int quad) {
super(name, hash);
q = quad;
}
public static Name1 getEmptyName() {
return EMPTY;
}
@Override
public boolean equals(int quad) {
return (quad == q);
}
@Override
public boolean equals(int quad1, int quad2) {
return (quad1 == q) && (quad2 == 0);
}
@Override
public boolean equals(int q1, int q2, int q3) {
return false;
}
@Override
public boolean equals(int[] quads, int qlen) {
return (qlen == 1 && quads[0] == q);
}
}
\end{lstlisting}
For example, \textit{sym.Name1} (whose sources are in Listing \ref{lst:name1})
has a package-private constructor and a \textit{public static final} instance of
itself. This is enough for \textit{Pattern4J} to flag the class as a singleton,
as its constructor is never called in Jackson core other than for initializing
the aforementioned field. However, by reading the documentation it is clear
that the class is meant to be instantiated multiple times. Indeed, its purpose
is to box and represent JSON string literals shorter than 4 bytes, implying the
class is meant to be initialized by clients of the core Jackson module.
Several less-than-obvious results like this one are reported by the tool,
namely:
\begin{description}
\item[sym.Name1, JsonLocation, DefaultIndenter,
util.DefaultPrettyPrinter\$FixedSpaceIndenter] are not singletons and thus
false positives. All these classes were detected because of ``default''
instances they include in themselves as \textit{static final} fields and
because their constructor, even if \textit{public}, is never used in Jackson
core itself. However, by checking the documentation all these classes are
meant to be extended and instantiated in other Jackson modules;
\item[JsonPointer, filter.TokenFilter] are as described above, however having
\textit{protected} constructors;
\item[JsonpCharacterEscapes, util.DefaultPrettyPrinter\$NopIndenter,
Version] may be considered variations of the singleton pattern that however
include a \textit{public} constructor that is never called in the module
code, but that may be called in tests. Given the \textit{public}
constructors, these classes are hardly solid singleton implementations.
However, we gave the benefit of the doubt to Jackson developers as the use
of the constructors in test code may hint to a purposefully open design to
allow for testability;
\item[io.JsonStringEncoder] is as described above, however the class is
declared as \textit{final};
\item[util.InternCache, io.CharTypes\$AltEscapes] are both rather standard
singleton pattern applications, however implemented with eager (non-lazy)
initialization (i.e.\ storing the instance in a \textit{public static final}
field);
\item[io.ContentReference] is as described above, however having a
\textit{protected} constructor instead of a \textit{private} one.
\end{description}
\subsection{Abstract Factory Pattern}
\textit{Pattern4J} detects only two instances of the abstract factory pattern:
\begin{description}
\item[TokenStreamFactory] which indeed is a factory for \textbf{JsonParser} and
\textbf{JsonGenerator} is a factory for JsonParser and JsonGenerator objects,
although two overloaded factory methods exist on this class (one for each
class) catering to a different combination of arguments. A concrete
implementation of this factory is included in the form of the
\textbf{JsonFactory} class, although other modules may add additional
implementations to cater to different encodings (like the
\textit{jackson-dataformat-xml} module for XML);
\item[TSFBuilder] which is also a factory for concrete implementations of
\textbf{TokenStreamFactory} allows slight changes in the serialization and
deserialization rules (e.g., changing the quote character used in JSON keys from
" to '). Like TokenStreamFactory, this class is only implemented by one class,
JsonFactoryBuilder, within this module's scope. Moreover, as mentioned
previously, this abstract factory will likely be extended by concrete
implementations in other Jackson modules. \end{description}
\subsection{Builder Pattern}
The builder pattern does not seem to be analyzed by \textit{Pattern4J}, as the
analysis output does not mention the pattern, even to report that no instances
of it have been found (as is the case with other patterns, e.g., the observer
pattern). A manual search in the source code produced the following results:
\begin{description}
\item[TSFBuilder] is also a builder other than an abstract factory. As mentioned
previously, this class allows slightly altering the serialization and
deserialization rules used to build outputting JsonFactory objects. Each
rule is represented by an object or enum instance implementing the
util.JacksonFeature interface. TSFBuilder then provides several overloaded
methods to enable and disable features represented by the interface. Enabled
features are stored in several bitmask-protected int fields, which are then
directly accessed by the constructor of the TokenStreamFactory concrete
implementation to build; \marginpar[right
text]{\color{white}\url{https://youtu.be/72b2nH-kdbU}}
\item[JsonFactoryBuilder] is a concrete factory implementation of
\textbf{TSFBuilder} that builds \textbf{JsonFactory} instances;
\item[util.ByteArrayBuilder] provides facilities to build \textit{byte[]}
objects of varying length, akin to \textbf{StringBuilder} building
\textbf{String} objects. This is not a strict implementation of the builder
pattern per se (as Java arrays do not have a ``real'' constructor), but it
is nevertheless included since the features it exposes (namely dynamic
sizing while building) are decoupled by the underlying (fixed-size) array
representation.
\end{description}
\section{Creational Patterns}
\subsection{Adapter Pattern}
\textit{Pattern4J} found many instances of the adapter pattern, however all but
one were shown to be false positives by checking the documentation and the code
using each alleged adaptee. The matches found are reported and commented
below. Matches are shown in the \textit{[Adapter] $\leftarrow$ [Adaptee]}
format.
\begin{description}
\item[JsonFactory $\leftarrow \{$ sym.ByteQuadsCanonicalizer,
io.InputDecorator $\}$] false positives, by reading the documentation it is
clear the classes have different purposes and \textbf{JsonFactory} is merely
using the other classes' functionality through composition;
\item[base.ParserBase $\leftarrow$ json.JsonReadContext] false positive,
\textbf{json.JsonReadContext} is instantiated several times in
\textbf{base.ParserBase} by mutating the container field with the new
instances;
\item[base.ParserBase $\leftarrow$ json.JsonWriteContext] false positive,
like above;
\item[$\{$ util.DefaultPrettyPrinter, util.MinimalPrettyPrinter $\}
\leftarrow$ util.Separators] false positives, another example of instances
used through composition;
\item[io.SerializedString $\leftarrow$ io.JsonStringEncoder] indeed an adapter
pattern application, although the adaptee backing field is \textit{private
static final}. \textbf{io.SerializedString} is a class that wraps a String
and allows it to be encoded using the \textbf{io.JsonStringEncoder} static
instance, storing the result and re-using it in case of multiple
serialization request (a tecnique similar to memoization). Therefore, the
main purpose of this adapter is not to adapt against any interface, but to
wrap the functionality of the adaptee and store its results for re-use;
\item[util.DefaultPrettyPrinter $\leftarrow$
util.DefaultPrettyPrinter\$Indenter (2 fields)] false positives, both
enclosed fields are simply used in a composition relationship.
\end{description}
\subsection{Decorator Pattern}
Decorator pattern lets you dynamically change the behaviour of an object at run
time by wrapping them in an object of a decorator class.
\textit{Pattern4J} found two instances of the decorator patter,
however we are probably in a case of ambiguity because in the documentation of the \textbf{util.JsonParserDelegate}
is stated that the patter used is a delegation pattern.
\begin{lstlisting}[language=java,label={lst:jsonparserdelegate}, caption={}]
/**
* Helper class that implements
* <a href="http://en.wikipedia.org/wiki/Delegation_pattern">delegation pattern</a>
* for {@link JsonParser},
* to allow for simple overridability of basic parsing functionality.
* The idea is that any functionality to be modified can be simply
* overridden; and anything else will be delegated by default.
*/
\end{lstlisting}
The decorator patter is similar to the delegation patter and the delegation patter is similar to the proxy patter,
in-fact the delegation patter is also known as ''proxy chains``.
We have a mismatch in this case because the decorato pattern uses a lot the delegation pattern to accomplish its task,
so thats why we have a misclassification signalling the decorator pattern and not the proxy patter.
\begin{description}
\item[util.JsonParserDelegate]
is clearly a false positive because the developer stated explicitly the design patter used for the class.
This class extends the \textbf{JsonParser} and fully implements the delegation patter.
\item[util.JsonGeneratorDelegate]
there is no clear statement by the developer if the used designed pattern is different from the one detected by the tool,
but we can make an assumption by looking on the authors contribution to the file.
\begin{lstlisting}[language=bash, caption={Display the number of commits on a file and sort it by the number of commits.},label=lst:gitcommand]
git shortlog -n -s -- $filename$
\end{lstlisting}
Using the command presente in Listing \ref{lst:gitcommand} we can see the number of authors of a single file
and the result is sorted by the number of commits.
By running the command on \textbf{util.JsonParserDelegate} and \textbf{util.JsonGeneratorDelegate} we can clearly see that the top contributor to the file is the same for both the classes, the out-put of the command are presented for the classes in Listing \ref{lst:gitcommandparser} and Listing \ref{lst:gitcommandgenerator}.
\begin{lstlisting}[caption={Command of Listing \ref{lst:gitcommand} executed on util.JsonParserDelegate class},label=lst:gitcommandparser]
git shortlog -n -s -- JsonParserDelegate.java
33 Tatu Saloranta
3 Tatu
1 Andrey Somov
1 LokeshN
\end{lstlisting}
\begin{lstlisting}[caption={Command of Listing \ref{lst:gitcommand} executed on util.JsonGeneratorDelegate class}, label=lst:gitcommandgenerator]
git shortlog -n -s -- JsonGeneratorDelegate.java
38 Tatu Saloranta
2 Cowtowncoder
1 Andrey Somov
1 Logan Widick
1 Martin Steiger
1 Oleksandr Poslavskyi
1 Q.P.Liu
1 Volkan Yaz${\i}$c${\i}$
\end{lstlisting}
Is more an empirical assumption, we can do a deeper analysis looking at the statistics of modified lines,
but in general the structure of the \textbf{util.JsonGeneratorDelegate} is very similar to the one in \textbf{util.JsonParserDelegate},
so is more probable that is a false positive.
This class extend the \textbf{JsonGenerator} class and it is implementing the delegate patter with a modification.
In the constructor of the class we have a boolean parameter \textit{delegateCopyMethods},
it is used in \textbf{writeObject, writeTree, copyCurrentEvent, copyCurrentStructure} methods to signal if delegate the function call to the delegator or to the super class.
\end{description}
\subsection{Bridge Pattern}
\textit{Pattern4J} found one instance of the bridge pattern.
The bridge pattern emphasises composition rather than inheritance.
Implementation details are moved from one hierarchy to another with separate hierarchies of objects.
Looking on the context of the library that is intended to be used as a core for a JSON parser
and by looking at the class implemented it make even more sense.
The class detected is \textbf{json.JsonGeneratorImpl} and the class used is \textbf{io.CharacterEscapes}.
The \textbf{io.CharacterEscapes} class define the escape character used in the file
and is particularly relevant to have this abstraction because there are different standards for string escaping on different systems.
For example on unix systems the escape sequence is ``\textbackslash n'',
where on Microsoft operating systems the escape sequence is ``\textbackslash r\textbackslash n''
and on IBM mainframe systems the escape sequence is ``\textbackslash 025''.
The class \textbf{json.JsonGeneratorImpl} is then extended by \textbf{json.WriterBasedJsonGenerator} and
\textbf{json.UTF8JsonGenerator}.
For the \textbf{json.WriterBasedJsonGenerator} class uses \textbf{Java.io.Writer},
so the the system automatically handles character encoding.
For the \textbf{json.UTF8JsonGenerator} the character encoding need to be managed manually because it works on an output stream.
\section{Behavioral Patterns}
\subsection{State Pattern}
Among the design patterns \textit{Pattern4J} detects, the state pattern is
detected in 5 classes. The state pattern is a variation of the strategy pattern
where the concrete strategy used by the matching context is determined by the
state of a finite state machine the context class implements. In other words,
the state pattern chooses the concrete strategy to use through the state of the
context.
By analyzing the \textit{Pattern4J} results and the code, we can say that all
the instances of the state pattern the tool finds are false positives. Namely:
\begin{description}
\item[util.DefaultPrettyPrinter \textit{\_inputDecorator} and
\textit{\_outputDecorator}] are fields flagged as states, thus flagging the
class as a state pattern instance. However, no ``state'' akin to a
finite-state machine is maintained by the class to determine which
implementation of these fields to invoke. What is detected are more likely
lightweight implementations of the strategy pattern, since these fields can
be mutated through matching getters and setters. Additionally, the
documentation of each of the matching \textit{...Decorator} field types
(namely interfaces) states that implementors are meant to be algorithms to
pre-process input before the formatting process (a feature labeled as
``decorator'' w.r.t.\ the library, not to be confused with the decorator
pattern);
\item[util.DefaultPrettyPrinter \_objectIndenter and \_arrayIndenter] are
false positives too, and are likely strategy patterns too for the reasons
described above.
\item[util.DefaultPrettyPrinter \_rootValueSeparator] is flagged as a state
field too, however the field is simply a boxed \textit{String-like}
immutable data structure (i.e.\ \textit{SerializableString}) that is
swapped during the pretty-printer parsing logic;
\item[json.WriterBasedJsonGenerator \_currentEscape] is a false positive for
the same reasons described above.
\end{description}
\subsection{Strategy Pattern}
\textit{Pattern4J} detects no instance of the strategy pattern in Jackson,
however the previous section regarding the state pattern referenced some false
positives that were indeed applications of this pattern. Due to the flexibility
of Jackson, there are many more instances of the strategy pattern to configure
and customize the serialization and deserialization pipeline in several stages.
\subsection{Template Method Pattern}
Due to the extendibility of Jackson, it is of no surprise that the template
method pattern is used extensively to create a class hierarchy that provides
rich interfaces while maintaining behavioural flexibility. \textit{Pattern4J}
correctly detects several instances of the pattern, namely
\textbf{JsonStreamContext}, \textbf{JsonGenerator}, \textbf{type.ResolvedType},
\textbf{JsonParser}, \textbf{base.ParserBase}, \textbf{base.GeneratorBase},
\textbf{base.ParserMinimalBase}. All these classes implement several concrete
\textit{public} methods throwgh the use of \textit{protected abstract} methods.
Although the concrete (i.e.\ the template) methods are usually not vary complex
(as the pattern example shown in class), they still follow the principles of the
template method pattern. We show as an example some template methods found in
\textbf{base.ParserBase}:
\begin{lstlisting}[caption=Template method \textit{void close()} and step
methods \textit{void \_closeInput()} and \textit{void \_releaseBuffers()} in
\textbf{base.ParserBase}., language=java]
@Override public void close() throws IOException {
if (!_closed) {
// 19-Jan-2018, tatu: as per [core#440] need to ensure no more data
// assumed available
_inputPtr = Math.max(_inputPtr, _inputEnd);
_closed = true;
try {
_closeInput();
} finally {
// as per [JACKSON-324], do in finally block
// Also, internal buffer(s) can now be released as well
_releaseBuffers();
}
}
}
protected abstract void _closeInput() throws IOException;
protected void _releaseBuffers() throws IOException {
/* implementation omitted */
}
\end{lstlisting}
Here the pattern is slightly modified by providing a default implementation of
\textit{void \_releaseBuffers()}. In this case, child classes occasionally
override the method with a body first calling \textit{super()} and then adding
additional buffer release code after.
\section{Conclusions}
From the analysis of the selected project, \textbf{FasterXML/jackson-core},
we can clearly see that a the patterns implemented are deviating from the standardised definitions.
For example in the case of the singleton pattern ,
we can see that we have public constructors in classes implementing this pattern and
those constructors are used during testing.
To see the real benefits of the patterns implemented in this project we need to analyse the modules on top,
because this project is a core library for a more larger project.
Being a often used library and a stable library,
we can assume that patterns implemented by this project are doing their work properly,
despite the deviation from the standardised definitions.
From the results obtained from the tool \textit{Pattern4J},
we can see that we have some imprecision for the classifications of the patterns.
The most striking found is for the decorator pattern,
the developer stated in the documentation that the design patter used is a delegation patter.
From a manual analysis of a subset of all the classes of the project,
we can wee that we have slightly more false positive rate compared to the true positive values,
so we can consider that in our case the tool have a precision lower that $50\%$.
The result are reported in Figure \ref{fig:conf},
in Sub-figure \ref{fig:conf:tab} are presented the classes analysed manually
and in Sub-figure \ref{fig:conf:mat} is presented the confusion matrix computed using the
results presented in Sub-figure \ref{fig:conf:tab}.
\end{document}