SlideShare a Scribd company logo
1 of 55
Download to read offline
10 tips for a 
reusable 
architecture 
Jorge D. Ortiz Fuentes 
@jdortiz
A POWWAU 
production
Agenda 
★Goal 
★ Principles 
★ Tips 
★Q&A
Goal
Write code that 
can be used as 
many times & in as 
many projects as 
possible.
Principles
SOLID 
★ Single Responsibility 
★Open/Closed 
★ Liskov Substitution 
★ Interface Segregation 
★Dependency Inversion
Tips
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.
1.
Don’t write 
reusable code
Don’t write start 
with reusable 
code
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
2.
But don’t commit 
code that is 
clearly not 
reusable
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.
3.
Move all the 
business logic to 
the model
Move to the model 
★Model > Data 
★Business rules 
• Behaviors 
• Validation 
• Importing & exporting 
• Migration
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) { 
…
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]; 
} 
}
4.
Don’t put 
presentation logic 
into the model
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,…).
Instead of 
// Set label to “3 days left” 
- (void) displayRemainingTime { 
self.remainingLabel.text = 
[self.task remainingTime]; 
}
do 
// Set label to “3 days left” 
- (void) displayRemainingTime { 
TaskPresenter *tp = 
[[TaskPresenter alloc] 
initWithTask:self.task]; 
self.remainingLabel.text = [tp 
remainingTime]; 
}
5.
Put the network 
closer to the 
model (instead of 
View Controller)
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
6.
Make classes for 
Data Sources & 
Delegates of 
table views
Data Source & Delegate 
Objects 
★ It exceeds VC responsibilities 
★Responsibility: View model 
★ They can be reused
Instead of 
// @interface MyVC: 
UITableViewController 
@implementation MyVC { 
//implicit (in super) 
// self.tableView.dataSource = self; 
// self.tableView.delegate = self; 
}
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
7.
But then, don’t 
let them take 
care of the views
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
Use a delegate 
numberOfSectionInTableView: 
tableView:numberOfRowsInSection: 
tableView:cellForRowAtIndexPath: 
MyVC MyDataSrc 
displayObject:inCell
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
8.
Test your code
Test 
★Reusable code = code + tests 
★ Tests contain 
• Validation 
• Assumptions 
• Documentation
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; 
}
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; 
}
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"); 
}
9.
Break up your 
Storyboards into 
workflows
Huge Storyboards 
Something to avoid
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)
Load another Storyboard 
- (IBAction) displayReport:(id)sender { 
UIViewController *reportVC = 
[[UIStoryboard 
storyboardWithName:reportStoryboard 
bundle:nil] 
instantiateInitialViewController]; 
[self presentViewController:reportVC 
animated:YES 
completion:nil]; 
}
10.
Create your own 
modules
Modular code 
★ iOS support 
• Until iOS 8: only static libraries (no 
resources, separated headers) 
• iOS 8: frameworks 
★Cocoapods: allow to share open source 
code
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'
Thank 
you! Images courtesy of Shutterstock

More Related Content

What's hot

AngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile ServicesAngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile ServicesRainer Stropek
 
Upgrading from Angular 1.x to Angular 2.x
Upgrading from Angular 1.x to Angular 2.xUpgrading from Angular 1.x to Angular 2.x
Upgrading from Angular 1.x to Angular 2.xEyal Vardi
 
Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0Eyal Vardi
 
Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | Fa...
Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | Fa...Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | Fa...
Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | Fa...FalafelSoftware
 
AngularJS Directives
AngularJS DirectivesAngularJS Directives
AngularJS DirectivesEyal Vardi
 
Performance Optimization In Angular 2
Performance Optimization In Angular 2Performance Optimization In Angular 2
Performance Optimization In Angular 2Eyal Vardi
 
Practical JavaScript Programming - Session 8/8
Practical JavaScript Programming - Session 8/8Practical JavaScript Programming - Session 8/8
Practical JavaScript Programming - Session 8/8Wilson Su
 
