System Design

System Design

Until now we had user stories for the project which are approved by the customer. It’s time for us to design the software system that we will build it in the future.

1. Behaviour/Interaction Diagram

We have almost 32 user stories to be implemented in the order of their priority but we realized that 5 user stories are the most core features (rest of them are almost closer to additional features). So for that reason we will cover only these 5 user stories for behaviour diagrams. These user stories are as follows:

  1. As a trackable user I want to send alert to tracking user so that he can track me just before start of my journey.
  2. As a trackable user I want to select a contact from my contacts so that my contact can track me.
  3. As a trackable user I should be alerted when I am not moving from same destination for very long time.
  4. As a trackable user I should send notification to my tracking user if I am in same location for very long and didn’t responded to alert from app.
  5. As a trackable user I should send notification to tracking user when I reach home.

Notations used in following diagrams are

  1. Trackable user - Followee
  2. Tracking user - Follower
1.1 Creating new Tracking session Activity Diagram

Create Session This activity diagram captures above user stories 1 and 2.

Create journey details : Followee will enter all his details like destination, estimated time to reach before the start of journey.
Select contact to follow : Once journey details are entered, he will select a contact requesting follower to track him.
Send request to contact to follow : All the journey details and request will be sent to the selected contact person through firebase backend server.
Received request to track : Follower gets a notification from followee requesting to track him.
            Accepted : When accepted it will add new followee to the list of trackings and also sends message to followee that his request has been accepted and new tracking session is created.
            Rejected : Send the message to followee that his request has been rejected. Followee has to again select another contact from his contact list.
Keep sending location details to follower - Since follower has accepted his request. Now user will start his journey and keep sending his details to follower.

1.2 Sending SOS signal to follower due to inactivity Activity Diagram

Send SOS This activity diagram captures above user stories 3 and 4.

When user is at same location - This will happen when app detects that user’s location is not changing for x minutes during the journey.
Alert user about the inactivity - App will alert the user asking him if he is all right. This alert will only stay for few seconds.
            User responds - When user responds to the app then nothing will happen and journey will proceed as usual.
            User doesn’t respond - When user won’t respond to the app then it will send SOS signal to follower through firebase server.
Received SOS - Follower will receive SOS with additional details like “last been location”, “minutes in that location”.
Ask follower to make a call - App once shown with details of SOS, it will ask follower whether he want to make a phone call to followee.

1.3 Interaction diagram when followee reached the destination

Reached home This interaction diagram captures above user story 5.

The class types Journey, Followee, BackendManager, Follower, Session are discussed in more detail in next section (Class Diagram section). We now just focus on how these objects interact with each other once followee reaches home.

  1. mFollowee will subscribe to mJourney object at the beginning of the app to listen to all interesting changes in the journey details. (More on observer pattern in Design patterns section)
  2. mFollower will subscribe to mBackend object at the beginning of the app to alert itself when there is any incoming message from backend server.
  3. mJourney will notify it’s observers that destination has been reached. mFollowee will also get notified which in turn will make method sendReachedHome() method get called.
  4. Now mFollowee will invoke callBackEndFunction(https) of mBackend object. The arguments will contain https link which is responsible for sending notification to follower.
  5. mBackend object will call the server asynchronously with provided link.
  6. At the backend when appropriate https link is called it will trigger server’s logic to send push notification to target follower with additional information(i.e reached home)
  7. Now at follower side mBackend object notify about incoming message. mFollower get’s notified with message and updates the session of the followee with updateSession(String, Session) function.

2. Class Diagram

This section contains only classes which are the core functionality of the app but not classes like Button, Activity(Details about them can be found here) Class diagram

User - This class represents any user who is using the app. Mostly instance of this is used as data structure to communicate between Follower and Followee to know about each other.

  • Attributes:-
    1. name : String - This represents the name of the user.
    2. phoneNumber : String - This represents the phone number of the user.
  • Methods:-
    Both methods getName() and getPhoneNo() acts as getter for name and phoneNumber.

