0% found this document useful (0 votes)
73 views27 pages

Binus University Code ReengineeringEncapsulation Smell

This document discusses various code smells related to encapsulation principles in object-oriented design. It describes deficient encapsulation, leaky encapsulation, missing encapsulation, and unexploited encapsulation smells. For each smell, it provides a definition, examples, potential impacts, and strategies for refactoring code to address the smells. The goal is to apply encapsulation principles more effectively to improve code understandability, changeability, extensibility, reusability, and reliability.

Uploaded by

raymond setiawan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
73 views27 pages

Binus University Code ReengineeringEncapsulation Smell

This document discusses various code smells related to encapsulation principles in object-oriented design. It describes deficient encapsulation, leaky encapsulation, missing encapsulation, and unexploited encapsulation smells. For each smell, it provides a definition, examples, potential impacts, and strategies for refactoring code to address the smells. The goal is to apply encapsulation principles more effectively to improve code understandability, changeability, extensibility, reusability, and reliability.

Uploaded by

raymond setiawan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 27

Subject : CODE REENGINEERING

Year : 2017

Encapsulation Smell
Session 17 & 18
Learning Outcomes

LO 2: Apply Advanced refactoring and its application

COMP6047 - Algorithm and Programming


Sub Topics

- Deficient Encapsulation
- Leaky Encapsulation
- Missing Encapsulation
- Unexploit Encapsulation

COMP6047 - Algorithm and Programming


Encapsulation Smell

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

Hide implementation details. An abstraction exposes to its clients only


“what the abstraction offers” and hides “how it is implemented.” The latter,
that is, the details of the implementation include the internal representation
of the abstraction (e.g., data members and data structures that the
abstraction uses) and details of how the method is implemented (e.g.,
algorithms that the method uses).

Hide variations. Hide implementation variations in types or hierarchies.


With such variations hidden, it is easier to make changes to the abstraction’s
implementation without much impact to the clients of the abstraction.
Design Smell and Violated Encapsulation
Technique

Violated Enabling Technique Design Smell


Hide Implementation Detail Deficient Encapsulation, Leaky
Encapsulation
Hide Variation Missing Encapsulation, Unexploited
Encapsulation
Deficient Encapsulation

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

A simple example of Deficient Encapsulation is from the java.awt.Point class. This


class has public x and y fields in addition to public getter and setter methods for
these fields (see Figure; only relevant members are shown in this figure). The
class exhibits Deficient Encapsulation, since the accessibility of its members is
more per- missive (i.e., members are declared public) than actually required (i.e.,
they should have been declared private).
Deficient Encapsulation Example Refactoring

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

Understandability—One of the main objectives of the principle of encapsulation


is to shield clients from the complexity of an abstraction by hiding its internal
details.

Changeability and Extensibility—Since the declared accessibility of members of


the abstraction is more permissive, the clients of the abstraction may depend
directly upon the implementation details of the abstraction.

Reusability—In the presence of Deficient Encapsulation smell, clients may


directly depend on commonly accessible state.

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.

Reliability—When an abstraction provides direct access to its data members, the


responsibility of ensuring the integrity of the data and the overall abstraction is
moved from the abstraction to each client of the abstraction.
Practical Consideration (Reification)

Lenient access in nested or anonymous classes

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

Consider a class CustomListBox, which is a custom implementation of a ListBox UI


control. One of the operations that you may perform on a ListBox object is to sort it.
Figure shows only the sort-related methods in CustomListBox class. The problem
with this class is that the name of the public method bubbleSort() exposes the
implementation detail that the CustomListBox implementation uses “bubble sort”
algorithm to sort the list.
Leaky Encapsulation Example Refactoring

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

Understandability—One of the main objectives of the principle of encapsulation


is to shield clients from the complexity of an abstraction by hiding its internal
details.

Changeability and Extensibility—When an abstraction “exposes” or “leaks”


implementation details through its public interface, the clients of the abstraction
may depend directly upon its implementation details.

Reusability—Clients of the abstraction with Leaky Encapsulation smell may


directly depend upon the implementation details of the abstraction.

Reliability—When an abstraction “leaks” internal data structures, the integrity of


the abstraction may be compromised, leading to runtime problems.
Practical Consideration (Reification)

Low-level classes

Consider an example of embedded software that processes and plays audio in a


mobile device. In such software, the data structures that store metadata about
the audio stream (e.g., sampling rate, mono/stereo) need to be directly exposed
to the middleware client. In such cases, when public interface is designed
purposefully in this way, clients should be warned that the improper use of those
public methods might result in violating the integrity of the object.
Missing Encapsulation
Component Description
Definition This smell occurs when implementation variations are
not encapsulated within an abstraction or hierarchy.
Rationale The Open Closed Principle (OCP) states that a type
should be open for extension and closed for
modification. In other words, it should be possible to
change a type’s behavior by extending it and not by
modifying it (see case study below). When the
variations in implementation in a type or a hierarchy
are not encapsulated separately,
Potential Causes • Lack of awareness of changing concerns
• Lack of refactoring
• Mixing up concern
• Naïve design decision
Missing Encapsulation Example
Assume that you have an existing Encryption class that needs to encrypt data using an
algorithm. There are various choices for such an algorithm including DES (Data
Encryption Standard), AES (Advanced Encryption Standard), TDES (Triple Data
Encryption Standard), etc. Figure 4.9 illustrates how the Encryption class encrypts
data using the DES algorithm. Suppose a new requirement is introduced that
requires data to be encrypted using the AES algorithm. A novice developer may
come up with the design shown in Figure 4.10, in which he introduces different
methods such as encryptUsingDES() and encryptUsingAES() in the Encryption class.
Missing Encapsulation Example Refactoring

The Encryption class would inherit from DESEncryptionAlgorithm or


AESEncryptionAlgorithm as needed and use the encrypt() method within.
However, the problem with this solution is that the Encryption class would
be tied to the specific encryption algorithm at compile time. A more
serious problem is that the classes would not share an IS-A relationship,
indicating a Broken Hierarchy smell
Impacted Quality

Understandability—When there are numerous services (many of which may not


be used) embedded in an abstraction, the abstraction becomes complex and
difficult to understand.

Changeability and Extensibility—When variations in implementation in a type or


a hierarchy are not encapsulated separately, clients are tightly coupled to these
different variations.

Reusability—When services are embedded within an abstraction, the services


cannot be reused in other contexts.
Practical Consideration (Reification)

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

We describe here a potential refactoring for the ColorModel class that


was discussed above. The refactoring here could be that instead of the
ColorModel class holding the transferType variable of type int, we
could use a DataBuffer instance instead. Thus,
Refactor to
Impacted Quality

Changeability and Extensibility—A hierarchy helps encapsulate variation, and


hence it is easy to modify existing variations or add support for new variations
within that hierarchy without affecting the client code.

Testability—When this smell is present, the same code segments may be repli-
cated across the client code.

Reliability—A common problem when using type-based checking is that pro-


grammers may overlook some of the checks. Such missing checks may manifest
as defects.
Practical Consideration (Reification)

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.

COMP6047 - Algorithm and Programming

You might also like