The intuitive skill of programmers who can design an absolutely fabulous piece of a solution to a given problem without the slightest inclination of design pattern concept comes with rigor and practice. They almost have developed an uncanny ability to see patterns that characterize a problem and the corresponding patterns that can be combined to create a solution. This is no doubt a fantastic quality of implementing a design solution, and can be reused on similar occasions. If you look more closely, these solutions have certain patterns. Design Patterns are such time-tested classic templates of solution architecture that, when used appropriately, not only ensure maintainability of code but also enhances productivity as well.
Design Patterns Are Not Providence
Although they may not be limited to these three—Creational Patterns, Structural Patterns, and Behavioral Patterns—they are the basic patterns popularized by the GoF (Gang of Four). Apart from the patterns mentioned within these three, there are many such patterns limited only by the problem domain and design evolution. They are unrestricted logically and can be co-implemented to fit a particular solution. They describe how to define a problem domain and implement it in code. However, they are not providence. We can always ask where we can exactly use these templates and where we differ and modify them according to our requirement.
Where Do Design Patterns Fit in a Design?
The secret of finding the exact pattern to suit our requirement is not only in the knowledge of various standard patterns but also on the thorough understanding of the problem domain. This understanding of facts starts from the very initial phases of design. Design patterns can be used in all phases of software design. To give an outline, after the analysis phase, the designer thoroughly studies the problem representation details and examines several constraints imposed on the problem. This detailed study gives an idea of how to determine the level of abstraction and what category of design pattern solution the problem fall into. In some cases, it's simply a matter of plug and play of standard patterns. However, challenges vary with the singularity of the problem at hand. What we can do is use the template of standard patterns in the present circumstances or modify it to fit our purpose. The use of standard patterns gives developers an opportunity to reuse existing design patterns when they meet the need of the design rather than creating new ones.
Common Problems in OOD, Overcome by Patterns
Finding a way to decompose a system into an abstraction of classes and objects is the basic building block of object-oriented design. Designers initially look for the most visible and obvious entities in the system and label them as the primary abstraction and then try to find the behavioral aspect on how the instances would interact with each other within the system. Unlike procedural programming, where we simply find out the functionality to implement the algorithmic behavior of the system, object-oriented designing is far more complex then that. Here, objects get a virtual existence; they are no longer treated as a set of simple procedures. In object oriented-design (OOD), where object implementation is at play, we must keep in mind some of the crucial concepts of OO design, such as encapsulation, granularity, dependency, flexibility, performance, re-usability, and many other factors. Using design patterns is a standard way out of this complexity. It's more like somebody has already encountered such a problem and provided a template of their insight to use and re-use whenever such a similar pattern surfaces in the problem domain.
Over the past decades, the evolution of design principles in the industry has made significant progress of proven architectures to construct flexible and maintainable object-oriented software. This is possible through design patterns that not only reduced the complexity of the design process but also stopped re-inventing the same wheel. Developing a complex system can be a formidable task without design patterns. The advantages are many; we can:
- Develop a complex system with relative ease by using proven architectures
- Develop a reusable design
- Reduce the time span required in the design phase
- Give standard nomenclature to refer to when communicating with other developers
- Identify common mistakes and pitfalls in design
- Design patterns that are implementation independent (can be implemented in any language: Java, C++, C#, and so on)
Just as arches and columns are established design elements of a building, so are these patterns in software design. Martin Fowler rightly said, "Patterns are half baked—meaning you always have to finish them yourself and adapt them to your own environment."
It's not a surprise. If you design a system correctly, your design elements will adhere to one or more standard patterns, even if you may not have any idea of a so-called "Design Pattern." The primary motivation is that industry experts have given us some templates to use in solving some common design problems. So, why not use them? Further, they not only ease the trouble of finding our own solution; they also reduce some crucial development time. This can definitely leverage productivity.