Architect:week3-Whatsapp
Origin
I joined leetcode system design group to discuss how to design software. This is week3 topic:
Messenger service like What’s App with the following functionalities
- One to One text messaging
- Group Chat, Storage
- Read/Delivery/Sent status
Gist:
- We are having a conversation between two parties. A -> B. Think of this process. What happens and how do you explain to interviewer
- Asynchronous - meaning, “You are on a flight and you receive messages once you land. So those messages were waiting some where!” (Hope you got it). How would you design it
- Horizontal scaling, Load Balancer
- For Read/Delivery/Sent status -> 3 way handshake protocol can give you an idea.
This is a good topic. I will try to design it.
Scenario
First of all, what’s the scenarios? The scenarios will correct my design. The scenario is in which way people use our software. So let’s think scenario first. The scenario should be atomic, and can not split into two or more scenarios. The scenario is a completed interaction. For example, The scenario like:
- User A send message to the system.
- The system send message to User B.
Step 1 or Step 2 is not a scenario. Step 1 with Step 2 is a completed scenario.
And our chat system will be like:
Figure 2.1 init system
Er…It’s too simple…So let’s write more scenarios:
Scenario 1: send and get message in realtime
- User A send message to the system.
- The system send message to user B.
Scenario 2: send message and get it after a while, because user is offline.
- User A send message to the system.
- At this time, user B is offline.
- User B is online.
- The system send message to User B.
Scenario 3: read old messages
- User can read old messages of chat in receive-time order.
Scenario 4: group chat in realtime
- User A, B, and C join a chat group
- A send message to the system
- B and C receive the message from system.
Scenario 5: group chat when someone is offline
- User A, B, and C join a chat group
- User A send message to the system.
- C will receive the message in realtime.
- At this time, user B is offline.
- When User B is online, the system send message to User B in create-time order.
Scenario 6: chat status changing
- User A chat with B
- When A is typing words, B will get “A is typing…” message from system.
- When A press “send” button, A will get “the message is sending” from system.
- When B’s app receive the message in background, A will get “the message is delivered”.
- When B open the chat with A, and scroll to the message, A will get “the message has been read.”
Here, scenario 5 and 4 is similar to 2 and 1. So can we consider scenario 2 and 1 are group chat with only one person? Can I chat with myself? And there should be more scenarios be considered. For example:
- User sign in
- User sign up
- User quit
- Invite other user to use the app
- Find a user
- Add relationship with other user, family, friends, enemy, lover, couple, and so on. Others should comfire the relationship.
- Break the relationship.
- Rebuild the relationship with the same user. Er…Are you crazy? …Trust me, most of lovers will repeat break-rebuild relationship scenarios. If you don’t believe it, you must be younger than me.
- Build a chat group, or invite other user one by one to join chat/group chat.
- Exit a chat group, but can not exit one-one chat, unless breaking the relationship.
- Type message with emoji, gif, png, voice, and other rich text.
- Search old messages
- Delete old messages.
- Set/Show online/offline or other user status to one or more users.
- Can we chat face to face?
- Change user own info
In this article, we can not talk all above. It’s too complicated. I will only focus on group chat and chat status changing scenarios.
Figure 2.2 scenarios relationship
Like Figure 2.2 describles, one-one chat is a special case of group chat. So here use inherit arrow. The interaction of scenario 6 will be included from group chat scenarios. But scenario 3 is alone. If scenario 3 is discarded, our message service will be like “Snapchat”. And I use “User” actor instead of “User A” or “User B”. Why I always write a rectangle as “Messager service”? Because the rectangle warns us, our service has its own boundary! We will not consider other scenarios. If those scenarios inside of rectangle do not be implemented, our service is useless. And if you want to add more functionalities, the rectangle will be bigger and bigger. So thinking about your limit time and money, can you add more functionalities? The correct thing is creating worked well service, notwriting piles and piles of functionalities. Mmmmm…sound like: I use your “Messager service”, will you add “beautify photo”? NO!!!
How to design?
Seems like we always talk about how user use our messager service. Er…Correct! So here I will write something about how to design it. I don’t know how to build the system. I only knows there should be a client and a server…So like that:
Figure 3.1 init components
Now, we have first components diagram. Let’s do more thinking. If we store data, we will have database. If we connect with others, there should have a channel mananger. My chat groups should be controlled by group manager. If some user is offline, can we send offline message to them by APNS? Adding schedule component for sending message to offline user is a good idea. There should have a component for transforming “chat message” to service data, and doing reverse. And another component called “chat service” controls all component to work togather.
Figure 3.2 decompose components
In Figure 3.2, I decompose “Client” into “Interface”, “Transform” and “Channel”, and decompose “Server” into other small components. How to use line to connect those components? The answer is if the connection between components exists, connecting them. It’s nosense!! And another way to deal with the connections is following data flows. In Message services, there exists at least two data flows.
- User -> Client Interface -> Transform message to bytes/data -> send to Channel -> Server Channel Mgr receive bytes/data -> Transfrom into server data -> according to data, pull group data from Group Mgr and store message into Database.
- According to group info, sending message to other group members -> Transfrom server data into bytes -> send to Channel Mgr -> delivery message to Client Channel -> Transform bytes to message -> display message to User.
- Schedule reading what cannot be deliveried -> send message through Chat Service -> Transfrom server data into bytes …
Er…Can we connect Group Mgr with DAO? YES. One point is you can change all diagrams in any time. And another point is, if you don’t draw line between Group Mgr and DAO, you can implement the system as well. For example,
- we can store group info into files
- we use Chat Service as proxy to store group info. Chat Service will call DAO to store group info, if chat exist. If the group members are all silence, the group will be destroyed after a while.
Is there a formal way to draw those components and lines? NO. This is why the software is attractive. Every software is artwork. Do you remember your first program? Always print: “Hello World!” It’s boring! Can we make the world different?
End? No. I will write how to decompose conponent into classes later.