Learn to grasp the VIPER architectural design sample, with some protocol oriented programming strategies utilizing Swift.
VIPER
After writing my greatest practices article about VIPER, I’ve made a couple of adjustments to the codebase. I used to be taking part in with these concepts in my thoughts already, however by no means had sufficient time to implement them correctly. Let’s me present you the adjustments…
VIPER protocols
My generic subject was that I needed to have a frequent interface for each single module part. That is why I created easy protocols for the next:
- View
- Interactor
- Presenter
- Entity
- Router
- Module
This manner for instance my router objects are implementing the Router
protocol, so if I make an extension on it, each single one could have that exact performance. It is a fairly small, however very nice addition that makes my modules far more highly effective than they have been earlier than. Actually talking I ought to have had this from the very starting, however anyway any more it is gona be like this. 😬
This transfer implied to arrange my VIPER protocols right into a customized framework, so I made one, with these elements. You’ll find it on github, it is a actually primary one, be happy to make use of it, you simply need to import VIPER
in your undertaking.
Module protocols
Since I used to be utilizing VIPER it had this nice urge to implement a customized module for presenting system default alert messages on iOS. You realize UIAlertController is the one I am speaking about. Really Robi (my true steel pal) instructed a surprisingly good common answer for the issue. His concept appeared like this:
Why do not we create a protocol for the router, so we might implement this on each different router, additionally we might merely name present(alert:) on them?
I cherished this strategy, so we have constructed it. Turned out, it is freakin superior. So we launched a brand new protocol for the module router, applied a default protocol extension and voilà routers are actually able to presenting error messages.
Observe that you should utilize the identical sample for plenty of different (comparable) issues as properly. The essential implementation appears to be like like this one under, I hope you get the thought. 💡
import VIPER
class AlertModule: Module {
}
protocol AlertModuleRouter: class {
func present(alert: AlertEntity)
}
extension AlertModuleRouter the place Self: Router {
func present(alert: AlertEntity) {
}
}
protocol MyModuleRouter: Router, AlertModuleRouter {
}
After all this method can work for different VIPER elements as properly, it is fairly simple to implment and the protocol oriented strategy provides us an enormous win. 🏆
Presenter to presenter interactions
I additionally modified my thoughts in regards to the place of the delegate implementations collaborating within the module communication circulation. In my final article I instructed you that I am storing the delegate on the router, however in a while I noticed that delegation is generally associated to enterprise logic, so I merely moved them to the presenter layer. Sorry about this. 🤷♂️
import VIPER
protocol AModulePresenterDelegate {
func didDoSomething()
}
class AModule: Module {
func construct(with delegate: AModulePresenterDelegate? = nil) -> UIViewController {
presenter.delegate = delegate
return view
}
}
class AModulePresenter: Presenter {
func someAction() {
self.delegate?.didDoSomething()
self.router?.dismiss()
}
}
class BModulePresenter: Presenter, AModulePresenterDelegate {
func didDoSomething() {
print("Hi there from module A!")
}
}
This manner you’ll be able to skip the whole router layer, plus all of the enterprise associated logic shall be applied within the presenter layer, which ought to be the one strategy to go. 🤪
Entities are right here to remain
Aside from the service layer generally it is fairly helpful to have an entity wrapper with some extra metadata for the mannequin objects. That is why I additionally made an Entity
protocol, and began to make use of it in my modules. For instance an internet view module that may open a hyperlink can have a WebViewEntity
with a title and a content material url property. 😅
import VIPER
struct AlertEntity: Entity {
let title: String
let message: String
}
The pattern alert module from above can use an AlertEntity
with some properties that may outline the title, message or the buttons. This manner you do not actually have to consider the place to place these objects, as a result of these are the actual VIPER entities.
IO protocols
This can be a WIP (work-in-progress) concept that I might prefer to check out, however the primary idea is considerably like that I need to separate enter and output protocols for VIPER module layers. Additionally this IO differentiation will be mirrored on the service layers too (possibly the entire object “mess” from the service layer goes for use as IO entities sooner or later), by mess I imply that there will be means too many objects within the Service/Objects listing, so which means these may very well be additionally grouped by modules (aka. entities).
Anyway, I am pondering of one thing like RequestEntity, ResponseEntity for service communication, and for the VIPER layer communication I might think about two separate protocols, eg. PresenterInput, PresenterOutput. We’ll see, however at first sight, it is looks as if fairly an overengineered factor (hahaha, says the VIPER advocate 😂).
VIPER vs [put your architecture name here]
No! Please do not suppose that x is healthier than y. Architectures and design patterns are easy instruments that may be utilized to make your life easier. In the event you do not like x, it’s best to attempt y, however you shouldn’t blame x, simply because that is your private opinion.
My present favourite structure is VIPER, so what? Perhaps in a yr or two I am going to go loopy in love with reactive programming. Does it actually issues? I do not suppose so. I’ve discovered and tried so many issues in the course of the previous, that I can not even bear in mind. 🧠
I am additionally continuously making an attempt to determine new issues, as you’ll be able to see this entire collection of articles about VIPER is the results of my studying progress & experiences. In the event you actually need to grasp one thing, it’s best to follow, analysis and check out lots, and most significantly be pleased with your successes and keep humble on the similar time. 🙏
That is it in regards to the VIPER structure for some time. I hope you loved studying the entire collection. You probably have any questions, be happy to ask me by way of twitter. 💭