The foundational building blocks of your software determine what’s easy and what’s not. It’s important to know how the choices you make at the lowest level will affect your ability to build features down the road. When your software architecture doesn’t match the problem domain, it feels like walking uphill. When you get it right, features seem to come together on their own.
Build Your Vocabulary
Before you can make effective decisions about which architecture is right for a project, you need to have a large vocabulary of different architectures to choose from.
Playing around with different languages and frameworks is a good way develop your architecture vocabulary. The Elm language has an instructive architecture for modeling an application’s state based on signals. A Lisp like Scheme or Clojure will teach you the power of using functions and closures.
Explore far and wide: it will hone your ability to identify the strengths and weaknesses of different architectures.
Make Sure You Understand the Problem
Once you have a broad vocabulary of architectures to choose from, it’s important to dive into the problem and understand as much as you can. Without a deep knowledge of the problem and where you want to go in the future, you’ll have a hard time anticipating how different architectures will stand the test of time. Comparing your needs to the advantages and disadvantages of different architectures gives you a sense of what’s right for the project and what isn’t.
For instance, several months ago I worked on a project for a client who needed to demonstrate to a diverse audience what was happening in a complex and important process. Not only did the algorithm need to adhere to state laws, it needed to be immediately apparent to those in the audience that the process was being executed correctly. A key realization when choosing an architecture was that the client needed, in essence, a very carefully timed and orchestrated PowerPoint presentation.
Avoid the Temptation to Fixate on Frameworks
As a developer, it’s easy to fixate on specific technologies, especially those we know or want to learn. This is a trap when choosing an architecture. For example, model-view-controller frameworks are popular and well-suited to certain problems, but the right solution might be different. Running straight to an MVC framework might leave you with a solution that doesn’t fit the problem.
In fact, for our client who needed a more sophisticated PowerPoint, that’s the exact mistake we made. We started by building the app with React.js. We wanted to learn it, and it made such great promises. We hardly thought at all about the fact that our problem wasn’t an MVC problem. We fixated on the framework instead of the architecture.
Weeks later, after we’d built the app and the client was testing it, it became apparent that there were several problems with our decision. One was that the client needed it to look exactly the same in Internet Explorer 9 as it did in other browsers, but since React.js only supported animations via CSS3 transitions (which don’t work in IE9), the experience in IE9 was abrupt and difficult to follow, violating our client’s main requirement.
There were also several other bugs that proved difficult to fix, most of them due to the state machine that drove the app’s internals, a state machine that became increasingly complex and difficult to reason about. As the bug reports piled up, the time came to look at alternative architectures. Since the whole animation process was driven by a list of high-level actions that needed to be shown on screen, an event stream processing model was a better fit for the problem.
Rather than simply consuming the animation steps and updating an internal model, we rewrote the app to turn that stream of high-level actions into a stream of lower level UI updates. We also abandoned React.js—not because it couldn’t support the architecture, but because it didn’t support the cleaner, better coordinated animations we needed. The app was simple enough that we didn’t need anything more than jQuery and Underscore.
In the end, the client was extremely happy with the rewrite and reported that the process of demonstrating the algorithm to their clients had gone very smoothly. Changing architectures improved the product dramatically and was the right choice for meeting the client’s needs.