Introduction
As you gain seniority in Software Engineering, the system design interview becomes the most important interview. This interview is focused on your ability as an engineer to look at and understand the design of an application from a holistic level. You are expected to start from a high-level view and then do a deep dive into individual components.
In this article, I have shared my recipe to approach the system design interview problem by going through an example. Sounds interesting?... Keep reading
I find the system design interview interesting because they are most realistic, holistic, and involve great communication skills.
Approaching a System Design Problem
So I watched different kinds of system design interviews tutorials and made my own custom script that made sense to me as a mobile developer. By no way or means, this is a comprehensive list, this is just something that has worked for me. So here is the rundown of different sections I used to tackle the system design questions. Here is my recipe 👇
1. Functional Requirements — Start by defining the use case and some features for the app.
2. Non-Functional Requirements — Define performance, experience, and scale requirements.
3. Assumptions — Define the boundary of the problem, any scale constraints, features, etc that you will work with.
4. Client-Server Communication — Define the connection options such as HTTP request, polling, server-side events.
5. API Design — Define the endpoints for the feature that you are building.
6. Data Models — Define data model fields of your objects.
7. App Flow (Use cases flow) — Define and walk through the user flow for the feature you are designing.
8. Performance & Tooling — Define how you will gather data and metrics to see how the app is performing — memory utilization, CPU utilization.
9. ADA — Make sure you define the accessibility feature and how the app will be made accessible.
10. Internationalization — How would you approach as the app grows internationally.
11. Security — Define how you would secure the app.
Now, let's approach a system design problem with an example to explain how I use this structure. I use a free tool called excalidraw to draw out my components. You can use any tool for diagrams you like. Let's say you are asked to design an app that lists interesting places around you.
Design an app that lists interesting places around you
1. Functional Requirement
- Display the list of interesting places around me.
- Load more as I scroll down
2. Nonfunctional requirement
- The list should load very quickly or have low latency
- The list should not jitter
- Should scroll smoothly
3. Assumptions
- How many daily active users?
- API's are available, we need to use them judiciously
4. Client-Server Communication
Primarily these are the following ways/protocols the client talks to the server. Define them for the interviewer, which one are you going to use. For our use case regular http request would be fine but let me share all the options and why you would use one over another in your specific situation.
- Regular HTTP request - This is the most generic use case scenario where a client asks for data/resources from the server. For eg, fetching a list of feed items in a feed.
- Polling - This way of communication has the following sub flavors
- Regular Polling - The client can keep making requests to the server to get the latest but a lot of time server might not have any update to give. This not only results in empty responses the majority of the time but also a waste of resources in setting HTTP connections multiple times.
- Long Polling - If we have a use case where we know we won't have frequent updates from the server. In this case, we can do is use long polling. The client will set up an HTTP connection with the server, and keep the connection open with the server so that server can push updates to the client when there is anything to push. This way we save useless work for opening and closing connections with the server. Keep in mind, this long polling connection may time out too, so we need to reinitiate the connection.
- WebSockets - In a situation where both client and server can initiate communication and there is constant back and forth between client and server we could use WebSockets. A great example of this use case will be a chat app.
- Server-Side Events (SSE) - Client establishes persistence and long-term connection with the server. This connection is used by the server to send data. The client is in listening mode as only the server can communicate with the client. If the client requires to communicate to the server, it needs to use a different protocol. The use case for this would be say, we have a social media app that lists out the feeds of friends. But now if there is an update that just happened while we were on the app, the client could easily get those updates with server-side events (SSE) protocols.
5. API Design
API communicate with each other via protocols. Common protocols are SOAP, REST, and GraphQL. Details about these are not part of this blog but you can search easily. For our use case here, REST should be fine and it will work for the majority of other use cases. Based on our requirements following things are clear:
a) We need a list of places
b) Since we list nearby places, one thing that comes to our mind the API call needs some sort of location info to return the data. This can be our query parameter.
c) Considering this is a mobile app and we don't have infinite resources like computation/connectivity and power like a desktop or a laptop, we need to be careful with the amount of data we should fetch. So it would be great to fetch the data in pieces and fetch more when we need it. So we need to have the capability to request data in pieces, that's where pagination comes in. Offset, KeySet and Cursor Based are different types of pagination servers support. Learn more about these if you don't already know. For our use case, we can pick either of them, but make sure you have some understanding of how pagination works. We will pick the Offset pagination. So we will have a page number and page limit to confine the number of resources. With this thought in mind, our API could look like this
GET - /places?lat={}&long={}&page={}&pageLimit={}
6. Data Model
In this section, we cover the potential data model that will make sense for our use case. Considering that we get a list of places our data models could look like this 👇
7. App Flow
In this section, we talk about the flow of our app. We can use any design pattern that fits your need. It can be MVC - Model View Controller, MVVM - Model View View Model, MVP - Model View Presenter, VIPER, etc. For our simple use case, I am using MVVM. You should use the pattern that makes sense in your use case and which you can defend as a choice.
This is the section to address your nonfunctional requirements and any other performance-related items. In this section, we talk about all the ways we can make the performance better for our app.
a) Show Skeleton - The perceived notion that something is loading makes the user feel like data is loaded faster. Showing some skeleton blocks while data is loading makes a huge impact on perceived user experience
b) Use images with proper dimensions. If API supports height and width as query param then you would fetch the resource that makes sense for your mobile device. Users' eyes cannot tell the difference between image sizes but it makes a huge impact on the performance of the app because you are loading lesser data.
c) Use Content Delivery Network (CDN) for static image caching to help content delivery much faster. In our use case use CDN for images and static content, this will cache place description and images.
d) Load data on a background thread so that the main thread is never obstructed and UI is never stuck.
These are some of the performance good practices, there are other ways too that you can dive into during the interview.
9. Accessibility
We always want everyone to use our apps. To make it really inclusive we need to take care of accessibility in our app. Here are some of the things we can do to address accessibility:
a) Use automated check with libraries for eg: GTXilib so that they can make sure every UI element has a label, proper trait, the label is not redundant.
b) Make sure color contrast is correct
c) Every target size is at least 44pt
d) Add custom calling for accessibility callouts
e) Using proper color schemes
f) Supporting dynamic font types
The practices I mentioned above can be applied to any mobile app. You can read more about accessibility on Google and Apple sites too.
10. Internationalization/Localization
The internationalization of an application gives its user a local and personal experience which goes a long way in the usage and adoption of the app. Usually, we can support this by having different localized strings files for the content/text in our application. You can also use advanced techniques like you send your device locale to the server and server returning the localized file. Depending on your need, you can take different routes to implement localization. Here is Apple's guide to localization.
11. Security
Security is a very broad and complicated topic. As a developer of mobile applications, there are some tips and tricks I usually follow on my apps. Here is a link to a detailed article you can follow for security best practices in the system design interview.
Conclusion
System Design is focused on our ability as an engineer to look/understand the design of an application from a holistic level rather than just the nitty-gritty of individual pieces. There is no right or wrong answer when approaching a system design problem. It is more of knowing ways and means to accomplish a certain set of requirements.