Practical JavaScript Programming - Session 4/8
Practical JavaScript Programming - Session 4/8Practical JavaScript Programming - Session 4/8
Practical JavaScript Programming - Session 4/8Wilson Su
 
Practical AngularJS
Practical AngularJSPractical AngularJS
Practical AngularJSWei Ru
 
Introduction to Zend Framework web services
Introduction to Zend Framework web servicesIntroduction to Zend Framework web services
Introduction to Zend Framework web servicesMichelangelo van Dam
 
20111030i phonedeveloperworkshoppublished
20111030i phonedeveloperworkshoppublished20111030i phonedeveloperworkshoppublished
20111030i phonedeveloperworkshoppublishedYoichiro Sakurai
 
Practical JavaScript Programming - Session 7/8
Practical JavaScript Programming - Session 7/8Practical JavaScript Programming - Session 7/8
Practical JavaScript Programming - Session 7/8Wilson Su
 
Intro to Angular.JS Directives
Intro to Angular.JS DirectivesIntro to Angular.JS Directives
Intro to Angular.JS DirectivesChristian Lilley
 

What's hot (20)

AngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile ServicesAngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile Services
 
Upgrading from Angular 1.x to Angular 2.x
Upgrading from Angular 1.x to Angular 2.xUpgrading from Angular 1.x to Angular 2.x
Upgrading from Angular 1.x to Angular 2.x
 
Angularjs Basics
Angularjs BasicsAngularjs Basics
Angularjs Basics
 
AngularJS Basics with Example
AngularJS Basics with ExampleAngularJS Basics with Example
AngularJS Basics with Example
 
Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0
 
AngularJS Framework
AngularJS FrameworkAngularJS Framework
AngularJS Framework
 
AngularJs
AngularJsAngularJs
AngularJs
 
AngularJs Crash Course
AngularJs Crash CourseAngularJs Crash Course
AngularJs Crash Course
 
AngularJS.part1
AngularJS.part1AngularJS.part1
AngularJS.part1
 
Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | Fa...
Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | Fa...Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | Fa...
Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | Fa...
 
AngularJS Directives
AngularJS DirectivesAngularJS Directives
AngularJS Directives
 
Performance Optimization In Angular 2
Performance Optimization In Angular 2Performance Optimization In Angular 2
Performance Optimization In Angular 2
 
Practical JavaScript Programming - Session 8/8
Practical JavaScript Programming - Session 8/8Practical JavaScript Programming - Session 8/8
Practical JavaScript Programming - Session 8/8
 
Practical JavaScript Programming - Session 4/8
Practical JavaScript Programming - Session 4/8Practical JavaScript Programming - Session 4/8
Practical JavaScript Programming - Session 4/8
 
Practical AngularJS
Practical AngularJSPractical AngularJS
Practical AngularJS
 
Design Patterns
Design PatternsDesign Patterns
Design Patterns
 
Introduction to Zend Framework web services
Introduction to Zend Framework web servicesIntroduction to Zend Framework web services
Introduction to Zend Framework web services
 
20111030i phonedeveloperworkshoppublished
20111030i phonedeveloperworkshoppublished20111030i phonedeveloperworkshoppublished
20111030i phonedeveloperworkshoppublished
 
Practical JavaScript Programming - Session 7/8
Practical JavaScript Programming - Session 7/8Practical JavaScript Programming - Session 7/8
Practical JavaScript Programming - Session 7/8
 
Intro to Angular.JS Directives
Intro to Angular.JS DirectivesIntro to Angular.JS Directives
Intro to Angular.JS Directives
 

Viewers also liked

cream code with objective-c
cream code with objective-ccream code with objective-c
cream code with objective-cidealistaimasd
 
10 tricks to get more app downloads
10 tricks to get more app downloads10 tricks to get more app downloads
10 tricks to get more app downloadsJavier Berlana
 
Mobile Analytics Betabeers VLC
Mobile Analytics Betabeers VLCMobile Analytics Betabeers VLC
Mobile Analytics Betabeers VLCJavier Berlana
 
iOS advanced architecture workshop 3h edition
iOS advanced architecture workshop 3h editioniOS advanced architecture workshop 3h edition
iOS advanced architecture workshop 3h editionJorge Ortiz
 
