$30 off During Our Annual Pro Sale. View Details »

Server Driven UI Workflow

Server Driven UI Workflow

Video: https://youtu.be/eHGFpRj_3Vk

Deploying an Android app to the play store always contains some cost in it. Furthermore the user isn't always keen to download (again) our latest versioned app. How about doubling the cost of development with the iOS app into account (or Web)?
At Square, we came up with a system in which the server owns the workflow of the client. This means the client doesn't know before hand which screen, which image or text it's gonna show next.

In this talk, we'll:

- Know why Square ended up choosing this system.
- Discover how we built it.
- Look at the challenges, the pros and cons of such an architecture.
- Talk about how we want to alter it for the future.

Attendees to this talk will be expose to solutions for problems every company is facing but don't address.

Benoît Quenaudon

April 24, 2019
Tweet

More Decks by Benoît Quenaudon

Other Decks in Programming

Transcript

  1. Server Driven UI workflow
    Benoît Quenaudon @oldergod
    Cash App

    View Slide

  2. View Slide

  3. A

    View Slide

  4. A

    View Slide

  5. View Slide

  6. View Slide

  7. View Slide

  8. A

    View Slide

  9. View Slide

  10. A

    View Slide

  11. A

    View Slide

  12. View Slide

  13. A

    View Slide

  14. View Slide

  15. A

    View Slide

  16. View Slide

  17. A

    View Slide

  18. View Slide

  19. A

    View Slide

  20. View Slide

  21. A

    View Slide

  22. View Slide

  23. A

    View Slide

  24. A

    View Slide

  25. View Slide

  26. A

    View Slide

  27. View Slide

  28. A

    View Slide

  29. View Slide

  30. View Slide

  31. Cash 1.0

    View Slide

  32. A

    View Slide

  33. A

    View Slide

  34. A

    View Slide

  35. View Slide

  36. Steps

    View Slide

  37. Steps
    • LINK_CARD
    • IDENTIFICATION_VERIFICATION (IDV)
    • CONFIRMATION

    View Slide

  38. enum Steps {
    LINK_CARD = 1;
    IDV = 2;
    CONFIRMATION = 3;
    }

    View Slide

  39. Cash 2.0

    View Slide

  40. View Slide

  41. View Slide

  42. enum Steps {
    LINK_CARD = 1;
    IDV = 2;
    CONFIRMATION = 3;
    }

    View Slide

  43. Blockers

    View Slide

  44. message IdentityVerificationBlocker {
    optional bool requires_birthdate = 1;
    optional bool requires_full_ssn = 2;
    optional bool requires_last_four_ssn = 3;
    optional bool requires_full_name = 4;
    optional bool requires_address = 5;
    }

    View Slide

  45. ...and the app kept growing

    View Slide

  46. Server sends back ExecuteContractResponse
    if (response is ExecuteContractResponse) {
    return R.layout.status_result_view;
    }
    Pass ExecuteContractResponse#statusResult to the view

    View Slide

  47. Server sends back ExecuteContractResponse
    if (response is ExecuteContractResponse) {
    return R.layout.status_result_view;
    }
    Pass ExecuteContractResponse#statusResult to the view

    View Slide

  48. Server sends back ExecuteContractResponse
    if (response is ExecuteContractResponse) {
    return R.layout.status_result_view;
    }
    Pass ExecuteContractResponse#statusResult to the view

    View Slide

  49. message StatusResult {a
    }d

    View Slide

  50. B
    C
    D
    message StatusResult {a
    enum Icon {b
    SUCCESS = 1;
    PENDING = 2;
    FAILURE = 3;
    ACTION_REQUIRED = 4;
    NONE = 5;
    }c
    optionaloIcon icon = 1;
    }d

    View Slide

  51. a
    C
    D
    message StatusResult {a
    enum Icon {b
    SUCCESS = 1;
    PENDING = 2;
    FAILURE = 3;
    ACTION_REQUIRED = 4;
    NONE = 5;
    }c
    optionaloIcon icon = 1;
    optionalostring text = 2;
    }d

    View Slide

  52. B
    a
    C
    message StatusResult {a
    enum Icon {b
    SUCCESS = 1;
    PENDING = 2;
    FAILURE = 3;
    ACTION_REQUIRED = 4;
    NONE = 5;
    }c
    optionaloIcon icon = 1;
    optionalostring text = 2;
    optionaloStatusResultButton primary_button = 3;
    optionaloStatusResultButton secondary_button = 4;
    }d

    View Slide

  53. B
    a
    C
    message StatusResult {a
    enum Icon {b
    SUCCESS = 1;
    PENDING = 2;
    FAILURE = 3;
    ACTION_REQUIRED = 4;
    NONE = 5;
    }c
    optionaloIcon icon = 1;
    optionalostring text = 2;
    optionaloStatusResultButton primary_button = 3;
    optionaloStatusResultButton secondary_button = 4;
    }d
    message StatusResultButton {
    enumoButtonAction {
    HOME_SCREENz=z1;
    LINK_CARDz=z2;
    OPEN_URLz=z3;
    }
    optionalnButtonAction actionz=z1;
    optionalnstring textz=z2;
    optionalnstring urlz=z3;
    }

    View Slide

  54. B
    a
    D
    message StatusResult {a
    enum Icon {b
    SUCCESS = 1;
    PENDING = 2;
    FAILURE = 3;
    ACTION_REQUIRED = 4;
    NONE = 5;
    }c
    optionaloIcon icon = 1;
    optionalostring text = 2;
    optionaloStatusResultButton primary_button = 3;
    optionaloStatusResultButton secondary_button = 4;
    optionalostring promo_textw=w5;
    }d

    View Slide

  55. message StatusResult {a
    enum Icon {b
    SUCCESS = 1;
    PENDING = 2;
    FAILURE = 3;
    ACTION_REQUIRED = 4;
    NONE = 5;
    }c
    optionaloIcon icon = 1;
    optionalostring text = 2;
    optionaloStatusResultButton primary_button = 3;
    optionaloStatusResultButton secondary_button = 4;
    optionalostring promo_textw=w5;
    }d

    View Slide

  56. ...and the app kept growing

    View Slide

  57. View Slide

  58. Cash 3.0

    View Slide

  59. • Skippability
    • Ordering
    • Scalability

    View Slide

  60. Form Blocker

    View Slide

  61. ButtonElement
    LocalImageElement
    RemoteImageElement
    MoneyElement
    SpacerElement
    TextElement
    CustomizedCardElement
    AddressElement
    TextInputElement
    OptionPickerElement
    DetailRowElement
    CurrencyConversionFlagsElement

    View Slide

  62. message FormBlocker {
    oneof Element {
    ButtonElement button_element = 1;
    LocalImageElement local_image_element = 2;
    RemoteImageElement remote_image_element = 3;
    MoneyElement money_element = 4;
    SpacerElement spacer_element = 5;
    TextElement text_element = 6;
    CustomizedCardElement customized_card_element = 7;
    AddressElement address_element = 9;
    TextInputElement text_input_element = 10;
    OptionPickerElement option_picker_element = 11;
    DetailRowElement detail_row_element = 12;
    CurrencyConversionFlagsElement currency_conversion_flags_element = 13;
    }
    repeated Element elements = 1;
    optional BlockerAction primary_action = 2;
    optional BlockerAction secondary_action = 3;
    }
    ButtonElement
    LocalImageElement
    RemoteImageElement
    MoneyElement
    SpacerElement
    TextElement
    CustomizedCardElement
    AddressElement
    TextInputElement
    OptionPickerElement
    DetailRowElement
    CurrencyConversionFlagsElement

    View Slide

  63. message FormBlocker {
    oneof Element {
    ButtonElement button_element = 1;
    LocalImageElement local_image_element = 2;
    RemoteImageElement remote_image_element = 3;
    MoneyElement money_element = 4;
    SpacerElement spacer_element = 5;
    TextElement text_element = 6;
    CustomizedCardElement customized_card_element = 7;
    AddressElement address_element = 9;
    TextInputElement text_input_element = 10;
    OptionPickerElement option_picker_element = 11;
    DetailRowElement detail_row_element = 12;
    CurrencyConversionFlagsElement currency_conversion_flags_element = 13;
    }
    repeated Element elements = 1;
    optional BlockerAction primary_action = 2;
    optional BlockerAction secondary_action = 3;
    }

    View Slide

  64. View Slide

  65. Option Picker Element
    Primary Action
    Text Element
    Primary Action
    Text Input Element
    Text Element

    View Slide

  66. Data Format Sharing

    View Slide

  67. [On iOS, we use a] convoluted series of script

    View Slide

  68. Challenges

    View Slide

  69. Backporting

    View Slide

  70. Percent of users active per app versions since January 2019

    View Slide

  71. 0.744% ≈ 50・000 customers

    View Slide

  72. • Force update
    • Redirect to Web App
    • Smoke&Mirror usage of old blockers
    • Use fallback blocker
    • Don't send blocker - skip it

    View Slide

  73. • Backporting
    • Bug Hunting
    • Complexity
    • Integration
    Challenges

    View Slide

  74. Pros

    View Slide

  75. • Real logic lives in only one platform
    • Lot of features/fixes don't involve clients at all
    • Client logic is simple - to some degree
    • Changes available without client updates

    View Slide

  76. Server Driven Design System?

    View Slide

  77. Benoît Quenaudon @oldergod
    Fin
    Cash App

    View Slide