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

Clean Architecture the Right Way. Or almost...

Clean Architecture the Right Way. Or almost...

Rubén Serrano

September 06, 2018
Tweet

More Decks by Rubén Serrano

Other Decks in Programming

Transcript

  1. ≥ Activity / Fragment Use Case Use Case … View

    models View Domain Presenter / ViewModel Entities
  2. ≥ Activity / Fragment Use Case Use Case … Entities

    View models View Domain Presenter / ViewModel Mapper
  3. ≥ Activity / Fragment Use Case Use Case … Entities

    View models Mapper View Domain Presenter / ViewModel Repository … Repository
  4. ≥ Activity / Fragment Use Case Use Case … Repository

    Entities … View models Mapper View Domain Repository Presenter / ViewModel Data
  5. ≥ Activity / Fragment Use Case Use Case … Repository

    Entities … View models Mapper View Domain Data Repository Presenter / ViewModel Repository Impl Repository Impl
  6. ≥ Activity / Fragment Use Case Use Case … Repository

    Entities … View models Mapper View Domain Data Repository Repository Impl Repository Impl Presenter / ViewModel Data Source … Data Source
  7. ≥ Activity / Fragment Use Case Use Case … Repository

    Data Source … Data Source Entities … View models Mapper View Domain Data Repository Repository Impl Repository Impl Presenter / ViewModel Database Remote API
  8. ≥ Activity / Fragment Use Case Use Case … Repository

    Data Source … Data Source Entities … View models Mapper Database Remote API View Domain Data Repository Repository Impl Repository Impl Presenter / ViewModel Data models
  9. ≥ Activity / Fragment Use Case Use Case … Repository

    Data Source … Data Source Entities … Data models View models Mapper Database Remote API View Domain Data Repository Repository Impl Repository Impl Presenter / ViewModel Mapper
  10. ≥ Activity / Fragment Use Case Use Case … Repository

    Data Source … Data Source Entities … Data models View models Mapper Mapper Database Remote API View Domain Data Repository Repository Impl Repository Impl Presenter / ViewModel
  11. ≥ Activity / Fragment Use Case Use Case … Repository

    Data Source … Data Source Entities … Data models View models Mapper Mapper Database Remote API View Domain Data Repository Repository Impl Repository Impl Presenter / ViewModel
  12. ≥ Activity / Fragment Use Case Use Case … Repository

    Data Source … Data Source … Data models View models Mapper Mapper Database Remote API View Domain Data Repository Repository Impl Repository Impl Presenter / ViewModel Entities
  13. ≥ Activity / Fragment … Repository Data Source … Data

    Source Entities … Data models View models Mapper Mapper Database Remote API View Domain Data Repository Repository Impl Repository Impl Presenter / ViewModel Use Case Use Case
  14. ≥ Activity / Fragment Use Case Use Case … Repository

    … Entities … Data models View models Mapper Mapper Database Remote API View Domain Data Repository Repository Impl Repository Impl Data Source Data Source Presenter / ViewModel
  15. ≥ Use Case Use Case … Repository Data Source …

    Data Source Entities … Data models View models Mapper Mapper View Domain Data Repository Repository Impl Repository Impl Presenter / ViewModel Activity / Fragment Database Remote API
  16. ≥ “Typically the data that crosses the boundaries is simple

    data structures. You can use basic structs or simple Data Transfer objects if you like […] We don’t want to cheat and pass Entities or Database rows. ”
  17. ≥ Activity / Fragment Use Case Use Case … Repository

    Data Source … Data Source Entities … Database Remote API View Domain Data Repository Repository Impl Repository Impl Presenter / ViewModel Data models View models Mapper Mapper
  18. ≥ Activity / Fragment Use Case Use Case … Repository

    Data Source … Data Source Entities … Data models View models Mapper Mapper Database Remote API View Domain Data Repository Repository Impl Repository Impl Presenter / ViewModel
  19. ≥ Activity / Fragment Use Case Use Case … Data

    Source … Data Source Entities … Data models View models Mapper Mapper Database Remote API View Domain Data Presenter / ViewModel Repository Repository Repository Impl Repository Impl
  20. ≥ “[…] use cases orchestrate the flow of data to

    and from the entities, and direct those entities to use their enterprise wide business rules to achieve the goals of the use case.”
  21. ≥ Activity / Fragment Use Case Use Case … Repository

    Data Source … Data Source Entities … Data models View models Mapper Mapper Database Remote API View Domain Data Repository Repository Impl Repository Impl Presenter / ViewModel
  22. ≥ Activity / Fragment Use Case Use Case … Data

    Source … Data Source Entities Data models View models Mapper Mapper Database Remote API View Domain Data Presenter / ViewModel
  23. ≥ Activity / Fragment Use Case Use Case … Repository

    Data Source … Data Source Entities … Data models View models Mapper Mapper Database Remote API View Domain Data Repository Repository Impl Repository Impl Presenter / ViewModel
  24. ≥ Activity / Fragment Use Case Use Case … Repository

    Data Source … Data Source Entities … Data models View models Mapper Mapper Database Remote API View Domain Data Repository Repository Impl Repository Impl Presenter / ViewModel
  25. ≥ Activity / Fragment Use Case Use Case … Repository

    Data Source Impl … Data Source Impl Entities … Data models View models Mapper Mapper Database Remote API View Domain Data Repository Data Source Data Source Presenter / ViewModel
  26. ≥ Activity / Fragment Use Case Use Case … Repository

    Entities … Data models View models Mapper Mapper Database Remote API View Domain Data Repository … Data Source Impl Data Source Impl Data Source Data Source Presenter / ViewModel
  27. ≥ “[…] a set of adapters that convert data from

    the format most convenient for the use cases and entities, to the format most convenient for some external agency such as the Database”
  28. ≥ Activity / Fragment Use Case Use Case … Repository

    Data Source Impl Data Source Impl Entities … Data models View models Mapper Mapper Database Remote API View Domain Data Repository Data Source Data Source Presenter / ViewModel …
  29. ≥ Activity / Fragment Use Case Use Case … Repository

    Entities … Data models View models Mapper Mapper Database Remote API View Domain Data Repository … Adapter Impl Adapter Impl Adapter Interface Adapter Interface Adapter
  30. ≥ Activity / Fragment Use Case Use Case … Repository

    Adapter Impl Adapter Impl Entities … Data models View models Mapper Mapper Database Remote API View Domain Data Repository Adapter Interface Adapter Interface Adapter …
  31. ≥ Activity / Fragment Use Case Use Case … Repository

    Adapter Impl Adapter Impl Entities … Data models View models Mapper Mapper Database Remote API View Domain Data Repository Adapter Interface Adapter Interface Adapter …
  32. ≥ Activity / Fragment Use Case Use Case … Repository

    Adapter Impl Adapter Impl Entities … Data models View models Mapper Mapper Database Remote API Frameworks Enterprise business rules Frameworks Repository Adapter Interface Adapter Interface Adapter Application business rules …
  33. ≥ Activity / Fragment Use Case Use Case … Repository

    Adapter Impl … Adapter Impl Entities … Data models View models Mapper Mapper Database Remote API Frameworks Enterprise business rules Frameworks Repository Adapter Interface Adapter Interface Adapter Application business rules
  34. ≥ Activity / Fragment Use Case Use Case … Repository

    Adapter Impl Adapter Impl Entities … Data models View models Mapper Mapper Database Remote API Frameworks Frameworks Repository Adapter Interface Adapter Interface Adapter Application business rules … Domain
  35. ≥ Activity / Fragment Use Case Use Case … Repository

    Adapter Impl Adapter Impl Entities … Data models View models Mapper Mapper Database Remote API Domain Repository Adapter Interface Adapter Interface Adapter Application business rules … UI Storage Remote
  36. ≥ Activity / Fragment Use Case Use Case … Repository

    Adapter Impl Adapter Impl Entities … Data models View models Mapper Mapper Database Remote API UI Domain Storage Repository Adapter Interface Adapter Interface Adapter … Remote N x Feature business rules
  37. ≥ Activity / Fragment Use Case Use Case … Repository

    Adapter Impl Adapter Impl Entities … Data models View models Mapper Mapper Database Remote API UI Domain Storage Repository Adapter Interface Adapter Interface N x Feature business rules … Remote Adapter
  38. ≥ Activity / Fragment Use Case Use Case … Repository

    Adapter Impl Adapter Impl Entities … Data models View models Mapper Mapper Database Remote API UI Domain Storage Repository Adapter Interface Adapter Interface N x Feature business rules … Remote Presenter
  39. ≥ Activity / Fragment Use Case Use Case … Repository

    Adapter Impl Adapter Impl Entities … Data models View models Mapper Mapper Database Remote API UI Domain Storage Repository Adapter Interface Adapter Interface N x Feature business rules … Remote Presenter
  40. ≥ Activity / Fragment Use Case Use Case … Repository

    Adapter Impl Adapter Impl Entities … Data models Mapper Database Remote API Domain Storage Repository Adapter Interface Adapter Interface Presenter N x Feature business rules … Remote View Interface UI
  41. ≥ Use Case Use Case … Repository … Repository Adapter

    Interface Adapter Interface Presenter N x Feature business rules … Activity / Fragment Adapter Impl Adapter Impl Entities Data models Mapper Database Remote API Domain Storage Remote UI View Interface
  42. ≥ Use Case Use Case … Repository … Repository Adapter

    Interface Adapter Interface Presenter N x Feature business rules … View Interface
  43. ≥ Use Case Use Case … Repository … Repository Adapter

    Interface Adapter Interface Presenter N x Feature business rules … View Interface Activity / Fragment Adapter Impl Adapter Impl Entities Data models Mapper Database Remote API Domain Storage Remote UI
  44. ≥ Use Case Repository Adapter Interface Adapter Interface Presenter N

    x Feature business rules … View Interface Activity / Fragment Adapter Impl Adapter Impl Entities Data models Mapper Database Remote API Domain Storage Remote UI
  45. ≥ Use Case Repository Adapter Interface Adapter Interface Presenter N

    x Feature business rules … State View Interface Activity / Fragment Adapter Impl Adapter Impl Entities Data models Mapper Database Remote API Domain Storage Remote UI
  46. ≥ sealed class State<out T : Any> class Loaded<out T

    : Any>(val data: T) : State<T>() class Loading() : State<Nothing>() class Error(val message: String) : State<Nothing>()
  47. ≥ fun loadProduct(productId: String) { val productDetailsState = getProductDetails.execute(productId) when(productDetailsState)

    { is Error -> view.renderDetailsError(productDetailsState.message) is Loading -> view.renderLoading() is Loaded -> view.renderDetails(productDetailsState.data) } }
  48. ≥ fun onPhoneNumberVerification(phoneNumber: String) { val result = checkPhoneNumber.execute(phoneNumber) result.fold({

    view.renderGenericError }, { checkPhoneState(it) }) } private fun checkPhoneState(state: VerificationState) { when (state) { is Invalid -> view.renderInvalidError() is ExhaustedAttempts -> view.renderExhaustedAttempts(state.code) is Verified -> view.navigateToSuccess() } }
  49. ≥ fun onPhoneNumberVerification(phoneNumber: String) { val result = checkPhoneNumber.execute(phoneNumber) result.fold({

    view.renderGenericError }, { checkPhoneState(it) }) } private fun checkPhoneState(state: VerificationState) { when (state) { is Invalid -> view.renderInvalidError() is ExhaustedAttempts -> view.renderExhaustedAttempts(state.code) is Verified -> view.navigateToSuccess() } }
  50. ≥ Activity / Fragment Use Case Adapter Impl Adapter Impl

    Entities Data models Mapper Database Remote API UI Domain Storage Repository Adapter Interface Adapter Interface Presenter N x Feature business rules … Remote State View Interface
  51. ≥ Activity / Fragment Use Case Adapter Impl Adapter Impl

    Data models Mapper Database Remote API UI Domain Storage Repository Adapter Interface Adapter Interface N x Feature business rules … Remote State View Interface Entities Presenter
  52. ≥ Use Case Adapter Impl Adapter Impl Data models Mapper

    Database Remote API UI Domain Storage Repository Adapter Interface Adapter Interface N x Feature business rules … Remote State View Interface Activity / Fragment Entities Presenter
  53. ≥ Use Case Adapter Impl Adapter Impl Data models Mapper

    Database Remote API UI Domain Storage Repository Adapter Interface Adapter Interface N x Feature business rules … Remote State View Interface Activity / Fragment Presenter Entities
  54. ≥ class Product( val id: String, val name: String, val

    price: String, val image: String, val description: String, val distanceInMeters: Int ) Domain module UI module internal fun Product.getPriceInEuros() = "$price €"
  55. ≥ Activity / Fragment Use Case Adapter Impl Adapter Impl

    Entities Data models Mapper Database Remote API UI Domain Storage Repository Adapter Interface Adapter Interface Presenter N x Feature business rules … Remote State View Interface
  56. ≥ Different asynchronous approaches •Use Case executed inside a ThreadPoolExecutor

    •Presenter subscribes to a Use Case (RxJava) •Coroutines for a “synchronous” code
  57. ≥ class PhoneVerificationPresenter( private val checkVerificationStatus: CheckVerificationStatusUseCase, ) { //…

    fun onViewLoaded() { launch(UI) { val state = async { checkVerificationStatus.execute() }.await() checkVerificationState(state) } } //…
  58. ≥ class PhoneVerificationPresenter( private val checkVerificationStatus: CheckVerificationStatusUseCase, ) { //…

    fun onViewLoaded() { launch(UI) { val state = async { checkVerificationStatus.execute() }.await() checkVerificationState(state) } } //…
  59. ≥ class PhoneVerificationPresenter( private val checkVerificationStatus: CheckVerificationStatusUseCase, ) { //…

    fun onViewLoaded() { launch(mainContext) { val state = async(backgroundContext) { checkVerificationStatus.execute() }.await() checkVerificationState(state) } } //…
  60. ≥ public class Application extends android.app.Application { //… private void

    setCorutineContexts() { CoroutineContexts.mainContext = WallapopContexts.getMain(); CoroutineContexts.backgroundContext = WallapopContexts.getBackground(); } //… }
  61. ≥ var WALLAPOP_MAIN: CoroutineContext = UI var WALLAPOP_BG: CoroutineContext =

    newFixedThreadPoolContext(2 * Runtime.getRuntime().availableProcessors(), "bg") object WallapopContexts { @JvmStatic var main = WALLAPOP_MAIN @JvmStatic var background = WALLAPOP_BG }
  62. ≥ @Test fun `render verification code when status is Verified`()

    { whenever(checkStatus.execute()).doReturn(Verified()) presenter.onViewLoaded() verify(view).renderSuccess() }
  63. ≥ abstract class UnitTest { init { CoroutineContexts.mainContext = CoroutineContextForTest

    CoroutineContexts.backgroundContext = CoroutineContextForTest } }
  64. ≥ Given a team… •The app you have to develop

    •The problems you have to solve •The rules you have to follow •The trade offs you have to evaluate •The agreements you decide to take