Clean architecture workshop
Clean architecture workshopClean architecture workshop
Clean architecture workshopJorge Ortiz
 
iOS viper presentation
iOS viper presentationiOS viper presentation
iOS viper presentationRajat Datta
 

Viewers also liked (9)

cream code with objective-c
cream code with objective-ccream code with objective-c
cream code with objective-c
 
10 tricks to get more app downloads
10 tricks to get more app downloads10 tricks to get more app downloads
10 tricks to get more app downloads
 
Groovy on Android
Groovy on AndroidGroovy on Android
Groovy on Android
 
Mobile Analytics Betabeers VLC
Mobile Analytics Betabeers VLCMobile Analytics Betabeers VLC
Mobile Analytics Betabeers VLC
 
Opinionated android
Opinionated androidOpinionated android
Opinionated android
 
iOS advanced architecture workshop 3h edition
iOS advanced architecture workshop 3h editioniOS advanced architecture workshop 3h edition
iOS advanced architecture workshop 3h edition
 
Clean architecture workshop
Clean architecture workshopClean architecture workshop
Clean architecture workshop
 
iOS viper presentation
iOS viper presentationiOS viper presentation
iOS viper presentation
 
Effective Android UI - spanish
Effective Android UI - spanishEffective Android UI - spanish
Effective Android UI - spanish
 

Similar to 10 tips for a reusable architecture

Taking a Test Drive
Taking a Test DriveTaking a Test Drive
Taking a Test DriveGraham Lee
 
CocoaHeads PDX 2014 01 23 : CoreData and iCloud Improvements iOS7 / OSX Maver...
CocoaHeads PDX 2014 01 23 : CoreData and iCloud Improvements iOS7 / OSX Maver...CocoaHeads PDX 2014 01 23 : CoreData and iCloud Improvements iOS7 / OSX Maver...
CocoaHeads PDX 2014 01 23 : CoreData and iCloud Improvements iOS7 / OSX Maver...smn-automate
 
Your Second iPhone App - Code Listings
Your Second iPhone App - Code ListingsYour Second iPhone App - Code Listings
Your Second iPhone App - Code ListingsVu Tran Lam
 
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCABeginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCAWhymca
 
iOS 101 - Xcode, Objective-C, iOS APIs
iOS 101 - Xcode, Objective-C, iOS APIsiOS 101 - Xcode, Objective-C, iOS APIs
iOS 101 - Xcode, Objective-C, iOS APIsSubhransu Behera
 
iOS Beginners Lesson 4
iOS Beginners Lesson 4iOS Beginners Lesson 4
iOS Beginners Lesson 4Calvin Cheng
 
Core data orlando i os dev group
Core data   orlando i os dev groupCore data   orlando i os dev group
Core data orlando i os dev groupAndrew Kozlik
 
Using a model view-view model architecture for iOS apps
Using a model view-view model architecture for iOS appsUsing a model view-view model architecture for iOS apps
Using a model view-view model architecture for iOS appsallanh0526
 
Apple Templates Considered Harmful
Apple Templates Considered HarmfulApple Templates Considered Harmful
Apple Templates Considered HarmfulBrian Gesiak
 
Formacion en movilidad: Conceptos de desarrollo en iOS (III)
Formacion en movilidad: Conceptos de desarrollo en iOS (III) Formacion en movilidad: Conceptos de desarrollo en iOS (III)
Formacion en movilidad: Conceptos de desarrollo en iOS (III) Mobivery
 
Introduction to Spring Boot.pdf
Introduction to Spring Boot.pdfIntroduction to Spring Boot.pdf
Introduction to Spring Boot.pdfShaiAlmog1
 
Testing C# and ASP.net using Ruby
Testing C# and ASP.net using RubyTesting C# and ASP.net using Ruby
Testing C# and ASP.net using RubyBen Hall
 
