If you want to grow in your career, you have to move from being a developer performing his given task to an architect designing systems which are scalable, maintainable and use the right technologies. The best way to do so is by actually designing systems and studying how the existing systems were developed.
As for this series, I would focus on system design questions from an interview perspective but the steps mentioned below are still valid for actually designing a system as part of your job.
Let's get started,
What is the basic difference between a system design and a coding question ?
System design questions are much more open-ended than coding questions.
For instance, compare designing whatsapp like chat system with finding least common ancestor of two nodes in a binary tree. Though the latter can be difficult to code and coding questions usually are , it has a definite answer to it and even if there can be multiple right answers, they will all provide the same result. It's not the same with chat system. The solution to this will depend on the requirements like do we need only text or audio/video/voice messages? Do we need to enable group chats? How much daily messages can be expected? How can the user sign in? so on and so forth. All of these requirements can potentially change a major part of the design or the entire design itself. So there is no definite answer to it, and can be expanded based on requirements.
Steps to approach a system design question
- Understand the problem statement/requirements clearly
Generally the questions are giving a direct but are vague, like design a parking lot. Now for someone who has already studied the question. He would just start writing the APIs and tell what they think is the right solution. But wait a minute! Does it clarify if the parking lot is just one floor or multiple floors? Does the mechanism to charge money need to be installed when the customer gets in or gets out? Whether it's to be fully automated or someone needs to check receipts? How can the customer pay? so on and so forth. There can be tonnes of questions which can be missed if you really haste to writing/explaining the solution. I am not saying we can think about all the questions to ask, but our primary mindset should be Do not assume anything! Just ask.
This also helps the interviewer understand that you are considering the possible scenarios and thinking on case by case basis. Never focus on writing the code, since usually the code is much simpler than the design needed to build it. This should also include understanding how much traffic a system can take. For instance, a parking lot won't be dealing with more than 2 instances together, one for entry and other for exit. However this can be different for a chat app where the user base can grow drastically and systems should be scalable enough to be able to handle it.
- Understanding data requirement and data modelling
Once you are done understanding the requirement, you should start modelling the objects in the system and what all data should be possibly stored. In case of parking lot, we should know number of parking spaces. When is one free? Which car is present? Do we want to store number plate of the car?Do we store UPI to request customer to pay? Does a parking spot need repair? Is it busy/free? Depending on the requirements you have got initially you can start putting the data required. This might not be final but should give you sense of information you should always have. You can make class diagrams for these if the time allows to else, a simple model class should do.
- Start with API requirements
Once you are sure what information you need. You can start thinking about how will you get this information, What are the end points where the information will be stored or who will be able to retrieve it. For instance, if a parking spot needs repair who is going to add that entry? How will that entry be added. How will you differentiate between unused, repair needed, repair in progress, used. Now you can add an API for this along with the data model. So here both 2 and 3 should be revisited until you get the sense of data flow and information required to actually be able to do what system needs to do.
- **High level design/ Use case diagram **
Once you have figured out what data you need and how it will flow. It's time to make the bigger picture to help the interviewer understand. You can start representing APIs in some sorts and which part of the system they will interact with. How the data will flow from there and how it will be retrieved when required. For instance, for parking system, let's say a customer number plate gets registered when he enters the parking and a digital display tells which parking spot to go. Then after two hours he exits from the same spot, and based on the hours his car was in the parking spot, he is charged.
Let's see in terms of design how can we make this possible.
We have one client which can do following functions:
During entry,
Check if parking spot is free :
getAvailableParkingSpot()
Scan car code, store time of entry and display the parking spot to
go.scanCodeEntry(Image image, Time time,ParkingSpot parkingSpot)
During exit,
Scan car code, calculate time difference. :
scanCodeExit(Image img, Time time)
Request payment from the customer, once approved. Mark parking spot as available :
requestPayment(User user, TimeDuration timeDuration)
,setAvailalbleParkingSpot(ParkingSpot parkingSpot)
This is a very simple example so it did not require complex design. We will be discussing more systems in further posts.
- Low level design
This part is mostly dependent on the design question and interviewer. If you are able to answer or explain all the aspects of the system through the above design, it's good. For straight forward design as above it should be good. In case there is some complexity involved in handling certain parts of the system, an interviewer can ask you to specifically add details to that part which does not mean to actually code it but how would you handle scalability issues, what you think can be the bottleneck among all the service calls require? Which API you think will be called most? is there a way to optimise/ reduce calls by storing more data or doing more computations? These are some questions you should always be ready to answer. These will differ from question to question but in general you might expect these questions to be asked on the design you implemented to get sense of comparison with the design you did not.
- Code
As I have already mentioned coding is usually the easier part in design questions since, it's the flow of data and functionality which is complex and not the logic behind it. Moreover, better systems should require less complex logic so are easily maintainable for newer people. However, always be ready to code. Sometimes just explaining the system does not make the cut. You have to code some parts of the system to explain that your design is actually possible and it's not some theoretical concept you have mugged up. It's always good to know an object oriented language such as Java, Python, C++ which can help in converting your design to code easily.
I will be starting a series on some standard design questions and hopefully help the readers to understand different possibilities of solution in each question contrary to standard solutions.
Keep coding ๐