ios development methodology

26
iOS Development Methodology Applying Best Practices to the Xcode World Thursday, July 25, 13 This is a “Guided Exploration”, though I will be talking a lot. Please feel free to ask questions at any time, I’d like this to be more of a discussion than a presentation. the Ruby community has been preaching test-first Agile methodologies for years, even if you don’t entirely buy into what they are saying, they are pushing the discussion forward and improving their best practices. Today I want to talk about applying some of these practices to iOS/ Objective-C development in Xcode.

Upload: smartlogic

Post on 22-Nov-2014

1.334 views

Category:

Technology


0 download

DESCRIPTION

A walkthrough of iOS development methodology from SmartLogic's Tom von Schwerdtner.

TRANSCRIPT

Page 1: iOS Development Methodology

iOS Development Methodology

Applying Best Practices to the Xcode World

Thursday, July 25, 13

This is a “Guided Exploration”, though I will be talking a lot.

Please feel free to ask questions at any time, I’d like this to be more of a discussion than a presentation.

the Ruby community has been preaching test-first Agile methodologies for years, even if you don’t entirely buy into what they are saying, they are pushingthe discussion forward and improving their best practices. Today I want to talk about applying some of these practices to iOS/Objective-C development in Xcode.

Page 2: iOS Development Methodology

Tom von Schwerdtner

SmartLogic

smartlogic.io

twitter.com/tvon

github.com/tvon

Thursday, July 25, 13

So you understand my perspective...

Developing websites for over 10 yearsRuby for past 2.5 yearsiOS for past 1.5 years

Page 3: iOS Development Methodology

What you’re in for

• Xcode’s bad influences

• Organization and Separation of Concerns

• Testing, and in Isolation

Code: https://github.com/smartlogic/ios-best-practices

or http://goo.gl/skgRY

Thursday, July 25, 13

This is what we’re going to talk about

This talk is aimed at beginner to intermediate developers (but hopefully something for everyone)

Some familiarity with the structure of iOS apps is somewhat necessary.

Page 4: iOS Development Methodology

Xcode’s Bad Influences

Thursday, July 25, 13

Page 5: iOS Development Methodology

Xcode’s Bad Influences

• Lack of Project Structure

• Questionable Templates

Thursday, July 25, 13

Two primary gripes.

Filesystem does not match project organizationLousy for any non-xcode view of the project (github/bitbucket)

Page 6: iOS Development Methodology

Solutions

• Create Folders for Groups

• Strip Comments

• Avoid UITableViewController

Thursday, July 25, 13

First and foremost you can actually create folders for groups.Ensures files added to that group will default to that folder.

UItableViewController adds unecessary noise (more on that later)

File comments are redundant in the world of git.

Page 7: iOS Development Methodology

Better Templates

github.com/mneorr/Alcatraz/

Alcatraz - Xcode Plugin Manager

Thursday, July 25, 13

Use Alcatraz.

We have templates that should show up there soon.

Starting with an empty Xcode project is good practice. It is important to know all the steps required to get to that Master-Detail view example

Page 8: iOS Development Methodology

Better Templates

github.com/mneorr/Alcatraz/

Alcatraz - Xcode Plugin Manager

(or build from scratch, it’s good practice)

Thursday, July 25, 13

Use Alcatraz.

We have templates that should show up there soon.

Starting with an empty Xcode project is good practice. It is important to know all the steps required to get to that Master-Detail view example

Page 9: iOS Development Methodology

Organization and Separation of Concerns

Thursday, July 25, 13

Page 10: iOS Development Methodology

What are Concerns?

• Roles within the Application

• View Controllers

• Views

• Services

• Models

• Delegates (protocol implementations)

Thursday, July 25, 13

Concerns are the different components that make up your application.

Controllers generally coordinate other objects (models, views, services and delegates)The other objects should essentially worry about themselves.

Page 11: iOS Development Methodology

How to Separate?

• Organize into groups/folders

• Keep as isolated as possible

• Stand-alone protocol implementations

Thursday, July 25, 13

Organization is important, just put each in it’s own place

Isolation may take some practice, let’s touch on that real quick.

Page 12: iOS Development Methodology

Data Source Isolation

Thursday, July 25, 13

A DataSource can be extremely simple.

Expose NSMutableArray “items” to be setup externallyPut Cell configuration code in the cell.

Page 13: iOS Development Methodology

Data Source Isolation

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ WidgetCell *cell = [tableView dequeueReusableCellWithIdentifier:WidgetCellIdentifier forIndexPath:indexPath]; [cell configure:[self.items objectAtIndex:indexPath.row]]; return cell;}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return [self.items count];}

Thursday, July 25, 13

A DataSource can be extremely simple.

Expose NSMutableArray “items” to be setup externallyPut Cell configuration code in the cell.

Page 14: iOS Development Methodology