iOSDevCamp 2011 Core Data
iOSDevCamp 2011 Core DataiOSDevCamp 2011 Core Data
iOSDevCamp 2011 Core DataChris Mar
 
Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
Formacion en movilidad: Conceptos de desarrollo en iOS (IV) Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
Formacion en movilidad: Conceptos de desarrollo en iOS (IV) Mobivery
 
MVC Puree - Approaches to MVC with Umbraco
MVC Puree - Approaches to MVC with UmbracoMVC Puree - Approaches to MVC with Umbraco
MVC Puree - Approaches to MVC with UmbracoAndy Butland
 

Similar to 10 tips for a reusable architecture (20)

Taking a Test Drive
Taking a Test DriveTaking a Test Drive
Taking a Test Drive
 
iOS testing
iOS testingiOS testing
iOS testing
 
CocoaHeads PDX 2014 01 23 : CoreData and iCloud Improvements iOS7 / OSX Maver...
CocoaHeads PDX 2014 01 23 : CoreData and iCloud Improvements iOS7 / OSX Maver...CocoaHeads PDX 2014 01 23 : CoreData and iCloud Improvements iOS7 / OSX Maver...
CocoaHeads PDX 2014 01 23 : CoreData and iCloud Improvements iOS7 / OSX Maver...
 
Your Second iPhone App - Code Listings
Your Second iPhone App - Code ListingsYour Second iPhone App - Code Listings
Your Second iPhone App - Code Listings
 
201104 iphone navigation-based apps
201104 iphone navigation-based apps201104 iphone navigation-based apps
201104 iphone navigation-based apps
 
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCABeginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
 
iOS 101 - Xcode, Objective-C, iOS APIs
iOS 101 - Xcode, Objective-C, iOS APIsiOS 101 - Xcode, Objective-C, iOS APIs
iOS 101 - Xcode, Objective-C, iOS APIs
 
iOS Beginners Lesson 4
iOS Beginners Lesson 4iOS Beginners Lesson 4
iOS Beginners Lesson 4
 
Core data orlando i os dev group
Core data   orlando i os dev groupCore data   orlando i os dev group
Core data orlando i os dev group
 
Using a model view-view model architecture for iOS apps
Using a model view-view model architecture for iOS appsUsing a model view-view model architecture for iOS apps
Using a model view-view model architecture for iOS apps
 
Apple Templates Considered Harmful
Apple Templates Considered HarmfulApple Templates Considered Harmful
Apple Templates Considered Harmful
 
Formacion en movilidad: Conceptos de desarrollo en iOS (III)
Formacion en movilidad: Conceptos de desarrollo en iOS (III) Formacion en movilidad: Conceptos de desarrollo en iOS (III)
Formacion en movilidad: Conceptos de desarrollo en iOS (III)
 
I os 11
I os 11I os 11
I os 11
 
2013-01-10 iOS testing
2013-01-10 iOS testing2013-01-10 iOS testing
2013-01-10 iOS testing
 
I os 04
I os 04I os 04
I os 04
 
Introduction to Spring Boot.pdf
Introduction to Spring Boot.pdfIntroduction to Spring Boot.pdf
Introduction to Spring Boot.pdf
 
Testing C# and ASP.net using Ruby
Testing C# and ASP.net using RubyTesting C# and ASP.net using Ruby
Testing C# and ASP.net using Ruby
 
iOSDevCamp 2011 Core Data
iOSDevCamp 2011 Core DataiOSDevCamp 2011 Core Data
iOSDevCamp 2011 Core Data
 
Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
Formacion en movilidad: Conceptos de desarrollo en iOS (IV) Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
 
MVC Puree - Approaches to MVC with Umbraco
MVC Puree - Approaches to MVC with UmbracoMVC Puree - Approaches to MVC with Umbraco
MVC Puree - Approaches to MVC with Umbraco
 

More from Jorge Ortiz

Tell Me Quando - Implementing Feature Flags
Tell Me Quando - Implementing Feature FlagsTell Me Quando - Implementing Feature Flags
Tell Me Quando - Implementing Feature FlagsJorge Ortiz
 
Unit Test your Views
Unit Test your ViewsUnit Test your Views
Unit Test your ViewsJorge Ortiz
 
