Modular Apps with a Tuist — Part 4 — Catch & Home

Ronan O Ciosoig
4 min readAug 3, 2021

A step-by-step code walkthrough converting an existing app to a modularised app using tuist.

In the previous article I covered how to refactor the UI code into a module, create a testing app, how to write a simple template to use with the scaffold feature to generate a target for shared code and some of the mistakes along the way when adding dependancies — Yeah, a bit too much for just one article, I know, but it’s a journey. There really is a lot of work, even in such a small app. This article is a lot less ambitious — I will only refactor both the Catch and Home scenes into separate modules, which is mostly a rinse and repeat of what has already been covered. If you have actually read all 3 previous ones and followed through the code, congratulations, you deserve a medal: Light reading it isn’t.

The repo for this series is here

Catch If You Can

The repo now has 4 projects and multiple targets in each, and as I refactor out the monolith each framework / target is more focused on a small part of the total. The only real difference between the Catch and Backpack scenes is that Catch has a dependancy on the network module. But there is a catch (pun intended) — the example project needs to load all the SPMs that are required for the main Pokedex project since they cannot (currently) be encapsulated into the NetworkKit target (with this commit). Other then that though it is all the same as has been done in the last 2 articles with no new gotchas. The example app mocks the Home scene and tapping on the button opens the Catch scene as expected, and the image resources for the scene are internal to the framework.

let placeholderImage = UIImage(named: “PokemonPlaceholder”, in: Bundle(for: CatchViewController.self), with: nil)

Just remember that Bundle:for requires a class, so a struct won’t do.

The Home Run

The last module that needs a refactor is HomeUI. It contains the home scene and the image assets used. This work is really trivial compared to the other modules, although it did have a name collision when it came to the UITesting target (a problem solved in the previous article). Since the chosen architecture in this project incorporates the Coordinator pattern, the HomeUI doesn’t even need any dependancy to be injected to show the other screens as this functionality is fully described in the Coordinator source — it is so simple in fact. And this means less test cases to cover and less possible bugs. A win-win.

The Final Graph

The starting point was the blue Pokedex project, and the yellow shapes are the 6 modules that have been defined in this series. The brown folders are the SPMs defined as dependancies to the main app and the networking module. The green shapes are the test targets for each module.

The above image uses the tuist graph command to generate the image. The initial goal set out at the beginning has now been achieved — except for one small detail. I didn’t split out the core from the main Pokedex project as it wasn’t necessary. Apart from that I think that the fact that refactoring the HomeUI was such an effortless task that this whole approach to project modularisation is justified. It’s an elegant solution to what is usually a complex and tiresome problem to manage on a day-to-day basis.

This Is The End — Or Is It?

The goal has been reached. I am done. It is completed. Now what? Well, a few of things do need some more attention.

I mentioned a couple of times that this really isn’t the best approach to tuist projects, and in fact it could be merged into a simpler hierarchy. That will be the subject of another article soon. 🚧

Next, although Moya has some syntax that I like, it does add a lot of baggage in the form of other dependancies which for this project, and quite possibly most others just isn’t needed. In fact in the current major project I have been working on, no 3rd party networking library is used at all. So sorry Ash Furrow, and the rest of the team that have diligently laboured on this and the other more known library (AlamoFire) — I think it is time from them to be removed. 💩

In case you haven’t noticed (🙈🙉), Apple has made quite a bit of noise about SwiftUI in the last 2 years, so replacing all the UIKit scenes with SwiftUI would be interesting, but not essential. I’d still do it though. 😇

Keeping Up With The Tuist Releases

I started this series of articles on tuist version 1.36, and at the time of writing this has advanced to 1.46. There are some new features on the way like caching dependancies as binaries, thus reducing build times which I will have to incorporate in the coming weeks. So, as they say on the radio — stay tuned.

Please follow to receive all the next articles as they are published.

The completed code for this article is here.

--

--

Ronan O Ciosoig

iOS software architect eDreams ODIGEO and electronic music fan