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

CQRS Architecture on Android

CQRS Architecture on Android

LT @ shibuya.apk #23

Keita Kagurazaka

March 20, 2018
Tweet

More Decks by Keita Kagurazaka

Other Decks in Programming

Transcript

  1. CQRS Architecture
    on Android
    Keita Kagurazaka

    View Slide

  2. What is CQRS?

    View Slide

  3. CQRS
    ● Command and Query Responsibility Segregation
    ● Architecture extending CQS principle

    View Slide

  4. CQRS
    ● Command and Query Responsibility Segregation
    ● Architecture extending CQS principle

    View Slide

  5. Command Query Separation (CQS) principle
    ● Design concept devised by Bertrand Meyer
    ● We should divide an object’s methods into either
    Command or Query
    ○ Commands change the state but return no value
    ○ Queries return a value but never change the state

    View Slide

  6. Command Query Separation principle
    fun getCount(): Int {
    return this.count
    }
    fun incrementCount() {
    this.count++
    }
    fun incrementCount(): Int {
    return ++this.count
    }
    Do. Don’t.

    View Slide

  7. Command Query Separation principle
    fun getCount(): Int {
    return this.count
    }
    fun incrementCount() {
    this.count++
    }
    fun incrementCount(): Int {
    return ++this.count
    }
    Do. Don’t.
    Apply the concept to Architecture level

    View Slide

  8. Traditional Layered Architecture
    Presentation Layer
    Application Layer
    Domain Layer
    Infrastructure Layer

    View Slide

  9. CQRS Architecture
    Presentation Layer
    Application Layer
    Domain Layer
    Infrastructure Layer
    Command Stack Query Stack
    Application Layer
    Domain Layer
    Command Model Query Model
    c
    Infrastructure Layer

    View Slide

  10. Command Stack / Query Stack
    ● Command Stack
    ○ Change the system state
    ○ Does not return the state to presentation layer
    ● Query Stack
    ○ Never change the system state
    ○ Returns the presentation models to presentation layer

    View Slide

  11. Command Stack

    Objects that have only
    command methods

    View Slide

  12. Command Stack

    Objects that have only
    command methods
    Command Stack’s objects can have query
    methods to achieve changing the system state

    View Slide

  13. Query Stack

    Objects that have only
    query methods

    View Slide

  14. Why should we segregate
    Command stack and Query stack?

    View Slide

  15. Complexity is coming by unifying Domain Model
    ● We have justified ourselves that Domain Model is complex
    because of Domain’s complexity
    ● Segregation of Command and Query makes it easier to
    express Domain in Domain Model
    ● CQRS lights up a new aspect of Domain

    View Slide

  16. Simple example: Conference app
    ● User can show sessions, speakers and rooms info
    ● User can make favorite sessions
    ● All info are fetched by API
    ● Use cache for improving user experience

    View Slide

  17. What is Domain Model?
    Session Speaker
    Room
    Entities

    View Slide

  18. How to construct repositories?
    class SessionRepository {
    fun findAll(): List =
    if (isInvalid) {
    isInvalid = false
    sessionApi.getAll().also(sessionDb::store)
    } else {
    sessionDb.findAll()
    }
    fun invalidate() {
    isInvald = true
    }
    ...

    View Slide

  19. How to construct repositories?
    class SessionRepository {
    fun findAll(): List =
    sessionDb.findAll()
    fun refresh() {
    sessionApi.getAll().also(sessionDb::store)
    }
    ...

    View Slide

  20. invalidate() or refresh() problem
    ● Repository exposes the concern to API
    ○ Against to “Collection-like interface for accessing
    entities”
    ● Repository is going to have the domain logic

    View Slide

  21. Is it really problem?
    ● Maybe no if in the small project
    ● However the bad feeling implies that we still have room for
    improving

    View Slide

  22. Segregate models into Command and Query
    ● Command Models - update the local storage
    ○ Fetch data from API
    ○ Write fetched data to the local storage
    ● Query Models - show the latest info
    ○ Retrieve the local storage
    ○ Re-query when the local storage is changed

    View Slide

  23. Command Models
    Session
    DAO
    ApiClient
    Session is just a Value Object
    UseCase
    Domain

    View Slide

  24. UseCase as a TransactionScript
    class RefreshSessions {
    operator fun invoke() {
    val newSessions = sessionApi.getAll()
    sessionDb.store(newSessions)
    }
    ...

    View Slide

  25. Query Models
    Session Speaker
    Room
    Entities

    View Slide

  26. Query Models as Domain Models
    data class Session(
    val startTime: Date,
    val endTime: Date,

    ) {
    fun getPeriodText(context: Context): String =
    context.getString(...)
    ...

    View Slide

  27. Query Models as Domain Models
    data class Session(
    val startTime: Date,
    val endTime: Date,

    ) {
    fun getPeriodText(context: Context): String =
    context.getString(...)
    ...
    Can take Android Context since Query Domain
    Models concern presentation

    View Slide

  28. Query Models as Domain Models
    data class Session(
    val startTime: Date,
    val endTime: Date,

    ) {
    fun getPeriodText(context: Context): String =
    context.getString(...)
    ...
    Can take Android Context since Query Domain
    Models concern presentation
    Avoid PresentationUtils class

    View Slide

  29. Re-query by observing Database changes
    ● Some ORMs support observable queries
    ○ Room - LiveData, RxJava
    ○ Realm - Callback, RxJava
    ○ Orma - RxJava, LiveData (in the plan)
    ● Room also supports to use original classes instead of
    @Entity class in @Query

    View Slide

  30. CQRS Architecture on Android
    ViewModel
    UseCase
    CommandRepository
    Command Stack Query Stack
    Query Domain Models
    Change event
    QueryRepository

    View Slide

  31. Flux?
    View
    ActionCreators
    State
    Store
    Action

    View Slide

  32. CQRS vs Flux
    ● Flux is a derivation of CQRS to optimize JavaScript world
    ○ Non-complex command models
    ○ No Database
    ● Main difference is that the app state is stored on either
    database or memory (Store)

    View Slide

  33. Summary
    ● CQRS is an architecture that segregate models into
    Command Stack and Query Stack
    ● The separation makes it easier to construct models since
    understanding of Domain is definitely changed
    ● CQRS and Flux are relatives

    View Slide

  34. Thanks!

    View Slide