Followee - This class represents the user who is being tracked by Follower. Every application has at most one instance of this type.

  • Attributes:-
    1. journey : Journey - This holds reference to journey object.
    2. followerNumber : String - This has follower’s phone number as string.
  • Methods:-
    1. setJourney(Journey) and getJourney() acts as setter and getter for journey variable.
    2. setFollowerNumber(String) and getFollowerNumber() acts as setter and getter for followerNumber.
    3. requestToFollowMe() - It will send details along with request to follower’s number to track this user.
    4. cancelTracking() - This is usually called when followee decides to cancel the session. It will set journey to null and sends message to follower about cancel tracking.
    5. pauseTracking() - This will pause the journey and sends message to follower that journey has been paused.
    6. resumeTracking() - This will resume the paused journey(otherwise it will do nothing) and sends message to follower that journey is resumed.
    7. sendSOS(String, BitMap, Location) - This will send SOS alert to follower with all the details. First argument is string about the reason of SOS, second argument is BitMap type which has image and final argument Location type contains co-ordinates of the location of followee.
    8. sendReachedHome() - This will send message to follower that followee has reached home.

Follower - This class represents the user who is tracking others. Every application has at most one instance of this type.

  • Attributes:-
    1. trackings : List<Session> - Follower maintains record of his trackings in a list.
  • Methods:-
    1. addNewFollowee(Session) - Adds new session to the list.
    2. removeFollowee(String) - Removes a session from the list. Pass phone number as argument describing the user who has to be removed.
    3. acceptOrRejectRequest(boolean) - This function sends message to followee whether his request to follow is accepted or rejected. True means accepted, false means rejected.
    4. cancelSession(Session) - It will both removes session from the list and sends followee that follower has stopped tracking him. Pass session argument which has to be cancelled.
    5. updateSessionWithActivity(String, Session) - Follower will receive several messages from many number of users. Those messages has to be updated in a session. First parameter is the message of type String. Second parameter is Session which has to be updated.

Journey - This class contains details of the journey, runs background logic about location of user and time and continually updates itself. This class will access location of the device to update it’s location variables.

  • Attributes:-
    1. details : JourneyDetails - Holds reference to journey details object
    2. observers : List<IJourneyObservers> - Holds list of observers which are subscribed to this instance
    3. maxIdleTimeSec : int - number of seconds in which followee is allowed to stay at one place
  • Methods:-
    1. getJourneyDetails() : Journey - Acts as getter to details variable
    2. startJourney() - It will start the ticking the time of the journey and keep updating the location.
    3. pauseJourney() - It will pause ticking the time of journey and stops accessing phone’s location temporarily.
    4. cancelJourney() - It will stop ticking the time of journey and stops accessing phone’s location and set details variable to null.
    5. subscribe(IJourneyObserver) - It will add object that has been passed as argument to the list of observers.
    6. unsubscribe(IJourneyObserver) - It will remove the object that has been passed as argument from the list of observers.
    7. processLocation() - This function handles the logic like “Is destination reached?”, “Is user idle at some location for maxIdleTimeSec” and also keeps updating location
    8. notifyAllObservers() - This function will notify all of the objects that are present in the list when home is reached or user is idle for more that maxIdleTimeSec seconds.

IJourneyObserver - This interface has to be implemented by other objects in order to subscribe to the events of Journey object

  • Methods:-
    1. onReachedDestination() - This will be called when followee reaches the destination.
    2. whenNoMovementAfterIdleTime() - This will be called when followee has not been moving from one location for very long time.

