Slide 1

Slide 1 text

Building SDKs with clean architecture babylon Londroid April 2018 Joao Alves and Sakis Kaliakoudas

Slide 2

Slide 2 text

Babylon Services

Slide 3

Slide 3 text

● Partner agreement to ship babylon services as SDKs ● 2 months to ship initial versions ● 5 months for them to integrate ● 3 months of going through a multi phase QA Lift off

Slide 4

Slide 4 text

● Initial discussion ● Many parallel streams ● Usually 2 developers per SDK ● At most 4 teams working in parallel in different SDKs Planning

Slide 5

Slide 5 text

How many SDKs?

Slide 6

Slide 6 text

Babylon SDKs Appointments SDK Authentication SDK Consultation SDK User SDK NHS GP SDK Maps SDK Clinical Records SDK Payment SDK AI Chatbot SDK Monitor SDK Notifications SDK Common SDK Wrapper

Slide 7

Slide 7 text

What did the code look like?

Slide 8

Slide 8 text

Views Presenters Interactors Gateways/ Repositories Retrofit Services Clean architecture layers

Slide 9

Slide 9 text

Views Presenters Interactors Gateways/ Repositories Retrofit Services What to ship?

Slide 10

Slide 10 text

View related Domain Views Presenters Interactors Gateways/ Repositories Retrofit Services What to ship?

Slide 11

Slide 11 text

Views Presenters Interactors Gateways/ Repositories Retrofit Services Legacy

Slide 12

Slide 12 text

Views Presenters Interactors Gateways/ Repositories Retrofit Services MVP

Slide 13

Slide 13 text

Views Presenters Interactors Gateways/ Repositories Retrofit Services MVP + Clean

Slide 14

Slide 14 text

Moving stuff around App Gateways/ Repositories Interactors Entities SDK 1 SDK 2 SDK N App Non-SDK Interactors Non-SDK Gateways SDK Gateways Entities

Slide 15

Slide 15 text

Moving stuff around App Gateways/ Repositories Interactors Entities App Non-SDK Interactors Non-SDK Gateways SDK Gateways Entities SDK 1 SDK 2 SDK N

Slide 16

Slide 16 text

Moving stuff around App Gateways/ Repositories Interactors Entities App Non-SDK Interactors Non-SDK Gateways SDK Gateways Entities SDK 1 SDK 2 SDK N

Slide 17

Slide 17 text

Gateways and entities sharing SDK Gateways Entities SDK 1 SDK 2 SDK N

Slide 18

Slide 18 text

Splitting it up Gateways 1 Gateways 2 Gateways N Entities SDK 1 SDK 2 SDK N

Slide 19

Slide 19 text

class DoSomethingInteractor{ private Gateway gateway; @Inject public DoSomethingInteractor(Gateway gateway){ this.gateway = gateway; } Disposable execute(Request request, Callback callback){ ... } } But what does it look like

Slide 20

Slide 20 text

interface Callback{ void onSuccess(Result result); void onError(Exception exception); } class Request { String someField1; String someField2; } class Result { String someField3; String someField4; } But what does it look like

Slide 21

Slide 21 text

class DoSomethingInteractor{ private Gateway gateway; @Inject public DoSomethingInteractor(Gateway gateway){ this.gateway = gateway; } Disposable execute(Request request, Callback callback){ ... } } But what does it look like

Slide 22

Slide 22 text

Client Clinical Records SDK Wrapping the interactors ClinicalRecordsApi clinicalRecordsApi = ClinicalRecordsSdk.getApiInstance(); clinicalRecordsApi.doSomething(request, callback); Client requests an instance of the API

Slide 23

Slide 23 text

Clinical Records API Client Clinical Records SDK Wrapping the interactors ClinicalRecordsApi clinicalRecordsApi = ClinicalRecordsSdk.getApiInstance(); clinicalRecordsApi.doSomething(request, callback); The SDK class instantiates the API

Slide 24

Slide 24 text

