Sprint 3 - ISIS3510-202410-Team23/Backend GitHub Wiki
In this sprint we focused on making our app performance aware and making all of our features aware of eventual connectivity issues. The goal in this sprint was to make sure all our features included functionality for supporting eventual connectivity and avoiding anti-patterns. Additionally we implemented caching, local storage and multi-threading / concurrency strategies. As per the last sprint, all of our repositories were managed using the following Git Workflow Guidelines. Finally, we underscore the ethical implications guiding our actions in the ethics video.
- Eventual Connectivity Scenarios
- Selected Business Questions
- List of Implemented Features
- Ethics Video
- Application Releases & APKs
Eventual connectivity refers to handling connectivity issues in mobile apps, where users may experience intermittent or lost connections. This is an important topic because it is crucial to prevent users from abandoning our mobile apps due to poor performance or functionality when the connection is lost.
In this section we detail eventual connectivity scenarios, which are possible situations a user can experiment in which the connection is lost. Following the guidelines on how to present eventual connectivity scenarios given in MS10, the following section details every scenario that we implemented on our apps, with screenshots on both Swift and Flutter applications.
The storage type is defined from this diagram, presented on the lectures:
This sprint expands on the last one by implementing specific business questions within our analytics system through an interactive Power BI dashboard. You can access the analytics dashboard through the next link:
Each question is aimed at enhancing our understanding of customer behavior and business operations. New questions will be marked with this emoji: π
To enhance the search bar functionality and simplify the process of users finding places they have previously visited, we have decided to incorporate the five most recent searches conducted by the user. Whenever the user searches for a specific restaurant by name, the application will automatically save the search to a list of spots that the user has previously searched for.
Moreover, if the user has conducted prior searches, the search history will be displayed, as illustrated in the following images:
Note: if you click on the images you can view a larger version of them.
This feature aims to streamline the search experience, allowing users to conveniently access places they have recently looked up.
- Visualization: Dashboard Card
- Description: Shows the percentage of users that have saved restaurants in bookmarks.
- Utility: This visualization is incredibly helpful for the team in order to analyze the way our app is being used. Understanding the proportion of users interacting with a feature, allows us to focus the development direction we want to give to our app. For example, on one hand, if there is a small amount of the user base using a certain feature, we may reduce development efforts on said feature. On the other hand, if a large part of our user base is using a feature, we could focus on improving it and the user's experience.

- Visualization: Bar graph (restaurant vs. Amount of unfinished reviews)
- Description: On the x-axis we are able to see the restaurants available in our app, while the y-axis shows the amount of unfinished reviews per restaurant.
- Utility: being able to see how many unfinished reviews each restaurant can also help us provide our analytics persona (a business person that wants to open a restaurant) a more complete insight on which are the most popular restaurants of our community. Having unfinished reviews is a metric that can be combined with the ratings of each restaurant and the amount of finished reviews in order to have different metrics to understand which spots are more popular.

