More Related Content Similar to Advanced #6 clean architecture (20) More from Vitali Pekelis (20) Advanced #6 clean architecture4. We want to be able to
REACT TO CHANGES
quickly & efficiently
6. Keep in mind
•Architecture is dynamic and ever-evolving
•There are always several solutions to every problem
•Every architecture decision is a trade-off
•There is no such thing as “the perfect
architecture”
10. Movie Night app layers
Presentation
Data
Domain
•UI
•Presenters
•Dependency Injection
•Web API
•Storage (DB/In-Mem)
•Use cases
•Interfaces
•Domain Entities
DependenciesFlow
13. Movie Night app layers
Presentation
Data
Domain
•UI
•Presenters
•Dependency Injection
•Web API
•Storage (DB/In-Mem)
•Use cases
•Interfaces
•Domain Entities
DependenciesFlow
14. The Domain Layer
•The baseline of the application
•Describes what the application is / what it can do
•Generic code
16. Domain Entities
• Simple data containers
• The basic building blocks of our application
• Acts as common language across the
application
38. Interfaces
• Dictates the contract the upper layers must
follow
• Ensures the application core functionality will
hold true, regardless implementation details
changes
41. Movie Night app layers
Data
Domain
•Web API
•Storage (DB/In-Mem)
•Domain Entities
•Interfaces
•Use cases
48. MyMapper.kt
class MyMapper: Mapper<MovieEntity, MovieData>() {
override fun mapFrom(from: MovieEntity): MovieData {
return MovieData(
id = from.id,
originalTitle = from.originalTitle,
releaseDate = from.releaseDate,
overview = from.overview
// ...
)
}
}
49. MyMapper.kt
class MyMapper: Mapper<MovieEntity, MovieData>() {
override fun mapFrom(from: MovieEntity): MovieData {
return MovieData(
id = from.id,
originalTitle = from.originalTitle,
releaseDate = from.releaseDate,
overview = from.overview
// ...
)
}
}
50. MyMapper.kt
class MyMapper: Mapper<MovieEntity, MovieData>() {
override fun mapFrom(from: MovieEntity): MovieData {
return MovieData(
id = from.id,
originalTitle = from.originalTitle,
releaseDate = from.releaseDate,
overview = from.overview
// ...
)
}
}
53. Why do we need Mappers?
The Data layer contains details
we want to hide.
60. Movie Night app layers
Presentation
Data
Domain
•UI
•Presenters
•Dependency Injection
•Web API
•Storage (DB/In-Mem)
•Use cases
•Interfaces
•Domain Entities
DependenciesFlow
72. LiveData 101
// Creating
val liveData = MutableLiveData<String>()
// Observing
liveData.observe(lifecycleOwner, Observer { data ->
// do something with data…
})
// Updating value
liveData.value = "Hello world!"
73. LiveData 101
// Creating
val liveData = MutableLiveData<String>()
// Observing
liveData.observe(lifecycleOwner, Observer { data ->
// do something with data…
})
// Updating value
liveData.value = "Hello world!"
74. LiveData 101
// Creating
val liveData = MutableLiveData<String>()
// Observing
liveData.observe(lifecycleOwner, Observer { data ->
// do something with data…
})
// Updating value
liveData.value = "Hello world!"
83. class PopularViewModel(val useCase: GetPopularMovies)
: BaseViewModel() {
var viewState: MutableLiveData<PopularViewState>
init {
viewState.value = PopularViewState()
}
PopularViewModel.kt
84. class PopularViewModel(val useCase: GetPopularMovies)
: BaseViewModel() {
var viewState: MutableLiveData<PopularViewState>
init {
viewState.value = PopularViewState()
}
PopularViewModel.kt
85. class PopularViewModel(val useCase: GetPopularMovies)
: BaseViewModel() {
var viewState: MutableLiveData<PopularViewState>
init {
// Sets the initial view state
viewState.value = PopularViewState()
}
// ...
PopularViewModel.kt
93. PopularMoviesFragment.kt
val viewModel = ViewModelProviders
.of(this, factory)
.get(PopularViewModel::class.java)
// ...
viewModel.viewState
.observe(this, Observer { state ->
handleViewState(state)
})
94. PopularMoviesFragment.kt
val viewModel = ViewModelProviders
.of(this, factory)
.get(PopularViewModel::class.java)
// ...
viewModel.viewState
.observe(this, Observer { state ->
handleViewState(state)
})