Clean Android Dev

Welcome to this brand-new publication dedicated to Android, Kotlin, and Kotlin Multiplatform development! If you’re diving into Android, Kotlin, or Kotlin Multiplatform development and want to ensure your code is as clean as it can be, you’ve come to the right place!

Follow publication

The “Real” Clean Architecture in Android: S.O.L.I.D.

Denis Brandi
Clean Android Dev
Published in
16 min readJul 18, 2022

--

Image by author

What is Clean Architecture?

Clean Architecture is the outcome of the S.O.L.I.D. principles.

S.O.L.I.D.

Liskov Substitution Principle

Derived classes must be substitutable for their base classes.

Testing

Single Responsibility Principle

A class should be responsible to one, and only one, actor (group of users or stakeholders).

From SRP to CCP

Gather into components those classes that change for the same reasons and at the same times.

Separate into different components those classes that change at different times and for different reasons.

Outcome of SRP

Dependency Inversion Principle

The most flexible systems are those in which source code dependencies refer only to abstractions, not to concretions.

View -> ViewModel -> Interactor -> Repository -> Data Store...
The outcome of SRP + DIP

Testing

@Test
fun test1() {
whenever(collaborator.method()).thenReturn(...)
//...
}
@Test
fun test2() {
whenever(collaborator.method()).thenReturn(...)
//...
}
@Test
fun test3() {
whenever(collaborator.method()).thenReturn(...)
//...
}
//... you got the point
class CollaboratorTestDouble: Collaborator {
fun mockMethod(...) { ... }
override fun method() {
// stub, mock, spy...
}
}
@Test
fun test1() {
collaborator.mockMethod(...)
//...
}
@Test
fun test2() {
collaborator.mockMethod(...)
//...
}
@Test
fun test3() {
collaborator.mockMethod(...)
//...
}
//...
Fake for SharedPreferences that uses an in-memory implementation

A funny story

Interface Segregation Principle

Keep interfaces small so that users don’t end up depending on things they don’t need.

interface UserService {
fun login(...)
fun logout(...)
fun createAccount(...)
//...
}
class LoginViewModel(
private val userService: UserService
): ViewModel() {
fun doSomething() {
//...
userService.login(...)
//...
}
}
interface LoginInteractor {
fun execute(...)
}
interface LogoutInteractor {
fun execute()
}
interface CreateAccountInteractor {
fun execute()
}
//...

ISP and SRP

From ISP to CRP

Don’t force users of a component to depend on things they don’t need.

Testing

Open-Closed Principle

A software artifact should be open for extension but closed for modification.

Flag Arguments AKA “Magic Booleans”

fun pay(isDebitCard: Boolean) { ... }
fun payWithDebitCard() { ... }fun payWithCreditCard() { ... }

Enums

enum class PaymentType {
DEBIT_CARD, CREDIT_CARD, BANK_TRANSFER, GOOGLE_PAY
}
fun pay(paymentType: PaymentType)
fun payWithDebitCard() { ... }fun payWithCreditCard() { ... }fun payWithBankTransfer() { ... }fun payWithGooglePay() { ... }

Summary

Last Notes

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Clean Android Dev
Clean Android Dev

Published in Clean Android Dev

Welcome to this brand-new publication dedicated to Android, Kotlin, and Kotlin Multiplatform development! If you’re diving into Android, Kotlin, or Kotlin Multiplatform development and want to ensure your code is as clean as it can be, you’ve come to the right place!

Denis Brandi
Denis Brandi

Written by Denis Brandi

Coaching the next generation of 10x devs.

Responses (11)

Write a response