(This question was originally How often does a user begin a review and leave it unfinished, i.e they close the app or return to home before submitting?)
This section shows a comprehensive list on all of the features implemented in both applications, including the ones developed in the last sprint. All of the new features are marked with this emoji: π
- Location between user and spot on the Browse View (GPS Sensor)
- Notification reminding the user to leave a review if they havenβt done so in a while.
- Answers the following type 2 business question: How many days have passed since the user last left a review? (e.g. 4 days, then it is suitable to suggest the user to write a new review)
- Notification when the user is on campus and it is lunchtime suggesting to find a spot for lunch on the app. (Context-aware, GPS usage)
- For You page of recommended spots (Smart feature)
- Authentication with Google
- External Service Connection: Firebase Firestore, Cloud Storage. Backend Endpoints
- π Drafting of spot reviews: users can leave a review unfinished and choose to save it in local storage. This draft can be used to re-fill in data if they chose to make a new review.
- π Bookmarks View + Functionality. Users can now bookmark their favorite spots and see them in the Bookmarks Tab. The chosen ones are saved in local storage (just the IDs). The details are saved in cache.
- π Dedicated view for showing profile related data + sign out button
In this section we detail eventual connectivity strategies, which are ways of solving the eventual connectivity scenarios detailed before.
- At launch time (background fetch): When the application starts, spots for the BrowseView and ForYouView are fetched from the backend to be stored in cache and be shown to the user as soon as they are retrieved.
- Pull (on user demand): the detailed data of spots (including reviews) is fetched once the user navigates to the spot detail view.
- Showing alerts and indicators while the user is in offline mode.
- We use both online-first strategies (in the Browse and ForYou views) and offline-first (in the Bookmarks view).
Caching improves performance, reduces energy use, and lowers backend load by storing frequently accessed data in faster temporary storage. And although caching is a useful strategy, it has limitations. Caching is more expensive than persistent storage, so the cache size is smaller and limited, often stored in RAM. Therefore, we had to carefully decide what data to cache in order to maximize the benefits. In this section, we will explain how we implemented these strategies following the concepts we saw in the lectures.
- Network falling back to cache when fetching data from the Browse Feed and ForYou. In the first instance, the application will try to get the spots data from the backend service (Firebase), if there is no connection and this data cannot be fetched then the information is retrieved from the cache. This strategy is relevant here because we want to prioritize having up to date information about the spots the user is browsing.
- Cache falling back to the network when fetching data for the Browse View, the application first checks if data is available in the cache, if so this the data that is fetched to be displayed. If there is no cached data then the information regarding the saved bookmarks is fetched from the backend service (Firebase). Here it is not as important to have the latest data but rather that it is available regardless of connection for the user.
All of these strategies use the following tools:
- Swift: NSCache
- Flutter: SharedPreferences
Concurrency is important to avoid overloading the main thread of execution. In Flutter, concurrency works only with asynchronous functions and futures, since it is a single threaded language. However, Swift does allow for multi-threading, which allows offloading long-running tasks to background threads, keeping the main thread responsive for a smooth user experience, while either executing in parallel or distributing the tasks. Taking these constraints into account, the following list details the strategies we use on each app for improving performance and user experience.
- [SWIFT] Delegate fetches (of browse and for you data) to other threads so it is done only once (at launch) not each time the user changes tab. β Implemented on top of the existing Browse and For You features
- [SWIFT] If more than 45 seconds have passed, dismiss the sign-in dialog that the GoogleSignIn package uses for showing its UI. (Since this component is not native to our application we couldnβt simply set a timeout, so the sign in flow executes on one thread and the timeout on another, if the latter finishes it first it synchronizes the UI to show the alert and dismiss the view, otherwise the flow continues as normal) β Implemented on top of the existing sign-in feature
- [FLUTTER] Due to Flutter's nature we were unable to develop multithreading strategies. After speaking with our lecturer, we were informed that we could do asynchronous programming instead of multithreading. Most of our tasks utilize this type of programming, for example we fetch the Suggestions list for the search bar with Futures and Awaits.
Futures and async/await work together to handle asynchronous operations without blocking your program. Futures represent the eventual result of an asynchronous task, while async/await functions allow your code to continue running other tasks while waiting for the future to complete, making asynchronous programming more readable and efficient. Flutter uses asynchronous programming (Futures, async/await) to keep your app responsive during potentially slow tasks (network, files). This avoids blocking the UI thread, which would cause lag and a bad user experience. By using Asynchronous programming we allow these tasks to run in the background while the UI stays smooth and interactive.
Local storage, or installed data, allows mobile apps to have all the necessary data stored locally on the device. This enables the app to function mostly offline, without needing to constantly connect to the internet to retrieve data. The following list details the way we are using local storage in our apps.
-
DB: the application saves drafts of reviews to a local SQLite database and the images within App-Specific files. Implemented with the feature of drafting of spot reviews:
- Swift: SQLite (Package to access local db) + FileManager (Image File)
- Flutter: SQLite (Package to access local db)
-
Preference: the application saves the IDs of the spots that have been bookmarked by the user in the Preferences β Implemented with the Bookmarks feature
- Swift: UserDefaults.shared
- Flutter: SharedPreferences
-
File Manager: the application saves the recent searches made by the users to an app-specific file. β Implemented on top of the existing search feature in the Browse View.
- Swift: FileManager (JSON)
- Flutter: SharedPreferences
You can watch our ethics video here or by clicking on the image.
- Release: The release for sprint 3 is here.
- APK: Pending instructions by lecturers or TAs.