SlideShare a Scribd company logo
Home Improvement:
Architecture & Kotlin
Jorge D. Ortiz-Fuentes
@jdortiz
#AdvArchMobile
A Canonical
Examples
Production
Home Improvement: Architecture & Kotlin
#AdvArchMobile
Disclaimer
Home Improvement: Architecture & Kotlin
#AdvArchMobile
Agenda
★ Architecture
★ Kotlin
★ Recap
Clean
Architecture
Persistance FW
View
Network
LocationFW
Presenter
Entity Gateway
Clean Architecture
Interactor
Entity
Dependency Inversion
Principle
High Level Low LevelAbstraction
Low Level
#AdvArchMobile
Respectful Criticism
about some
Opinionated
Decisions
#AdvArchMobile
Architecture Components
★ Awesome starting point
★ View Models (inner layer) depend on the
SDK:AndroidViewModel (outer layer)
Kotlin
#AdvArchMobile
Kotlin
★ Conciseness
★ Data Classes
★ Extensions
★ Property Delegation
★ Sealed Classes
Conciseness
#AdvArchMobile
Conciseness (code)
@Module public class ProgrammersListModule {

private ProgrammersListActivity activity;



public ProgrammersListModule(ProgrammersListActivity activity)
{ this.activity = activity; }



@Provides ProgrammersListPresenter
provideProgrammersListPresenter(ShowProgrammersListUseCase useCase) {

ProgrammersListPresenter presenter = new
ProgrammersListPresenter(useCase);

useCase.setPresenter(presenter);

presenter.setView(activity);

return presenter;

}



@Provides ProgrammersListConnector provideProgrammersListConnector()
{

return new ProgrammersListConnector(activity);

}

}
#AdvArchMobile
@Module class ProgrammersListModule(private val activity: ProgrammersListActivity) {

@Provides fun provideProgrammersListPresenter(useCase:
ShowProgrammersListUseCase): ProgrammersListPresenter =

ProgrammersListPresenter(useCase = useCase).apply {

useCase.presenter = this

view = activity

}



@Provides fun provideProgrammersListConnector() = ProgrammersListConnector(view
= activity)

}
Conciseness (code)
@Module public class ProgrammersListModule {

private ProgrammersListActivity activity;



public ProgrammersListModule(ProgrammersListActivity activity) { this.activity = activity; }



@Provides ProgrammersListPresenter provideProgrammersListPresenter(ShowProgrammersListUseCase useCase) {

ProgrammersListPresenter presenter = new ProgrammersListPresenter(useCase);

useCase.setPresenter(presenter);

presenter.setView(activity);

return presenter;

}



@Provides ProgrammersListConnector provideProgrammersListConnector() {

return new ProgrammersListConnector(activity);

}

}
#AdvArchMobile
@Module class ProgrammersListModule(private val
activity: ProgrammersListActivity) {

@Provides fun
provideProgrammersListPresenter(useCase:
ShowProgrammersListUseCase): ProgrammersListPresenter =

ProgrammersListPresenter(useCase =
useCase).apply {

useCase.presenter = this

view = activity

}



@Provides fun provideProgrammersListConnector() =
ProgrammersListConnector(view = activity)

}
Conciseness (code)
#AdvArchMobile
Conciseness (test)
@Test public void
itemIsConfiguredWithNameOfFetchedProgrammer() {

ProgrammersListItemView item =
Mockito.mock(ProgrammersListItemView.class);

List<ProgrammerResponse> data = new
ArrayList<ProgrammerResponse>() {{

add(TestUtils.createMainProgrammerResponse());

add(TestUtils.createAltProgrammerResponse());

}};

ArgumentCaptor<String> captor =
ArgumentCaptor.forClass(String.class);

sut.presentProgrammers(data);

sut.configureItem(item, 1);

verify(item).displayName(captor.capture());

assertEquals(TestData.programmerAltFullName,
captor.getValue());

}
#AdvArchMobile
@Test fun itemIsConfiguredWithNameOfFetchedProgrammer() {

val item = mock<ProgrammersListItemView>()

val data = listOf(TestData.createMainProgrammerResponse(),

TestData.createAltProgrammerResponse())

sut.present(programmers = data)



sut.configureItem(item, 1)



argumentCaptor<String>().apply {

verify(item).displayName(capture())

assertEquals(TestData.altFullName, lastValue)

}

}
Conciseness
@Test public void itemIsConfiguredWithNameOfFetchedProgrammer() {

ProgrammersListItemView item = Mockito.mock(ProgrammersListItemView.class);

List<ProgrammerResponse> data = new ArrayList<ProgrammerResponse>() {{

add(TestUtils.createMainProgrammerResponse());

add(TestUtils.createAltProgrammerResponse());

}};

ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);

sut.presentProgrammers(data);

sut.configureItem(item, 1);

verify(item).displayName(captor.capture());

assertEquals(TestData.programmerAltFullName, captor.getValue());

}
#AdvArchMobile
@Test fun itemIsConfiguredWithNameOfFetchedProgrammer() {

val item = mock<ProgrammersListItemView>()

val data =
listOf(TestData.createMainProgrammerResponse(),

TestData.createAltProgrammerResponse())

sut.present(programmers = data)



sut.configureItem(item, 1)



argumentCaptor<String>().apply {

verify(item).displayName(capture())

assertEquals(TestData.altFullName, lastValue)

}

}
Conciseness
Data Classes
#AdvArchMobile
Entities
data class Programmer(
val firstName: String,
val lastName: String,
val emacs: Int, val caffeine: Int,

val realProgrammerRating: Int,
val interviewDate: Date,
val favorite: Boolean) {

val fullName: String

get() = "$firstName $lastName"

}
#AdvArchMobile
But
★ Not a value type
★ No defensive copy
#AdvArchMobile
Defensive Copying
data class Entity
private constructor(var private _date: Date) {
companion object {
fun create(date: Date): Entity =
Entity(_date = Date(date.time))
}
var date: Date = Date(_date.time)
get() = Date(field.time)
set(value) {
field = Date(date.time)
}
}
Extensions
#AdvArchMobile
Presentation Logic
fun Date.relativeDateFormat(origin: Date = Date()): String {

fun differenceInDays(date1: Date, date2: Date): Long {

val MILLISECONDS_IN_A_DAY = 24 * 60 * 60 * 1000

return (date1.time - date2.time) /
MILLISECONDS_IN_A_DAY

}



val daysAgo = differenceInDays(origin, this)

return when {

daysAgo < 0 -> "In the future"

daysAgo < 1 -> "Today"

daysAgo < 7 -> "Less than a week ago"

daysAgo < 30 -> "Less than a month ago"

daysAgo < 365 -> "Less than a year ago"

else -> "Long time ago"

}

}
#AdvArchMobile
But
★ A class cannot implement an interface using
extensions
★ Methods are declared independently
Property Delegation
#AdvArchMobile
Observation
data class ProductRequest(var name: String, var units: Int)
class Presenter() {
var request: ProductRequest by Delegates.observable(ProductRequest(name="",
units=0)) {
prop, old, new ->
requestChanged()
}
fun requestChanged() { print("Request: $request”) }
fun changeDoesNotTrigger() {
request.name = "Something"
request.units = 1
}
fun completeChangeThatTriggers() {
request = ProductRequest(name="Else", units= 2)
}
}
#AdvArchMobile
Delegating Reference
Type
class WeakReferenceHolder<T, U> {

private var propertyRef: WeakReference<U>? = null



operator fun getValue(t: T, property: KProperty<*>): U? =
propertyRef?.get()



operator fun setValue(t: T, property: KProperty<*>, newValue: U?)
{

propertyRef = if (newValue != null) {

WeakReference(newValue)

} else {

null

}

}

}

var view: ProgrammersListView? by
WeakReferenceHolder<ProgrammersListPresenter, ProgrammersListView>()
Sealed Classes
Enum
considered
harmful
#AdvArchMobile
Avoid Enums
★ Space
★ Performance
Sealed
Classes
Too!
#AdvArchMobile
Don’t*
sealed class Interactor {
class ShowProducts(val completion: ()-
>Unit): Interactor() {}
class DeleteProduct(id: String,
completion: ()->Unit) {}
}
when (interactor) {
is ShowProducts -> …
}
#AdvArchMobile
Do
sealed class Result<V: Any, E:
Exception> {
class Success<V: Any, E:
Exception>(val value: V) : Result<V,
E>() {//…}
class Failure<V: Any, E:
Exception>(val error: E) : Result<V,
E>() {//…}
}
Recap
#AdvArchMobile
Recap
★ Kotlin makes advanced architectures easier
★ Learn your options and choose
★ Still learning the idioms, work with the
community
Thank
You!
@jdortiz
#AdvArchMobile

More Related Content

PDF
Qt for Beginners Part 3 - QML and Qt Quick
 
PDF
Best Practices in Qt Quick/QML - Part IV
 
PDF
Best Practices in Qt Quick/QML - Part II
 
PDF
QVariant, QObject — Qt's not just for GUI development
 
PPTX
Hello, QML
PDF
One Year of Clean Architecture - The Good, The Bad and The Bob
PDF
Qt for beginners part 2 widgets
 
PDF
The Future of Qt Widgets
Qt for Beginners Part 3 - QML and Qt Quick
 
Best Practices in Qt Quick/QML - Part IV
 
Best Practices in Qt Quick/QML - Part II
 
QVariant, QObject — Qt's not just for GUI development
 
Hello, QML
One Year of Clean Architecture - The Good, The Bad and The Bob
Qt for beginners part 2 widgets
 
The Future of Qt Widgets

What's hot (20)

PDF
Best Practices in Qt Quick/QML - Part 1 of 4
 
PDF
Building Native Apps- A Digital Canvas for Coders and Designers with Walter Luh
PDF
Qt Widget In-Depth
PDF
Basics of Model/View Qt programming
 
PDF
Practical Model View Programming (Roadshow Version)
PDF
Practical Model View Programming
PDF
The Next Generation Qt Item Views
PPTX
Immutable Libraries for React
PDF
Petri Niemi Qt Advanced Part 1
PPT
CodeMash - Building Rich Apps with Groovy SwingBuilder
PDF
AngularJs in Las Palmas de GC
PPTX
Practical QML - Key Navigation, Dynamic Language and Theme Change
PPT
Ken 20150306 心得分享
PDF
Integrating React.js Into a PHP Application: Dutch PHP 2019
PDF
C# Advanced L02-Operator Overloading+Indexers+UD Conversion
PDF
Performant APIs with GraphQL and PHP (Dutch PHP 2019)
DOC
Oops lab manual2
PDF
Receipt processing with Google Cloud Platform and the Google Assistant
ODP
Treinamento Qt básico - aula III
PDF
Why Grails?
Best Practices in Qt Quick/QML - Part 1 of 4
 
Building Native Apps- A Digital Canvas for Coders and Designers with Walter Luh
Qt Widget In-Depth
Basics of Model/View Qt programming
 
Practical Model View Programming (Roadshow Version)
Practical Model View Programming
The Next Generation Qt Item Views
Immutable Libraries for React
Petri Niemi Qt Advanced Part 1
CodeMash - Building Rich Apps with Groovy SwingBuilder
AngularJs in Las Palmas de GC
Practical QML - Key Navigation, Dynamic Language and Theme Change
Ken 20150306 心得分享
Integrating React.js Into a PHP Application: Dutch PHP 2019
C# Advanced L02-Operator Overloading+Indexers+UD Conversion
Performant APIs with GraphQL and PHP (Dutch PHP 2019)
Oops lab manual2
Receipt processing with Google Cloud Platform and the Google Assistant
Treinamento Qt básico - aula III
Why Grails?
Ad

Similar to Home Improvement: Architecture & Kotlin (20)

PDF
Architecture Patterns in Practice with Kotlin. UA Mobile 2017.
PDF
Adapting clean architecture in android apps
PDF
How to become an Android dev starting from iOS (and vice versa)
PDF
Jorge D. Ortiz Fuentes "Hands on Implementation of Clean Architecture for And...
PDF
Android clean architecture workshop 3h edition
PDF
Android meetup
PPTX
Kotlin decoration - February Berlin Kotlin Meetup
PDF
Building Modern Apps using Android Architecture Components
PDF
Clean Architecture @ Taxibeat
PDF
My way to clean android (EN) - Android day salamanca edition
PPTX
The Best Way to Become an Android Developer Expert with Android Jetpack
PDF
Kotlin in practice
PPSX
SOLID Principles and The Clean Architecture
PPTX
MV(X) architecture patterns
PDF
Современная архитектура Android-приложений - Archetype / Степан Гончаров (90 ...
PDF
My way to clean android - Android day salamanca edition
PDF
Kotlin Multiplatform in Action - Alexandr Pogrebnyak - IceRockDev
PDF
A Separation of Concerns: Clean Architecture on Android
PDF
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Architecture Patterns in Practice with Kotlin. UA Mobile 2017.
Adapting clean architecture in android apps
How to become an Android dev starting from iOS (and vice versa)
Jorge D. Ortiz Fuentes "Hands on Implementation of Clean Architecture for And...
Android clean architecture workshop 3h edition
Android meetup
Kotlin decoration - February Berlin Kotlin Meetup
Building Modern Apps using Android Architecture Components
Clean Architecture @ Taxibeat
My way to clean android (EN) - Android day salamanca edition
The Best Way to Become an Android Developer Expert with Android Jetpack
Kotlin in practice
SOLID Principles and The Clean Architecture
MV(X) architecture patterns
Современная архитектура Android-приложений - Archetype / Степан Гончаров (90 ...
My way to clean android - Android day salamanca edition
Kotlin Multiplatform in Action - Alexandr Pogrebnyak - IceRockDev
A Separation of Concerns: Clean Architecture on Android
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Ad

More from Jorge Ortiz (20)

PDF
Tell Me Quando - Implementing Feature Flags
PDF
Unit Test your Views
PDF
Control your Voice like a Bene Gesserit
PDF
Kata gilded rose en Golang
PDF
CYA: Cover Your App
PDF
Refactor your way forward
PDF
201710 Fly Me to the View - iOS Conf SG
PDF
Architectural superpowers
PDF
Architecting Alive Apps
PDF
iOS advanced architecture workshop 3h edition
PDF
To Protect & To Serve
PDF
Clean architecture workshop
PDF
Escape from Mars
PDF
Why the Dark Side should use Swift and a SOLID Architecture
PDF
Dependence day insurgence
PDF
Architectural superpowers
PDF
TDD for the masses
PDF
7 Stages of Unit Testing in iOS
PDF
Building for perfection
PDF
TDD by Controlling Dependencies
Tell Me Quando - Implementing Feature Flags
Unit Test your Views
Control your Voice like a Bene Gesserit
Kata gilded rose en Golang
CYA: Cover Your App
Refactor your way forward
201710 Fly Me to the View - iOS Conf SG
Architectural superpowers
Architecting Alive Apps
iOS advanced architecture workshop 3h edition
To Protect & To Serve
Clean architecture workshop
Escape from Mars
Why the Dark Side should use Swift and a SOLID Architecture
Dependence day insurgence
Architectural superpowers
TDD for the masses
7 Stages of Unit Testing in iOS
Building for perfection
TDD by Controlling Dependencies

Recently uploaded (20)

PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
PDF
Softaken Excel to vCard Converter Software.pdf
PDF
Understanding Forklifts - TECH EHS Solution
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PPTX
ai tools demonstartion for schools and inter college
PPTX
Reimagine Home Health with the Power of Agentic AI​
PDF
wealthsignaloriginal-com-DS-text-... (1).pdf
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PDF
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
PPTX
L1 - Introduction to python Backend.pptx
PDF
System and Network Administration Chapter 2
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PDF
medical staffing services at VALiNTRY
PPTX
Introduction to Artificial Intelligence
2025 Textile ERP Trends: SAP, Odoo & Oracle
Softaken Excel to vCard Converter Software.pdf
Understanding Forklifts - TECH EHS Solution
Adobe Illustrator 28.6 Crack My Vision of Vector Design
ai tools demonstartion for schools and inter college
Reimagine Home Health with the Power of Agentic AI​
wealthsignaloriginal-com-DS-text-... (1).pdf
Internet Downloader Manager (IDM) Crack 6.42 Build 41
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
L1 - Introduction to python Backend.pptx
System and Network Administration Chapter 2
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
Navsoft: AI-Powered Business Solutions & Custom Software Development
How to Migrate SBCGlobal Email to Yahoo Easily
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
medical staffing services at VALiNTRY
Introduction to Artificial Intelligence

Home Improvement: Architecture & Kotlin

  • 1. Home Improvement: Architecture & Kotlin Jorge D. Ortiz-Fuentes @jdortiz
  • 9. Dependency Inversion Principle High Level Low LevelAbstraction Low Level
  • 11. #AdvArchMobile Architecture Components ★ Awesome starting point ★ View Models (inner layer) depend on the SDK:AndroidViewModel (outer layer)
  • 13. #AdvArchMobile Kotlin ★ Conciseness ★ Data Classes ★ Extensions ★ Property Delegation ★ Sealed Classes
  • 15. #AdvArchMobile Conciseness (code) @Module public class ProgrammersListModule {
 private ProgrammersListActivity activity;
 
 public ProgrammersListModule(ProgrammersListActivity activity) { this.activity = activity; }
 
 @Provides ProgrammersListPresenter provideProgrammersListPresenter(ShowProgrammersListUseCase useCase) {
 ProgrammersListPresenter presenter = new ProgrammersListPresenter(useCase);
 useCase.setPresenter(presenter);
 presenter.setView(activity);
 return presenter;
 }
 
 @Provides ProgrammersListConnector provideProgrammersListConnector() {
 return new ProgrammersListConnector(activity);
 }
 }
  • 16. #AdvArchMobile @Module class ProgrammersListModule(private val activity: ProgrammersListActivity) {
 @Provides fun provideProgrammersListPresenter(useCase: ShowProgrammersListUseCase): ProgrammersListPresenter =
 ProgrammersListPresenter(useCase = useCase).apply {
 useCase.presenter = this
 view = activity
 }
 
 @Provides fun provideProgrammersListConnector() = ProgrammersListConnector(view = activity)
 } Conciseness (code) @Module public class ProgrammersListModule {
 private ProgrammersListActivity activity;
 
 public ProgrammersListModule(ProgrammersListActivity activity) { this.activity = activity; }
 
 @Provides ProgrammersListPresenter provideProgrammersListPresenter(ShowProgrammersListUseCase useCase) {
 ProgrammersListPresenter presenter = new ProgrammersListPresenter(useCase);
 useCase.setPresenter(presenter);
 presenter.setView(activity);
 return presenter;
 }
 
 @Provides ProgrammersListConnector provideProgrammersListConnector() {
 return new ProgrammersListConnector(activity);
 }
 }
  • 17. #AdvArchMobile @Module class ProgrammersListModule(private val activity: ProgrammersListActivity) {
 @Provides fun provideProgrammersListPresenter(useCase: ShowProgrammersListUseCase): ProgrammersListPresenter =
 ProgrammersListPresenter(useCase = useCase).apply {
 useCase.presenter = this
 view = activity
 }
 
 @Provides fun provideProgrammersListConnector() = ProgrammersListConnector(view = activity)
 } Conciseness (code)
  • 18. #AdvArchMobile Conciseness (test) @Test public void itemIsConfiguredWithNameOfFetchedProgrammer() {
 ProgrammersListItemView item = Mockito.mock(ProgrammersListItemView.class);
 List<ProgrammerResponse> data = new ArrayList<ProgrammerResponse>() {{
 add(TestUtils.createMainProgrammerResponse());
 add(TestUtils.createAltProgrammerResponse());
 }};
 ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
 sut.presentProgrammers(data);
 sut.configureItem(item, 1);
 verify(item).displayName(captor.capture());
 assertEquals(TestData.programmerAltFullName, captor.getValue());
 }
  • 19. #AdvArchMobile @Test fun itemIsConfiguredWithNameOfFetchedProgrammer() {
 val item = mock<ProgrammersListItemView>()
 val data = listOf(TestData.createMainProgrammerResponse(),
 TestData.createAltProgrammerResponse())
 sut.present(programmers = data)
 
 sut.configureItem(item, 1)
 
 argumentCaptor<String>().apply {
 verify(item).displayName(capture())
 assertEquals(TestData.altFullName, lastValue)
 }
 } Conciseness @Test public void itemIsConfiguredWithNameOfFetchedProgrammer() {
 ProgrammersListItemView item = Mockito.mock(ProgrammersListItemView.class);
 List<ProgrammerResponse> data = new ArrayList<ProgrammerResponse>() {{
 add(TestUtils.createMainProgrammerResponse());
 add(TestUtils.createAltProgrammerResponse());
 }};
 ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
 sut.presentProgrammers(data);
 sut.configureItem(item, 1);
 verify(item).displayName(captor.capture());
 assertEquals(TestData.programmerAltFullName, captor.getValue());
 }
  • 20. #AdvArchMobile @Test fun itemIsConfiguredWithNameOfFetchedProgrammer() {
 val item = mock<ProgrammersListItemView>()
 val data = listOf(TestData.createMainProgrammerResponse(),
 TestData.createAltProgrammerResponse())
 sut.present(programmers = data)
 
 sut.configureItem(item, 1)
 
 argumentCaptor<String>().apply {
 verify(item).displayName(capture())
 assertEquals(TestData.altFullName, lastValue)
 }
 } Conciseness
  • 22. #AdvArchMobile Entities data class Programmer( val firstName: String, val lastName: String, val emacs: Int, val caffeine: Int,
 val realProgrammerRating: Int, val interviewDate: Date, val favorite: Boolean) {
 val fullName: String
 get() = "$firstName $lastName"
 }
  • 23. #AdvArchMobile But ★ Not a value type ★ No defensive copy
  • 24. #AdvArchMobile Defensive Copying data class Entity private constructor(var private _date: Date) { companion object { fun create(date: Date): Entity = Entity(_date = Date(date.time)) } var date: Date = Date(_date.time) get() = Date(field.time) set(value) { field = Date(date.time) } }
  • 26. #AdvArchMobile Presentation Logic fun Date.relativeDateFormat(origin: Date = Date()): String {
 fun differenceInDays(date1: Date, date2: Date): Long {
 val MILLISECONDS_IN_A_DAY = 24 * 60 * 60 * 1000
 return (date1.time - date2.time) / MILLISECONDS_IN_A_DAY
 }
 
 val daysAgo = differenceInDays(origin, this)
 return when {
 daysAgo < 0 -> "In the future"
 daysAgo < 1 -> "Today"
 daysAgo < 7 -> "Less than a week ago"
 daysAgo < 30 -> "Less than a month ago"
 daysAgo < 365 -> "Less than a year ago"
 else -> "Long time ago"
 }
 }
  • 27. #AdvArchMobile But ★ A class cannot implement an interface using extensions ★ Methods are declared independently
  • 29. #AdvArchMobile Observation data class ProductRequest(var name: String, var units: Int) class Presenter() { var request: ProductRequest by Delegates.observable(ProductRequest(name="", units=0)) { prop, old, new -> requestChanged() } fun requestChanged() { print("Request: $request”) } fun changeDoesNotTrigger() { request.name = "Something" request.units = 1 } fun completeChangeThatTriggers() { request = ProductRequest(name="Else", units= 2) } }
  • 30. #AdvArchMobile Delegating Reference Type class WeakReferenceHolder<T, U> {
 private var propertyRef: WeakReference<U>? = null
 
 operator fun getValue(t: T, property: KProperty<*>): U? = propertyRef?.get()
 
 operator fun setValue(t: T, property: KProperty<*>, newValue: U?) {
 propertyRef = if (newValue != null) {
 WeakReference(newValue)
 } else {
 null
 }
 }
 }
 var view: ProgrammersListView? by WeakReferenceHolder<ProgrammersListPresenter, ProgrammersListView>()
  • 33. #AdvArchMobile Avoid Enums ★ Space ★ Performance Sealed Classes Too!
  • 34. #AdvArchMobile Don’t* sealed class Interactor { class ShowProducts(val completion: ()- >Unit): Interactor() {} class DeleteProduct(id: String, completion: ()->Unit) {} } when (interactor) { is ShowProducts -> … }
  • 35. #AdvArchMobile Do sealed class Result<V: Any, E: Exception> { class Success<V: Any, E: Exception>(val value: V) : Result<V, E>() {//…} class Failure<V: Any, E: Exception>(val error: E) : Result<V, E>() {//…} }
  • 36. Recap
  • 37. #AdvArchMobile Recap ★ Kotlin makes advanced architectures easier ★ Learn your options and choose ★ Still learning the idioms, work with the community