From Passion to Profession
  • Home
  • Notes
  • Projects
  • Resources
    • Discovery Log
    • Books I Read
    • Blogs I Visit
    • Tools I Use
  • Home
  • Notes
  • Projects
  • Resources
    • Discovery Log
    • Books I Read
    • Blogs I Visit
    • Tools I Use

OOD / OOP Principles

3/3/2014

0 Comments

 
Picture
Not every senior software developer understand good design principles. Good object-oriented design is not common. It's all about knowing the 'why' then devote to learning to design with good OOD concepts and OOP principles in programming. It takes disciplines and  years of experiences.

In object-oriented design, classes are great to achieve Separation of Concerns that is modular, flexible, and reusable software. In addition, there are three good primary OOD concepts I'd like to fall back on, and 5 OOP principles that I initially forced myself practice coding Java, then I gradually became natural doing so.

3 OOD concepts

Low Coupling - the extent to which the parts of the system rely on each other.

Introduce abstraction to decouple common points of interaction so parts of the system don't need to know about each other directly. Shoot for correct level of low coupling, not for no coupling at all. Coupling means interaction between pieces of the system to make the application useful. No coupling is not possible. No coupling means the software will not do anything.

High Cohesive - the extent to which the parts of a system work together for a single purpose.

High cohesion is when you have a class centered around a well defined job in which methods has much in common. Break out various needs into separate classes each with their own value to form a more cohesive system from various perspectives. For example, separate the user interface needs, the data loading and saving needs, and the processing of the data. 

Strong Encapsulation - the extent to which the details of implementation are hidden.

Hide not just data, but also hide process and logic as well. Strong encapsulation is evidenced by the ability for a developer to use a given class or module by its interface alone. The developer does not, and should not, need to know the specific class implementation.

5 OOP Principles

SOLID principles was compiled by Robert C. Martin in the 1990s. They are considered essential principles of object-oriented programming.

S: Single Responsibility Principle (SRP) - Every class should have one single responsibility. Single responsibility means classes should have one and only one reason to change driven by the needs of the business context. For example, consider a class that both compiles and prints a report, then such a class has 2 reasons (the content and the format) to change, which is not good.

O: Open-Closed Principle (OCP)- System can be extended by adding new functionality via new code or new classes, keeping as much as possible existing code unchanged. Abstraction is key to OCP. There are many design patterns that help us to extend code without changing it, such as Decorator, Factory Method, Observer, Strategy, Template, State, and many others to facilitate the changes and avoid a cascade of changes.

L: Liskov Substitution Principle (LSP) - Subtypes should respect their parents. Subtypes should not violate the intent or semantics of the abstraction that they are inheriting from. In other words, functions that use pointers or references to base classes must be able to be swapped in with objects of derived classes without knowing it is using the derived classes and the code still work. If you have code that have to check on the type of the class and depend on the class type you do different things, then you're probably violating LSP.

I: Interface Segregation Principle (ISP) - Do not force a client to depend on a 'fat' interface that the client does not need to use. When we can, we should break interfaces into many smaller ones, so they better satisfy the exact needs of the clients.  Ideally, we want each client uses all the methods from all the interfaces they depend on. Interface has no implementation, so if there's duplication of the method name among interfaces, such duplication is manageable.

D: Dependency Inversion Principle (DIP) -  Have your implementation details depend on the higher-level abstractions, and not have the abstractions depend on concrete details. For example, a class does not contain another class implementation directly. Instead, use an interface binding based on abstraction. A class uses an interface from which an implementation inherit from the interface. This allows us to plug in different types of implementation through using interface. 

code example

The example is about an Employee class that needs to be able to be persisted to XML and a database. If we placed toXML() and toDB() functions in the class, we'd be violating the single responsibility principle. 
public class Employee{
  public String toXML(){
    ...
  }

  public String toDB(){
    ...
  }
}

If we created a persist function that takes a value to represent whether to print to XML or to DB, we'd be hard-coding a set of devices and thus be violating the open-closed principle.
public class Employee{
  public String output(String saveMethod){
    if (type.equals("xml")){
    ...
  }
  else if (type.equals("db")){
    ...
  }
    ...
  }
}
The best way to do this would be to:
  1. Create an interface class (e.g. DataWriter) that can be inherited from for XML (XMLDataWriter) or DB (DbDataWriter) Saving, and
  2. Create a class (e.g. Employee below) that would expose an output(DataWriter saveMethod) which accepts a dependency as an argument. 
public interface DataWriter{
  public String output();
}

public class XMLDataWriter implements DataWriter{
  public String output(){
    ...
  }
}

public class DbDataWriter implements DataWriter{
  public String output(){
    ...
  }
}

public class Emplyee{
  public String output(DataWriter saveMethod){
    ...
  }
}
Going forward, if you'd need to output Employee using other save method like socket or bus, you're open to extend the functionality by introducing new class of SocketDataWriter or BusDataWriter, without needing to modify any existing code.

references

  • S.O.L.I.D. Software Development, One Step at a Time
  • A Good Example of Liskov Substitution Principle
  • SOLID: Part 3 - Liskov Substitution & Interface Segregation Principles
  • SOLID: Part 4 - The Dependency Inversion Principle
  • The Open-Close Principle
  • Inversion of Control
0 Comments



Leave a Reply.

    Categories

    All
    Algorithm
    Concurrency
    CQ
    Data Structure
    Design Pattern
    Developer Tool
    Dynamic Programming
    Entrepreneur
    Functional Programming
    IDE
    Java
    JMX
    Marketing
    Marklogic
    Memory
    OSGI
    Performance
    Product
    Product Management
    Security
    Services
    Sling
    Social Media Programming
    Software Development

    Feed Widget

    Archives

    May 2020
    March 2020
    April 2018
    March 2018
    February 2018
    December 2017
    March 2017
    November 2016
    June 2016
    May 2016
    April 2016
    October 2015
    September 2015
    August 2015
    September 2014
    July 2014
    June 2014
    May 2014
    March 2014
    January 2014
    December 2013
    November 2013
    October 2013
    September 2013
    August 2013
    July 2013
    June 2013

    RSS Feed

in loving memory of my mother  and my 4th aunt
Photos from net_efekt, schani, visnup, Dan Zen, gadl, bobbigmac, Susana López-Urrutia, jwalsh, Philippe Put, michael pollak, oskay, Creative Tools, Violentz, Kyknoord, mobilyazilar