The VIPER Architecture

Architecture

Just like MVC or MVVM, VIPER is a design pattern created to facilitate the development by creating layers of abstraction and isolation of concerns, creating a cleaner code, and bringing more maintainability further down the road

VIPER is an acronym for View-Interactor-Presenter-Entity-Router. Each functionality or module must be defined by these five components.

View

It’s what the user sees, the view that represents a functionality. In some cases, a single functionality can have multiple views, for example, an onboarding flow with multiple steps. The Router is responsible for transitioning between those views, and they will all use the same Interactor, Presenter, Entity, and Router.

  • It’s the interface layer, which means UIKit files, mostly UIViewController subclasses and all the other stuff. Views don’t do anything that’s related to business logic

Interactor

Responsible for handling logic after receiving orders from the Presenter. Returns the result through a delegate on the Presenter.

  • The interactor is responsible for retrieving data from the model layer, and its implementation is completely independent of the user interface.
  • It’s important to remember that data managers (network, database, sensor) are not part of VIPER

Presenter

It’s the crossroad that connects all the other components. Receives user actions from the View, sends and receives data from the Interactor, and route to other screens using the Route

  • UIKit independent class that prepares the data in the format required by the view and take decisions based on UI events from the view, that’s why sometimes it’s referred as an event handler. It’s the core class of a VIPER module, because it also communicates with the Interactor and calls the router for wire-framing
  • It’s the only class that communicates with almost all the other components. That’s the ONLY job of the presenter, so it should not know anything about UIKit or low level data models. Basically it’s the heart of the application, or some would say it’s the place where all the business logic gets implemented.

Entity

It’s the information and data used on the functionality. In our case, it will be CoreData since our information will be stored there.

  • Plain model classes used mostly by the interactor. Usually I’m defining them outside the VIPER module structure (in the service layer), because these entities are shared across the system.

Router

Controls the navigation flow between screens using UINavigationControllers or between modules by changing the root ViewController of the current Window.

  • Also if you have to pass data between VIPER modules it feels like a right place to do this in the router. I usually communicate between two module using a delegate pattern, so I picked up this habit of calling delegate functions in the router

Builder

It’s only responsibility is to build the complete module by using dependency injection for all the extenal services. It can also build mock or other versions of the same module. That’s quite helpful if it comes to unit testing. Totally makes sense


Comparison with MVVM

A design pattern that offers a similar level of abstraction is MVVM (Model-View-ViewModel). Between both patterns, we can identify the similarities, for example:

  • The View on MVVM is the View on VIPER
  • The Model on MVVM is the Entity on VIPER
  • The ViewModel is represented by the rest of the VIPER components (Interactor, Presenter, and Router).

VIP Cycle

Data transfer between modules

Imagine a list, you select an item and go to a new controller scene. You have to pass at least a unique indentifier between VIPER modules to make this possible.

It’s usually done somewhat like this:

  1. The view calls the didSelect method on the presenter with the id
  2. The presenter forwards the id to the router using the routeFor(id) method
  3. The router calls the builder to build a new module using the id
  4. The builder builds the new module using the id
  5. The router presents the new module using it’s view (controller)
  6. The new module passes the id for everyone who needs it (router, presenter)
  7. The new module’s presenter gets the id
  8. The new module’s interactor loads the data and gives it for the presenter
  9. The new module’s presenter gives the data for the view and presents it
  10. Detail screen appears with proper data.

Advantages

  1. Simplicity - for large teams on complex projects
  2. Scalability - simultaneous work seamlessly
  3. Reusability - decoupled app components based on roles
  4. Consistency - module skeletons, separation of concerns
  5. Clarity - Single responsibilities (SOLID)
  6. Testability - separated small classes, TDD, better code coverage
  7. Interfaces - module independence, well defined scopes
  8. Bug fixing - easier to track issues, locate bugs and problems
  9. Source control - smaller files, less conflicts, cleaner code
  10. Easy - codebase looks similar, faster to read others work

Drawbacks

  • Verbosity - many files per module
  • Complexity - many protocols and delegates
  • On-boarding - lack of proper VIPER knowledge
  • Engagement - VIPER is bad, because it’s complex, meh!

When

Ref

Marcelo Gracietti - VIPER architecture: Our best practices to build an app like a boss

Pedro Alvare, VIPER Architecture and Solid Principles in iOS

Posts in this Series