D V N C I — A Storyboardless & Clean & Multidirectional Architecture Pattern
In these days iOS applications are in a transition, slow paced passing to SwiftUI framework from our beloved UIKit. Who knows how many years left we can keep using UIKit but my purpose is to make best of it
When it comes to build an app in UIKit with a clean structure, we all use most common patterns such as MVVM, VIPER, VIP, MVVM-C…
However they are mainly designed for projects that are using Storyboard.
And when you want to develop a project without Storyboard, you are simply out of these standards.
In professional area, -I am too- developing apps using these accepted standards, using storyboards… Yet in my playgrounds i am working on a new pattern to support Storyboardless development style and be more Single Responsibility focused.
Let’s keep it short,
I call it DVNCI, reading it as you guess “Da Vinci”
All letters come from layers;
As stated in the diagram, it is multidirectional. But it is dangerous in terms of memory leaks if you do not be careful. So, in DVNCI, Controller has strong references of all layers. but others have weak reference of Controller. In this way we avoid memory leaks, when a scene gets dismissed, all layers get completely deinitialized.
Other than that, let’s check out all layers and have a brief description.
DataSource
I don’t see a best practice in conforming reusable view protocols on UIViewController, so DVNCI has an extra layer that extends NSObject, so it can conform reusable view protocols. It holds items array [Any] which can hold different types of objects. You can reuse different cell types by type checking at IndexPath on cellForRowAt method.
What if you don’t have a reusable view(tableView, collectionView)
in module? You can still stash your updatable properties here.
View
This is a UIView class. We create subviews, adjust auto layout and pass user input into Controller from here. There is no business logic here, this layer has to have no idea of what it is. View layer is expected to present what is demanded by controller.
Navigator
Some call it coordinator, i call it navigator. This layer is assigned to manage navigation across modules with dependency injection if needed. It also creates an instance of the module.
Controller
In Swift, we don’t have a pure Controller, by default, it’s unified with View layer, yet still, it has one job in DVNCI, control the flow. If you want to configure UIViewController for transitions, navigationBar… You can commit them all at creation of module, in navigator layer.
Interactor
VIPER users are familiar with this layer, that uses network or coredata workers to get data, then passes decoded object into Controller.
Sublayers;
There is a Cell folder in every module. Reusable view files which belong to module.
There is also Model folder too in a module, which holds Decodable Structs, if there any business logic needs to be handled, there is ViewModel too for mapping raw Decodable to present data in view layer.
If we want to implement Single Responsibility principle, All layers have to have their own specific job.
Off the topic but prepareForReuse method is significant. Since you have to nullify reusable labels, imageviews, hopefully i have an extension deals with all.
Setting up views and layout programmatically, is beyond easier than you think, if you were using stackviews and auto-layout libraries such as Constren
As you can see bind method does not have any knowledge what type of data is coming to present. It expects an optional Any type.
If you want to use a reusable view on multiple modules, you can easily extend it by protocols with multiple methods in order to bind different types of data.
Passing user inputs by protocols directly to the Controller, since we conformed this protocol in DataSource layer.
Developers are mostly using ViewModel in popular architectures, assigning other jobs for instance handling network requests. Yet true purpose of a ViewModel is below, UIKit is not imported here. And if Unit Tests required, you can easily put these structs to test by mocking, without having affairs with UIKit classes.
As you can see, this architecture is the cleanest you could ever seen. I am developing my personal apps using this architecture. No matter how complex the app, it never gets messy.
Once you get used to, maintenance, modifications, Unit Tests can be made so easily and without breaking SOLID principles. I say, give it a try. Feedbacks are always good, since no one can have a perfect knowledge, only sharing will improve us all…
As a parting gift, I have prepared an XCode template which will help you to create a DVNCI module like you create a swift file. You can get from here
Thanks for your reading.