stoyicker / symbio-assignment

Jorge Antonio Diaz-Benito Soriano

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

symbio-assignment - Jorge Antonio Diaz-Benito Soriano

Get the latest APK here.

Build Status

This project is developed on top of my master-slave demo for the New York Times reactive cache framework for Android (Store), stoyicker/master-slave-clean-store.

Build instructions

./gradlew assemble (or something like gradlew.bat assemble on Windows I guess). You can also get an APK from the Releases tab, courtesy of Travis.

Architecture

This is a reactive app: it runs by reacting to user interactions. Here is how:

Architecture

which reads as:

The user interacts with the content view of an activity, which delegates to coordinators, which are implementations of functionalities. These trigger actions on the domain layer whose implementations reside in the data layer - usually consisting of retrieving data from somewhere (like the cloud), mapping it to domain-defined business entities and moving them back up to the coordinator, which updates the view accordingly via an interface.

Language choice

I chose Kotlin over Java because:

  • It is less verbose than Java.
  • It is more natural both to read and write, which makes writing code easier and faster while still allowing Java developers who have never seen it to understand it.
  • It can be configured to generate Java 6/8 bytecode, which means its evolution is independent from that of the platform.
  • It is officially supported by Google as a first-class language for Android.

Documentation

Documentation is generated using Dokka, which is the code documentation generation tool for Kotlin, similar to what Javadoc is for Java. index.html for the documentation of each module can be found in their build directories: module_name/build/dokka/module_name/index.html.

Tests

Unit and integration tests are written using Spek, the specification framework for Kotlin (just some syntactic sugar for JUnit really). Run them with the test Gradle task in each module. Instrumentation tests are only present in the app module and can be run using the cAT task.

Decisions decisions (you probably want to read the relevant parts of the code first)

Splash screen - Why didn't you use ApplicationLifecycleCallback to perform a runtime theme change in the main activity instead of using a separate one?

  1. I'm using the splash activity to perform what you could call pre-fetching. I could do this on the main activity too of course, but in detriment of higher coupling.
  2. Even if coupling wasn't a problem (suppose I wasn't doing anything in the splash), runtime configuration changes are slow and are the differences between apps that run only on Pixel phones and whatnot and apps that run also in budget phones.

Caching - Store vs client-side header manipulation

This project implements caching by using Store, an abstraction layer that sits between your Retrofit interface and your domain logic and implements the Store pattern with a reactive approach. It fits very nicely with reactive architectures and its 1:1: mapping to endpoints make it a very nice tool for low coupling, which is a factor I consider important.

A more traditional, some would say simpler approach, is client-side header manipulation. Something like this. However that requires modifying the very own network client for each different endpoint needs, which I don't quite like.

Note that image caching is not handled by Store, but Picasso instead.

Single<List<T>> vs Observable<T>, do you not understand data streams?

Well enough to know that the response from the only request this app executes is not a data stream. We get an ordered bunch of items, that is, a list of items, but only in one bunch at a time. Just because there are several items it doesn't mean we should use a stream-like representation - we are not observing for interactions with a UI element or leave an open port for incoming connections or similar - therefore using Observable/Flowable is conceptually incorrect. Moreover, supposing we used one of these classes instead, there would be a rather unnecessary overhead, because on our subscriber we will either queue a UI update for every element (country, in this case) that is received in onNext, or manually collect them and then request a single UI update, which is what is happening in the actual implementation, only that we don't unfold the list into an unnecessary Observable/Flowable and therefore we don't need to put it back together either.

When transitioning from master to slave, you're sending the entire item instead of an id

I am indeed. I know it is recommended that you pass only the id and then use this to retrieve the id from the database as this is faster than Parcel-induced marshalling and demarshalling for objects that are not hierarchically complex, like the ones in this project. However, I haven't spent the time setting up a database.

Feel free to bring this or any other points up for discussion at an interview if you disagree with my thoughts.

About

Jorge Antonio Diaz-Benito Soriano


Languages

Language:Kotlin 98.1%Language:Shell 1.9%