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.

8

Share

Download to read offline

10 tips for a reusable architecture

Download to read offline

Get some hints on how to write the code of your iOS apps in a more reusable way. This will make you more efficient and happier.

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

10 tips for a reusable architecture

  1. 1. 10 tips for a reusable architecture Jorge D. Ortiz Fuentes @jdortiz
  2. 2. A POWWAU production
  3. 3. Agenda ★Goal ★ Principles ★ Tips ★Q&A
  4. 4. Goal
  5. 5. Write code that can be used as many times & in as many projects as possible.
  6. 6. Principles
  7. 7. SOLID ★ Single Responsibility ★Open/Closed ★ Liskov Substitution ★ Interface Segregation ★Dependency Inversion
  8. 8. Tips
  9. 9. Forgive me, because I am going to sin ★ The following are tips, not rules. ★ They might not apply to your code. ★But I would, at least, think about them.
  10. 10. 1.
  11. 11. Don’t write reusable code
  12. 12. Don’t write start with reusable code
  13. 13. Don’t start with reusable code ★ Start with the right idea ★But don’t need the perfect code ★ You can always refactor ★ Shipped is better than perfect
  14. 14. 2.
  15. 15. But don’t commit code that is clearly not reusable
  16. 16. Commit reusable code ★Do the Right Thing™ before committing to the development branch or any shared branches. ★Be a good boy scout: If you revisit the code and it can be improved, do so.
  17. 17. 3.
  18. 18. Move all the business logic to the model
  19. 19. Move to the model ★Model > Data ★Business rules • Behaviors • Validation • Importing & exporting • Migration
  20. 20. Instead of - (IBAction) importPasteText:(id)sender { UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; if ([pasteboard containsPasteboardTypes:@[@"public.utf8-plain-text", @"public.text"]]) { NSInteger rejectedItems = 0; CheckItem *newItem = nil; [self.undoManager beginUndoGrouping]; NSString *textToImport = [pasteboard.string copy]; NSArray *items = [textToImport componentsSeparatedByString:@"n"]; NSUInteger objectNumber = 0; if ([[self.itemsTableViewDataSource.fetchedResultsController sections] count] > 0) { id <NSFetchedResultsSectionInfo> sectionInfo = [self.itemsTableViewDataSource.fetchedResultsController sections][0]; objectNumber = [sectionInfo numberOfObjects]; } for (NSString *item in items) { NSArray *itemComponents = [item componentsSeparatedByString:@":"]; NSString *itemName = [itemComponents[0] stringByTrimmingCharactersInSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]]; if ([itemName length] > 0) { …
  21. 21. do - (IBAction) importPasteText:(id)sender { UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; if ([pasteboard containsPasteboardTypes:@[@“public.utf8-plain-text", @"public.text"]]) { [self.undoManager beginUndoGrouping]; [self.model importItemsInChecklist: self.checklist fromString:pasteboard.string]; [self.undoManager endUndoGrouping]; } }
  22. 22. 4.
  23. 23. Don’t put presentation logic into the model
  24. 24. Presentation logic ★ It isn’t business logic, but “UI logic” ★ In the VC, it could be inconsistent, better “centralized”. ★ It shouldn’t be in the model. ★ It can contain UI dependent information (colors, fonts,…).
  25. 25. Instead of // Set label to “3 days left” - (void) displayRemainingTime { self.remainingLabel.text = [self.task remainingTime]; }
  26. 26. do // Set label to “3 days left” - (void) displayRemainingTime { TaskPresenter *tp = [[TaskPresenter alloc] initWithTask:self.task]; self.remainingLabel.text = [tp remainingTime]; }
  27. 27. 5.
  28. 28. Put the network closer to the model (instead of View Controller)
  29. 29. Network code ★ The view controller is responsible for responding events: • lifecycle • UI generated ★Controlling networking is OK ★ Doing networking is wrong ★ In the model or a category: • Provide business logic with network functionality • Handle concurrency
  30. 30. 6.
  31. 31. Make classes for Data Sources & Delegates of table views
  32. 32. Data Source & Delegate Objects ★ It exceeds VC responsibilities ★Responsibility: View model ★ They can be reused
  33. 33. Instead of // @interface MyVC: UITableViewController @implementation MyVC { //implicit (in super) // self.tableView.dataSource = self; // self.tableView.delegate = self; }
  34. 34. do // @interface MyVC: UITableViewController @interface MyVC @property (strong) MyDataSrc *myDataSrc; @end @implementation MyVC - (void) viewDidLoad { [self assignDataSource]; } - (void) assignDataSource { self.myDataSrc = [[MyDataSrc alloc] initWithMOC:self.moc]; self.myDataSrc.fetchedResourceController.delegate.self; self.tableView.dataSource = self; [self.myDataSource performFetch]; } @end
  35. 35. 7.
  36. 36. But then, don’t let them take care of the views
  37. 37. DataSource & Delegate responsibilities ★Metadata: How many rows, sections… ★ Act on data: add or delete row ★ Provide views, view info and present data ★ Act on selections
  38. 38. Use a delegate numberOfSectionInTableView: tableView:numberOfRowsInSection: tableView:cellForRowAtIndexPath: MyVC MyDataSrc displayObject:inCell
  39. 39. TableViewViewModelDele gate @protocol TableViewViewModelDelegate <NSObject> - (NSString *) cellIdentifier; - (CGFloat) cellHeight; - (UITableViewCell *) displayObject:(NSManagedObject *)object inCell:(UITableViewCell *)cell; - (NSString *) headerIdentifier; - (CGFloat) headerHeight; - (UITableViewHeaderFooterView *) displayObject:(NSManagedObject *)object inHeader: (UITableViewHeaderFooterView *)header; @optional - (void) didSelectObject:(NSManagedObject *)object; - (void) didSelectAccessoryForObject:(NSManagedObject *)object; @end
  40. 40. 8.
  41. 41. Test your code
  42. 42. Test ★Reusable code = code + tests ★ Tests contain • Validation • Assumptions • Documentation
  43. 43. Test your Core Data model @implementation CoreDataTestCase - (void) setUp { [super setUp]; [self createCoreDataStack]; } - (void) createCoreDataStack { NSBundle *bundle = [NSBundle bundleForClass:[self class]]; model = [NSManagedObjectModel mergedModelFromBundles:@[bundle]]; coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model]; store = [coordinator addPersistentStoreWithType: NSInMemoryStoreType configuration: nil URL: nil options: nil error: NULL]; context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; context.persistentStoreCoordinator = coordinator; }
  44. 44. Test your view controllers - (void) setUp { [super setUp]; [self createFixture]; [self createSut]; } - (void) createSut { UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil]; sut = [storyboard instantiateViewControllerWithIdentifier:viewControllerID]; sut.data = data; }
  45. 45. Test your view controllers (2) - (void) testOnViewDidLoadTitleIsSetToChecklistName { [sut view]; XCTAssertTrue([sut.title isEqualToString:sut.checklist.name], @"View controller title must be set to the checklist name"); }
  46. 46. 9.
  47. 47. Break up your Storyboards into workflows
  48. 48. Huge Storyboards Something to avoid
  49. 49. Workflows ★Huge Storyboards: • Teams get conflicts in the Storyboards often • Difficult to maintain ★Better Storyboards: • One per workflow (sign in/sign up, statistics, preferences) • Even combine with XIB (useful for cells)
  50. 50. Load another Storyboard - (IBAction) displayReport:(id)sender { UIViewController *reportVC = [[UIStoryboard storyboardWithName:reportStoryboard bundle:nil] instantiateInitialViewController]; [self presentViewController:reportVC animated:YES completion:nil]; }
  51. 51. 10.
  52. 52. Create your own modules
  53. 53. Modular code ★ iOS support • Until iOS 8: only static libraries (no resources, separated headers) • iOS 8: frameworks ★Cocoapods: allow to share open source code
  54. 54. Create a pod ★ Isolate the code (use pod-template) ★Create .podspec & LICENSE ★ pod lib create coolpod ★ In your Podfile: • pod ‘coolpod', :git => 'https:// server/repoURL/coolpod.git'
  55. 55. Thank you! Images courtesy of Shutterstock
  • mari0tt0

    Mar. 7, 2015
  • jberlana

    Nov. 26, 2014
  • filippocamillo

    Nov. 26, 2014
  • ManfrediGiordano

    Nov. 25, 2014
  • PNawani

    Nov. 25, 2014
  • albertuslm

    Nov. 24, 2014
  • kremizask

    Nov. 24, 2014
  • enniom

    Nov. 22, 2014

Get some hints on how to write the code of your iOS apps in a more reusable way. This will make you more efficient and happier.

Views

Total views

6,914

On Slideshare

0

From embeds

0

Number of embeds

3,445

Actions

Downloads

21

Shares

0

Comments

0

Likes

8

×