Control your Voice like a Bene Gesserit
Control your Voice like a Bene GesseritControl your Voice like a Bene Gesserit
Control your Voice like a Bene GesseritJorge Ortiz
 
Kata gilded rose en Golang
Kata gilded rose en GolangKata gilded rose en Golang
Kata gilded rose en GolangJorge Ortiz
 
CYA: Cover Your App
CYA: Cover Your AppCYA: Cover Your App
CYA: Cover Your AppJorge Ortiz
 
Refactor your way forward
Refactor your way forwardRefactor your way forward
Refactor your way forwardJorge Ortiz
 
201710 Fly Me to the View - iOS Conf SG
201710 Fly Me to the View - iOS Conf SG201710 Fly Me to the View - iOS Conf SG
201710 Fly Me to the View - iOS Conf SGJorge Ortiz
 
Home Improvement: Architecture & Kotlin
Home Improvement: Architecture & KotlinHome Improvement: Architecture & Kotlin
Home Improvement: Architecture & KotlinJorge Ortiz
 
Architectural superpowers
Architectural superpowersArchitectural superpowers
Architectural superpowersJorge Ortiz
 
Architecting Alive Apps
Architecting Alive AppsArchitecting Alive Apps
Architecting Alive AppsJorge Ortiz
 
Android clean architecture workshop 3h edition
Android clean architecture workshop 3h editionAndroid clean architecture workshop 3h edition
Android clean architecture workshop 3h editionJorge Ortiz
 
To Protect & To Serve
To Protect & To ServeTo Protect & To Serve
To Protect & To ServeJorge Ortiz
 
Escape from Mars
Escape from MarsEscape from Mars
Escape from MarsJorge Ortiz
 
Why the Dark Side should use Swift and a SOLID Architecture
Why the Dark Side should use Swift and a SOLID ArchitectureWhy the Dark Side should use Swift and a SOLID Architecture
Why the Dark Side should use Swift and a SOLID ArchitectureJorge Ortiz
 
Dependence day insurgence
Dependence day insurgenceDependence day insurgence
Dependence day insurgenceJorge Ortiz
 
Architectural superpowers
Architectural superpowersArchitectural superpowers
Architectural superpowersJorge Ortiz
 
TDD for the masses
TDD for the massesTDD for the masses
TDD for the massesJorge Ortiz
 
7 Stages of Unit Testing in iOS
7 Stages of Unit Testing in iOS7 Stages of Unit Testing in iOS
7 Stages of Unit Testing in iOSJorge Ortiz
 
Building for perfection
Building for perfectionBuilding for perfection
Building for perfectionJorge Ortiz
 
TDD by Controlling Dependencies
TDD by Controlling DependenciesTDD by Controlling Dependencies
TDD by Controlling DependenciesJorge Ortiz
 

More from Jorge Ortiz (20)

Tell Me Quando - Implementing Feature Flags
Tell Me Quando - Implementing Feature FlagsTell Me Quando - Implementing Feature Flags
Tell Me Quando - Implementing Feature Flags
 
Unit Test your Views
Unit Test your ViewsUnit Test your Views
Unit Test your Views
 
Control your Voice like a Bene Gesserit
Control your Voice like a Bene GesseritControl your Voice like a Bene Gesserit
Control your Voice like a Bene Gesserit
 
Kata gilded rose en Golang
Kata gilded rose en GolangKata gilded rose en Golang
Kata gilded rose en Golang
 
CYA: Cover Your App
CYA: Cover Your AppCYA: Cover Your App
CYA: Cover Your App
 
Refactor your way forward
Refactor your way forwardRefactor your way forward
Refactor your way forward
 
201710 Fly Me to the View - iOS Conf SG
201710 Fly Me to the View - iOS Conf SG201710 Fly Me to the View - iOS Conf SG
201710 Fly Me to the View - iOS Conf SG
 
Home Improvement: Architecture & Kotlin
Home Improvement: Architecture & KotlinHome Improvement: Architecture & Kotlin
Home Improvement: Architecture & Kotlin
 
