We have mentioned the basic concept of Object-Oriented, but it seem to be not enough for a good software since we still need somethings else – we need good design and architecture. What are them? Is there any hint for us to have good design and architecture?
To answer these questions are not easy tasks. We may need to read thousands of papers and get much experience to know what are the good software design and architecture, since they are not simple concepts. However, they are all come from the same base, that is Object-Oriented principle or we can call them design principles.
Why need OO principles?
Basic syntax of an OOP is not hard to learn, the issues is how we can enhance the program in order to leverage the advantages of OO. You may already learn something about Patterns such as GoF, they are reusable solutions. In fact, they are all come from basic OO principles. Fortunately, there are a few of them which are easy to follow.
Overview
Poor design and programming is everywhere, it make the OOP seems to be not a good stuff.
Two main issues are always come with OOP, they are coupling and cohesion.
coupling is the degree of dependencies between two modules(usually classes or components) and
cohesion is how diverse are the things inside a module. Two main goals for better software are
- highly cohesive modules.
- Loosely coupled modules
Let us discuss a bit more on coupling and cohesion at first.
Coupling
Modules have to be realted in order to compete task or we can think they have to interact with each other, so they can provide functionalities to others, Modules relate with the followings way:
- Invoke operations (function call)
- Passing data
- Defined in terms of each other
It is clear that coupling is needed but we should always keep them simple. Moreover, coupling should be a direct connection and we should give enough flexibility to the coupling.
cohesion
It mean class should represent a single abstraction or it should address a single general responsibility. With the procedural programming practice, we often make a bad OO modules, that may lead the followings problems
- Hard to understand
- one-to-one relationship often exists, too many connection / dependencies.
- Classes hard to change
- Classes often need to modified.
- Performance issue
The object-oriented principles are going to help us to write flexible and better code by achieving high cohesion and low coupling.
Common OO principles
Real-world problems can be fixed according sound principles.
Followings are some common OO principles :
Open-Closed Principle (OCP)
A module (class) should be open for extension but closed for modification"
(originally by Bertrand Meyer).
This principle describes that classes should be open for extending without requiring modification. That is to extend the behaviour of a system when responding to changes by adding new code without modifying the existing code. Abstraction and also polymorphism by subtype are the keys to the Open Closed Principle.
Single-Responsibility Principle (SRP)
A class should have only one reason to change (originally from Martin).
It is a matter of cohesion. A responsibility is “a reason for change.” and axes of change. If the class has two responsibilities, they are coupled in the design, and so have to change together. Simple, yet hard to get right.
We often use delegation to achieve SRP.
Interface Segregation Principle (ISP)
Many client-specific interfaces are better than one general purpose interface. (Robert Martin)
If a class has several different usage, create separate (narrow) interfaces for each usage. It should be better than all usage share the same, large interface. Clients can be as small as possible and as coherent an interface as possible. large interfaces lead to inadvertent couplings and may add dependencies between classes.
Liskov Substitution Principle (LSP)
Subclasses should be substitutable for their base classes. (originally by Barbara Liskov)
A client of a base class instance should still work with the instance of a derived class instead. A derived class should have some kind of specialized behaviour, it should provide the same services as the superclass with some variety in the behaviour only. The contract of the base class must be honoured by the derived class.
If this principle is violated, the Open-Closed Principle will also to be violated too.
Dependency Inversion Principle (DIP)
Depend upon abstractions. Do not depend upon concrete implementations (originally defined by Robert Martin).
High level modules should not depend upon low-level modules. Both should depend upon abstractions.
Abstractions should not depend upon details. Details should depend upon abstractions. High level classes should contain the “business logic”, low-level classes should contain the details of the (current) implementation. Access instances using interfaces or abstract classes is a common way for dependency inversion.
Don’t Repeat Yourself(DIY)
DRY says that every piece of system knowledge should have one authoritative, unambiguous representation (Andy Hunt and Dave Thomas)
It is a principle for general software development, so it may be the most fundamental one. The principle target to reduce the repetition or duplication of information, it is specially important to the modern muti-tier architecture such as JavaEE. It apples broadly on software development including database schema, testing and coding. The violations of these principle are known as WET, which usually refer to " we enjoy typing", “We edit terribly" or “Write Everything Twice". Sometimes, we may use WET to solve a particular problem or act as a temporary solution, but we should do it with a strong rationale.
As an experienced developer, we should know how to reduce the duplication of code by appropriate practice and proper abstraction. In short, we can reduce the rrepetition in process calls by automation and reduce the rrepetition in logic by abstraction.
The DRY principle provides fundamental guidance to software developers and let us have simpler, more maintainable, higher-quality applications. We should follow this principle with regard to structure, logic, process, and function in the development.
Favor composition over inheritance
Because inheritance exposes a subclass to details of its parent’s implementation, it’s often said that ‘inheritance breaks encapsulation‘". (Gang of Four)
The principle state that the favour way to create thing is composition rather than inheritance. Using inheritance is simple with OOP but constructing a complex hierarchy of inheritance do not allows the software to extend easily. Although the overuse of inheritance in OOD is common and understandable, favor composition over inheritance is a design principle that gives the design higher flexibility, giving business-domain classes and more stable business domain in the long-term. In other words, HAS-A can be better than an IS-A relationship.
The implementation of composition is often not as simple as inheritance, It typically begins with the creation of various interfaces.
Delegation principle
Using prototypical objects to implement shared behavior in object-oriented systems – Henry Lieberman
This principle state that it unnecessary to accomplish all the task in one module, delegates the task to an associated helper whenever possible. The principle help us create a programs with flexibility and it often given as the way to composition. However, there are always some confusion with delegation, the concept of delegation is not just a method forwarding in object collaboration.
Java and OO principles
The original Java APIs have implement many principles mentioned above, you can just enjoy the benefits by using Java as OOP. By using suitable principle you can create a better program with high cohesion and low coupling. One of the best way to implement corresponding principle is the pattern. However, apply a suitable principle to a particular problem is not a straightforward and easy thing, and there are always some trade-off.
We will use Java as an example to learn more for those principles.
Peter
近期迴響