Post on 23-Jun-2015
description
transcript
1
Building Quality Code That Lasts: A Dropbox StoryAshley Nelson-Hornstein · 10 - 30 - 14
2
Product
Testing
Background
Case Studies
Future of iOS at Dropbox
TODAY’S TALK
3
Dropbox for iOSDeveloped natively
Team of one engineer
First consumer of Dropbox public APIs
Released for iPhone in 2009
iPad support in 2010
4
Sync SDK
UI Code
Core SDK
Data Layer
5
6
6
6
6
TODAY’S TALK
Product
Testing
Background
Case Studies
Future of iOS at Dropbox
7
Product RoadmapCollaborative process
Mix of
Infrastructure
User facing features
Code modernization
8
Release ManagerRotating role
Feature gatekeeper
Project manager
Task prioritization
Scheduling
Build stabilization
9
Development
10
BranchingDefault branch
All changes are checked in here first
Release branch
hg graft —log from default branch
Verified by release manager
11
12
13
13
Style Guide
14
Coding ConventionsPrefix internal methods with db_
Prefer class methods
Hide implementation detail
Class extensions
15
16
// DBFile.h !
@interface DBFile : NSObject !
@property (readonly, strong) NSData *contents; !
@property (readonly, strong) NSURL *publicShareLink; !
@property (strong) NSDictionary *permissions; !
- (void)copyToNewPath:(NSString *)newPath; !
@end
// DBFile.m !
@interface DBFile () !
@property (readwrite, strong) NSData *contents; !
@property (strong) NSString *localFilePath; @end !
@implementation DBFile !
- (void)copyToNewPath:(NSString *)newPath { ... } @end
Comments// TODO: (ashleynh) 2014-10-30
Reminder for future improvement
// FIXME: (ashleynh) 2014-10-30
Generates compiler warning, not for release
// HAX: (ashleynh) 2014-10-30
Non-obvious API workaround
17
Builds
18
Continuous IntegrationPool of build machines
Executes functional tests
Builds are available to office
State changes are emailed to team
19
20
Crash ReporterDeveloped in-house
Predates other crash report services
Uploads crash logs from device
Groups crashes by stack trace
Provides symbolication
21
22
TODAY’S TALK
Testing
Case Studies
Future of iOS at Dropbox
Background
23
Product
Developer SettingsToggle features on/off
View
Run log
Network and device stats
File cache inspection
24
Shake to ReportInternal bug reporting
Captures
Screenshot
Crash log (if applicable)
Run log
Issues reported directly to bug tracking tool
25
Helper Apps
26
DropolineDeveloped in-house
Tests inter-app workflows
File import/export
Photo backup
Storage provider extension
27
Car KeysDeveloped in-house
Keychain
Inspection
Deletion
28
Automata
29
Automata BackgroundFunctional testing framework
Developed in-house
Run tests locally or using Jenkins
Python API
Rich set of libraries to simplify automation
High productivity
30
Automata BenefitsSeparate process enables inter-app testing
Single test can manipulate two apps
Automating screenshots and screenshot diffs
Objective-C experience not required
Hooks into Objective-C runtime
31
32
Automata
Dropbox Dropoline
32
Automata
Dropbox Dropoline
Automata FutureSupport for iOS 8 extensions
GUI that records test scripts
Open source
33
TODAY’S TALK
Testing
Case Studies
Future of iOS at Dropbox
Background
34
Product
File Cache
35
BackgroundProvides access to user’s Dropbox files
Coordinates with REST API and disk
Critical component
36
IssuesFile names of stored files are Dropbox paths
Unusually long file paths
Unsupported unicode characters
File loading race conditions
Providing readwrite access to file refs
37
/* * Hello there, friend. I wish you luck in your voyage through the following code. * * We need to avoid doing disk I/O in this callback, because it will be called in quick succession * repeatedly on photos tab as we load lots of thumbs. Since we're on the main thread right now, * we can't afford to do costly disk I/O. It will seriously impact scroll performance on photos tab * if we do. * * The following code checks to see if what we just loaded has only a thumbnail repr. If it does, * it updates the cacheSize property of the file to -1. -1 is a special flag, indicating to the LRU cleanup * mechanism that this file doesn't need to be purged from the disk during LRU cleanup. * * Why not cleanup these files during LRU cleanup? Because with the release of photos tab, we may * have thousand of files on disk. And starting them all during LRU cleanup is much too slow. So, * we've opted to just not clean up files that only have thumbnail reprs. * * This code is not "correct". For example, if you load a thumbnail *AND* the BestFit repr, the thumbnail * could now be cleaned up during LRU cleanup. * * This is basically a huge hack to make scrolling performance not stutter in photos tab. * */
38
/* * Hello there, friend. I wish you luck in your voyage through the following code. ! * This is basically a huge hack to make scrolling performance not stutter in photos tab. */
39
GoalsEnsure file name integrity
Operations on separate queue
Smarter file loading system
Defensive return values
40
ApproachUnit Tests
Uncovered existing bugs
Set a baseline for expected behavior
Maintained API for consumers
Limited project scope
41
ImplementationStore files by UUID instead of Dropbox path
File Cache on background serial queue
Return immutable stubs of file refs
LoadingFileManager
42
Consumer FileCache
RO Cached File
Core Data
Disk
Loading File Manager
Single Background Queue
43
BenefitsEasier to understand
Performant
Stable
44
App Delegate
45
[[UIApplication sharedApplication] delegate]
46
47
Issues
48
IssuesApp could be entered in a number of ways
48
IssuesApp could be entered in a number of ways
User initiated
48
IssuesApp could be entered in a number of ways
User initiated
File import
48
IssuesApp could be entered in a number of ways
User initiated
File import
API connection
48
IssuesApp could be entered in a number of ways
User initiated
File import
API connection
Notification
48
IssuesApp could be entered in a number of ways
User initiated
File import
API connection
Notification
Etc.
48
IssuesApp entry state could be
48
IssuesApp entry state could be
Passcode on
48
IssuesApp entry state could be
Passcode on
Passcode off
48
IssuesApp entry state could be
Passcode on
Passcode off
Locked out
48
IssuesApp entry state could be
Passcode on
Passcode off
Locked out
Already displaying a modal
48
Overly complex logic
48
GoalsProperly define app states
Encapsulate state logic
Transition easily between states
Speed launches
49
ImplementationState Pattern
DBState
Initial
NotLoggedIn
ContinueAs
LoggedInNoPasscode
LoggedInPasscode
50
BenefitsReduced 2600 lines to 500 lines
Easier to understand
Encapsulated logic in clear boundaries
51
TODAY’S TALK
Testing
Case Studies
Future of iOS at Dropbox
Background
52
Product
SwiftExcited by the promise
Practical approach
Tooling
Encapsulated features
53
54