Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Building scalable applications inspired into M...

Building scalable applications inspired into Micro-service Architecture

Experiences using modular arquitectures in android.

Erik Jhordan Rey

June 26, 2019
Tweet

More Decks by Erik Jhordan Rey

Other Decks in Programming

Transcript

  1. Monolithic Architecture • All code in a single module •

    Coupled code • Different code styles • Hard to maintain • Hard to add new functionalities • Wrong dependency injection implementations • Unreliable test or not tests • Not CI • Demotivated Teams
  2. Architecture In most successful software projects, the expert developers working

    on that project have a shared understanding of the system design. This shared understanding is called ‘architecture.’ This understanding includes how the system is divided into components and how the components interact through interfaces. These components are usually composed of smaller components, but the architecture only includes the components and interfaces that are understood by all the developers.
  3. Microservice Characteristics • Componentization • Organized around Business Capabilities •

    Decentralized Governance • Decentralized Data Management • Design for failure • Evolutionary Design
  4. Modularized Library Architecture • Different android projects • Complicated navigation

    between libraries • Difficult upgrades (implies a new library release) • Hard to maintain multiple libraries / projects • Hard to handle library version • Transitive dependencies
  5. Modularized Feature Architecture • Different android modules inside an android

    project • Modules organized around business functionality • Coupled & cyclic feature modules • Hard to maintain cyclic dependencies • Hard to share resources (custom views, colors, strings)
  6. Modularized Layer Architecture • Different android modules inside an android

    project • Modules organized around layer functionality • Coupling Modules (strong dependencies) • Hard upgrades • Exposed to create a bunch of git conflicts
  7. Modularized Layer Architecture • Faster build time • Decoupled of

    DI library (not dagger in everywhere) • Better structure • Componentization • Decentralized Data • Maintainability • Designed to failure • Let's to write reliable tests
  8. Android Stack • Kotlin • Architecture Components ◦ ViewModel ◦

    LiveData ◦ Room • RxJava / RxAndroid • Retrofit • OkHttp • Gson • dagger 2 (dagger-android) • JUnit • Mockito • Hamcrest • MockWebServer • Persistence Room Testing • Barista
  9. Removing an extra abstraction class LoginRepositoryImpl(val loginRemoteDataSource: LoginRemoteDataSource) : LoginRepository

    { override fun signIn(userCredentials: UserCredentials): Single<Session> = loginRemoteDataSource.signIn(userCredentials).map { it.toSession() } } interface LoginRepository { fun signIn(userCredentials: UserCredentials): Single<Session> }
  10. We can replace collaborators and test it @Test fun callSignInRepository()

    { val userCredentials = givenUserCredentials() val session = givenSession() given(loginRepository.signIn(userCredentials)).willReturn(Single.just(session)) signInUseCase.signIn(userCredentials) verify(loginRepository, times(1)).signIn(userCredentials) }
  11. interface Scheduler { fun io(): Scheduler fun computation(): Scheduler fun

    newThread(): Scheduler fun ui(): Scheduler } Scheduler Abstraction
  12. Taking advantage of kotlin fun <T> Observable<T>.runOnIo(scheduler: Scheduler): Observable<T> =

    subscribeOn(scheduler.io()).observeOn(scheduler.ui()) fun <T> Single<T>.runOnIo(scheduler: Scheduler): Single<T> = subscribeOn(scheduler.io()).observeOn(scheduler.ui()) fun <T> Flowable<T>.runOnIo(scheduler: Scheduler): Flowable<T> = subscribeOn(scheduler.io()).observeOn(scheduler.ui()) fun Completable.runOnIo(scheduler: Scheduler): Completable = subscribeOn(scheduler.io()).observeOn(scheduler.ui())
  13. Use Case Component class SignInUseCase(val loginRepository: LoginRepository, val scheduler: Scheduler)

    { fun signIn(userCredentials: UserCredentials): Single<Session> = loginRepository.signIn(userCredentials).runOnIo(scheduler) }
  14. Multiple LiveData & Observers class LoginViewModel : ViewModel() { var

    liveDataLoading = MutableLiveData<Any>() // Show progress bar var liveDataSession = MutableLiveData<Session>() // Show user session var liveDataError = MutableLiveData<SessionError>() // Show some error
  15. States Sealed Class sealed class StateData { object Loading :

    StateData() data class Success(var data: Any) : StateData() { inline fun <reified T> responseTo() = data as T } object Complete : StateData() data class Error(val error: Throwable) : StateData() { inline fun <reified T> errorTo() = error as T } }
  16. LiveData class LoginViewModel : ViewModel() { var _stateDataLogin = MutableLiveData<StateData>()

    var stateDataLogin : LiveData<StateData> get() = _stateDataLogin
  17. / SCHIBSTED MEDIA GROUP class LoginFragment : Fragment() { ...

    private fun handleState(stateData: StateData?) { when (stateData) { is StateData.Loading -> { showProgress() } is StateData.Success -> { val session = stateData.responseTo<Session>() showUserSession(session) } is StateData.Error -> { handleError(stateData) } } }
  18. https://martinfowler.com/articles/microservices.html Microservices - Martin Fowler http://files.catwell.info/misc/mirror/2003-martin-fowler-who-needs-an-architect.pdf Who needs an architect

    - Martin Fowler http://worrydream.com/refs/Brooks-NoSilverBullet.pdf Essence and Accident in Software Engineering - Frederick P. Brooks, Jr. Service Oriented Ambiguity - Martin Fowler https://martinfowler.com/bliki/ServiceOrientedAmbiguity.html Further Reading