After writing my best practices article about VIPER, I’ve made just a few 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…
My generic challenge was that I needed to have a common interface for each single module element. That is why I created easy protocols for the next:
This manner for instance my router objects are implementing the
Router protocol, so if I make an extension on it, each single one can 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 further 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 parts. You’ll find it on github, it is a actually fundamental one, be happy to make use of it, you simply need to
import VIPER in your venture.
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 metal good friend) instructed a surprisingly good normal answer for the issue. His concept gave the impression of 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, carried out a default protocol extension and voilà routers are actually able to presenting error messages.
Notice that you need to use the identical sample for many different (related) issues as properly. The essential implementation seems to be like this one beneath, I hope you get the concept. 💡
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
In fact this system can work for different VIPER parts as properly, it is fairly straightforward to implment and the protocol oriented strategy provides us an enormous win. 🏆
Presenter to presenter interactions
I additionally modified my thoughts concerning the place of the delegate implementations taking part within the module communication circulation. In my final article I instructed you that I am storing the delegate on the router, however afterward I noticed that delegation is usually 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("Whats up from module A!")
This manner you may skip the complete router layer, plus all of the enterprise associated logic will probably be carried out within the presenter layer, which must be the one technique to go. 🤪
Entities are right here to remain
Aside from the service layer typically it is fairly helpful to have an entity wrapper with some further 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 online 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.
This can be a WIP (work-in-progress) concept that I would prefer to check out, however the fundamental idea is considerably like that I need to separate enter and output protocols for VIPER module layers. Additionally this IO differentiation may be mirrored on the service layers too (perhaps the entire object “mess” from the service layer goes for use as IO entities sooner or later), by mess I imply that there may be method too many objects within the Service/Objects listing, so because of this these may very well be additionally grouped by modules (aka. entities).
Anyway, I am considering 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 best than y. Architectures and design patterns are easy instruments that may be utilized to make your life simpler. For those who don’t love x, it is best to strive y, however you shouldn’t blame x, simply because that is your private opinion.
My present favourite structure is VIPER, so what? Possibly in a 12 months or two I will go loopy in love with reactive programming. Does it actually issues? I do not suppose so. I’ve discovered and tried so many issues through the previous, that I am unable to even bear in mind. 🧠
I am additionally always making an attempt to determine new issues, as you may see this entire sequence of articles about VIPER is the results of my studying progress & experiences. For those who actually need to grasp one thing, it is best to follow, analysis and take a look at quite a bit, and most significantly be happy with your successes and keep humble on the similar time. 🙏
That is it concerning the VIPER structure for some time. I hope you loved studying the entire sequence. In case you have any questions, be happy to ask me by twitter. 💭