Five ways to improve your system design and software architecture skills
I always thought working in software development and data science, and building systems more generally, that writing code would take up the majority of the time. I mean you 'learn to code' right? You don't 'learn to design systems'. I thought coding creative solutions to problems would be the main task, and data structures and algorithms would be the main skills. Although these things are very important, it didn’t really turn out to be the case. I found the majority of the time would be spent in meetings explaining to stakeholders and others, how systems worked or would work. I learnt quickly that when features were suggested or requested, it wasn’t coding ability that would allow you to discuss them, it was the ability to discuss whether there was a workable design. This can be particularly hard when you’re just starting out.
After these conceptual discussions of feasibility with the business stakeholders, there would be technical discussions like estimation and planning how to divide the tasks, whether they could be performed concurrently, or whether any exploration was required. Still no code had been written at this point. So the main skill being used here is one of system design. How to either create a new system or extend an existing one. It’s almost like a mini system design interview process. Knowing what’s possible from a system design point of view can really help you zone in on whether an ask is feasible, technically possible, and most importantly, if it’s even needed in the first place! The main reason to constantly improve your architecture aptitude is to always ensure you are building solid, inexpensive, maintainable, scalable and speedy technical solutions or features. Whether that be a machine learning model, a web application, an automated process or anything else, they will all benefit from these things. So if you’ve focused a little too much on the code and neglected your system design and software architecture skills, read on to find out five things you can do to improve them.
Know the core concepts of system design
Technopedia describes system design as:
“the process of defining the elements of a system such as the architecture, modules and components, the different interfaces of those components and the data that goes through that system. It is meant to satisfy specific needs and requirements of a business or organization through the engineering of a coherent and well-running system.”
System design is a vast subject that includes the following topics:
- Programming paradigms - Object oriented, Functional
- Programming design patterns - Gang of Four
- Code organisation
- Frameworks
- Dependencies
- Design principles
- Components
- Functional vs. Non-functional requirements
- N-tier Layering
- Microservices
- Messaging
- Caching
- Load balancing
- Performance
- Relational and NoSQL databases
- Database design
- Data model design
- API design
- Polling and Sockets
- User interface design
- Networking and Proxies
- Scaling! Both horizontal and vertical
- Capacity and demand estimations
- Storage
- Fault tolerance
- Maintainability
- Extensibility
- Accessibility - WCAG 2.1
- Security - OWASP Top Ten
- Analytics and Machine Learning
- Communication
- Authentication - OIDC, WsFederation, JWT
As we can see from this list, there is so much involved in system design! I think although all of the things listed above are important, the key one to understand scalability. It is really useful to understand how to scale a system from 100 to 1,000,000 users. The seperation of concerns is a key factor in scalability, hence the adoption of N-tier architecture, MVC (Model-View-Controller) or MVVM (Model-View-ViewModel) and Microservices or service oriented architecture patterns.
An analytics system I have been in the process of designing recently had the same pattern as the scaling to millions of users diagram. I think it is a great starting point for most designs. I am a big fan of the component template from systeminterview.com and utilised it in this design diagram.
Just knowing the core components and concepts that go into a robust solid system, then allows you to start putting components together and building your own designs. It also means you have a general awareness of the kinds of things to start considering learning more about. Whether it be networking, databases or object oriented design, you'll no doubt find some weaker area that you can go away and read up on.
Learn from the designs of existing systems
You can learn a lot from systems that have already been built and most are documented online. I created this Trello board which served as my checklist and notes on designing various systems from Netflix and YouTube to Facebook and Amazon. This not only meant I would be more prepared for any system design interviews, but for building real systems within those industries such as e-commerce, video streaming, content management, social media, storage, chat and messaging applications.
You can find walkthroughs on how to design some of these systems on The System Design Primer Github page. There is also a page exploring real world architectures.
Another key resource to explore are company technical blogs, where you can get an inside view on design decisions taken by engineering teams. These are some of my favourite engineering and data blogs at the moment:
- Discord Engineering Blog
- Twitter Engineering Blog
- Instagram Engineering Blog
- LinkedIn Engineering Blog
- Data in Government Blog
- Dropbox Infrastructure Blog
- Stripe Engineering Blog
- Government Digital Service Blog
- Heroku Engineering Blog
- Netflix Tech Blog
- Spotify Engineering Blog
- Airbnb Tech Blog
- Uber Engineering Blog
- Google Developers Blog
Follow a framework for practical system design
A quote by Richard Pattis I added to my favourite quotes article says 'If you cannot grok the overall structure of a program while taking a shower, you are not ready to code it'. This means the design is not clear enough, and for me the essence of good software design is reducing and managing complexity. That is, the ability to easily understand how a system works, and therefore easily modify it. This is the main theme of the book A Philosophy of Software Design which I found really insightful.
To create a clear design, a framework can help to structure it and ensure nothing is missed out. I like the PEDALS method from The System Design Interview to guide the process of architecting a system. This stands for:
- Process requirements
- Estimate
- Design the system
- Articulate the data model
- List the architectural components
- Scale
This provides a nice easy to remember process to kick off designing a system. I know this is geared to system design interviews but really the process should also be very useful on the job. I mean I’ve always thought of a system design interview as a conversation between two or more engineers that need to plan out a solution, this process facilitates that conversation very well.
Once you've mastered using the PEDALS framework, you might want to explore more 'enterprise-level' architecture frameworks. These might include The Open Group Architecture Framework (TOGAF) and The Zachman Framework.
Explore cloud computing providers and services
With most solutions now deployed using cloud infrastructure it helps to know the range of cloud providers and their offerings. The big players are Microsoft Azure, Amazon Web Services (AWS) and Google Cloud Platform (GCP). Other providers include Heroku, Linode, IBM Cloud, Digital Ocean and more. Each provider offers a whole range of services, with Microsoft Azure for example provides over 200 products and cloud services. These include Machine Learning, Virtual Machines, Chatbots, Web App Hosting, Storage, Databases, Serverless Functions and many other services.
The benefits of cloud computing are numerous and it seems most big companies and government organisations are moving towards the cloud, so having a good understanding of the providers and services and how they fit into a robust cloud based architecture is vital. Most of the cloud services providers offer free introductory trials - usually for 12 months. This allows you to try some of their services, and build your own cloud based solutions for practice. You usually need a credit card to register, but as long as you only use the free services you shouldn't be charged. Always check your costs section though, as if you use any service not part of the free trial, it will be added to your bill. This is good practice for making sure you're provisioning cost efficient services, and keeping an eye on their cost as demand and usage increases! That skill alone is vital for a company to manage costs and prevent them from spiralling out of control. Most cloud services providers have tools to calculate product usage costs, here is the Azure Pricing Calculator as an example.
To learn more about cloud solution architecture (but geared towards AWS) a good book is Solution Architect’s Handbook.
Study, practice then prototype
System design is a huge topic and can feel overwhelming. I think the more you implement different aspects of systems, you learn what’s possible and it becomes easier. Therefore the best way to continually improve your system design expertise is constant learning and experimenting with new ideas. I like using diagrams.net for planning out a design - a free open source tool.
You can practice estimating system capacity using our System Capacity Calculator. If you decide to read The System Design Interview book, you can run the scenario metrics in chapter 4 (Estimates) on page 27 through the calculator. This calculator was built to help with both system design interview scenarios, alongside building real world scalable systems.
After planning the design, go ahead and try to build a small working prototype of the system in your selected tech stack. This will teach you a lot of how a more complex version of the system might work. This is an essential step and reminds me of one of my favourite quotes from John Gall "A complex system that works is invariably found to have evolved from a simple system that worked. A complex system designed from scratch never works and cannot be patched up to make it work. You have to start over, beginning with a working simple system".
Conclusion
The key takeaway is to never stop learning, practising and improving your system design skills. Using the five things discussed in this article, you'll be able to improve no matter your current experience level. We've never had access to more opportunities to learn and improve skills. This morning at 11am, I observed a two minute silence for Remembrance Day which is a reminder how lucky we are to have the freedom and tools to learn.
I should also explain why I chose the cover image I did for this article. It was in reference to Margaret Hamilton who led to the team which developed the onboard flight software for the Apollo space program. Here is an interesting interview about her journey. An incredible feat of software development and engineering, and a very inspirational story on how important well designed, well built systems are when other's lives are on the line.
Finally, here are some recommended resources for further learning:
- System Design Playlist by Gaurev Sen
- System Design Interview
- The System Design Interview
- Solution Architect's Handbook
- A Philosophy of Software Design
- Web Scalability for Startup Engineers
- Release It!: Design and Deploy Production-Ready Software
- Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems
- Software Engineering at Google: Lessons Learned from Programming Over Time
- The Imagineering Process: Using the Disney Theme Park Design Process to Bring Your Creative Ideas to Life