Library Oriented Architecture

Part 5: A better architecture for mobile apps

I had my Serverless Architecture plans in place but I hadn't worked on the app in a few months. Swift 4 was on the horizon and I had some down time coming up, perfect time to resurrect this project. I created a fresh new project in XCode, and started setting up my pod file for dependencies. Then I stopped and wondered, I've been using CocoaPods for a long time, is there something better out there? Procrastination at its finest!

Had this been a client project, it would've been pods all the way, but this was another chance for me to hone my craft. With iOS there was really only two choices: CocoaPods and Carthage. Apple had announced the Swift Package Manager (SPM) as part of Swift 3.0, but it was not widely used. I figured this was a good time to check on its progress.

The documentation had a nice little example of using the package manager in a card game. They put the card objects in one package and the shuffle algorithm and dealer functions in two separate packages. I loved the abstraction and decide to use it in my app. Then came the news - SPM doesn't support iOS. You can still use SPM with XCode and iOS, but it takes a bit of manual configuration, I'll write a post about it if people are interested.

Main-App - This project includes the main app settings, provisioning profiles and entitlements, localization, view controllers and views. Everything that's required to deploy the app and everything the user sees. It's also the only project that includes UIKit (I'll come back to this later). Dependency: App-Core

App-Core - This project includes all the business logic, view models, any app wide themes. Dependency: App-Kit and App-Native

App-Kit - The networking code to interface with the APIs and the persistence code for storing data locally. Optionally the data persistence code could be moved into its own library, but in my experience, these two pieces are always closely connected.

App-Native - The data models used in the app, usually just plain structs.

After working with this setup the last few months, lessons learned:

  • Obvious separation of concerns helped me focus on specific tasks.
  • Separating the Main-App from the App-Core, App-Kit and App-Native libraries (which don't rely on UIKit) allowed me to reuse them for other apps like a MacOS, TVOS or a WatchOS app.
  • Another advantage of not having UIKit is that App-Core, App-Kit and App-Native can be tested on a MacOS target. These tests are blazing fast now since they doesn't require the iPhone Simulator.
  • It's a bit of overhead early on when developing by myself, next time around I would start it as one project and separate them out after a fews weeks.
Follow my thoughts, checkout projects that interest me, connect with me professionally or send me an old fashioned email.