I really like the beginning of a new project. The time when you plan everything is a really important step which makes some things easier or harder to achieve in the future. One of the questions is always which pattern architecture I should use. Of course we can choose the well-known MVC pattern and there is nothing wrong with that choice, but we need to remember about few important problems. I think every iOS developer who wrote at least few applications using MVC knows about those difficulties like Massive View Controllers…
Searching the best way of developing mobile applications
I need to admit — I made my first applications using MVC but I soon realised that I needed to change my approach. I’ve got some experience with C# applications so I started working with MVVMC pattern in iOS apps for some time. That was a really amazing experience — most MVC problems suddenly disappear. My code started being more organised and solid. Testing the application became easier and more comfortable. I thought that MVVMC would be my favourite architecture pattern which I would like to keep for my next applications.
Personally, I’m the kind of person who really likes trying new things, especially connected with my work (which happens to be my hobby also). When I heard about the VIPER pattern architecture I decided to check what is it exactly. I started from the most popular article at www.objc.io. You can imagine my confusion. The pattern looked really advanced and a little bit unreadable at the beginning. I started looking at examples supplied to clear my thoughts but unfortunately that was even worse. There were a lot of files, the whole structure was really strongly divided and I started wondering if it was a good approach at all.
After some time I had a lot of questions. Keep coding with MVVMC? Spend some time on VIPER to fully understand that pattern? Worth a try? I decided to give VIPER a second chance. I knew that using VIPER for the first time wouldn’t be easy especially after my first impression. When I face problems like this, I like to resolve them by preparing really simple dummy project from scratch. In this case I did the same. I created a new application in Xcode and started working with my first module. Step by step I analysed the examples I found on the internet and tried adapting those solutions to my sample project. I added my first presenter, interactor, data manager and view interface. I spent a lot of time on thinking about the responsibilities of each module’s item. Day by day the whole pattern became clearer and more understandable. After this experience I made a decision — I would create my next serious project with VIPER.
As you read this I’ve already finished that project. You already know how my story began but I would like to share with you what has changed after few months of development.
- Tests — I can easily admit that was my most tested application ever. Having that strongly divided structure means that you can really comfortably test every module’s item like presenter, interactor, etc. I strongly recommend you testing those classes with Quick and Nimble libraries from github.com/Quick. In terms of mocks, stubs and fakes I decided to create them on my own.
- Structure — Yes, there are a lot of files within one module (even a simple one), but after few days of development you know from the beginning where you should put every part of code, for example you don’t need to spend time on wondering where you should format your output data because you know that presenter has that responsibility. All modules are independent so you don’t need to worry about side effects during editing specified module.
- Improvements — Many times I had that feeling that I’m building a really simple screen but I need to create a quite advanced module. I’m spending a lot of time on something which I can achieve really quickly using for example MVC. But there is something really amazing — when you need to improve that screen, add some features or functionalities you realise that it’s really simple. You already have well prepared structure so you don’t have that feeling that you need to rebuild part of your application because of those changes.
- Time — You need to realise that building an app with VIPER is quite time-consuming. I don’t have a strong opinion about building a simple app using that pattern architecture. I think it’s more complex problem and more less depends on that if you are going to develop that project further in the future. Just like I mentioned before, VIPER can save you time when you need to extend or improve functionalities.
- CoreData — When you need to use CoreData inside your app you probably would use NSFetchResultController to simplify fetching data from database. It’s not quite obvious how to connect it with a module’s item and where to put it. At the moment I think the best solution is to store NSFetchResultController object inside your data manager class and make interactor a delegate of it.
- Modules Communication — Another problematic thing is passing data between modules. Let’s say you’ve got two view controllers: master and details. After selecting specific row from master you want to display some details of it. Right now I solve it like this: from the first module presenter I use the second module wireframe to present that module and passes those parameters to the wireframe’s method responsible for creating all module parts. I’m quite happy with that solution but that’s the one of the things which I would like to improve in my next project.
- Navigation — Navigation across the whole app is one of those things you should really consider before you start doing anything. Every module has an object responsible for initialising presenter, interactor, etc — the wireframe. The only thing you need to do is to find a good way to move from one view controller to another. My current solution is based on class named RootWireframe. A shared object of that class is responsible for storing the root navigation controller and presenting view controllers inside it. Every module’s wireframe uses that RootWireframe shared object to show or dismiss a module’s view controller.
Presenter — So far all my presenters have two responsibilities: returning formatted data for the view interface and catching all events from view controllers (like user selection). This means some of my modules have really massive presenters. In my next project I would like to have a separate module item called event handler to split those tasks into presenter and event handler.
As you can see there is a lot to consider using VIPER inside iOS applications. You start wondering about basic stuff like passing data, the responsibilities of objects — and that makes you a better developer. In the next few months I plan like to improve some of my solutions based on VIPER to make it even more solid and unbreakable.