Written the README file.
This commit is contained in:
parent
d80597ac5a
commit
7954e3a98f
41
README.md
41
README.md
@ -1,2 +1,43 @@
|
||||
# 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.
|
||||
|
||||
<center>
|
||||
<video controls>
|
||||
<source src="static.rock-n-code.com/mp4/deep-linking-app-demo.mp4" type="video/mp4">
|
||||
</video>
|
||||
</center>
|
||||
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:
|
||||
|
||||
- [x] fetch locations from a remote server;
|
||||
- [x] handle `loading`, `loaded` and `error` states reactively when loading data;
|
||||
- [x] add locations manually to the list by obtaining locations from map;
|
||||
- [x] clean map of selected location if required;
|
||||
- [x] open the **Wikipedia** app when location is selected from a list;
|
||||
|
||||
While the **Wikipedia** app does:
|
||||
- [x] open a location in the right position on the map of *Places* screen from a deep link;
|
||||
|
||||
## Design
|
||||
|
||||
<object data="static.rock-n-code.com/pdf/deep-linkg-app-design.pdf" type="application/pdf" width="100%" height="800px">
|
||||
<p>Unable to display a PDF file with some design considerations. Please <a href="static.rock-n-code.com/pdf/deep-linkg-app-design.pdf">Download the file</a> instead.</p>
|
||||
</object>
|
||||
|
||||
## Implementation
|
||||
|
||||
This application was built as a `UIKit` application given that the [assignment](https://repo.rock-n-code.com/rock-n-code/deep-linking-assignment/wiki/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](https://apple.com) 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](https://en.wikipedia.org/wiki/Model–view–viewmodel)-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](https://www.swift.org/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](https://en.wikipedia.org/wiki/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](https://www.swift.org) language rather than using a 3rd party dependency for this case.
|
||||
|
Loading…
x
Reference in New Issue
Block a user