This Design Class Diagram (DCD) shows the relationship among the backend components of the app (UI is ommitted for simplicity). As you can see, Different class have different responsibilities such as HANDLE_JSON being used to process all JSON entries, SpotifyCalls being used for all nonasyncronous calls to the Spotify API and FIRESTORE being used for all calls to the database. By decoupling these classes from the UI, code reuse is improved and it is easy to detect and manage bugs.
GRASP
GRASP - standing for "General Responsibility Assignment Software Patterns" - is a set of object-oriented design patterns that focuses on associating responsibilities with different classes and objects. In our code, we would utilize the following principles:
- Creator
- Information Expert
- High Cohesion
- Indirection
The Creator principle states that objects should be instantiated in classes which have the most information to create said object. For example, our MainActivity class would not handle obtaining the information and creation of the User object which we reference. Instead, the HANDLE_JSON class handles the creation of this object as, ultimately, we draw the information needed to create the User object from the JSONs which we are given, whether it be from Firebase or the Spotify API.
The Information Expert dictates that a class should be assigned a responsibility if and only if it has the necessary information to complete that responsibility. The RefreshAsync class - a subclass of AsyncTask - is used to refresh the access token if the current access token is invalid. This class is one of two classes to have the base-64 encoded Client ID and Client Secret codes. Thus, it is assigned the responsibility of refreshing the token as doing so requires the base-64 encoded String.
The RefreshAsync task specifically handles the refreshing of the tokens, as compared to the GetTokenAndRefreshToken class which also extends AsyncTask but instead specifically handles getting both the access and refresh token from the Spotify API. The High Cohesion principle states that classes should focus on performing and excelling at one thing well. In other words, the RefreshAsync and GetTokenAndRefreshToken classes are split up as each has two different jobs but simply require access to the same pieces of information in order to allow each class to focus on one responsibility and do it well.
Finally, the Indirection principle is utilize to reduce direct coupling by introducing an intermediary class which handles interactions between two different classes. For example, our FIRESTORE class handles pulling JSONs from Firebase. We utilize the HANDLE_JSON class to translate this information to our User class in order to enhance readability, reduce the amount of responsibilities on one class, and reduce coupling.
Singleton Pattern
The Singleton Pattern is a design pattern which handles the problem of needing only one way to gain access to an instance of an object. Our FIRESTORE class - while not exactly fulfilling the pattern - is the closest we came. It handles interactions with Firebase and is the only class capable of doing so. Moreover, the only way to access methods related to Firebase are through the FIRESTORE class. By utilizing the FIRESTORE class, we ensure that there is only one global way to access Firebase at all times.