Learning About Design Patterns in Software
One of the most effective ways to develop your skills as a Software Engineer is by familiarizing yourself with design patterns. You might have some understanding of patterns that already exist from projects you’ve worked on or used, but the mark of an effective problem solver is a deep and insightful repertoire. A deep repertoire ensures that you as an engineer arrive at the best fitting solution for a given problem. It’s often the case that an engineer will apply one generalizable solution to a wide suite of problems — while this might solve the immediate problem, if this solution does not account for the particular nuances associated with the problem at hand, the solution will fail to scale, produce technical debt, and almost certainly cause growing pains down the line that might influence a costly redesign. With an understanding of why we should build our knowledge of design patterns, how does one go about building such a repertoire?
The first thing to understand is that such a repertoire is never complete. Technology constantly evolves, and effective engineers take the time to learn new design patterns and incorporate these patterns in the software they build. Because change is constant, we as engineers are constantly looking to understand the best ways to design and build software — an exhausting process, but one that underlies the intellectual vigor of our profession. In the truest sense of the phrase, developing knowledge about design patterns is almost entirely about the journey, and not the destination.
While I have been programming for many years, my body of work on large scale, production ready systems is relatively small. Thus, while I do have an understanding of some design patterns, I still have much to learn. In order to develop my understanding of differing architectures and design philosophies, I’ve consulted a few resources that have helped shape and further my learning. Among them, exploring the architecture of open source projects, building out small mocks using new technologies, and most importantly, posing questions to my mentors — the more experienced engineers in my life.
Exploring the architecture of open source projects #
Open source projects are an excellent way to understand unfamiliar design patterns. Popular projects are tried and true, and you can be sure that the patterns established within these projects can potentially be used for other projects you might end up working on. This won’t be the case for every open source project you come across — many have patterns built specifically for the need that project was designed to address, but understanding these patterns will only benefit future design work you undertake. I’ve personally explored how to build python modules effectively, integrate test suites with strong coverage, and refine CI/CD pipelines by exploring open source projects on Github. Finding open source projects that are worth exploring is a challenge in and of itself. While some argue you should just pick something that’s interesting to you, I never found that advice to be very useful. The first thing to understand when beginning to explore open source is that it’s everywhere. Almost everything you touch is built on some type of open source software. The best projects to explore are those that you actively consume — you already understand how they are used, so the learning curve is less steep. Exploring projects that you actively use will also enlighten you to the implementation and design details that make a piece of software useful, by your own definition.
In addition to actually exploring open source projects, I’ve found books to be a refreshing way to learn more about design patterns. In particular The Architecture of Open Source Applications is an excellent resource on learning about the design decisions that underlie some of the most widely used and and powerful open source projects out there. Trying to learn from open source can be like drinking from a fire hose — I’ve found it helpful to learn as much as I can from as many diverse sources as I can.
Building out Mocks and MVPs #
Learning is active, not passive. Reading about and exploring other people’s code is helpful, but actually solidifying ideas and concepts in your brain is made possible by building things. While trying to learn new patterns and paradigms, I’ve taken to building out small mocks and minimum viable products to test existing ideas and experiment with new ones. These projects are often low risk (I’m the only one that will ever see them), and have high educational value. A well built mock or MVP can be used as a type of starter project for downstream work that might need to borrow from the foundations laid in this initial experimentation.
These mini projects can take any form you like, and it is completely up to the engineer to determine the level of detail they’d like to commit to a particular body of work. What’s important to remember while working on these projects is that they are not meant to be inherently scalable or production ready — they are there to help you build scalable and production ready software more efficiently down the line.
The single, most powerful piece of my learning has been having brilliant and talented engineers as mentors. Collectively, they’ve worked at large and small organizations, hundreds of projects, and have written thousands of lines of code — the benefit of their experience has made me a better programmer, and more importantly, a better person. Far more than learning in a vacuum, leveraging formal and informal networks will accelerate learning and provide you with a large number of opportunities to grow your skills. In our profession, I believe mentorship is essential. Design patterns are abstract by nature and highly difficult to understand — learning from others can help you identify the solid steps necessary to actually implement a new idea or identify a situation in which some paradigm will be most useful.
Being able to effectively identify a design paradigm that will best suit the needs of a particular problem will help you build better software. Improving your skills by learning new ways to build and architect software is one of the best ways to continue to ensure that you’re growing as an engineer, and shipping better code as a result. These lessons are applicable to engineers at all levels — no matter your seniority, there is always an opportunity to learn something new. If there wasn’t the opportunity for constant growth and room for intellectual curiosity, software engineering would not be a worthwhile endeavor. We’re lucky it is.