In this article you will learn about some most important concepts of the Object-Oriented Design. Moreover, you will be introduced to UML diagrams and to some common application design principles.
Object Oriented Programming
The OOP consists of:
- Serve to represent an abstract version of specific real things.
Ex: Clothing (shirts, pants, shoes)
- Cannot be instantiated.
- Used to define common methods and variables for their sub-classes.
- Information hiding
- Code re-use
- Improved debugging and testing
Object Oriented Design
In order to build a new software application or a system, you generally follow three essential steps: Analysis, Design, and Programming.
- Identify problem to solve
- Identify key components
- Apply findings from analysis
- Develop blueprints models
Implement the plan laid out during the design stage using the programming language.
Modeling of classes and systems
A solid software system must conform to one or more of the following design principles:
SOLID, GRASP, DRY, CRC
To model software applications, we use the UML (Unified Modeling Language).
- Models objects, attributes, operations and relationships
- Models dynamic behavior of the system by showing collaborations among objects and changes to the internal states of objects.
There are four UML diagrams to model a system:
- Use case diagram: key behavior and requirements
- Structure diagram: classes and objects being modeled
- Behavior diagram: behavior of the system
- Interaction diagram: sequences, program flow
To draw the UML diagrams, you can use one of the following tools:
- Microsoft Visio
- Some plugins for Eclipse and NETBeans IDE
- Online tools, like LucidChart
Use case diagram
- Graphical representation of the system or solution.
- Visually represents the key behavior and requirements.
- Use case (what actors can do)
- Subsystem or components
The following use case diagram represents some of the multiple functionalities of the Banking Machine (ATM).
Represents the classes and objects being modeled.
The flowing structure diagram shows a modeling of an employee. There is an abstract class Employee and some more specific objects which derives from it: a Janitor and an Electrician.
Represents the behavior of the system.
The following behavior diagram shows a simple scenario of the steps implied when using a banking machine.
Represents the sequences, a program flow.
The following interaction diagram shows the different steps performed by different actors while interacting with a banking machine.
Application Design Principles
Don’t repeat yourself.
Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
Problem: duplication of logic in objects used in program
Solution: write reusable, modular code
- Write once and call it when needed: interfaces, methods.
- DRY is achieved through a proper planning.
Class responsibility collaboration card.
Alternative to UML use cases
Documents responsibilities and collaborations of a class.
- What a class is
- What a class knows
- What a class can do
SOLID Design principles
Single responsibility, Open-closed, Liskov substitution, Interface segregation and
Best practices for OOD.
SRP: single responsibility principle
- Classes should only ever have one reason to change
- Objects have very singular purpose (easier to maintain and easier to understand)
OCP: open-closed principle
- Open for Extension but closed for Modification
- Use inheritance to add new features
- Attempt to leave existing classes alone
LSP: Liskov substitution principle
- Functions that use references to base classes should be able to use child classes.
- Should be able to substitute a child class for a parent without losing any functionality
- (Will inherit properties and methods of the parent. Child classes should be able to act as substitute for parent).
- All child classes are of the same type as their parent
- Ex: Dogs and Cats are both Animals
- Stress the “is a ” relationship
ISP: Interface segregation principle
- Clients should not be forces to depend on interfaces they don’t use.
- Don’t create an interface that does too many things (Break larger single interface into smaller multiple ones. Attempt to be as granular as possible.)
DIP: Dependency inversion principle
- High level modules should not depend on low level modules. Both should depend on
- Abstractions should not depend on details, but details should depend on abstractions.
- Parent classes should not know child classes
- More detailed child classes depend upon abstract parents
General Responsibility Assignment Software Patterns.
Focus on responsibilities for classes (Can be a single object, group of objects working together, notion of designing blueprints for classes).
GRASP 9 key principles:
1. Information Expert
Problem: what is a basic principle by which to assign responsibilities to objects?
Solution: assign responsibilities to the class that has the information needed to fulfill it.
Give the right job to the right class that has all the needed information.
Problem: who should be responsible to creating new objects?
Solution: assign a responsibility to the class that: needs to contain other objects, uses other objects, has information needed to create other objects.
- Ex: Car contains an engine.
- Stress the “has a” relationship.
3. Low coupling
Problem: how can we promote reuse and reduce the impact that changes in one object has on others?
Solution: Stress low coupling so that objects do not depend on other objects too much.
Easier to : maintain, understand, reuse.
4. High cohesion
Problem: How can we make sure that the functions or responsibilities of an object are as focused as possible?
Solution: Attempt to use high cohesion so that responsibilities are focused as tightly as possible.
- Similar to low coupling – one often goes with the other.
- Easier to: maintain, understand, reuse.
Problem: How can we make sure objects not part of the UI are handling requests properly?
Solution: Use a controller to redirect the work.
- Controller gets request from UI then assigns to proper object to do the work.
- Similar to Model View Controller (MVC) Separates UI from business logic.
- Stresses delegation.
Problem: How can we use an object as if it were an object of its superclass?
Solution: Use Polymorphism to ensure you can substitute a child for a parent and still be of the same type.
- Ability to use an object as if it were an object of its superclass, while still using its overridden methods.
- Inheritance and overriding form basis of Polymorphism.
- Implement subclass -specific versions of a superclass method.
- Create subclasses, by extending superclasses.
- Hide superclass variables
- Override superclass methods, adding specific functionality.
7. Pure fabrication
Problem: What do we do when we need to perform operations that don’t really belong with any of our objects?
Solution: Create a “fake” class to handle these operations (class does not fit with other object in the system).
- Allows us to implement high cohesion
- Ex: Data Adapter (to connect to the Database)
Problem: How can we decouple multiple objects to support reuse?
Solution: Create an intermediary to act as a “middleman” between the objects so they are not directly coupled.
- Maintains low coupling
- Ex: Adapter classes (taxes, banking systems persistent storage). Bank Adapter can provide low level API for clients to interact with.
9. Protected variations
Problem: How do we avoid the impact of changes of some objects on others in system?
Solution: Use interfaces to stabilize predicted changes or variations.
- Look for points where change seems likely (interest rates, tax rates)
- Ex: polymorphism, data encapsulation, interfaces.