Clinical Records API Client Clinical Records SDK Wrapping the interactors ClinicalRecordsApi clinicalRecordsApi = ClinicalRecordsSdk.getApiInstance(); clinicalRecordsApi.doSomething(request, callback); Returns it to the client

Slide 25

Slide 25 text

Clinical Records API Interactors Interactors Interactors Gateways Interactors Entities Client Clinical Records SDK Wrapping the interactors ClinicalRecordsApi clinicalRecordsApi = ClinicalRecordsSdk.getApiInstance(); clinicalRecordsApi.doSomething(request, callback); Client can access all the SDK interactors via the API

Slide 26

Slide 26 text

SDK API Interface /** * Get list of appointments for the main user and its registered children * (if any). * * @param request the request object that contains the required information * to get the user appointments. * @param output the callback through which the results are returned. * * @return an RxJava 2 {@link Disposable} resource to manage this request. */ Disposable getAppointments(GetAppointmentsRequest request, GetAppointmentsOutput output);

Slide 27

Slide 27 text

String patientId = "patientId"; GetAppointmentsRequest request = GetAppointmentsRequest.create(AppointmentType.UPCOMING, patientId); babylonAppointmentApi.getAppointments(request, new GetAppointmentsOutput() { @Override public void onFetchAppointmentsSuccess(List appointments) { if (appointments.isEmpty()) { getView().showNoAppointments(); } else { getView().showAppointments(appointments); } }}); Presenter using the SDK:

Slide 28

Slide 28 text

Dog fooding ● Using the SDKs inside our Apps ● Local development with local gradle module dependencies ● CI builds the SDKs, publishes them, then builds the app using artifact dependencies

Slide 29

Slide 29 text

Build and deploy Local Maven Repo Artifactory Single Gradle Task ● ~25 releases in 10 months (excluding hotfixes) ● Releases around every 10 days a day an hour a minute

Slide 30

Slide 30 text

Security ● No sensitive information stored locally ● Encryption with Android keystore ● Using Dexguard ● Logging based on environment ● Timber Wrapper

Slide 31

Slide 31 text

Uniquely identifying clients via their public certificate Offline: ● Get certificate hash ● Merge it together with the application id to generate a new hash ● Save this hash inside the SDKs Runtime: ● Calculate the same hash ● Match it against the precomputed value

Slide 32

Slide 32 text

Activities in the SDKs?

Slide 33

Slide 33 text

Kotlin?

Slide 34

Slide 34 text

SDK size ● Trimming all dependencies ● Native libraries ● Dexguard

Slide 35

Slide 35 text

Documentation ● JavaDoc with CheckStyle ● Release notes - from git diff to git code owners ● Sample App ● Wiki page

Slide 36

Slide 36 text

Support ● Slack support ● Dedicated JIRA board ● Daily/Weekly calls

Slide 37

Slide 37 text

Finish line ● Improved code quality ● Much less legacy code ● Modularized project ● Loads of knowledge ● Much bigger user base

Slide 38

Slide 38 text

What does the code look like now?

Slide 39

Slide 39 text

Lessons learned ● Planning + Planning + Planning ● Don’t create silos - merge often ● More logging ● Version controlled documentation

Slide 40

Slide 40 text

● Problems are bound to happen and trust us they will happen. And they don’t come on their own they come in herds. ● Work your way through them and you’ll eventually get to the finish line. Don’t Panic

Slide 41

Slide 41 text

Questions? Presented by Joao Alves and Sakis Kaliakoudas Say hi on Twitter & Medium: @jcmsalves & @skaliakoudas PS: we’re hiring, come and talk to us to know more

Slide 42

Slide 42 text

Useful links ● SDK class example: (https://tinyurl.com/MyBossMadeMeDoThis) ● Getting a certificate hash (https://tinyurl.com/tralalatralalo) ● Merging a certificate hash with an application id to generate a new hash (https://tinyurl.com/we-r-hiringgg) ● Calculating the same hash at runtime (https://tinyurl.com/PleaseDontAskQuestions)