Slide 1

Slide 1 text

Long Lasting iOS Projects Julian Gutierrez Ferrara — iOS Engineer at EachScape @jugutier

Slide 2

Slide 2 text

‘07 ‘08 ‘09 ‘10 ‘11 ‘12 ‘13 ‘14 ‘15 ‘16 ‘17 January 9 It’s been a fast decade

Slide 3

Slide 3 text

Project lifecycle Client comes with app idea Extract requirements Develop Publish

Slide 4

Slide 4 text

Pros & Cons • Clean Slate • Ability to experiment different architectures & patterns • Easier to apply lessons from mistakes made in the past • Little or no reusability • Ramp-up time is higher for every project • Cost and resources need to be higher

Slide 5

Slide 5 text

But what happens with a larger codebase?

Slide 6

Slide 6 text

Are mobile projects throwaway by nature? Let’s gather some data…

Slide 7

Slide 7 text

Developer experience (average) 0 10 0 10 0 10 Combined

Slide 8

Slide 8 text

Trends per language # ppl Years

Slide 9

Slide 9 text

Years in the App Store 0 10 # ppl Years

Slide 10

Slide 10 text

What happened to your code since the first iOS release?

Slide 11

Slide 11 text

Objective-C 1.0 ‘07 ‘08 ‘09 ‘10 ‘11 ‘12 ‘13 ‘14 ‘15 ‘16 ‘17 @implementation MyDasource - (id) init { self = [super init]; if (self) { datasource = [[self buildDatasource] retain]; } return self; } -(NSDictionary *) buildDatasource { NSArray *objects = [NSArray arrayWithObjects:@"Hello World!", nil]; NSArray *keys = [NSArray arrayWithObjects:@"message", nil]; NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys]; NSString * currentKey; for(int i = 0; i< [keys count]; i++) { currentKey = [keys objectAtIndex:i]; NSLog(@"Value = %@", [dictionary valueForKey:currentKey]); } return dictionary; } @end Xcode 3.0 October 26

Slide 12

Slide 12 text

Objective-C 2.0 ‘07 ‘08 ‘09 ‘10 ‘11 ‘12 ‘13 ‘14 ‘15 ‘16 ‘17 @implementation MyDasource - (id) init { self = [super init]; if (self) { datasource = [[self buildDatasource] retain]; } return self; } -(NSDictionary *) buildDatasource { NSDictionary * dictionary = @{//Uses in-line literal @"message": @"Hello World, Again!" }; for (NSString * currentKey in dictionary) { //fast enumeration NSLog(@"Value2 = %@", dictionary[currentKey]);//subscript accessing } return dictionary; } @end Xcode 3.1-4.1.1 August 2

Slide 13

Slide 13 text

ARC Migration ‘07 ‘08 ‘09 ‘10 ‘11 ‘12 ‘13 ‘14 ‘15 ‘16 ‘17 Xcode 4.2 October 12 @implementation MyDasource - (id) init { self = [super init]; if (self) { datasource = [self buildDatasource]; //ARC Increases retain count +1 when assigning to iVars } return self; } -(NSDictionary *) buildDatasource { NSDictionary * dictionary = @{ @"message": @"Hello World, Again!" }; for (NSString * currentKey in dictionary) { NSLog(@"Value2 = %@", dictionary[currentKey]); } return dictionary; } @end

Slide 14

Slide 14 text

iOS 8's new Coordinate system ‘07 ‘08 ‘09 ‘10 ‘11 ‘12 ‘13 ‘14 ‘15 ‘16 ‘17 September 17 Xcode 6.1 1.0 @interface ESViewController : UIViewController @end @implementation ESViewController - (UIInterfaceOrientationMask)supportedInterfaceOrientations { return UIInterfaceOrientationMaskAll; } //whoops... deprecated method - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { if (interfaceOrientation == UIInterfaceOrientationPortrait) { // some logic } return YES; } //easy fix.. when wrapping external code - (BOOL)shouldAutorotate { UIInterfaceOrientation orientation = [[UIDevice currentDevice] orientation]; return [self shouldAutorotateToInterfaceOrientation: orientation]; } @end

Slide 15

Slide 15 text

Nullability ‘07 ‘08 ‘09 ‘10 ‘11 ‘12 ‘13 ‘14 ‘15 ‘16 ‘17 Xcode 6.3 1.2 @implementation MyDasource //... NS_ASSUME_NONNULL_BEGIN -(NSDictionary *) buildDatasource { NSDictionary * dictionary = @{ @"message": @"Hello World, Again!" }; for (NSString * currentKey in dictionary) { NSLog(@"Value2 = %@", dictionary[currentKey]); } return dictionary; } //... -(NSString *) stringForKey:(NSString *)aKey{ NSString * key = datasource[aKey]; return key ? key: @""; } NS_ASSUME_NONNULL_END @end April 8

Slide 16

Slide 16 text

Bridging to Swift 3.0 ‘07 ‘08 ‘09 ‘10 ‘11 ‘12 ‘13 ‘14 ‘15 ‘16 ‘17 Xcode 8.0 3.0 class SwiftViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() self.testBridging() } func testBridging(){ let datasource = MyDatasource.init() let message : String! = datasource.string(forKey:"message") print("The message is", message) } } June 13 @implementation MyDasource //... NS_ASSUME_NONNULL_BEGIN //... -(NSString *) stringForKey:(NSString *)aKey{ NSString * key = datasource[aKey]; return key ? key: @""; } NS_ASSUME_NONNULL_END @end

Slide 17

Slide 17 text

Can we do something to be better prepared for this changes?

Slide 18

Slide 18 text

Don’t abuse libraries • If you just need a small piece of functionality try to implement it yourself. • Library maintainers might not be as fast as you need them to be or might move on to something else, leaving you with a liability. • Every line of code that is part of your project is a line you commit to maintain.

Slide 19

Slide 19 text

Wrap third party libraries • Single point of communication, one place to fix/maintain if requirements change. • This is a (failed) wrapper:

Slide 20

Slide 20 text

Don't let your classes know more than they should. • Ask your class: what do you do? ✓ESNetworkRequest ✴AppResource “If you can't describe what your class does in one line and without using AND you probably need to break it up.” ~Robert Martin, Clean Code

Slide 21

Slide 21 text

Code Analysis $ curl -sL bit.ly/codeDistribution | sh Distribution of Code Lines AlamoFire (1) 43 Files EachScape (2) 518 Files RxSwift (3) 939 Files AFNetworking (4) 81 Files

Slide 22

Slide 22 text

How is the plant always so shiny and clean? Clean as you go…

Slide 23

Slide 23 text

• Avoid third party libraries whenever possible. • Add layers between your code and external libraries (single point of communication) • Even UIKit and Apple frameworks are code you don't control! So don't take things for granted. • As you pass by files you don't frequent, check for code style, smelly code and clean it up! Conclusions

Slide 24

Slide 24 text

Questions? Julian Gutierrez Ferrara — iOS Engineer at EachScape @jugutier

Slide 25

Slide 25 text

Thanks! Julian Gutierrez Ferrara — iOS Engineer at EachScape @jugutier