VIPER is not clean, not even close
Let’s destroy the anti-pattern known as VIPER
Ahh shit, here we go again
The year is 2020, and VIPER continues to spread misinformation on how it is supposed to solve massive view controller problem.
First, there’s no massive view controller problem. What we really have is lazy/shit developer problem that doesn’t know how to arch / refactor properly.
Let’s look at some of the 2020 VIPER articles to expose their hypocrisies and contradictions and that what VIPER offers is a proposal rather than a solution.
Graphite on the roof
This article summarizes the pros and cons of VIPER:
Our traditional MVC and MVM architecture that we are all acquainted with have one primary problem i.e Bulky Controllers. Since all our business logic has been dumped in the controller, in the end, we see a huge and fat controller which becomes difficult to manage if our project is to be scalable. So these are the primary reasons why we need VIPER:
To make the structure more modular.
To build the application on the Single Responsibility Principle.
To reduce the load and dependency on controllers.
To build the app on the basis of use cases or behavior-based.
On the other hand, it lists the below disadvantages:
Disadvantages of VIPER
Don’t get away with the modularity of VIPER. There are many disadvantages of VIPER as well:
We do have lots of code to write down.
We have lots of files added to our project.
Communication between different file handlers become difficult and needs to be planned before implementation.
VIPER in small projects can be a killer, time consuming and bulgy.
…well then by definition VIPER is not CLEAN.
It’s insidious how VIPER devs conveniently downplays one of the most important criteria for clean code, if not the most important, then state without proof or comparison with alternatives that it provides some architectural benefits.
Anyone can propose an architecture that solves something.
The problems are:
- At what cost
- Prove it
- How is it better than alternatives, or SDK?
For example, why stops at 5 roles? I propose a COBRA architecture as follows:
- It has 100 roles, which means creating 100 extra objects manually for each view.
- No mercy
- COBRA Kai never dies!
It solves massive view controller problem with some minor disadvantage like insane amount of codes to write down.
It’s of course very modular, duh. It contains every possible step you would ever encounter in app development.
It conforms to single responsibility principle but there are 100 responsibilities per view.
It reduces dependencies and overloads of view controller, which is now only responsible for creating 100 objects. This creates complex interactions between 100 objects, but that’s the price I’m willing to pay.
Not only can you build your app with use cases or behavior-based, you can also build it upside down, left side right, and/or test-driven.
I’ll omit the tutorial in which I create 100 objects for a hello world app. But trust me, this scales well to large projects.
Do you see the irony?
Ideas are cheap, and proposals are easy, whereas implementation is hard.
If your implementation is not clean, your architecture has failed. And you should start over. The hardest part of SDK design is so that the rest follows naturally, and compactly without glue codes.
Or you can be shameless and slap “clean architecture” sticker on your every tutorial to establish your brand despite evidence says otherwise. This appears to be the route that VIPER takes.
How does an VIPER interactor explode?
When you create interactor (Controller in MVC sense) outside of SDK view controller hierarchy, incorporate it with presenter which inherits some of worst problems of MVVM in iOS (no binding), and add a useless router on top of it.
Why is Router useless you ask? It’s dependency injection and shit.
Because there are far easier ways to do router dependency injection without shoving a Router up your ass for every view. If VIPER devs are at all competent, this is where they should stop and rethink their design. But they are not, and we are flooded with idiotic VIPER tutorials online.
Take RIB, which claims to be an improvement over VIPER for example. It says “you know what, let’s not do things on view basis, e.g.; create presenter for every view, let’s do things on control basis”. Then it went on to re-create an interactor hierarchy to replace SDK view controller hierarchy, which is redundant, useless. Like that of VIPER, the most reliable way to determine the value of an architecture is to see if its clean. As in clean clean, not “you didn’t see graphite on the roof so it’s clean” clean. RIB failed miserably in that aspect. But as its predecessor, RIB also claims to be a “clean architecture” that solves massive view controller problem. I mean, who doesn’t?
Look, if there’s any universal criteria determining the cleanness. It’s how clean you can do a hello world. If you need to create 5 files for a hello world, you have failed, and your architecture is worthless. Don’t give me that auto-gen bullshit, you fail even harder if you require so many glue codes that it needs auto-gen. If you think an architecture that requires 5 files and glue codes and maybe auto-gen for a hello-world is easily scalable to large projects, I offer a deal to double whatever bitcoin you send to my wallet.
Cost of lies
There’s one thing in common between MVVM, RxSwift, and VIPER.
They never bother building their architecture around Swift unique language features. In fact I think they didn’t even bother mentioning any of those.
So you would see this funny scenario:
- Move things to a external view model object
- Create binding via observables and observers from RxSwift.
- Depending on one’s ego, throw interactor, router, protocol, generics or other over-generalizations on top of it
- Publish tutorial on how it solves massive view controller problem.
- Never mention the fact that if you don’t do step 1, you can just use property observer for the same effect, omitting step 2–3.
- Any competent devs would choose function over object then use POP to refactor out functions to keep view controller compact.
- But step 6 is equivalent to following SDK, which is bad for selling tutorial. So we are back to step 1.
So what is the cost of promoting these shits?
The real danger is that we no longer recognize powerful Swift language features, so we never archive the maximum efficiency the new language would provide.
Take a grain of boron and sand
To answer this guy’s title question:
The VIPER architecture
Is this the best choice for your needs?
It is NOT.
It is in fact the worst choice you can find. When you take boilerplate mess for granted, what other code smell should you normalize next?
If we normalize enough code smells, then we no longer recognize code smells at all.
Don’t take online tutorials of named architecture or design pattern at their face value. Take a grain of boron and sand. Remember that this is a new language, there’s no value type in the ages of MVVM, and there’s still no binding mechanisms in UIKit. I was told it’s an equivalent of one chest X-rays to manually create binding for every view. But it is in fact one million. You should not blindly follow online guides, and you should learn to recognize code smell. Hey, don’t even take my words for it, use your judgement.
Here’s a guideline I find useful: WWSD.
What would SwiftUI do?
See how SwiftUI does model-view mapping and binding.
See how SwiftUI eliminates dispose bag and Observable.
See how SwiftUI removes View Controller, do you see MVC devs cry and insist creating an external Controller object for every model?
See how SwiftUI builds around value type and enhances / generalize property observer.
Now make your own comparison between implementation of MVVM, RxSwift, VIPER with that of SwiftUI. Can you tell the difference?