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

Mind map your app (with notes)

Mind map your app (with notes)

My talk – with presenter notes – from NSBudapest meetup held as part of Craft Conf 2018 in Budapest, on May 10th.

If you need version without presenter notes:

It's a short dive into a proper use of Coordinators and Layers architecture to really separate View Controllers into manageable, isolated units.

More Decks by Aleksandar Vacić (Radiant Tap)

Other Decks in Programming


  1. M I N D - M A P
    Y O U R A P P
    A l e k s a n d a r Va c i ć
    C R A F T 2 0 1 8 · N S B u d a p e s t
    Mind-mapping an app…”what the heck that even means”.

    I’d like to think of it as somewhat new approach to architecting an app. Or maybe it’s an old approach, dusted-out from the basement of programming.

    You decide what it is, at the end.

    View Slide

  2. App starts with an idea.
    A business plan would help too,
    but let’s not digress too much.
    App sprouts from an idea. I see a problem that I feel I have a good solution for.

    View Slide

  3. Thus I usually start sketching on paper (and obviousy I’m not the only one).

    View Slide

  4. If you’re lucky to have a proper designer in the team, this rough phase is followed up wirefrmes, where you flesh-out the user stories.

    View Slide

  5. Then User Experience is detailed out, with layouts for each screen and transitions and connections between them.

    View Slide

  6. Finally look & feel is applied on top of the wireframes.

    So, we now need to code this up.

    View Slide

  7. UI / UX is done.
    The only thing left: code
    It is my firm belief that the best code is the code you don’t have to write nor maintain.

    Thus before jumping into Xcode, I first spend as many days as needed to plan code: data models, data flows, what each of those user stories and
    workflows needs to make them a reality.

    This is crucial high-level step as it helps to identify data types before you get deep into the boilerplate code required for collection views and what not.

    View Slide

  8. Some teams use post-it notes. It’s a..good tool..to figure out the details: where each screen fits inside the app, what initiates its display, what data is
    needed to display the content, is data coming (a)sync etc.

    After days of brainstorming and moving little colored paper slips here and there – now you know what View Controllers you need. Where you need to
    implement Delegate pattern so data can flow back. What VC will push which other controllers. What’s being presented as popup and when.

    View Slide

  9. Code is done.
    What’s left to do is the grunt work of actually writing all that code.

    It should be easy, peasy, now…right?

    If only. Heh…

    View Slide

  10. And why: because this is fiction. I don’t know a single, even moderately complex app that is this clean.

    I mean – just look at this lovely UX we have here. You have a home screen, views loads stuff in proper order: promo blocks, some content categories, nice
    browsing system; then somewhere along the line we will have Add-to-cart, display Cart, check Account status (and login if needed) then UX flow proceeds
    with Payment etc.

    View Slide

  11. HomeController
    If you follow UIKit by the book, this means you will HomeController, which will instantiate & display ProductController and give it a list of Products.

    Where, after some cell tap, a ProductDetailsController will be instantiated and passed a single Product from the received list.

    Etc. You are happy, there’s a clear path how the app works.

    So you implement all this, beta 1 is ready and you send it off to all stakeholders for approval and to show off the progress. And then…

    View Slide

  12. They congratulate you and tell you that app needs to be able to jump directly to the Details screen all the way down here. You need to deep link a product
    and needs to be shown instantly after the app start. But, you may say, app needs to load the products list first, then to instantiate the intermediary VCs and
    fetch data sources and only then it can show the product…And they look at you, like “ok, yeah…?”

    Weather you manage to charge the client for that feature creep and change – you still need to do it.

    With the UIKit as it is, you will start to wing it.

    Most likely add some property called deepLinkProduct and then if it’s not nil DetailController will be pushed automatically onto UINC stack without even
    showing the Home and Products browse…

    Oh boy…

    View Slide

  13. Architecture of complex apps is
    ever evolving, quite often in
    unforseen ways.
    Then you follow it up with a Boolean flag here. Another property there. Few more ifs in the business logic of the app to accomodate another new user-flow
    that comes along.

    Over time you add far too many special cases. Your code is a mess where not even you can figure out all the code paths.

    View Slide

  14. – M A R T I N F O W L E R
    “Architectural refactoring is hard, and we’re still
    ignorant of its full costs, but it isn’t impossible.”
    Patterns of Enterprise Application Architecture
    Hence, quite possibly even before you reach ver 1.0, you may need to re-factor your app’s architecture. Depending on what comes up, this may be a partial
    or total rewrite.

    If you think – well, it can’t possibly go really, really bad… – think again.

    View Slide

  15. In order to avoid an insanity like this – that’s a real story, not fiction – you need an architecture that will allow re-factoring of any complexity.

    So: how to prepare yourself for any possible scope change in the project lifetime? In an app of any complexity? (Really infinite).

    View Slide

  16. O N I O N
    Your app needs to be an
    (Psst - I know this is garlic, but bear with me)
    Your app needs to be an onion.
    Lovely, beautiful onion with layers as thin as they can be, so if you add one or remove or replace one it does not break the overal structure.

    You need as composable architecture as possible, with ability to seamlessly plug-in layers that you need.

    Each layer should be self-contained, as much as possible.

    View Slide

  17. Data Delivery
    Data Source
    Data Storage
    You need:

    (1) data storage separated from data sourcing

    (2) data source separated from data delivery

    Because if you combine any of these domains, you are bound to get into a situation where you will repeat the same code in multiple places or be entirelly
    unable to implement a feature.

    View Slide

  18. Data Delivery
    Data Source
    Data Storage
    What’s Delivery mechanism? It can be network (URLSession) or it can be file(s) loaded from the Bundle. Or app’s sandbox. This layer have no idea what it
    deals with - it gets binary Data blob and transfer it to the Source layer.

    Source is usually an API. And another API. Or wrapper for a file hierarchy or chunks of data from socket streaming. It knows what Data blobs actually are
    converts them from Data into JSON or XML. Something that Data Manager can work with.

    Data Manager handles Storage which can be Realm or Core Data or in-memory store. This module convert the raw data formats into classes, structs and
    enums – your Model objects: Product, Cart, Item, Account, Customer, Song, Album etc.

    Anything that comprises your app’s internal data model.

    View Slide

  19. Data Delivery
    Data Source
    Data Storage
    Let’s look at UX flows from before. Everything is sort of fine…

    …until your controllers need to jump hoops.

    Add Product to Cart. 1-click buy which jumps to Payment. Etc.

    VC represented by just one independent post-it note is a lie, because it’s not independent, it’s glued, hard-wired with other VCs around it.

    View Slide

  20. Data Delivery
    Data Source
    Data Storage
    This pile of stuff is (one of) the reason for the so-called MassiveVC problem. The problem does not stop there though.

    What’s missing here..?

    Where are all the data paths between UI and Data – if I add them, this will turn into a ball of twine…

    View Slide

  21. N O T M Y FA U LT … H O N E S T !
    It’s messy as hell.

    View Slide

  22. Data Delivery
    Data Source
    Data Storage
    All that wiring going in and out – that’s not the job for the UIViewController.

    Starting and instantiating UIVCs – that’s also not the job for the UIViewController.

    (This is why I can’t stand UISegue and wish I could burn it out of existence).

    UIKit is digging its own hole here. Let’s stop digging and first get rid of this mess…

    Every one of these boxes should be unaware of any other box.

    Your VCs should be entirely boxed-in. They take some data and use to display a view. They recognize significant actions inside the views and pass them
    along…to something else. They don’t care who is going to react to those actions – their job is to recognize them and pass them along, up the chain.

    View Slide

  23. Data Delivery
    Data Source
    Data Storage
    If VCs deal with just one task, they become small and manageable.

    View Slide

  24. Data Delivery
    Data Source
    Data Storage
    Content VCs shoud not care where they are. In NC, presented as popup, inside PageVC, they literally don’t know nor care.

    But someone else needs to handle these connections, something else should control the UX/data flow…

    View Slide

  25. Data Delivery
    Data Source
    Data Storage
    UI Coordinators
    …and that’s where Coordinators comes in.

    Their only job is to be the wiring between the global data store for the app and various views those data are shown in. Between the VCs. To move the data
    flow along.

    We have one more missing layer here…

    View Slide

  26. Data Delivery
    Data Source
    Data Storage
    UI Coordinators
    …which I call middleware managers.

    These are things like AccountManager which handles what Customer is currently logged in. CartManager which manages the one specific Order being
    built. Etc. This is the business logic of your app.

    Pay attention – this is not Core Data’s job. Data Storage is fairly simplistic, it reads and writes data but does not handle data transactions. For example: it
    knows to create an instance of some Customer object when requested to do so by AccountManager, which knows that this particular instance is specially
    important because it’s a logged-in Customer. DataManager could not care less, it creates the objects, passes it on and forgets about it.

    (Middleware sounds a lot like micro-services which are all the fancy in web backend world right now).

    View Slide

  27. If you manage to separate all this,
    then you don’t need colored post-it notes.
    You can mind-map in code, no intermediary
    prototyping tools required.
    Code Mapping, enabled by…
    (If you manage…)

    (You can mind-map…)

    You just need Xcode and your knowledge of Swift and UIKit.

    (Code Mapping…)

    View Slide

  28. L AY E R S
    A R C H I T E C T U R E
    So let me introduce you to my implementation of LAYERS architecture with middleware and a special kind of Coordinator implementation.

    I promise you it is really this yummy, unlike the onions. Or garlic.

    View Slide

  29. • Coordinator

    Swift implementation of Coordinator pattern, with
    several advanced features
    • Swift-Network

    Thin URLSession wrapper which allow seamless usage
    with Operation and OperationQueue
    • Swift-Essentials

    Various useful extensions, particularly AsyncOperation
    subclass of Operation
    It’s loose puzzle of several Swift micro libraries, all available on my GitHub repository.

    Instead of showing you dry code and explaining those libraries which may take an hour or so, I’m going to show them in action. Which I hope will be
    enough to pick your interest and then you’ll figure them out on your own.

    View Slide

  30. Let’s demo this approach by code-
    mapping a bespoke Spotify app…
    in 15-ish minutes
    ! "
    Let’s DEMO…

    View Slide

  31. Aleksandar Vacić
    Follow me as @radiantav on Twitter.
    Read my iOS dev blog at aplus.rs.
    Use my open source stuff on GitHub.com/radianttap.
    Photos (from Unsplash) by
    • delfi de la Rua
    • Otto Norin
    • Mike Kenneally

    View Slide