%in Soweto+277-882-255-28 abortion pills for sale in soweto
Micro Anti-patterns in Java Code
1. Micro Antipatterns in Java code
Ganesh Samarthyam
January 18, 2016
Abstract
1 Descriptions of Micro Antipatterns
1.1 Degenerate Classes
1.1.1 Constant Interface
Constant interfaces have only static final data members declared in them with-
out any methods. This antipattern violates the rule “Use interfaces only to
define types” (item 19 in [1]).
Here is a quick summary of this antipattern described in [1]. When an
interface has only constants (public static final fields), it is convenient for classes
to implement the interface and directly access the members without any explicit
qualification of the class name. A constant interface has many problems when
the constants represent some details about the implementation. So, it leads to
many problems: 1) the implementation details (because of value of constants)
gets exported to public API of the class. This hinders evolution of the class since
it is not possible to remove the interface in future (that would result in binary
incompatibility). If the class implementing the constant interface is non-final,
all the subclasses get access to the constants and hence their namespaces get
polluted.
The solution for this antipattern depends on kind of constants present in the
constant interface: the constants can get added as members in the class, related
can be rewritten as enums, or a utility class can be created to hold these values.
The interface java.io.ObjectStreamConstant is an example for this antipat-
tern.
1.1.2 Pseudo Class
This is an antipattern noted under “Base Classes” in “Inheritance” category in
[5]. Here is the description from [5]:
A Pseudo Class is an abstract class, with no instance fields, and such
that all of its instance methods are abstract; static data members
1
2. and methods are permitted. A Pseudo Class could be mechanically
rewritten as an interface. For instance, class Dictionary, the abstract
parent of any class which maps keys to values, could be rewritten as
an interface.
Pseudo Class is an “anti-pattern” and is not so common; its preva-
lence is only 0.4%.
1.1.3 Global Variable Class
The class has one public static (non-final) field. Since its freely available for
modification by anyone, it becomes an equivalent to a C-like global variable,
with only difference that the variable name is prefixed by the class name, thus
avoiding name-clashes.
Contrast global variable class with the Canopy pattern [5]: “A Canopy is a
class with exactly one instance field which can only changed by the constructors
of this class”. Contrast to Canopy, a Global Variable Class is not an immutable
class; also the field is not an instance field - it is a static (non-final) field.
1.1.4 Global Function Class
A Global Function Class is a public class that has only one static public method
and no other fields or methods; it can have an optional private constructor to
disallow instantiation. It is equivalent to a C like global function, except that
the function needs to be prefixed by the class name to access the function.
1.1.5 C-like Structs
A C-like Struct is a public class with public non-final, non-static data members
and no methods (with an optional constructor). It is difficult to maintain public,
C-like classes, as [1] notes:
Because such classes are accessed by their data fields, they do not
offer the benefits of encapsulation. You cannot change the represen-
tation of such a class without changing its API, you cannot enforce
any invariants, and you cannot take any auxiliary action when a field
is modified.
So, such C-like structs are not bad if it is non-public since its easier to change
the implementation if necessary.
Record pattern and Data Manager pattern are very similar to this anti-
pattern and is described in [?] as patterns. To quote from [?], “A class matches
the Record micro pattern if all of its fields are public and if has no methods other
than constructors and methods inherited from Object”. Also, “we say that a
class is a Data Manager if all of its methods (including inherited ones) are either
setters or getters”.
[1] covers this topic in item 19, ‘Replace structures with classes’. It notes:
2
3. Several classes in the Java platform libraries violate the advice that
public classes should not expose fields directly. Prominent exam-
ples include the Point and Dimension classes in the java.awt package.
Rather than examples to be emulated, these classes should be re-
garded as cautionary tales.
What is the difference between C-like Struct antipattern and Record pattern?
C-like Struct is a public class and not a package-private or nested private class
whereas Record pattern does not make this distinction.
This pattern is similar to ‘indecent exposure’ code smell, which is a general
problem about exposing mutable fields; C-like Struct is specifically about public
classes with only mutable fields.
1.2 Inheritance
1.2.1 Concrete Root
If the base class of an inheritance hierarchy is a concrete class, then it is a Con-
crete Root antipattern. Experienced designers almost always have an abstract
class as the root of their class hierarchy as in the rule “The top of the class
hierarchy should be abstract” (rule 6 in [2]). In the heuristic “All base classes
should be abstract classes” (heuristic 5.7 in [3]), the context is a hierarchy,
meaning that roots of an inheritance tree should be abstract. It is considered
as an antipattern in this paper to violate this heuristic/rule.
In general, it is good to derive from an abstract class instead of a concrete
class. However, it is not practical to say that every base class should always be
an abstract class; it is acceptable and often useful to have a concrete base class.
When it comes to a class hierarchy with large number of derived classes, then
it is better to have an abstract rootclass. The rationale is this. Inexperienced
programmers tend to extend existing classes by adding more functionality, and
hence often result in hierarchies rooted with concrete classes. For this reason,
this antipattern is likely the most prevalent one. Experienced designers find
abstractions from concrete classes in such hierarchy and refactor them to have
an abstract class as the base class. The refactoring Extract Interface is also a
good choice.
What is the depth of inheritance that we can use as a limit to consider
making the root class abstract? Six seems to be a good limit. To quote from
[3], “In theory, inheritance hierarchies should be deepthe deeper, the better.”
But: “In practice, inheritance hierarchies should be no deeper than an average
person can keep in his or her short-term memory. A popular value for this depth
is six.” So, when the depth of inheritance is more than 6, and if the root class
is concrete, we consider the concrete root class as an antipattern.
An obvious exception for this antipattern is Object class, which is a concrete
class.
3
4. 1.2.2 Abstract Leaf
Abstract classes are most meaningful and useful when we have them near the
roots of a hierarchy. In another extreme, it is meaningless to have them as
leaves in a hierarchy: they are useless and can be eliminated; abstract leaf
classes usually indicate a design mistake.
1.2.3 Illegal Abstract Inheritance
An abstract class shold not derive from a concrete class. The fix is to make
both of the classes abstract or remove the inheritance relationship.
An obvious exception for this antipattern is when Object class is the base
class; after all, all abstract classes derive from Object class, which is a concrete
class.
The name of this antipattern is from [6].
1.2.4 Orphan Abstract
An abstract class does not have any concrete derived classes. An abstract class
can be used meaningfully only when implemented by concrete derived classes.
If the abstract class is not useful, it can be removed. If the class can be
instantiated consider, making it concrete. If it represents an useful abstraction,
provide concrete one or more classes that implement that abstract class.
1.2.5 Forgotten Interface
A class implements all the methods with same signatures as the methods listed
in an interface. It is a likely mistake that the class intended to implement an
interface, but forgot to list the interface as its base type. Consequence of this
antipattern is that the objects of the class cannot be treated as subtype of
the interface and hence the benefit of subtyping/runtime polymorphism is not
exploited.
1.2.6 Shrinker
A derived class should extend the functionality of a base class. However, a
common mistake in inheritance is to shrink the functionality provided by the
base class. A Shrinker class restricts the methods inherited from the base class;
it also does not add any more methods than the ones provided in the base class
or interfaces.
Syntactically all the non-private methods in the base class are avaialble in the
derived class. However, semantically, a progammer can disallow or nullify the
effect of a base class method in the derived class. For example, by overriding
the method by throwing an exception, it is possible to disallow an operation
provided in the base class. Another example is providing an empty overridden
method in the derived class when the base class method has some functionality
(one or more executable statements in it). This definition of Shrinker covers
4
5. only these two categories of restricting a method in the derived class that was
declared in the base class.
1.3 Class Dependency
1.3.1 Lonely Class
The class does not depend or use any other class; also, no other classes depend
or use the class.
This might not really be a mistake/error in design; however, it is rare to see
a very independent class that neither uses other classes nor used by any other
classes. So, it is possible that its a design mistake.
1.3.2 Circular Dependency
Circular dependency happens when two or more classes are dependent on each
other.
Classes that are dependent on each other have many problems. For example,
when classes A and B dependent on each other, a serious problem can happen
when construction of A object triggers construction of B object, resulting in a
deadlock (an infinite loop). Changes in one of the classes in ciruclar dependent
classes often result in changes in other dependent classes; so such classes should
always be maintained together, which is a maintenance problem.
1.4 Others
1.4.1 Tagged class
This antipattern is based on a mistake often made by programmers from struc-
tured programming background. They often define classes like structs and in-
stead of providing an inheritance hierarchy of related types and use runtime
polymorphism, they often have an enumeration to list types and have switch-
case statements (or chained if-else statements) to distinguish between the types
to do type specific operations.
The term ‘tag class’ is used to describe this antipattern in [1]; it is “a class
whose instances come in two or more flavors and contain a tag field indicating
the flavor of the instance”.
A detect a tag class in code, check is made for the following features:
• An enumeration (or public static final ints) to indicate the flavour of the
instance
• A field to store the value of the enum/int; typically, the constructor sets
this field
• A switch statement in one or more methods which execute code based on
the tag value
Obvious refactoring of the tagged class is a class hierarchy.
5
6. 1.4.2 Clone class
A Clone class has an exact replica of another class (unrelated by inheritance).
Essentially, only the name of the class is different, but all its members, their
signature, accessibility etc. are same. A constraint is that atleast one member
should be present in the class. An exception is that order of its members might
be different.
If two or more classes have common data and behavior, they should inherit
from a common class that captures those data and behavior. So, one fix is
to check if it is possible to provide a common base class and make the clone
classes as derived classes. Clone classes often happen because of copy-paste
programming done by novice programmers; in that case, it is better to remove
such duplicate classes and instead use a unique class.
References
[1] Joshua Bloch, Effective Java, 3rd Edition, Prentice Hall, 2008.
[2] Ralph E. Johnson and Brian Foote, Designing Reusable Classes, Journal of
Object-Oriented Programming, June/July 1988.
[3] Arthur J. Riel, Object-Oriented Design Heuristics, Addison Wesley, 1996.
[4] Anthony J.H. Simons, The Theory of Classification, Part 15: Mixins and the
Superclass Interface, Journal of Object Technology, Nov-Dec 2004.
[5] Joseph (Yossi) Gil and Itay Maman, Micro patterns in Java code, ACM SIG-
PLAN Notices, 2005.
[6] Siemens Design Advisor tool.
6