Patterns in Software Engineering
What comes to your mind when you think of the concept ‘pattern’? A simple google search throws the Wikipedia definition, “A pattern is a regularity in the world, in human-made design, or in abstract ideas. As such, the elements of a pattern repeat in a predictable manner”. The most important part in this definition is that the elements of a pattern repeat in a predictable manner. Patterns can be man-made as well as naturally occurring. Stripes on a tiger’s body or a fractal are the naturally occurring patterns, where the tiling or decorative designs are the man-made ones.
Now in context of software engineering, what do they represent? What is their significance? Some of the elements in space of software design and engineering work approximately in a similar fashion across different places or systems. When one tries to understand different system architectures or low level designs, he/she can notice some of the things work in similar way. Human beings are generally excellent at noticing patterns, so much so that they notice pattern even when there isn’t any. While designing a new system, experienced folks can roughly predict these patterns which they’ve seen or worked on before and they can mould it in such a way that it fits the description of current system.
If the parts of code work in exactly same way in multiple places, we generally abstract them away in for of a library or a SDK. So that the folks who are interested in using these parts, they can directly import it from the library and it’ll solve the problem. But sometimes they don’t work in exactly the ‘same’ way. The idea of software patterns came in as a solution to address this issue. To classify certain idea as pattern, it must have recurrence at different situation. They should be seen as abstractions of solutions to a certain problem and they should be agnostic of platform or a language etc. In short, the patterns should have generic use-cases across different problems, systems or languages.
These patterns in space of software help us to identify places where a idea or solution is already predefined, and it can be used in a predictable way to address the given problem. They are well documented, so we don’t need to re-invent the wheel for generally occurring use-cases. It is the responsibility of developer or the architect to identify the pattern and apply it in their system using their own judgement. During documentation, these patterns are categorized into certain forms. The most famous one is the GOF form. GOF stands for Gang of Four, four authors came together to write a book that launched the idea patterns in software world.
Now lets look at some of the examples.
- Creational Patterns:
As the name suggests, these patterns are used to deal with creation of classes, objects etc. Based on what pieces of software we’re dealing with, they are further categorized into the likes of Factory, Builder, Singleton etc. Most common example of Singleton pattern is creating a class for database connection one single time and using it across multiple places, so that you won’t have to deal with multiple DB connections (as DB connections are resource intensive, and useless connections will hamper the performance of system). Similarly the Factory patterns is used to achieve loose coupling between two or more moving parts of systems, so that even if one part is changed, functionality of others won’t be impacted. - Structural Patterns:
These kind of patterns deal with overall structuring of a software project. They deal with classes and objects to form larger structures and provide new functionality. Decorator, Adaptor, Facade etc. are the sub-types of this category of design patterns. Classic example would be the way problems related to impedance mismatch are dealt with. If there are differences between payloads, schemas etc. of producing and consuming interfaces, we use adaptor pattern to convert the schema or payload so that consumer can consume the required information. - Behavioral Patterns:
Behavioral design patterns are concerned with algorithms and the assignment of responsibilities between objects. Chain of Responsibility, Command, Observer, Mediator etc. are some of the sub types. For example, consider there is a system which has chaotic dependencies between multiple objects, Mediator pattern restricts direct communications between the objects and forces them to collaborate only via a mediator object.
For further reading, please refer:
Book: Head First Design Patterns by O’REILLY publication