iOS VIPER: where to put the form validation code?
Asked Answered
A

4

8

I read many articles about the clean iOS architecture VIPER, I understand the main puropose: the separation of concerns.

I currently use it for my project. I have modules, each split by Views, Interactors, Presenters, Entities and Routers (with Storyboard).

I have a module: Address and a submodule Add for the add address page.

So, I have my protocol View implemented by my UIViewController. The view controller holds all weak IBOutlet labels and text fields (for the new address form).

The address form contains few fields like:

  • person first name and last name
  • postcode
  • country
  • state
  • phone
  • email
  • etc...

In my case the presenter just relies user interactions to the interactor which performs the API call.

But, before performing the API call, I want to pre-validate the form to avoid consume useless network resource.

I need to check for example:

  • the content of country and tell to the view that field is required if empty...
  • the format of email and tell to the view that field is invalid...

My question is, where can I put my form validation code?

Which VIPER component should be fill that job?

Thank you in advance!

Adhere answered 23/5, 2016 at 21:41 Comment(0)
C
6

One of the key benefits from VIPER is separation of concerns, since information is encapsulated in the appropriate element.

The Interactor deals with the "business logic", which includes most of the validation concern (part of that validation can possibly done by the Entity itself). The view would therefore pass its data to the Presenter, which would refer it to the Interactor, which would check its Business Validity and ask the Entity to inform it about the coherence of the data.

However, use of libraries to speed your developments can force you to trade off encapsulation for ease of use. For example, SwiftValidator offers pretty extensive validation rules, but require you to pass your UITextFields to the Validator component.

The choice is therefore yours, between a better encapsulated architecture relying on an Interactor (possibly beefed by a library like Validators), or a more MVVM-oriented tool like SwiftValidator.

Clamper answered 2/6, 2016 at 15:25 Comment(0)
S
2

Since this is related to business logic, I would say that validation should go to interactor. You can even create worker that will be called form interactor - if your validation is too big, but interactor is the place to do it. With delegates you can notify user if something is wrong, what exactly is wrong, error message etc.

I would refer to http://clean-swift.com/clean-swift-ios-architecture/ as well.

Satirize answered 2/6, 2016 at 13:3 Comment(1)
Small side note: I think the author of the clean-swift.com site has not completely understood the basic idea of clean code. From my point of view it is not a good idea to introduce a circular dependency (VC->I->P->VC). The view controller should be dumb and just know it's presenter. So I would suggest to have it more like (VC->P->I) - with back references implemented as delegates.Wychelm
S
2

It seems you should consider using a SOA architecture approach for this purpose.

Generally speaking, the clean architecture for app using VIPER modules can be divided into following layers:

  1. Assembly

    There is all code related creating your viper module components.

  2. Presentation

    You should keep there components like Animator, LayoutPerformer, Presenter, View, ViewController, Router.

  3. Business logic

    It's designed for Interactor and bunch of services. Ideally each service is a stateless and it uses classes from Core Components layer. For example, service encapsulates some network client and requests and it produces some models as an output.

  4. Core components

    The purpose of this layer is connected to your question. Here's a place for things like Response Validator, Object Mapper, Network Client, etc. So the answer is put it into core component layer.

  5. Model layer

    It's the deepest layer which is supposed to keep all entities.

Ok, it sounds good, but how can I structure the project in this case?

You can use for example the structure bellow.

--Modules
----Module
------Interactor
------Presenter
------Assembly
------Router
------View
--Services
--Core
----Validators
----Mappers
--Models
Sunshade answered 11/4, 2017 at 12:27 Comment(0)
D
0

You can check this boilerplate (https://github.com/CheesecakeLabs/Boilerplate_iOS_VIPER) from this post (https://www.ckl.io/blog/best-practices-viper-architecture) for an example.

The Presenter is responsible for form validation, but you shouldn't leave the code on the Presenter ifself. Instead, call a FormValidationHelper() for the Presenter.

Dirge answered 11/4, 2017 at 2:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.