Slide 1

Slide 1 text

Hey, you can do it! How to contribute to the client projects.

Slide 2

Slide 2 text

Self introduction JD Security Computer Science Android iOS Mobile Security Server

Slide 3

Slide 3 text

What makes you think it's difficult?

Slide 4

Slide 4 text

I think.. ● To layout UI ● To support multiple device (multiple Screen Resolution) ● To interact many users ○ System ○ User

Slide 5

Slide 5 text

Yeah, but… Is that really the reason?

Slide 6

Slide 6 text

Hmm, We are gonna help you.

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

Let’s break the huddles step by step!

Slide 9

Slide 9 text

Do you know? Clean Architecture Domain Driven Design

Slide 10

Slide 10 text

We have multi-module architecture. The server team has the microservices.. link link awesome slide: awesome doc:

Slide 11

Slide 11 text

If you wanna add some functions to the config service Write the code

Slide 12

Slide 12 text

If you wanna add a feature

Slide 13

Slide 13 text

How do we handle async tasks? fetchAds(param, object : FetchAdsListener { override fun onSuccess(ads: List) { fetContents(param, object : FetchContentsListener { override fun onSuccess(contents: List) { ... } ... } } ... }) Observable .zip(fetchAds(param), fetchContents(param)) { ads, contents -> // do something } fetchAds(param) .flatMap { it.toObservable() } .filter { it.type == TypeVideo } .map { it.transformToCampaign() } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(...) Study ReactiveX

Slide 14

Slide 14 text

We'll do it, you don't. class GetVideoAdCampaignUseCase constructor(...) { operator fun invoke(param: GetVideoAdCampaignUseCaseParam) : Observable = fetchAds(param) .flatMap { it.toObservable() } .filter { it.type == TypeVideo } .map { it.transformToCampaign() } } fun callGetVideoAdCampaignUseCase() { val param = GetVideoAdCampaignUseCaseParam(...) val disposable = GetVideoAdCampaignUseCase(param) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(...) disposables.add(disposable) }

Slide 15

Slide 15 text

How can I fetch the data from other data sources? interface DataSource { fun fetchAds(param: Param) : Observable> } // Delegate to CLAVENGERS class RemoteDataSource constructor( private val serviceApi: ServiceApi // Generated by Retrofit ) : DataSource { override fun fetchAds(param: Param) : Observable> { ... } } class RemoteDataSource constructor( private val serviceApi: ServiceApi // Generated by Swagger ) : DataSource { override fun fetchAds(param: Param) : Observable> { ... } } https://github.com/Buzzvil/buzzapis

Slide 16

Slide 16 text

Before you implement the class ● CMD + SHIFT + T ● Write down the test.

Slide 17

Slide 17 text

It's not that different from the server, is it?

Slide 18

Slide 18 text

So, How about the user interface? Delegate to

Slide 19

Slide 19 text

MVC, MVP, MVVM, MVI, (RIBs) ... I strongly recommend MVP. Because it is super easy. interface Contract { interface View { fun renderLoadingStateView() fun renderLoadedStateView(...) fun renderErrorStateView() } interface Presenter { fun requestLoad() } } class PresenterImpl : Contract.Presenter { override fun requestLoad() { modelLoader.load() .doOnSubscribe { view.renderLoadingStateView()} .subscribe({ model -> view.renderLoadedStateView(model) }, { e -> view.renderErrorStateView() }) } }

Slide 20

Slide 20 text

Now, you've done almost everything. So, really delegate it to

Slide 21

Slide 21 text

Wait… How do I contribute to the iOS?

Slide 22

Slide 22 text

iOS is equivalent to AOS. But.. You should learn Objective-C. #import @import ReactiveObjC; #import #import #import #import @protocol BuzzConfigServiceApi - (RACSignal *)getListConfigsWithRequest:(BuzzApiListConfigsRequest *)request; @end

Slide 23

Slide 23 text

So, I will break the huddle to help you as soon as possible

Slide 24

Slide 24 text

The future Business Logic I will focus on how to share to same business logic on each platform.

Slide 25

Slide 25 text

I’m going to use Multi-platform framework. ● Does that mean using React-Native, Flutter, Ionic, Xamarin? ○ NO! ○ They try to solve almost every task with the same code. ○ However, some features, rendering, and IO operations are prone to unexpected exceptions. ○ Most importantly, there is no code base and we have to work from scratch. ● So, I’m going to use Kotlin Multi Platform. ○ Easy to migrate (AOS already has) ○ I love kotlin. ○ => I will restrict the code base with the same idea as RIBs.

Slide 26

Slide 26 text

https://github.com/uber/RIBs ● Business logic drives the app, not the view tree. Unlike with MV*/VIPER, a RIB does not have to have a view. This means that the app hierarchy is driven by the business logic, not the view tree. ● Independent business logic and view trees. RIBs decouple how the business logic scopes are structured from view hierarchies. This allows the application to have a deep business logic tree, isolating business logic nodes, while maintaining a shallow view hierarchy making layouts, animations and transitions easy.

Slide 27

Slide 27 text

Please join us even before that day comes. Are you ready?

Slide 28

Slide 28 text

We will be watching you 👀

Slide 29

Slide 29 text

Thank you for listening.

Slide 30

Slide 30 text

Q & A