GRASP – General Responsibility Assignment Software Patterns.
When writing software is simply not the process of just writing code, regardless of how much fun that may be. But rather how it is written in the context of the software. That means that during the development process, there will a point where starting designing the software. This is where using design patterns comes place. Note, these are not the same as the development processes, like iterative, scrum, and agile, which deals with how to structure the development process.
Furthermore, these design patterns are not rules, but techniques for improving code and structure. Additionally, using any design pattern will change the software restriction, limitations, and capabilities. However, what is most important is that you know what implication a design pattern will create and not how many you know, since they are just tools to improve the software.
Singleton
The singleton is one the simplest to implement. Since it only requires a couple of lines of code and allows for quick early development. It is a quick way to add an object as a global object and manage its creation cycle. However, despite its easy implementation. It should not be overused, absent-mindlessly. Furthermore, misuse can cause program architecture to become weak and non-flexible. So use it with care on stuff that you know will only need a single instance and will not break other components’ life cycles.
public class Singleton<T> { internal static T _instance = null; public static T GetInstance() { if (_instance == null) { _instance = new T(); } return _instance; } }
If misused it can easily become an anti-pattern, which can be through both increased coupling and reduced cohesion by making everything more entangled. That can increase the amount of development required for simple features exponentially.
Low Coupling
Low Coupling and the following pattern High-Cohesion are very much associated with one other, which you will soon see. Nevertheless, one of the most useful design patterns in software development.
The Low Coupling design pattern attempts to minimize the number of associations between each model/class. This pattern is about simplifying the program since there is no need to make software unnecessarily complex.
Furthermore, it differed from many other patterns that usually have some code associated with them. It is more a principle/strategy for how to structure your program from architecture software design.
High Cohesion
The High Cohesion pattern, similar to low coupling is about getting the design within a goal. But let us take a look at what this pattern is all about. This pattern is all about reducing the delegation of problems to the least number of classes for instance.
For the given problem of having multiple entity classes in your program the need to communicate with the database. Each class could have its own implementation for how to communicate with the database. But this would yield a low cohesion since everyone knows how to communicate with the database in their own way. However, instead, you give a better cohesion of the software.
Another example is looking at the real world. Would it be good if we all had to know how to be doctors, programmers, lawyers, artists and etc. No, it would make it hard to delegate what one should. Rather, if I can focus on being a programmer, then my doctor can focus on how to be an Instead of everyone being doc
We create a dedicated class that will handle all the communication to the database in between. So that each of the classes will only communicate with this new class instead of never knowing of to communicate with the database.
Polymorphism
The polymorphism design pattern is related to the object-orientated programming feature inherited or interfaces. It allows other parts of the software architecture to refer to an object, for instance, IO abstract. However, there can exist multiple IO implementations, one for File, Serial, and Network. Where the construction of the inherited class handles all the specifics related to that implementation. Thus removing the coupling of the rest of the software if the IO is Serial, Network, File and etc.
Encapsulation
The Encapsulation pattern is simple but very useful for various reasons that we will see. The essence of the encapsulation pattern is that object/struct data fields shall not be accessed directly. Instead, rather, they are accessed via some method/function. Of course, this will add an additional cycle overhead to fetch the data.
struct _mm_ { uint32_t addr; uint32_t ref; uint32_t size; }; uint32_t get_size(struct _mm_* mm) { return mm->size; }
However, by encapsulation, the method itself is self-containing. meaning that it can be improved later without having any effect on the compilation.
In regard to performance overhead, if a function were to be invoked frequently it can be resolved in some programming languages as inline. However, in order to allow for future update of the software, the inline function should be a pure functional functional. That is to say it take all the data it need as arguments.
How to Apply Design Pattern
Great, we look at some design patterns, but let us talk about the actual challenge, and how to apply these patterns to our software.
Of course, the amount of design is proportional to the complexity of the software. Though, it does not mean you should just make it complex for the sake of the privilege of having made a complex system. The simplest design option is the best design choice. Additionally, through understanding each of the design patterns and their consequences on the software architecture, choose the most fitting one. A software design most likely does not require to use of all possible design patterns.
Free/Open software developer, Linux user, Graphic C/C++ software developer, network & hardware enthusiast.