Binus University Code ReengineeringEncapsulation Smell
Binus University Code ReengineeringEncapsulation Smell
Year : 2017
Encapsulation Smell
Session 17 & 18
Learning Outcomes
- Deficient Encapsulation
- Leaky Encapsulation
- Missing Encapsulation
- Unexploit Encapsulation
Consider the example of a car. Do you need to know exactly how the engine
of the car works in order for you to be able to drive it? Is it really required for
you to know how the anti-braking system (ABS) of your car works? Well,
you may know these details (if you are an automobile engineer), but these
details are not required for you to drive the car
Enabling Technique for Encapsulation
Principles
Component Description
Definition This smell occurs when the declared accessibility of
one or more members of an abstraction is more
permissive than actually required. For example, a
class that makes its fields public suffers from
Deficient Encapsulation.
Rationale This smell occurs when the declared accessibility of
one or more members of an abstraction is more
permissive than actually required. For example, a
class that makes its fields public suffers from
Deficient Encapsulation.
Potential Causes • Easier testability
• Procedural Thinking in Object Oriented Context
• Quick-fix solution
Deficient Encapsulation Example
Make the data members in classes Point and SizeRequirements private and provide
suitable accessor and mutator methods for the fields. For fields such as alignment
in SizeRequirements class, provide the necessary validation for acceptable values in
the mutator method.
Impacted Quality
Testability—Globally accessible data and data structures are harder to test, since
it is very difficult to determine how various code segments access or modify the
common data.
Performance considerations
Leaky Encapsulation
Component Description
Definition This smell arises when an abstraction “exposes” or
“leaks” implementation details through its public
interface. Since implementation details are exposed
through the interface, it not only is harder to change
the implementation but also allows clients to directly
access the internals of the object (leading to
potential state corruption).
Rationale For effective encapsulation, it is important to
separate the interface of an abstraction (i.e., “what”
aspect of the abstraction) from its implementation
(i.e., “how” aspect of the abstraction).
Potential Causes • Lack of awareness of what should be hidden
• Viscocity
• Use of fine-grained interface
Leaky Encapsulation Example
The suggested refactoring for the CustomListBox example is to replace the method
name bubbleSort() with sort() (see Figure 4.8). With this, the sort() method can
internally choose to implement any suitable sorting algorithm for sorting the
elements in the CustomListBox. For instance, the class CustomListBox can internally
use Strategy pattern to employ the relevant algorithm at runtime.
Note that this class is part of the public API, so changing the method name will
break the clients of the class. A work-around, to address this problem and the
smell at the same time, is to introduce a new sort() method and deprecate the
existing bubbleSort() method. Design is hard; API design is harder!
Impacted Quality
Low-level classes
None
Unexploited Encapsulation
Component Description
Definition This smell arises when client code uses explicit type
checks (using chained if-else or switch statements
that check for the type of the object) instead of
exploiting the variation in types already encapsulated
within a hierarchy.
Rationale The presence of conditional statements (such as
switch-case and if-else) in the client code that check a
type explicitly and implement actions specific to each
type is a well-known smell.
Potential Causes • Procedural Thinking in Object Oriented Language
• Lack of application of object-oriented principles
Unexploited Encapsulation
Example
In JDK, the hierarchy rooted in the abstract class DataBuffer is designed to wrap data
arrays of various primitive types. DataBuffer’s subclasses DataBuffer- Byte, DataBufferDouble,
DataBufferFloat, DataBufferInt, DataBufferShort, DataBufferUShort provide support for data arrays
of specific primitive type (see Figure 4.17). The class DataBuffer also defines the
constants TYPE_BYTE, TYPE_ DOUBLE, TYPE_FLOAT, TYPE_INT, TYPE_SHORT,
TYPE_UNDEFINED, and TYPE_USHORT. The JavaDoc comment for this class states, “the
Java 2D API image classes use TYPE_BYTE, TYPE_USHORT, TYPE_INT,
TYPE_SHORT, TYPE_FLOAT, and TYPE_DOUBLE DataBuffers to store image
data.”
Unexploited Encapsulation Example
Refactoring
Testability—When this smell is present, the same code segments may be repli-
cated across the client code.
None
References
Girish Suryanarayana, Ganesh Samarthyam and Tushar Sharma, Chapter 2 - Design Smells, In
Refactoring for Software Design Smells, edited by Girish Suryanarayana and Ganesh
SamarthyamTushar Sharma, Morgan Kaufmann, Boston, 2015, Pages 9-19, ISBN
9780128013977, http://dx.doi.org/10.1016/B978-0-12-801397-7.00002-3.
M. Fowler and K. Beck, "Bad Smells in Code," in Refactoring: Improving the Design of
Existing Code, Addison-Wesley, 2000
W. Stevens, G. Myers and L. Constantine, "Structured Design," IBM Syst J, vol. 13, no. 2, pp.
115-139, 1974.