In the world of software programming, it isn’t unusual to face the same issues over and over. It is also not uncommon that these issues present themselves once the code is already out there. This can be avoided with the simple use of Design Patterns. Design Patterns are a collection of already established solutions to common coding problems. If you are in the middle of a project and you think to yourself, how has no one ever gone through this before… chances are, they have. Design patterns are a documented version of all of those things! OK, that’s cool, but so what? Well…The reason this is so valuable is because it makes the application irrelevant and the information is transferrable.
Think of using design patterns as you would think about changing lanes while driving. Regardless if you are driving a car, a bike, or a truck or if you are going to work, a museum or another city you will still turn on your flasher, check your mirrors, check your blind spot and then change lanes. That process will never alter, it is a design pattern to get you to do what needs to be done in the best way.
There are 3 types of design patterns: Creational, Structural and Behavioral. Each of these have many design pattern types related to them, essentially offering a template of how to easily Solve certain recurring problems.
Creational Design Patterns
This group of patterns give your program more flexibility in deciding which objects to create for your application. They create the objects on your behalf instead of you taking the time to build them. For example, an object can be cloned (Prototype) or created without specifying the exact class (Factory Method).
Structural Design Patterns
This group focuses specifically on class and object composition. Using inheritance, Structural Design Patterns compose interfaces and define ways to compose objects to be able to do something different. As an example, there is a design pattern designed to compose zero-or-more comparable objects so that they can be manipulated as one (Composite). Another allows you to provide a simplified interface to a lot of code (Façade)
Behavioral Design Patterns
Finally, the third group focuses on communicating between the different objects. With Behavioral Design Patterns you can manipulate objects like delegating commands to a series of objects or have them carry out a specific language.
These are just some examples of the different design patterns that have been documented, but many books have been published on the subject. Each one is basically a template outlining what can be done and how to do it. Most notably the Gang of Four published Design Patterns: Elements of Reusable Object-Oriented Software outlining all of these templates, including case studies. Can you think of any situations where a predefined map would have saved you a lot of trouble?
Take test specifically. Here is a way these design patterns can be used to maximize efficiency and promote reusability. Often, measures are taken at the application level of a station. A test station will always need to do the following:
- Manage instrument failure
- Manage the replacement of an instrument
- Coordinate communication between multiple instruments in order to set the station in a specific mode.
By using design patterns, a reusable Hardware Abstraction Layer can execute the task, independent of the application, increasing overall station and production efficiency.
Using the Bridge Design Pattern
The Bridge Design Pattern lets you decouple abstraction from implementation allowing you to manipulate them independently. You can also share an instance of implementation among multiple objects while the abstraction manages the actual instruments, not the application.
Creating Redundancy Through Implementation
The Implementation structure makes it general enough to be able to assign to any developer, as opposed to the architect or a specific individual. In addition, the abstraction can be reused as it are instantiated with the station. In the example below using LabVIEW, a constant object is being used but it is built from a configuration file. This way it assigns the right implementation and the Redundant Power Supply Object. Meanwhile, the concrete abstract class Redundant Power Supply can reassign a new implementation upon the occurrence of an error.
Using the Mediator Design Pattern
Mediator enables you to centralize the coordination of multiple objects and reuse them. This is no simple task considering they communicate with a lot of other objects and detect problems within a station such as detecting the need to replace an instrument, as an example.
Hot Swap & Redundancy Implementation
When building with Mediator in LabVIEW, the upper layer of the UML diagram can be generic and used at the beginning of the framework. The concrete mediator is then represented by the concrete station therefore it can be reused in any application that would use the same station. The ConcreteMediator implements the NotifyInstruments method in a way that is specific to the station. The Instruments use NotifyInstrument.vi when required. The instrument communicates directly with the station and the station mediator can act on all the other instruments along with the station. It is essentially a callback. This application can work without having to touch the management of the station itself. This structure allows an efficient reuse and readability of the material which provides the ability to easily assign future development to anyone with some experience with coding.
This is one example of so many where design patterns simplify the overall structure of writing code therefore simplifying the users’ lives. Avoiding common problems before it’s too late while promoting reusability is the developers’ dream. Think of it as a simple case of fool me once, shame on you, fool me twice, shame on me.