Via MVP to VIPER. Part One: MVP


    Not so long ago I published a translation. Why VIPER is a bad choice for your next application . And, as often happens, the opinion of the translator did not coincide with the opinion of the author of the original article. Therefore, in this post I will briefly tell you how I am trying (still trying) to introduce VIPER into my projects.


    When I started work on my previous project, the team had exactly two point zero mobile developers: one wrote a version for Android, the second for iOS.


    Naturally, the iOS version was created on the classic MVC pattern recommended by Apple itself .


    I had a View: a “favorite” storyboard that had over9000 quite a few screens, and that looked like this:



    I had a model - classes, for storing settings, user data, some data that was stored in the internal database.


    And I had a view controller for each screen on the storyboard. The view controller should have hosted user action handlers, as well as notifications from the model (receiving data on request or changing data). But in fact, something like this happened there:


    Networking.request(.POST, withURL: serverAddress, andParameters: parameters) { (dictResult, error) in
        if let dictResult = dictResult {
            // some actions with view
            if let rates = dictResult["rates"] as? [AnyObject] {
                for rate in rates {
                    if let rateDictionary = rate as? JSONDictonary {
                        let result = Result(jsonDictionary: rateDictionary)
                        self.resultsArray.append(result)
                    }
                }
            }
            // some actions with view
        } else {
            if let error = error {
                DispatchQueue.main.async(execute: {
                    self.showError(error)
                })
            }
        }
    }

    In general: I was confidently moving from Model View Controller to Massive View Controller and I had to do something about it.


    I began to study possible architectures for mobile applications, and of course, I immediately liked the Clean architecture pattern (which is essentially VIPER):



    picture from The Book of VIPER


    I boldly spent several days exploring this pattern. I looked through several video tutorials and wrote a lot of simple sample applications on it. I also found convenient scripts for generating module files, because one module is about a dozen files (protocols, configurators, directly classes, storyboards, unit tests). But pretty quickly the understanding came that if I now try to introduce VIPER “in the forehead”, then I’ll lose a lot of time. After all, out of habit, I will have too much time spent on the correct division of responsibility between all layers. And I decided to go the simpler way and share responsibility gradually.



    But what if I tell you that the UIViewController is a View.

    That is why I took up the MVP . The most difficult and at the same time - the simplest - to understand that the UIViewController - refers to the View layer. It should work with the UI and only with it: take from the user actions related to the UI (button presses, text input, etc.) and change the display of the UI itself. At first it seemed complicated, but I came up with a few simple rules that help put everything I need into the view controller, and at the same time not put anything superfluous there:


    1. All methods and algorithms of the view controller should work with the UI. If you see some method or piece of code that can work without using UIKit, be aware that this method / block of code does not belong here.


    2. For the presenter, everything is exactly the opposite: there should not be a single method for which UIKit is needed. If such methods are detected, you need to carefully study these sections of code and submit them to the view controller.


    3. The view controller and presenter have protocols to which they are signed, these are their external interfaces. It defines methods that can be called for them from the outside. Therefore, if all of a sudden, you see in a view controller a method call from the interface (protocol) of the same view controller - this method should not be in the view controller, but in the presenter.

    Switching to MVP taught me the main thing: to share responsibility between entities. So far, I have only separated work with the UI from everything else, but ahead, VIPER is still waiting for me. Perhaps classic, and perhaps more layered.


    I hope that I will get to him soon and continue my story.


    Also popular now: