Interface Segregation Principle
Previous examples and articles
have shown that interface-based designs are much more effective in making a
software module flexible. In
the Java language, interface provides a way of inheriting the methods, without
inheriting the implementation. The alternative is the inheritance mechanism (used by the
extends
keyword in Java), where you inherit all the public and
protected method implementations by default.
The previous
choice
between inheritance
or composition is a delicate one.
Remember that the interface-based
composition gives you more flexibility in terms of design.
While designing with interfaces is a grand idea, care
should be taken when designing the interfaces themselves. In Java,
interface is the way to guarantee certain behaviors through the
objects that implement the interface. The problem
comes when multiple objects implement the same interface. The Interface
Segregation Principle (ISP) helps you to achieve appropriate separation of
interfaces. Formally stated, the ISP reads:
Many specific interfaces are better than a single general
interface.
Why is this? Look at the following example. Imagine that in
your application you are required to write some Data Access Objects (DAO).
These data objects should support a variety of data sources. Let's consider that
the two main data sources are file and database.
You must be careful enough to come up with an interface-based design, where
the implementation of data access can be varied without affecting the client
code using your DAO object. The following design is a good example of the above
requirements (Figure 3).
Figure 3: The initial DAO class hierarchy
There's another aspect that needs be to considered.
What happens if the data source is read-only?
The methods for
inserting and updating data are not needed. On the other hand, if the
DAO object should implement
the DAO interface, it will have to provide a null implementation for
those methods defined in the interface. This is still acceptable, but the
design is gradually going wrong. What if there
is a need to
rotate the file data source to a different file once a certain amount of data has been
written to the file? That will require
a separate method to add to the DAO interface.
This is just to add the flexibility to the clients using this FileDAO
object to enable them to choose either the
normal append feature to the file data
source or to make use of the improved file rotation feature.
With the DatabaseDAO
implementation now broken, we'll need to change it, to provide a null implementation
of the new method added to the interface. This is against the
Open-Closed Principle.
So, what went wrong? In the basic design,
the fact that the file data access operation and
database access operation can differ fundamentally must be considered.
We defined the behaviors
for both the data access operation, and the database access operation
together in a single interface.
This caused problems at a later stage in the development. It is not necessary to be a guru in Object Oriented System Design,
to solve this problem nor is vast experience in designing software applications needed.
What is necessary is to think of interfaces as the behaviors
to be provided through
particular objects. If two or more objects implementing the interface depict
different sets of behaviors, then they probably cannot subscribe to a single
interface.
When a single interface is designed to support different
groups of behaviors, they are, by virtue, inherently poorly designed, and are called Fat
interfaces. They are called Fat because they grow enormously with each additional
function required by clients using that interface.
Thus, for the problem with
the Data Access Objects, follow the Interface Segregation Principle,
and separate the
interfaces based on the behaviors. The database access classes
and file access classes should subscribe to two separate interfaces. The
following design is obtained by applying the Interface Segregation Principle
(Figure 4).
Figure 4: The final DAO class hierarchy
With this design, the Fat interface symptom
is avoided and
the interfaces clearly delineate their intended purpose. If any imaginary data
access object requires a combination of operations defined in both of these
interfaces, they will be able to do so by implementing both the interfaces.
Conclusion
This article summarizes the concepts of the
Composite Reuse Principle and Interface Segregation Principle. The first principle
addresses a good interface-based system design, while the second addresses
the issues of designing interfaces which are more cohesive, grouped on the behaviors they
support.
This ties up the loose ends in our discussion about the
design of class structure. In my next article, I will explore how
package structure is as important as class structures, and examine a
few principles governing proper package structure.
New on the Java Boutique:
New Review:
Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling
API boasts simplicity, ease-of-integration, a well-rounded feature
set, and it's free!
New Applet:
Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA
sequences into three useful formats.
Elsewhere on internet.com:
WebDeveloper Java
Lots of Java information on webdeveloper.com
WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.
ScriptSearch Java
Hundreds of free Java code files to download.
jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.
|