JourneyDetails - This class acts like a data container. The instance of this class is used just to transfer data between Follower and Followee. Journey object is usually responsible to update the variables of this class.

  • Attributes:-
    1. startLocation : Location - This represents location from which user has started the journey.(More on Location type. See here)
    2. destination : Location - This represents location that followee is supposed to reach
    3. currentLocation : Location - This represents location currently user is at.
    4. estimatedTimeSec : int - The amount of time it will take for the user to reach the destination from current location to destination.
  • Methods:-
    1. updateDetails(Location, Location, Location, int) - This function will update the details of the journey. First argument is to update startLocation, second argument to update destination, third to update currentLocation and final argument is to update estimatedTimeSec. Any of the first three arguments can be set to null if we don’t want to update respective attribute. Last parameter can be set to any negative number if you don’t want to update estimatedTimeSec.
    2. updateDetailsFromJSON(String) - This function will update the details of the journey from the string. Since communication between the servers is usually through strings then this function is used to update directly through JSON string
    3. getStartLocation(), getDestination(), getCurrentLocation(), getEstimatedTime() all acts as getters to the respective variables of this class.
    4. toJSON() : String - Since journey details has to be sent through server it has to be converted to String. This will return a String which has data about the journey details.
    5. fromJSON(String) : JourneyDetails - This is a static function which will create new instances out of valid json string otherwise it will return null.

Session - This class represents a tracking session which are tracked by follower. Usually instances of this class is referenced by Follower since he maintains record of all his trackings as Session type.

  • Attributes:-
    1. user : User - Holds a reference to a user who is usually a followee
    2. journeyDetails : JourneyDetails - Contains data about journey details of above variable’s user.
    3. activities : List<String> - Contains list of activities that followee has done. Eg :- Pausing, resuming, reaching home, etc..
  • Methods:-
    1. getName() : String - It will return name of the user in user variable.
    2. getPhoneNo() : String - It will return phone number of the user.
    3. addNewActivityFromFollowee(String) - This will update the activities done by the user
    4. getAllActivities() : List<String> - This will return activities variable.

BackendManager - This class is responsible for sending and receiving messages from backend. Followee and Follower classes use this class instance to communicate with each other. This class is capable of authenticating, sending files for cloud storage, write data and read data from real time database.

  • Attributes:-
    1. instance : BackendManager - This class only has one instance(More on singleton pattern in Design patterns section).
    2. messageObservers : List<IMessageObserver> - It contains list of observers who will be notified when there is any incoming message from backend server.
    3. dataObservers : List<IDataObserver> - It contains list of observers who will notified where there is a change in real time database.
  • Methods:-
    1. getInstance() : BackendManager - This will return instance variable.
    2. subscribeToMessages(IMessageObserver) - This function will add objects to messageObservers list. These objects should implement IMessageObserver interface and passed as argument to this function.
    3. unsubscribeToMessages(IMessageObserver) - This function will remove object from messageObservers list and they won’t be notified about incoming messages from server.
    4. subscribeToDataChange(IDataObserver) - This function will add object to dataObserver list. The object should implement IDataObserver interface and passed as argument in this function.
    5. receiveMsgFromCloud(String) - This function will process the messages that came from the server. It may also notify all the objects in messageObservers list about a message.
    6. readDataWhenChanged(String) - This function will process when there is a change in data in real time database. It may also notify all the objects in dataObservers list.
    7. writeData(String) - This function will write data to server. Argument passed will be the new data in the server.
    8. uploadPhoto(BitMap) - This function will upload a photo to server’s storage. Argument passed is the photo to be uploaded.
    9. downloadPhoto(UrlRequest) - This function will download the photo present at the the URLRequest that is passed as argument.
    10. callBackendFunction(URLRequest) - This function will trigger backend to execute a function like making push notification, etc. Argument passed is the URLRequest to be called for a particular backend function.
    11. isAnyUserLoggedIn() : boolean - This function will return true if user is already logged in otherwise false.
    12. logIn(String, IAuthCallBack) - This function will try to login the user using first argument phone number as String and responds the login result with IAuthCallBack object which is passed as second argument
    13. signOut() - This function will sign out already logged in user.

IMessageObserver - This interface has to be implemented by objects to get notified and receive messages from backend server.

  • Methods:-
    1. onNewMessage(String) - This will be called whenever there is a message from the server and that message will be passed as String as arguments.

