Javier Cicchelli 842c3e1a6c [Setup] Wrapping up (#13)
This PR contains the work on wrapping the development of this app, at least for the time being.

To give further details on the work done:
- [x] removed the `Shared` package from the project as it was not used;
- [x] added some missing Xcode target schemes;
- [x] added a design document and a demo video;
- [x] written a README document;

Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Reviewed-on: rock-n-code/deep-linking-assignment#13
2023-04-13 09:25:45 +00:00

5.1 KiB

Deep linking: Wikipedia

App

The ultimate purpose of this application is to open the Wikipedia app in the right location when a user tap on one of the locations listed in the Locations app.

Of course, to accomplish such goal the app therefore shows a list of locations (which are either fetched from a remote server or created by the user) and also, allows the user to add new location coordinates to this list.

Features

In its current state, the Locations app does:

  • fetch locations from a remote server;
  • handle loading, loaded and error states reactively when loading data;
  • add locations manually to the list by obtaining locations from map;
  • clean map of selected location if required;
  • open the Wikipedia app when location is selected from a list;

While the Wikipedia app does:

  • open a location in the right position on the map of Places screen from a deep link;

Design

Implementation

This application was built as a UIKit application given that the assignment explicitedly indicates the app should target the iOS platform (iPhone app only, in this particular case) and also, because it disallow the use of the SwiftUI framework. It is out of discussion that the UIKit framework has been battle-tested for over a decade now and Apple keeps updating and adding features to it on a regular basis. The imperative nature of the framework, which is based in implementing how the UI components for iOS platform should work, is perfectly suitable the developer who want absolute control over the UI, at a cost of maintaining platform-specific, more complex codebases.

With regards to the choice of framework to built this app, it also comes the question of the type of architecture pattern to use in it: for this particular case, and given the limitations of how the view controllers have been defined in the Apple platforms, I chosed to define a MVVM-C that facilitates the separation between logic and UI compoments while decoupling them from the navigation logic by using coordinates (and routers).

Now that design patterns have been mentioned, in this exercise some well-known patterns are being used in some degree. For example, the Singleton pattern is used to initialise the PersistenceService service in the Persistence library. Both public and internal Interfaces that either describe an object or how it should behave are used throughout this codebase, as this pattern is essential to create decoupled components that can be easily plugged as dependencies whenever needed because it forces the developer to think about (single) responsibilites and, as a consequence, these components are also easy to test in isolation as developer can easily create mocks, stubs and spies out of them. Last, but definitely not least, the Use cases are a pattern from Android that basically execute a function based on some given input, and provides an output after that particular function is finished. This pattern is particularly useful to encapsulate some certain logic that a view model needs to execute in a simple way.

This application was built with scalability in terms of the codebase in mind, which tries to address how this codebase could grow in a controllable, organised manner. For this very reason, this application uses the Swift Package Manager (or simply SwiftPM) to define the Core, Dependency, Persistence and Remote libraries of the Library package, that the Locations target should use extensively. These libraries focus on a specific purpose, and they can be self-contained, like in the case of the Persistence library that contains its own CoreData data model definitons and respective assets inside. Packages could use 3rd party dependencies if needed. This approach forces the developer to think about actual separation of concerns, as the different dependencies are grouped as independent, reusable building blocks, and to move the code into the SPM packages out of the main app target, reducing compiling time and overal weight of the application.

As a (indirect) consequence for the use of SwiftPM packages, the dependency injection pattern comes into question. I implemented my own simple DI mechanism that uses extensively the dynamic property wrapper functionality in the last versions of the Swift language rather than using a 3rd party dependency for this case.