Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

From mvc to viper

10,331 views

Published on

A journey from MVC to VIPER is a try to leverage different application architectures (as well as some concepts on top of MVC) to build more clean and readable software in Cocoa. Most of the described techniques can be successfully used while dealing with legacy codebase.

Published in: Technology

From mvc to viper

  1. 1. from MVC to VIPER Krzysztof Profic @kprofic
  2. 2. Legacy codebase Better codebase
  3. 3. Pragmatic approach what hurts my eyes?
  4. 4. Pragmatic approach what hurts my eyes? UIViewController
  5. 5. Massive UIViewController
  6. 6. 4 Steps • MVC on diet • MVVM • Intentions • VIPER
  7. 7. 4 Steps • MVC on diet • MVVM • Intentions • VIPER
  8. 8. MVC on diet Massive View Controller Light View Controller
  9. 9. Reducing Massive ViewController • extract datasource • move domain logic into the model • move view code into the view layer objc.io #1
  10. 10. Reducing Massive ViewController • extract datasource • move domain logic into the model • move view code into the view layer objc.io #1
  11. 11. Reducing Massive ViewController • extract datasource • move domain logic into the model • move view code into the view layer objc.io #1
  12. 12. Reducing Massive ViewController • Separation of concerns • Single responsibility principle objc.io #1
  13. 13. Reanimate your MVC reduce MVC principles violation put ViewController on a diet
  14. 14. What is the Rule?
  15. 15. “Keep the code where it belongs”
  16. 16. Layer
  17. 17. Controllers Use Cases Entities Presenters Gateways UI DB External Interfaces Devices The Clean Architecture Enterprise Business Rules Application Business Rules Interface Adapters Frameworks & Drivers Web Controller Use Case Interactor Presenter Use Case Output Port Use Case Input Port Flow of control <I> <I> http://blog.8thlight.com
  18. 18. separation of concerns = dividing software into … Layers
  19. 19. “Keep the code on the right layer”
  20. 20. The Dependency Rule
  21. 21. Controllers Use Cases Entities Presenters Gateways UI DB External Interfaces Devices The Clean Architecture Enterprise Business Rules Application Business Rules Interface Adapters Frameworks & Drivers Web Controller Use Case Interactor Presenter Use Case Output Port Use Case Input Port Flow of control <I> <I> http://blog.8thlight.com
  22. 22. MVC variation
  23. 23. MVC variation
  24. 24. MVVM
  25. 25. 4 Steps • MVC on diet • MVVM • Intentions • VIPER
  26. 26. Let’s talk code
  27. 27. - (void)viewDidLoad { [super viewDidLoad]; if (self.model.salutation.length > 0) { self.nameLabel.text = [NSString stringWithFormat:@"%@ %@ %@“, self.model.salutation, self.model.firstName, self.model.lastName]; } else { self.nameLabel.text = [NSString stringWithFormat:@"%@ %@“, self.model.firstName, self.model.lastName]; } NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"EEEE MMMM d, yyyy"]; self.birthdateLabel.text = [dateFormatter stringFromDate:model.birthdate]; } PersonViewController.m
  28. 28. @implementation PersonViewModel - (instancetype)initWithPerson:(Person *)person { self = [super init]; if (!self) return nil; _person = person; if (person.salutation.length > 0) { _nameText = [NSString stringWithFormat:@"%@ %@ %@“, self.person.salutation, self.person.firstName, self.person.lastName]; } else { _nameText = [NSString stringWithFormat:@"%@ %@", self.person.firstName, self.person.lastName]; } NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"EEEE MMMM d, yyyy"]; _birthdateText = [dateFormatter stringFromDate:person.birthdate]; return self; } @end PersonViewModel.m
  29. 29. - (void)viewDidLoad { [super viewDidLoad]; self.nameLabel.text = self.viewModel.nameText; self.birthdateLabel.text = self.viewModel.birthdateText; } PersonViewController.m
  30. 30. 4 Steps • MVC on diet • MVVM • Intentions • VIPER
  31. 31. Motivation • ViewController implements only viewWill* viewDid*
  32. 32. • encapsulate small pieces of business logic • use case approach (form validation, login user) • hookable via & • reusable Intentions Architecture is about Intent “Uncle Bob” IBOutlet IBAction
  33. 33. @interface ViewController () @property (strong) IBOutlet ModelContainer* modelContainer; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; PersonViewModel * pvm = [[PersonViewModel alloc] initWithModel:self.person]; self.modelContainer.viewModel = pvm; } @end ViewController.m
  34. 34. Observing ViewModel
  35. 35. @interface ObserveIntention () @property (strong, nonatomic) IBOutlet id sourceObject; @property (strong, nonatomic) IBOutlet id target; @property (copy, nonatomic) IBOutlet NSString *sourceKeyPath; @property (copy, nonatomic) IBOutlet NSString *targetKeyPath; @end
  36. 36. @implementation ObserveIntention - (void)awakeFromNib { [super awakeFromNib]; [self updateValue]; [self.sourceObject addObserver:self forKeyPath:self.sourceKeyPath options:0 context:nil]; } - (void)updateValue { id value = [self.sourceObject valueForKeyPath: self.sourceKeyPath]; if (self.targetKeyPath) { [self.target setValue:value forKeyPath:self.targetKeyPath]; } } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)obj change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:self.sourceKeyPath]) { [self updateValue]; } } @end
  37. 37. Behaviours UIControl objc.io #13
  38. 38. Login
  39. 39. User Story #90.10 - Login • A. When I as a user open the app the first time I enter the “main login” page, where I need to login with my username (email address) and password. • B. When I tap the “login button” while online and no errors occur I’m moved to initial page with users profile.
  40. 40. User Story #90.10 - Login • A. When I as a user open the app the first time I enter the “main login” page, where I need to login with my username (email address) and password. • B. When I tap the “login button” while online and no errors occur I’m moved to initial page with users profile.
  41. 41. @interface LoginIntention() @property (strong) IBOutlet UITextField * usernameTextField; @property (strong) IBOutlet UITextField * passwordTextField; @property (strong, nonatomic) IBOutlet UILabel * statusLabel; @end @implementation LoginIntention - (IBAction)login:(id)sender { self.statusLabel.text = @"connecting..."; [self sendActionsForControlEvents:UIControlEventValueChanged]; self.statusLabel.text = [NSString stringWithFormat:@"Authenticating %@“, self.usernameTextField.text]; [self sendActionsForControlEvents:UIControlEventValueChanged]; self.statusLabel.text = @"done"; [self sendActionsForControlEvents:UIControlEventValueChanged]; } @end LoginIntention.m
  42. 42. @implementation LoginViewController - (IBAction)loginIntentionStateChanged:(LoginIntention *)sender { if ([sender.statusLabel.text isEqualToString:@"done"]){ [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; } } @end LoginViewController.m
  43. 43. 4 Steps • MVC on diet • MVVM • Intentions • VIPER
  44. 44. If you want more, checkout VIPER • View • Interactor • Presenter • Entity • Routing
  45. 45. Summary: MVC on diet MVVM Intentions / Behaviours VIPER
  46. 46. Thank you! Krzysztof Profic @kprofic
  47. 47. • http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean- architecture.html • http://www.scottlogic.com/blog/2014/05/11/ reactivecocoa-tableview-binding.html • http://chris.eidhof.nl/posts/intentions.html • http://www.objc.io/issue-13/behaviors.html • http://www.objc.io/issue-13/viper.html

×