val words = Observable.just("Adenor", "Leonardo", "Bacchi") words.test() .assertComplete() .assertTerminated() .assertNoErrors() .assertValueSequence(listOf("Adenor", "Leonardo", "Bacchi")) #$ %&' more verifications given(words) { assertThatSequence { should be completed should be terminated should notBe broken } verifyForEmissions { items match sequenceOf("Adenor", "Leonardo", "Bacchi") firstItem shouldBe "Adenor" never emmits "Parreira" } }
val words = Observable.just("Adenor", "Leonardo", "Bacchi") words.test() .assertComplete() .assertTerminated() .assertNoErrors() .assertValueSequence(listOf("Adenor", "Leonardo", "Bacchi")) #$ %&' more verifications given(words) { assertThatSequence { should be completed should be terminated should notBe broken } verifyForEmissions { items match sequenceOf("Adenor", "Leonardo", "Bacchi") firstItem shouldBe "Adenor" never emmits "Parreira" } }
@Test fun `should fetch from local cache, with cache hit`() { `cache has previous data`() val execution = fetcher.execute( SupportedStatistic.AverageMarketPrice, FetchStrategy.FromPrevious ) val mapped = BitcoinInfoMapper(PREVIOUSLY_CACHED) given(execution) { assertThatSequence { should be completed } verifyForEmissions { firstItem shouldBe mapped } } }
@Test fun `should fetch from local cache, with cache hit`() { `cache has previous data`() val execution = fetcher.execute( SupportedStatistic.AverageMarketPrice, FetchStrategy.FromPrevious ) val mapped = BitcoinInfoMapper(PREVIOUSLY_CACHED) given(execution) { assertThatSequence { should be completed } verifyForEmissions { firstItem shouldBe mapped } } }
Concrete Derivative (conforms to Domain Service) ViewModel Activity External World Bridge Observable Observable Observable Disposable D != P (preferred) D != V (eventually)
Domain Service ViewModel Activity External World Bridge Observable Observable Observable Disposable Domain Service Observable External World Bridge Observable
Domain Service ViewModel External World Bridge Observable Observable Observable Domain Service Observable External World Bridge Observable Use-case Observable Disposable Activity
Domain Service ViewModel External World Bridge Observable Observable Observable Domain Service Observable External World Bridge Observable Use-case Observable Disposable Activity
A Senior Engineer knows that composition should be preferred over inheritance Therefore, you should EVER avoid inherit from a given use-case base class
internal class BlockchainInfoInfrastructureTests { @get:Rule val rule = InfrastructureRule() lateinit var infrastructure: BrokerInfrastructure @Before fun `before each test`() { infrastructure = BrokerInfrastructure( service = rule.api, ) }
val execution = infrastructure.fetchStatistics(AverageMarketPrice) given(execution) { assertThatSequence { should be completed should emit something } verifyForEmissions { firstItem shouldBe expected } } @Test fun `should retrieve Bitcoin market price with success`() { Tested in a integrated fashion
sealed class UIEvent object Launched : UIEvent() data class Failed(val reason: Throwable) : UIEvent() data class Result(val value: T) : UIEvent() object Done : UIEvent()
class DashboardViewModel( private val machine: StateMachineprivate val usecase: RetrieveStatistics) { fun retrieveDashboard() = usecase .execute() .map { BuildDashboardPresentation(it) } .compose(machine) } Mapping function runs in the Scheduler defined by the upstream (IO or Computation)
Multi-module design "Should this new module be Kotlin-only or Android-library?” Can we maximize the number of Kotlin-only modules? How do you handle circular dependencies? How do you share assets between feature modules? How do you handle DI between modules? How do you share configuration logic between Gradle files? Does this design scale?
Eventually, let the composition of your modules to be “inspired” by the design your architectural layers specially when extracting modules from an existing codebase
Build speed + multi-module projects Kotlinx.Serialization for JSON D8 for AAC Lifecycle or Java8 desugaring Isolate modules that require kapt Minimize the # of modules relying on kapt If doomed by Dagger2: consider dagger-reflect https://github.com/JakeWharton/dagger-reflect