I just wrote about reusable software, and I figured reusable software design deserves its own article. Perhaps the biggest problem I identified with reusable code is that if it is has problems, the time required to learn the code just to fix it largely negates any value in using it in the first place. If we could easily understand reusable code enough to consistently adapt it to our own use cases, it would be perfect, but that is not how code works. Code is inherently hard to understand. Often, we even have a hard time understanding our own code after a few weeks of separation. Isn't there some way we can consistently benefit from existing work, without the risk of having to spend so much time learning how it works that the cost is greater than the benefits? It turns out that there is, and in some ways it may even be able to mitigate the costs of choosing not to use reusable code. The solution is reusable design!
Design patterns have formally existed since object oriented programming became a thing. Most design patterns are built around OOP. They don't have to be though. Things like loops and coherent if statements are primitive design patterns. Functions are a kind of design pattern as well. We often don't recognize this, because these have become integral elements of programming, but it is true. These are all examples of design patterns that don't rely on object orientation. In fact, very few design patterns require
OOP. Around a year ago, I wrote an event handler that uses the Event
Queue design pattern, in C, and I have used the Observer pattern in C as
well. Any programming style or language can use design patterns (even assembly language). Design patterns are not limited to OOP languages.
Design patterns are superior to concrete code for reuseability, because they are more abstract and flexible. Design patterns don't specify implementation. They merely provide a template. For example, the "for loop" design pattern does not specify the exact number of iterations, the data type of the index variable, or the iteration step. We can use it to do simple counting, to step through a string one (or two, or five...) character at a time, or to traverse an array. These are flexible implementation details. The if statement may or may not have an else or if-else clause. The expression used to generate the boolean value used as the conditional is not defined for us. We can use if statements for all kinds of things, because implementation is not defined for us. Design patterns are flexible enough that it is trivial to adapt them to a particular application.
Good design can save a lot of coding time. A friend of mine likes to say, "Hours of coding can save minutes of design." Reusable code is generally endorsed for how much time it can save developers, but it comes with potentially serious costs. Good design may take longer than crummy design, but it always pays for itself many times over. Good design can save more time than using reusable code can. Reusable design (design patterns) can save significant amounts of design time. This is a double win, because judicious use of reusable design comes with no additional costs, and time spent (or saved) on design is generally more valuable than time spent on implementation. When we save design time, we also save significantly more coding time.
Good design can reduce the need for reusable code, by finding ways to make coding from scratch faster than learning and using an external library or framework. When reusable code is the best option, good design can optimize its use to reduce the costs.
Reusable design is, in my opinion, of far greater value than reusable code. Design patterns are generic enough to solve a large number of problems, and they are easy enough to understand to customize them to a particular application. Because design time is more valuable than coding time, they also have the potential to save far more time than reusable code. Reusable design is probably something we should spend significantly more time and effort on.
No comments:
Post a Comment