Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Tips & Tricks of Effective iOS Developers

Tips & Tricks of Effective iOS Developers

Talk given at CocoaConf Chicago, 2014

023a6a37e8177cb2f84a236bbce643cf?s=128

Ben Scheirman

March 08, 2014
Tweet

Transcript

  1. Tips & Tricks of Effective iOS Developers

  2. BEN SCHEIRMAN @subdigital

  3. None
  4. Weekly Screencasts on iOS DEVELOPMENT $9/month

  5. Tips & Tricks of Effective iOS Developers

  6. ? Effective

  7. effective |iˈfektiv| adjective ! successful in producing a desired or

    intended result
  8. ! DEVELOPERS Effective

  9. ! DEVELOPERS FIX PROBLEMS Effective

  10. ! DEVELOPERS WRITE CODE FASTER Effective

  11. ! DEVELOPERS CONFIDENTLY REFACTOR Effective

  12. ! DEVELOPERS WRITE BETTER CODE Effective

  13. ! DEVELOPERS WRITE FEWER BUGS Effective

  14. ! DEVELOPERS GET THINGS DONE Effective

  15. ! DEVELOPERS SHIP BETTER SOFTWARE Effective

  16. SHIP BETTER SOFTWARE

  17. ME?

  18. None
  19. I aspire to be Effective

  20. Objective-C Tips

  21. Always use braces for conditionals if ([self isHungry]) { [self

    eatBurger]; } if ([self isHungry]) [self eatBurger]; if ([self isHungry]) [self eatBurger]; [self takeNap]; if ([self isHungry]) { [self eatBurger]; [self takeNap]; }
  22. if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0) goto fail; if

    ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0) goto fail; goto fail; if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0) goto fail; ... ! fail: SSLFreeBuffer(&signedHashes); SSLFreeBuffer(&hashCtx); return err; Always use braces for conditionals
  23. None
  24. @interface Player ! - (void)moveLeft; - (void)moveRight; - (void)jump; -

    (void)hit; ! @end Use Class Continuations for Private Properties @interface Player () @property CGFloat health; @property Texture *texture; @end ! @implementation Player … @end Player.h Player.m
  25. Use Class Continuations for Private Properties @interface ViewController () @property

    IBOutlet UILabel *label; @end ! @implementation ViewController … @end
  26. Use intention revealing method names - (NSDate *)nextDate:(NSDate *); -

    (NSDate *)nextBillingDateAfterDate:(NSDate *);
  27. Name single parameter BOOL arguments -(void)showPanel:(BOOL)animated; [self showPanel:NO];

  28. Name single parameter BOOL arguments -(void)showPanelAnimated:(BOOL)animated; [self showPanelAnimated:NO];

  29. Add Comment Documentation to Public Methods

  30. - (void)viewDidLoad { [self.fetchedResultsController performFetch:nil]; } Lazily Initialize Properties -

    (NSFetchedResultsController *)fetchedResultsController { if (_frc == nil) { _frc = [[NSFetchedResultsController alloc] initWithFetchRequest: self.fetchRequest ... ] } ! return _frc; }
  31. Lazily Initialize Properties - (NSFetchRequest *)fetchRequest { if (_fetchRequest ==

    nil) { _fetchRequest = … } return _fetchRequest; }
  32. Lazily Initialize Properties - (void)didReceiveMemoryWarning { self.fetchResultsController = nil; self.fetchRequest

    = nil; … }
  33. Use Refactor Method judiciously - (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)

    indexPath { UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:@“cell”]; NSArray *peopleInSection = self.sections[indexPath.section]; Person *person = peopleInSection[indexPath.row]; cell.textLabel.text = [NSString stringWithFormat:@“%@ %@“, person.firstName, person.lastName]; cell.detailTextLabel.text = person.email; return cell; }
  34. Use Refactor Method judiciously - (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)

    indexPath { UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:@“cell”]; Person *person = [self personAtIndexPath:indexPath]; cell.textLabel.text = [NSString stringWithFormat:@“%@ %@“, person.firstName, person.lastName]; cell.detailTextLabel.text = person.email; return cell; }
  35. Use Refactor Method judiciously - (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)

    indexPath { UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:@“cell”]; Person *person = [self personAtIndexPath:indexPath]; cell.textLabel.text = person.fullName; cell.detailTextLabel.text = person.email; return cell; }
  36. Use Refactor Method judiciously - (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)

    indexPath { UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:@“cell”]; Person *person = [self personAtIndexPath:indexPath]; [self updateCell:cell forPerson:person]; return cell; }
  37. Understand Dependencies method1 method2

  38. Understand Dependencies

  39. Understand Dependencies

  40. Understand Dependencies

  41. Keep your dependencies in check OO is your friend

  42. objc-dependency-visualizer http://paultaykalo.github.io/objc-dependency-visualizer

  43. http://jomnius.blogspot.com/2012/01/dependency-graph-tool-for-ios-projects.html

  44. http://jomnius.blogspot.com/2012/01/dependency-graph-tool-for-ios-projects.html

  45. Reduce Dependencies by… Loose Coupling Programming to interfaces Dependency Inversion

    Reduce God Objects Reduce Singletons
  46. With Less Dependencies you can… Refactor Change your mind Change

    your implementation Add features
  47. “Ruthlessly modularize functionality. Design, implement, and package everything as if

    it were to be distributed as 3rd-party code”
  48. “Ruthlessly modularize functionality. Design, implement, and package everything as if

    it were to be distributed as 3rd-party code”
  49. Mattt Thompson

  50. Slim down your classes

  51. Slim down your classes

  52. Try to impose limits

  53. Challenge Yourself Photograph by Mikey Schaefer

  54. Max LOC for .m: ~150 Max LOC for method: 4-5

    Cesare Rocchi
  55. Automate it

  56. awk

  57. find "${SRCROOT}" \(-name "*.h" -or -name "*.m"\) -and \( -path

    "${SRCROOT}/Pods/*" -prune -o -print0 \) | xargs -0 wc -l | awk '$1 > 400 && $2 != "total" { for(i=2;i<NF;i++) { printf "%s%s", $i, " “ } print $NF ":1: warning: File more than 400 lines (" $1 "), consider refactoring." }' http://matthewmorey.com/improved-xcode-build-phases/
  58. Xcode Tips

  59. Completing Methods

  60. “- ta”

  61. Label your views in Interface Builder

  62. Learn Keyboard Shortcuts Photo credit: Wikipedia

  63. ⌘0

  64. ⌘⌥0

  65. ⌘⇧J

  66. ⌘⇧Y

  67. ⌘⇧C

  68. ⌘⌃J ⌘⌃←

  69. Jump in Assistant, back

  70. ⌘⌃E (Edit all in Scope)

  71. ⌃I (Re-indent selection)

  72. So many to learn

  73. Pick 2 you don’t know

  74. Deliberately Practice them

  75. Repeat.

  76. None
  77. Snippets

  78. Xcode / TextExpander

  79. “pns” @property (nonatomic, strong)

  80. “propint” @property (nonatomic, assign) NSInteger

  81. “propstr” @property (nonatomic, copy) NSString *

  82. “mark” #pragma mark -

  83. #pragma mark

  84. #pragma mark

  85. “tvds”

  86. “swf”

  87. “tvdel”

  88. “networkact” [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];

  89. Repetitive code? Boilerplate code? ! Make a snippet.

  90. Source Control Tips

  91. (git)

  92. Use the command line

  93. Leverage GUIs for specific tasks

  94. http://rowanj.github.io/gitx/ GitX

  95. Commits aren’t just ⌘S

  96. Commit in logical chunks.

  97. Write a good commit message

  98. http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html Capitalized, short (50 chars or less) summary ! More

    detailed explanatory text, if necessary. Wrap it to about 72 characters or so. In some contexts, the first line is treated as the subject of an email and the rest of the text as the body. The blank line separating the summary from the body is critical (unless you omit the body entirely); tools like rebase can get confused if you run the two together. ! Write your commit message in the imperative: "Fix bug" and not "Fixed bug" or "Fixes bug." This convention matches up with commit messages generated by commands like git merge and git revert. ! Further paragraphs come after blank lines. ! - Bullet points are okay, too ! - Typically a hyphen or asterisk is used for the bullet, followed by a single space, with blank lines in between, but conventions vary here ! - Use a hanging indent
  99. $ git log --oneline ! 9511f6c Add mixpanel gem 47a3e6d

    Add a sleep to not get throttled by facebook ce30dcb Kick Jenkins build 2e6802f Merge pull request #981 from DeliRadio/venue-favorites-rabls 99eb628 stub master account to avoid fail when run in test suite. b4e0435 before(:all) -> before(:each) to avoid certain test to fail when execute e4b10b6 Update schema 7b1e053 Fix banner check for venues in autocomplete 83ca7cb Update ci reporter 6eae32f Fix admin manages events spec. 7c8902b Add new line at the end of file so Github likes it. a153a48 Call Rails.application.eager_load! right before it is needed so that its 4a4d050 Refactoring test so it finishes faster. 4155ac6 fix crash when correcting country code from geolocated params 08c5bdb Proper auth token generation for facebook login: 4efaf1e Venue needs to have shareable_id and shareable_type implementation. Defa a9cdd7a Implemented a test to check shareable_id and shareable_type. Since Favor 9e1e6c2 fix after_party task syntax dde3ae9 add after_party task to fill in fb birthdays where we can 6e99a74 Implemented tests to check renderability of all ActiveRecord instance th b174af9 Added four templates that are required for favoritable items. 07218a0 year_of_birth, not birth_year be562bf update attribs from fb even for existing users 29041f0 Add logging to facebook oauth responses
  100. None
  101. Branches are basically free

  102. None
  103. REBASE Learn to

  104. master origin/master

  105. master origin/master

  106. master origin/master MERGE METHOD “git pull” by default

  107. master origin/master

  108. master origin/master REBASE METHOD

  109. 99% of the time you want ! git pull --rebase

  110. Make this the default git config branch.autosetuprebase always

  111. Never rebase public branches

  112. git bisect

  113. None
  114. git bisect start

  115. git bisect bad

  116. git checkout HEAD~15

  117. git bisect good

  118. ?

  119. git bisect bad

  120. git bisect bad

  121. None
  122. git bisect good

  123. None
  124. git bisect good

  125. None
  126. git bisect good

  127. None
  128. git bisect run <script>

  129. Oops, I made a git mistake!

  130. git reflog

  131. None
  132. Branch Per Feature

  133. Keep Master Releasable

  134. Don’t veer too far from working software

  135. “I attempt to keep the app in a working state

    as much as possible. That means test driving small changes, committing often, and only hooking things up to the UI when I think they're ready…”
  136. “… If I'm not in a position to push my

    code at least every hour or so, I feel like I haven't broken my work down properly”
  137. Stew Gleadow

  138. http://collectorcare.blogspot.com/

  139. http://cobcottagegifts.com/

  140. Effective Habits

  141. “I'm not a great programmer; I'm just a good programmer

    with great habits.” ! - Kent Beck
  142. Keep an improvement list ! !

  143. Have a side project ! !

  144. Read Other People’s Code

  145. “I form opinions about the code I study. Not all

    of it is good. I want to reflect on why I feel that way.”
  146. Jonathan Penn

  147. Learn how to ask for help

  148. None
  149. None
  150. Don’t ask ! Questions. 5

  151. Ask ! Question. 1

  152. Distill The Problem

  153. Reduce Variables

  154. Also works for:

  155. “Before asking for advice, take a careful look at what

    you know and what you are looking to have answered. Often that will put you in a spot where you answer your own question.” ! !
  156. Daniel Steinberg

  157. None
  158. Program in other Languages

  159. “Don't just program in Objective C, make sure you regularly

    use another language. There is a lot we can learn from other technologies and communities” ! - Stew Gleadow ! !
  160. Write Tests.

  161. Go Forth, and be Effective

  162. Thank you BEN SCHEIRMAN @subdigital chaione.com