Architectural superpowers
Architectural superpowersArchitectural superpowers
Architectural superpowers
 
Architecting Alive Apps
Architecting Alive AppsArchitecting Alive Apps
Architecting Alive Apps
 
Android clean architecture workshop 3h edition
Android clean architecture workshop 3h editionAndroid clean architecture workshop 3h edition
Android clean architecture workshop 3h edition
 
To Protect & To Serve
To Protect & To ServeTo Protect & To Serve
To Protect & To Serve
 
Escape from Mars
Escape from MarsEscape from Mars
Escape from Mars
 
Why the Dark Side should use Swift and a SOLID Architecture
Why the Dark Side should use Swift and a SOLID ArchitectureWhy the Dark Side should use Swift and a SOLID Architecture
Why the Dark Side should use Swift and a SOLID Architecture
 
Dependence day insurgence
Dependence day insurgenceDependence day insurgence
Dependence day insurgence
 
Architectural superpowers
Architectural superpowersArchitectural superpowers
Architectural superpowers
 
TDD for the masses
TDD for the massesTDD for the masses
TDD for the masses
 
7 Stages of Unit Testing in iOS
7 Stages of Unit Testing in iOS7 Stages of Unit Testing in iOS
7 Stages of Unit Testing in iOS
 
Building for perfection
Building for perfectionBuilding for perfection
Building for perfection
 
TDD by Controlling Dependencies
TDD by Controlling DependenciesTDD by Controlling Dependencies
TDD by Controlling Dependencies
 

10 tips for a reusable architecture

  • 1. 10 tips for a reusable architecture Jorge D. Ortiz Fuentes @jdortiz
  • 3. Agenda ★Goal ★ Principles ★ Tips ★Q&A
  • 5. Write code that can be used as many times & in as many projects as possible.
  • 7. SOLID ★ Single Responsibility ★Open/Closed ★ Liskov Substitution ★ Interface Segregation ★Dependency Inversion
  • 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. 1.
  • 12. Don’t write start with reusable code
  • 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. 2.
  • 15. But don’t commit code that is clearly not reusable
  • 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. 3.
  • 18. Move all the business logic to the model
  • 19. Move to the model ★Model > Data ★Business rules • Behaviors • Validation • Importing & exporting • Migration
  • 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. 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. 4.
  • 23. Don’t put presentation logic into the model
  • 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. Instead of // Set label to “3 days left” - (void) displayRemainingTime { self.remainingLabel.text = [self.task remainingTime]; }
  • 26. do // Set label to “3 days left” - (void) displayRemainingTime { TaskPresenter *tp = [[TaskPresenter alloc] initWithTask:self.task]; self.remainingLabel.text = [tp remainingTime]; }
  • 27. 5.
  • 28. Put the network closer to the model (instead of View Controller)
  • 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. 6.
  • 31. Make classes for Data Sources & Delegates of table views
  • 32. Data Source & Delegate Objects ★ It exceeds VC responsibilities ★Responsibility: View model ★ They can be reused
  • 33. Instead of // @interface MyVC: UITableViewController @implementation MyVC { //implicit (in super) // self.tableView.dataSource = self; // self.tableView.delegate = self; }
  • 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. 7.
  • 36. But then, don’t let them take care of the views
  • 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. Use a delegate numberOfSectionInTableView: tableView:numberOfRowsInSection: tableView:cellForRowAtIndexPath: MyVC MyDataSrc displayObject:inCell
  • 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. 8.
  • 42. Test ★Reusable code = code + tests ★ Tests contain • Validation • Assumptions • Documentation
  • 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. 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. 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. 9.
  • 47. Break up your Storyboards into workflows
  • 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. Load another Storyboard - (IBAction) displayReport:(id)sender { UIViewController *reportVC = [[UIStoryboard storyboardWithName:reportStoryboard bundle:nil] instantiateInitialViewController]; [self presentViewController:reportVC animated:YES completion:nil]; }
  • 51. 10.
  • 52. Create your own modules
  • 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. 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. Thank you! Images courtesy of Shutterstock