I hope, you have
already read "Preface" of this post. Also don't miss to refer corresponding
example java code (not for production, illustrative purposes only) to
understand each fundamental topic.
About Building Object Oriented System
- Its all about Objects - Instantiating, Communicating, Managing, Extending, Monitoring…
- In most of the cases,
Everything is done by Developer.
- What developers end up
without knowledge of object oriented design principles and patterns? --- Answer is "Complex Code" –
which is hard to maintain, extend and reuse. Because of,
- Writing to much boilerplate
- Duplication
- Entangled interfaces
- Complicated dependencies
- Rigid, Fragile and Immobile
code
ABC of Object Oriented Design and Responsibilities
- OO Design
- Identify classes and objects
- Decide methods belong to
what class/object and how they interact
- Responsibilities
- Assigned to classes/methods
during design
- Translation of
responsibilities into classes/methods is influenced by the granularity of
responsibility
- Responsibilities are not
same as methods, but methods fulfill responsibilities
- Two Types of
responsibilities - Doing & Knowing
Goal of a Object Oriented Design
- Reusability, Flexibility, Extendibility, Maintainability...
Characteristics of Bad Design / Design Smell
Yes, designs or code
can smell. They point to problems with the structure of code: class
organization, relationships, collaborations/dependencies, responsibilities etc.
Software OOP fundamentals and design principles represent a set of guidelines
that helps us to avoid having a bad design.
Some of key
characteristics of bad design are,
- Rigidity = It is hard to change
because every change affects too many other parts of the system. That
means, difficult to add new features.
- Fragility = When you make a change,
unexpected parts of the system break. That means, unable to identify
impact of the change.
- Immobility = Code is hard to reuse in
another application because it cannot be disentangled from the current
application. That means, no reusability.
- Viscosity = Going with the flow of bad
practices already being present in the code.
- Needless
Complexity = the
design adds additional structure that provides no direct benefit.
- Opacity = It is hard to read and
understand. The code does not
express its intent well.
OOP Fundamentals
Abstraction = Looking only at the information
that is relevant at the time.
- Abstraction is the process
or result of generalization by reducing the information content of a
concept or an observable phenomenon, typically in order to retain only
information which is relevant for a particular purpose.
- Functional abstraction -
means that a function can be used without taking into account how the
function is implemented.
- Data Abstraction - means
that data can be used without taking into account how the data are
stored.
|
- The process of binding or
wrapping the data and the codes that operates on the data into a single
entity. This keeps the data safe from outside interface and misuse. One
way to think about encapsulation is as a protective wrapper that
prevents code and data from being arbitrarily accessed by other code
defined outside the wrapper.
- For example, if a field is
declared private, it cannot be accessed by anyone outside the class,
thereby hiding the fields within the class.
|
- The process where one
object acquires the members of another; plus can have its own.
- For example, Dog (subclass)
is-a of type Animal (superclass). So Dog can inherit (reuse) members of
Animal class; plus it can have
its own new behavior and properties.
|
- How Polymorphism is
supported in Java? - In terms of interface, inheritance, method
overloading and method overriding. (Method overloading and
method overriding uses concept of Polymorphism in Java where method
name remains same in two classes but actual method called
by JVM depends upon object at run time and done
by dynamic binding in Java. In case of overloading method signature
changes while in case of overriding method signature remains same and
binding and invocation of method is decided on runtime based on actual
object. This facility allows Java programmer to write very flexibly and
maintainable code using interfaces without worrying about
concrete implementation. One disadvantage of using Polymorphism in
code is that while reading code you don't know the actual type
which annoys while you are looking to find bugs or trying to
debug program. But if you do Java debugging in IDE you will
definitely be able to see the actual object and the method call and
variable associated with it.)
- Where to use Polymorphism
in code? - You should use super type in method argument, variable name
and return type of method.
- Parameteric Polymorphism in
Java - Java started to support parametric polymorphism with
introduction of Generic in JDK1.5. Collection classes in JDK 1.5
are written using Generic Type which allows Collections to hold any type
of object in run time without any change in code and this has been
achieved by passing actual Type as parameter.
|
Delegation = hand over the responsibility for
a particular task to another class or method. (example code snippet)
- If you need to use
functionality in another class but you do not want to change that
functionality then use delegation instead of inheritance.
- Classical example of
delegation design principle is equals() and hashCode() method in
Java. In order to compare two object for equality we ask class itself to
do comparison instead of Client class doing that check. Benefit of this
design principle is no duplication of code and pretty easy to modify
behavior.
|
- Aggregation is an
association represents a part of a whole relationship where a part can
exist without a whole. It has a weaker relationship.
- For example, If line-item
HAS-A product, then a line item is a whole and product is a part. If a
line item is deleted, then corresponding product needs not to be
deleted.
|
- Composition is an
association represents a part of a whole relationship where a part
cannot exist without a whole. If a whole is deleted then all parts are
deleted. It has a stronger relationship.
- Favor Composition over
Inheritance.
- For example, if order HAS-A
line-items, then an order is a whole and line items are parts. If an
order is deleted then all corresponding line items for that order should
be deleted.
|
Loose Coupling = Low dependencies between
“artifacts” (classes, modules, components). (example code snippet)
- There shouldn’t be too much
of dependency between the modules, even if there is a dependency it
should be via the interfaces and should be minimal.
- Avoid tight-coupling for
collaboration between two classes (if one class wants to
call the logic of a second class, then they first
class needs an object of second class it means
the first class creates an object of second class).
- Strive for loosely coupled
design between objects that interact.
- Inversion Of Control (IoC)
/ Dependency Injection (DI) - With DI objects are given their
dependencies at creation time by some third party (i.e. Java EE CDI,
Spring DI…) that coordinates each object in the system. Objects aren’t
expected to create or obtain their dependencies—dependencies are
injected into the objects that need them. The key benefit of DI—loose
coupling.
|
- The
responsibilities/methods are highly related to class/module.
- The term cohesion is used
to indicate the degree to which a class has a single, well-focused
responsibilities. Cohesion is a measure of how the methods of a class or
a module are meaningfully and strongly related and how focused they are
in providing a well-defined purpose to the system. The more focused a class is, the
higher its cohesiveness - a good thing.
- A class is identified as a
low cohesive class, when it contains many unrelated functions within it.
And that what we need to avoid, because big classes with unrelated
functions hamper their maintaining. Always make your class small and
with precise purpose and highly related functions.
|
Few principles,
every developer should always keep in mind and apply when writing code.
Interface based design = Coding to an
interface, not to an implementation
- One of the best practices
that object oriented programmers should try to strive for is to write
java classes to interfaces instead of concrete classes.
- Writing to interfaces
reduces coupling and gives a great flexibility in running the unit and
integration tests without having to modify the client code whenever the
implementation of a service component is changed.
- It can achieve code reuse
with the help of object composition.
|
DRY principle = Don't repeat yourself
- Software development
principle to reduce repetition of information of all kinds.
- Every piece of knowledge
must have a single, unambiguous, authoritative representation within a
system.
- Avoid copy-paste of code.
Otherwise change in the code would have to be made in all the places
where its been copied.
- Don't write duplicate code
for "application logic", instead abstract common things
in one place.
- For example - If you use a
hardcoded value more than one time consider making it public
final constant. If you have block of code in more than two place
consider making it a separate method.
|
KISS principle = Keep it simple, stupid /
keep it simple and straightforward
- Simplicity should be the a
goal of design and unnecessary complexity should be avoided.
- For example - If there is a
need of grate manipulations on collections, then don't write your own
complex custom implementation. If you like the "Function"
style, maybe make use of the proven Guava library (which has the
Function interface and many helper methods that work with them on
collections). That is DRY (because you don't repeat yourself, and re-use
code that already exists), and still KISS (because those are well
understood patterns).
|
YAGNI principle = You aren't gonna need it
- A principle of extreme
programming (XP) that states a programmer should not add
functionality until deemed necessary.
- Don't be tempted to write
code that is not necessary at the moment, but might be in the future.
- Recommended to be used in
combination with several other practices, such as continuous refactoring, continuous
automated unit testing and continuous integration.
- See also - Over-engineering
|
AOP = Aspect Oriented Programming
- A programming
paradigm that aims to increase modularity by allowing
the separation of cross-cutting concerns (e.g. logging,
exceptional handling, caching…). Identify the aspects of your
application that vary and separate them from what stays same.
- AOP is a concept and as
such it is not bound to a certain programming language or programming
paradigm. The Java implementation of AOP is called AspectJ. Or Spring AOP can be used.
|
Changes History:
- 6-Apr-2014: Added links for example java code
No comments:
Post a Comment