There’s a Big Ball of Mud on Your Plate of Spaghetti
Welcome to what is potentially your last day on the job. Your project is about to be canceled. Your customers are angry. Your boss is freaking out. Your boss’s boss is in Antigua, but when she comes back next week, heads will probably roll. There’s no way to sugar-coat it. You might want to update your résumé and brush up on your algorithms, so that you’re ready for an imminent job search.
How did it come to this? We had a plan. The hardware architecture was simple. The first few releases went off without a hitch and our users were delighted. Our client even presented a whole new set of feature requests and signed a contract extension. How have we found ourselves at the precipice of sure and sudden doom?
The situation we have found ourselves in here is far from unique. According to many academic accounts, five out of six software projects are canceled. Others fail by running behind schedule or over budget. Software projects are hard. There’s no such thing as a simple program. There’s really no project that you can knock out in a week, then ship, and that’s the end. It doesn’t work that way. This phenomenon is unique to the software industry. Structural engineers who design bridge are pretty much done when the bridge opens for public traffic. Electrical engineers design and test circuits on breadboards, then hand those designs off to be manufactured. Aeronautical engineers, such as my grandfather, who designed power plants (as in, engines) for Beechcraft, generally designed and prototyped engines, but didn’t do much beyond that. It was up to others to manufacture the engine, mount it on the aircraft, and others to maintain the engine.
In contrast, software engineers must design, build, test, and often maintain the systems that they develop in a continuous delivery environment. Many projects are never “done.” I’ve been working on the same software project for the last 9 years. We certainly haven’t built the perfect project with perfect architecture, but the project has endured. New features are produced, and bugs are discovered and fixed.
What differentiates projects that run continually for many years from the vast majority that get canceled? While there are many ways this can happen, we’re going to focus solely on the design and architecture of our software. I’ll start with how it very often goes wrong. In keeping with the title of this book, we’ll spend some time in this chapter discussing a set of antipatterns. While I haven’t directly introduced the concept of patterns yet, I suspect that you can make an educated guess about what they are, along with what their antithesis is. A pattern, for now, is simply a formally explained, abstract, best practice solution to a common development requirement. An antipattern is a formal example of what you shouldn’t do. Patterns are arguably good. Antipatterns are inarguably bad.
This chapter will present some of the most common antipatterns, including the following:
- Stovepipe systems
- The Big Ball of Mud
- The Golden Hammer
Once we’ve learned about a few antipatterns, we’ll focus in later chapters on principles and patterns designed to combat and correct the circumstances where antipatterns have either taken hold or might soon take hold. In Chapter 2, Prepping for Practical Real-World Applications of Patterns in C#, I will prepare you for your work with patterns. Software development is an odd business in that we all come to it traveling different roads. I am personally self-taught. I started when I was 12 years old. The only books about computer programming were available for purchase at Radio Shack. There were about a dozen. We didn’t have resources such as Packt Publishing plying the market with fascinating and useful books on every facet of software development. In 1991, the year that I graduated from university, a computer science degree would have focused on software development for mainframes using FORTRAN, which is a far cry from the work I do now. The mainframe programming course I took in 1987 was the last class to use punch cards. If you’re not sure what they are, go look them up. I’ll wait. Are you back? Are you horrified? Me too. The point is, there are a lot of people such as me out there who learned programming out of necessity, and they learned informally.
There are many university-trained software developers out there, but not all software development programs are the same. Computer science programs focus on elements such as mathematical theory and algorithm development but teach only a minimal amount of practice. Software engineering programs, boot camps, and trade schools have more of an engineering focus, where you learn to build software with less of a focus on the theory. Regardless of where you started, Chapter 2 aims to ensure that you understand the most important formal engineering concepts needed in order to work with patterns. Patterns were created using a set of rules and Chapter 2 covers those rules.
In Chapters 3, 4, and 5, we cover patterns in earnest using a story format. I’ve done this in the hope of creating a learning experience very different than my own, having read some of the more heavy-handed academic treatments of design patterns. The patterns that I have selected for this book come from what is perhaps the seminal work on patterns in the software industry, Design Patterns: Elements of Reusable Object-Oriented Software, by Eric Gamma, Richard Helm, Ralph Johnson, and John Vlissides. These four authors are known collectively as The Gang of Four (GoF), and the book that they wrote is colloquially referred to as The GoF book or just GoF. The GoF book contains 23 patterns, broken down into three categories:
- Creational patterns deal with the creation of objects beyond simply using the new keyword.
- Structural patterns deal with the way that you structure your classes to maximize flexibility, reduce tight coupling, and help you focus on reusability.
- Behavioral patterns deal with how objects interact with one another.
The creational patterns I’ll be covering in Chapter 3 include the following:
- The Simple Factory (technically not a pattern)
- The Factory Method pattern
- The Abstract Factory pattern
- The Builder pattern
- The Object Pool pattern
- The Singleton pattern
Within the realm of structural patterns, in Chapter 4, I’ll be covering the following:
- The Decorator pattern
- The Façade pattern
- The Composite pattern
- The Bridge pattern
Practical pattern coverage will conclude in Chapter 5 with this set of behavioral patterns:
- The Command pattern
- The Iterator pattern
- The Observer pattern
- The Strategy pattern
Again, I’ll point out that this book is designed to focus on real-world software development. In the real world, we don’t always perfectly follow the rules presented in Chapter 2. Many books present a perfect experience. Expert authors always present all of their examples as perfect on the first try. I won’t be doing that because that isn’t in keeping with reality. As we flow through Chapters 3, 4, and 5, we will find ourselves faced with “gotchas” that you will find in actual practice. There’s no way around them. Even if you execute the patterns and strategies in these chapters perfectly, nobody can foretell the future. In Chapter 6, a plot twist in our story arises and we have a chance to rethink everything that we’ve done up to that point. In Chapter 6, we’ll design a new system based on an old one using the patterns that we’ve learned so far. Chapter 6 is all about creating a design and a plan. In Chapter 7, we implement that plan.
I won’t be covering every pattern covered by the GoF. Instead, I’ll be focusing on the patterns you are most likely to need as a C# .NET software developer working in the field. I’ve selected my list of patterns based on popularity, usefulness, and complexity. Complex patterns that are not often seen in the wild have been omitted from the main text of the book. That said, I do circle back in Chapter 8 to give you a rundown on the patterns that I didn’t cover, and the usual advice on where to go from there.
This book assumes that you have a few years of experience working with C#. In addition to my day job, I have taught software development at colleges for the last 25 years. I presently teach at Southern Methodist University’s Full Stack Code Bootcamp. Some of the programs I taught focused on C#, while others haven’t. At SMU we teach JavaScript. If you’re coming to this book without recent C# experience, or perhaps with none at all, I’ve added Appendix 1 at the end of the book. It is designed to give you what I hope is enough orientation in the C# language to make the rest of the book useful. The truth about patterns is they are language-agnostic. They apply to any object-oriented language, and I’ve even seen some of them shoehorned into languages that are not object-oriented with arguable levels of success.