Singleton pattern rewrite

This commit is contained in:
Claudio Maggioni 2022-10-24 15:13:31 +02:00
parent 8fcf99e6b6
commit a8e2eef258
2 changed files with 47 additions and 22 deletions

Binary file not shown.

View file

@ -168,29 +168,27 @@ 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 17 or above. We used JDK 11 instead, as it is the most recent LTS version of the
JDK to still support this target. JDK to still support this target.
An XML dump of the \textit{Pattern4j} analysis results is included in the An XML dump of the \textit{Pattern4J} analysis results is included in the
submission as the file \textit{analysis.xml}. submission as the file \textit{analysis.xml}.
In the following sections each detection of the \textit{Pattern4J} 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 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, design pattern is varied in any way in its application. For the sake of brevity,
when referring to a class by its fully-qualified nomain name the prefix 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 \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. core project reside in this package or in a sub-package of this package.
\section{Structural Patterns} \section{Structural Patterns}
\subsection{TO REWRITE Singleton Pattern} \subsection{Singleton Pattern}
Ensure a class only has one instance and provide a global point of access to it. \textit{Pattern4J} found a lot of instances of the singleton pattern, namely 13.
The tool found thirteen instances with the Singleton pattern. Doing a deeper However, some discussion is required to understand the ways the Jackson core
analysis of the found instances, we discovered that some results are false project applies this pattern, as the instances found are sometimes wildly
positives. Example, \textit{sym.Name1} has a private different from the standard application or outright false positives.
package constructor and a public static final instance of it, but reading the
documentation, the class represents (short) JSON string literals and is
initialized by client code.
\begin{lstlisting}[caption=Name1 class,language=java] \begin{lstlisting}[caption=The \textit{sym.Name1}
class.,language=java,label=lst:name1]
public final class Name1 extends Name { public final class Name1 extends Name {
private final static Name1 EMPTY = new Name1("", 0, 0); private final static Name1 EMPTY = new Name1("", 0, 0);
private final int q; private final int q;
@ -226,17 +224,44 @@ public final class Name1 extends Name {
} }
\end{lstlisting} \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} \begin{description}
\item[sym.Name1, JsonLocation, DefaultIndenter, \item[sym.Name1, JsonLocation, DefaultIndenter,
util.DefaultPrettyPrinter\$FixedSpaceIndenter] is not a singleton (detected cause of "convenient" default instance given as static final field), the constructor is not used, but the class is extensible util.DefaultPrettyPrinter\$FixedSpaceIndenter] are not singletons and this
\item[JsonPointer, filter.TokenFilter] is like the above, but constructors are protected 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, \item[JsonpCharacterEscapes, util.DefaultPrettyPrinter\$NopIndenter,
Version] a singleton but with a public constructor that is never called in the module code, Version] may be considered variations of the singleton pattern that however
may be called in tests include a \textit{public} constructor that is never called in the module
\item[io.JsonStringEncoder] like above, but the class is final code, but that may be called in tests. Given the \textit{public}
\item[util.InternCache, io.CharTypes\$AltEscapes] constructors, these classes are hardly solid singleton implementations.
actual singleton, thread-unsafe initialization However, we gave the benefit of the doubt to Jackson developers as the use
\item[io.ContentReference] like above, but constructor is protected 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} \end{description}
\subsection{Abstract Factory Pattern} \subsection{Abstract Factory Pattern}
@ -273,7 +298,7 @@ A manual search in the source code produced the following results:
TBD TBD
\subsection{Decorator Pattern} \subsection{TBD Decorator Pattern}
Decorator pattern lets you dynamically change the behavior of an object at run time by wrapping them in an object of a decorator class. Decorator pattern lets you dynamically change the behavior of an object at run time by wrapping them in an object of a decorator class.
(com.fasterxml.jackson.core omitted for brevity) (com.fasterxml.jackson.core omitted for brevity)
@ -283,7 +308,7 @@ Decorator pattern lets you dynamically change the behavior of an object at run t
\item[JsonParser] \item[JsonParser]
TBD TBD
\end{description} \end{description}
Only in Pattern4j Only in Pattern4J
\subsection{Bridge Pattern} \subsection{Bridge Pattern}
TBD TBD
@ -341,7 +366,7 @@ pattern);
\end{description} \end{description}
\subsection{Strategy Pattern} \subsection{Strategy Pattern}
\textit{Pattern4j} detects no instance of the strategy pattern in Jackson, \textit{Pattern4J} detects no instance of the strategy pattern in Jackson,
however the previous section regarding the state pattern referenced some false however the previous section regarding the state pattern referenced some false
positives that were indeed applications of this pattern. Due to the flexibility 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 of Jackson, there are many more instances of the strategy pattern to configure