Ufuk Canlı
Ufuk's Blog

Follow

Ufuk's Blog

Follow
Building an indie app, architectural problems and design patterns

Building an indie app, architectural problems and design patterns

Ufuk Canlı's photo
Ufuk Canlı
·Feb 14, 2021·

7 min read

Hello, there! Hope you're doing fine. In this blog post I want to talk about obstacles I can't help thinking about that I may come across while developing my first independent iOS application. I've been trying to transform my ideas into prototypes lately. I'm not familiar with UI design terms so my works may be got bigger than simple prototypes. I'm taking it slow in purpose, trying not to burn out in this process. Although turning ideas and into reality is any developer's dream, it is really hard to do the all the stuff by yourself if you are passionate about creating something useful that people may like and something that could turn into passive income someday.

While designing user interface of my first indie app, I also think about how to handle the data and the business logic. For example, there is this screen that have connection with multiple screens kind of a root of the app. I didn't even write single line of code for it but I could easily see that it may become another example of the joke iOS developers constantly use while talking about the cons of MVC architectural design pattern which is "massive view controller".

I almost always try to write my view code in its own files by subclassing related object from iOS SDK. If you are doing things programmatically this is a big help for avoiding the massive view controller issue. Although it helps, you still have to handle presentation logic or business logic in our poor friend view controller. Well some of you may start to yell at me now: "You supposed to handle business logic in the model not in the view controller, you are doing it wrong!" and I believe you are right but I just didn't come across a good use of MVC in our lovely iOS community so far. Every book I read, every course I take they all do business logic in the view controller. If you start to doing that way, you never see the model files as a place that you can handle the business logic beside that structuring simple data models.

On the other hand, Apple really encouraged us to use MVC so far, I got a feeling that it is changed after the SwiftUI. Just because you can use binding so easy with the little help of Combine, Apple's first party reactive programming framework, MVVM start to become de facto choice of a lot of developers. SwiftUI bring a lot of problems with itself but that's an another blog post material. Anyway, I loved the MVVM approach which turned out that I was trying to use this approach while developing web apps with React unconsciously. But there is a big problem in the UIKit land that there is no binding feature!

Binding is may be the most important part of MVVM design pattern according to my researches. You have to to find your own solution to use this pattern in the UIKit land and I think another problem is everyone approach this problem differently. I personally like to have a single way of doing things, it clears a lot of confusion and help us not to think so much about how to solve the problem. Everyday we face a lot of complexity while writing software and I think having a common way of doing things helps us a lot. Physically and of course mentally. To be honest, there is a true disease called "imposter syndrome" that we face everyday as developers.

Anyway, after doing a lot of research in few days I found using the boxing approach more easy to grasp and apply MVVM design pattern, at least for now. If I become more SOLID in mind developer(!) in the future don't be surprise that I could find another approach better. For now I don't want to handle with coordinator pattern or protocol-oriented programming or third party reactive framework as an extra, I just want to minimize my view controllers' responsibilities. That's it. To do that, I need that binding feature so that I can easily maintain the communication between our view controllers and view models. Let's create a generic class to be able to have that kind of functionality in our project.

import Foundation

class Observable<T> {

    var value: T? {
        didSet {
            observer?(value)
        }
    }

    var observer: ((T?) -> Void)?

    func bind(observer: @escaping (T?) -> Void) {
        self.observer = observer
    }
}

With this generic class we somehow created a data type that have a value, can be bind and observe the changes in that value. T represents the standart data types we'll be using with this generic type. For example, T might be a String or Bool if we need it. With the help of closures we can listen the changes in two place at the same time by calling it. We have a superpower named two way binding now 🚀

P.S. I started to write this blog post by just talking about what bothers me lately then it got bigger than I was planned it to be and suddenly turned into a tutorial. I really didn't want this post to be that kind of article so I cut it off. If you want to see how this pattern can be applied you can just get in touch with me!

Cover photo by Ali Yahya on Unsplash