IDataObserver - This interface has to be implemented by objects to get notified whenever there is change in data at the backend server. Usually Follower will implement to get notified whenever there is change in location data of the Followee.

  • Methods:-
    1. whenDataChange(String) - This will be called whenever there is new updated data in the server and the new data is passed as String as arguments.

IAuthCallBack - This interface has to be implemented by objects to know the result of the login process.

  • Methods:-
    1. onVerificationComplete() - This is called when login process is successful
    2. onVerificationFailed(String) - This will be called when login process is failed and the reason for login failure is sent as argument.

3. Design Patterns

We are utilizing three design patterns in our project:

3.1 MVC pattern

Model View Controller is more of a architecture pattern than design pattern. We will still discuss about it on how we have divided our classes into Model, View and controller layer.
Model Layer - All the classes that are discussed in previous section will fall under model layer. They have all the core functionalities of the app within them and how data is stored and managed.
Controller Layer - These classes will manages the interaction between the user’s UI(View) and the model layer. In our software these classes usually extend Activity or Fragment class which are provided by android library. Some of the classes are as follows:

  1. LoginActivity - This class will control user view to receive login credentials from user. These details will be sent to model layer(i.e BackendManager class). Once the model layer processes the login request this class will update View layer with user details.
  2. JourneyActivity - This class will control user’s ui which shows journey details and in the background model layer(ie.Followee class) will keep updating the journey details. This class will keep both user’s UI and model data in sync.
  3. MyTrackingsActivity - This class will control follower’s ui with all the model data about his trackings(i.e Follower, Session classes). When there is any update from backend server model layer will update from it which in turn will update UI view by this class.

View Layer - Mostly these classes are not written by us unless if we want a custom UI. They are already provided by android libraries. Information about them can be found here.

MVC pattern

3.2 Singleton Pattern

We have used singleton pattern for BackendManager class. Having multiple instances of this class to call backend server will lead to accessing internet resources of the device multiple times. It will also lead to losing track of messages when server responds with new message. Instead all the objects which are interested in backend server will interact with just one instance and this instance will send and receive messages from server.

Singleton pattern

3.3 Observer Pattern

This design pattern has been used at two places in our system design. One at Journey class and another at BackendManager class.

  • Journey - This class instance will always be updating data about location and time left for the journey. It is important for other objects to know about these important updates. For this they will subscribe to the Journey object by implementing the IJourneyObserver interface. In return Journey object will notify them when there is something interesting happens in journey(like reached home).

Journey observer pattern

  • BackendManager - This class receives messages from server and objects which are interested in those messages needed to be notified when there is a new message. For this other objects needed to subscribe to this class. There are two kinds of notification that this class can do. First, when there is message from other user (Followee sending message to Follower or vice versa). Secondly, when there is a change in data in real time database (when Followee keeps updating his data about his location). For this reason there are two interfaces(IDataObserver, IMessageObserver) where each serve one of the above two purposes.

Message observer pattern

Data observer pattern

4. Development Strategy

With system design in hand it’s time for us to get into programming. If you have been following our previous blog you know that our approach to this project development is by using SCRUM. In requirement analysis phase we estimated time required for each user story and priority of each user story to be developed. We stacked top user stories to be developed at front and then grouped them into several sets such that each set of user stories will have fixed development time(1 week).

During each sprint(each week) we will pick the top set and proceed for development. Each user story in the set will be further divided into tasks (Eg:- Create User class). All our team members will pick the tasks they want to work on and start developing.

Scrum

We also utilize burndown chart to see how well we are progressing in the project each week. Below picture is one of our sprint (May 21st - May 27th). This shows we are on time and can finish our sprint one day before the deadline of sprint.

Burndown chart

5. Summary of Changes

From the time when the customer approved the requirements we gathered till the time of this blog writing, we didn’t faced any new or modified requirements. If in the future there are any new requirements or modification of old requirements are necessary from the customer then we will try to integrate them into our system design.

Thank you for reading this blog. See you again in next blog!