DataSource Isolation- (void)viewDidLoad{

// (minor setup code)

// WidgetCellIdentifier declared in data source header [self.tableView registerClass:[WidgetCell class] forCellReuseIdentifier:WidgetCellIdentifier]; self.dataSource = [[WidgetsTableDataSource alloc] init]; self.tableView.dataSource = self.dataSource; [WidgetAPIService getWidgets:^(NSMutableArray *widgets) { self.dataSource.items = widgets; [self.tableView reloadData]; }]; }

Thursday, July 25, 13

The entire UIViewController is basically the viewDidLoad method.Our service loads items based on an API call.

This gives us a nicely isolated data source.

This is a good lead in to testing in isolation

Page 15: iOS Development Methodology

Testing, and in Isolation

Thursday, July 25, 13

Testing in isolation means testing individual components without relying on external components.

If you need to be sold on testing, in short it allows you to change and refactor your code and knowing that doing so doesn’t break anything (or finding it and fixing it).

It reduces the

Page 16: iOS Development Methodology

A Note on Tools

• BDD Tool: Kiwi

• Web Mocking: Nocilla

• (Ditch whatever Xcode gives you)

Thursday, July 25, 13

Hitting the network for every test is just a bad idea.I like to test against a dev server until tests are greeen, then stub requests.

Page 17: iOS Development Methodology

A Category Test

Testing the parsing of a timestamp string to an NSDate

Thursday, July 25, 13

This is a good first test. It is isolated by nature (being a category).

This is a legitimate test, whenever you are parsing a string to turn it into something else you should test that your parsing works.

Page 18: iOS Development Methodology

A Category Testdescribe(@"NSDate+Timestamps", ^{ it(@"Initializes an NSDate from a timestamp string", ^{ NSString *timestamp = @"2010-02-03T04:05:06Z"; NSDate *date = [NSDate dateWithTimestamp:timestamp]; NSUInteger units = NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit| NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit; NSDateComponents *components = [[NSCalendar currentCalendar] components:units fromDate:date]; [[theValue(components.year) should] equal:theValue(2010)]; [[theValue(components.month) should] equal:theValue(2)]; [[theValue(components.day) should] equal:theValue(3)]; [[theValue(components.hour) should] equal:theValue(4)]; [[theValue(components.minute) should] equal:theValue(5)]; [[theValue(components.second) should] equal:theValue(6)]; });});

Thursday, July 25, 13

Our test. Give it a timestamp string, expect a proper NSDate back.

Page 19: iOS Development Methodology

Implementation

Thursday, July 25, 13

If we TDD this, we should first get a “no known class method with selector...” error.

Page 20: iOS Development Methodology

Implementation

+(id)dateWithTimestamp:(NSString *)string{

return [NSDate date];}

Thursday, July 25, 13

Implement the bare minimum to get past that error, and we get an NSDate but all of the values are wrong.

Page 21: iOS Development Methodology

Implementation

+(id)dateWithTimestamp:(NSString *)string{ NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"]; return [dateFormatter dateFromString:string];}

Thursday, July 25, 13

At this point we implement the method and the test should pass.

Page 22: iOS Development Methodology

Testing a Data Source

Thursday, July 25, 13

This is where we test our stand alone data source.

By splitting out the class, we can now test it without involving the view controller (and any weight that may carry)

Page 23: iOS Development Methodology

Testing a Data Sourcedescribe(@"WidgetsTableDataSource", ^{ it(@"Returns WidgetCell configured with correct Widget", ^{ UITableView *tableView = [[UITableView alloc] init]; WidgetsTableDataSource *dataSource = [[WidgetsTableDataSource alloc] init]; Widget *widgetOne =[[Widget alloc] init]; widgetOne.name = @"First Widget"; Widget *widgetTwo =[[Widget alloc] init]; widgetTwo.name = @"Second Widget"; dataSource.items = [@[widgetOne, widgetTwo] mutableCopy]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; UITableViewCell *widgetCell = [tableView cellForRowAtIndexPath:indexPath]; [[((WidgetCell *)widgetCell).nameLabel.text should] equal:@"First Widget"]; });});

Thursday, July 25, 13

Step through.

We initialize a table view (data source methods require it)We initialize our data sourceWe add two widgets to the data source items.We verify that cellForRowAtIndexPath returns the correct cell data.Note that this somewhat inadvertently tests WidgetCell, but that is not our concern so much as the verification that the right cell is returned.

Why test something this simple? Well, they say that the two hardest things in computer science are cache invalidation, naming things and off-by-one errors.

Besides which, your items array could be a more complex collection.

Page 24: iOS Development Methodology

Testing a Data Source

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ WidgetCell *cell = [tableView dequeueReusableCellWithIdentifier:WidgetCellIdentifier forIndexPath:indexPath]; [cell configure:[self.items objectAtIndex:indexPath.row]]; return cell;}

Thursday, July 25, 13

Once again, the Data Source implementation.

Very simple.

Page 25: iOS Development Methodology

Exercises for the Reader

• Test WidgetCell configuration• Isolate the Data Source Test (don’t rely on widget cell)

Thursday, July 25, 13

There are improvements that could be made here, if interested.

Page 26: iOS Development Methodology

Questions?

smartlogic.io

twitter.com/smartlogic

github.com/smartlogic

facebook.com/smartlogic

Thursday, July 25, 13

So that’s it. Depending on time left we can discuss testing techniques, organization or even work ona particular problem if someone has something they’d like to discuss.