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 conceptsLow 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 PrinciplesSOLID 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 exampleThe 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{ 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{ The best way to do this would be to:
public interface DataWriter{ 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
0 Comments
Leave a Reply. |
Categories
All
Archives
May 2020
|