$30 off During Our Annual Pro Sale. View Details »

Working on a Legacy App

Marco Sero
August 27, 2015

Working on a Legacy App

Marco Sero

August 27, 2015
Tweet

More Decks by Marco Sero

Other Decks in Programming

Transcript

  1. Hi

    View Slide

  2. Marco Sero
    @marcosero

    View Slide

  3. Microsoft

    View Slide

  4. iOS @ Yammer

    View Slide

  5. WORKING ON A
    LEGACY APP

    View Slide

  6. DEFINITION OF
    LEGACY

    View Slide

  7. "Anything handed down
    from the past, as from an
    ancestor or predecessor"

    View Slide

  8. "Obsolete"

    View Slide

  9. DEFINITION OF
    LEGACY CODE

    View Slide

  10. No Unit Tests

    View Slide

  11. Still used in
    Production

    View Slide

  12. IT JUST
    WORKS*
    *most of the time

    View Slide

  13. Written in a language
    that you don't
    typically do new
    development in

    View Slide

  14. Swift 1.2

    View Slide

  15. Old and complicated
    History

    View Slide

  16. Many
    Contributors...

    View Slide

  17. ...That have all quit

    View Slide

  18. Let's recap
    ✔ Still used in production !
    ✔ Old or deprecated language !
    ✔ Without unit tests !
    ✔ Old history with many, many contributors... !
    ✔ ...most of which not around anymore !

    View Slide

  19. Or whenever
    you feel like this

    View Slide

  20. Not much
    Legacy
    on iOS

    View Slide

  21. iOS development is new(ish)
    Short app lifetime
    Easier to re-write

    View Slide

  22. So why bother?

    View Slide

  23. View Slide

  24. View Slide

  25. JUST
    STOP
    PLEASE
    STOP

    View Slide

  26. WHERE DO I
    START?

    View Slide

  27. STATS

    View Slide

  28. Identify the risk and start there
    $ find YourApp -iname "*.h" |
    xargs grep -h 'interface' |
    cut -d ' ' -f 2 |
    while read class;
    do echo `grep -r "\b$class\b" YourApp --include "*.m" | wc -l` $class;
    done |
    sort -n -u
    from Destroy All Software screencasts.

    View Slide

  29. View Slide

  30. Leverage
    git

    View Slide

  31. Git Blame
    ⌥⌘⇧㾑

    View Slide

  32. View Slide

  33. View Slide

  34. View Slide

  35. git log -L 1,1:/your/file

    View Slide

  36. COMMIT MESSAGES

    View Slide

  37. View Slide

  38. View Slide

  39. Your
    COMMIT MESSAGES
    are your
    LEGACY

    View Slide

  40. (Maybe) DEAD
    CODE

    View Slide

  41. TOMBSTONES
    - (void)possibleDeadCode
    {
    // current date when tombstone was added
    log_tombstone(@"2015-08-21");
    }
    • Log found?
    ➡ Code is alive !
    • Log not found?
    ➡ Code is dead "
    From David Schnepper's Ignite talk, "Isn't
    That Code Dead?"

    View Slide

  42. CONTINUOUS
    DESTRUCTION

    View Slide

  43. Inheritance

    View Slide

  44. View Slide

  45. @implementation RootViewController
    - (void)doSomething:(NSString *)aString { }
    @end
    @implementation RootViewController_iPad
    - (void)doSomething:(NSString *)aString {
    NSLog(@"%@ iPad", aString);
    }
    @end
    @implementation RootViewController_iPhone
    - (void)doSomething:(NSString *)aString {
    NSLog(@"%@ iPhone", aString);
    }
    @end
    RootViewController *vc = [[RootViewController_iPad alloc] init];
    [vc doSomething:@"cool"]; // prints "cool iPad"

    View Slide

  46. @implementation RootViewController
    - (void)doSomething:(NSString *)aString { }
    @end
    @implementation RootViewController_iPad
    - (void)doSomething {
    NSLog(@"iPad");
    }
    @end
    @implementation RootViewController_iPhone
    - (void)doSomething:(NSString *)aString {
    NSLog(@"%@ iPhone", aString);
    }
    @end
    RootViewController *vc = [[RootViewController_iPad alloc] init];
    [vc doSomething:@"cool"]; // prints nothing

    View Slide

  47. class RootViewController: UIViewController {
    func doSomething(aString: String) { }
    }
    class RootViewController_iPad: RootViewController {
    override func doSomething(aString: String) {
    print(aString + "iPad")
    }
    }
    class RootViewController_iPhone: RootViewController {
    override func doSomething(aString: String) {
    print(aString + "iPhone")
    }
    }

    View Slide

  48. class RootViewController: UIViewController {
    func doSomething(aString: String) { }
    }
    class RootViewController_iPad: RootViewController {
    override func doSomething() { // COMPILE ERROR
    print("iPad")
    }
    }
    class RootViewController_iPhone: RootViewController {
    override func doSomething(aString: String) {
    print(aString + "iPhone")
    }
    }

    View Slide

  49. "I've got your
    back"
    — Chris Lattner on Swift's Safety

    View Slide

  50. THIRD-PARTY
    DEPENDENCIES

    View Slide

  51. AVOID
    THEM
    (if possible)

    View Slide

  52. Build a small, but non-trivial, Rails app. [...] Go away for six
    months. Come back and update all of your dependencies. Your
    app no longer works.
    — Gary Bernhardt

    View Slide

  53. Build a small, but non-trivial, iOS app. [...] Go away for six months.
    Come back and update all of your dependencies. Your app no
    longer works.
    — Marco Sero

    View Slide

  54. FORKS

    View Slide

  55. Recap:
    • Start identifying the risk
    • Leverage Git
    • Spend some time writing good commit messages
    • Continuous destruction of dead code
    • Avoid subclasses and touch them with care
    • Third party dependencies have a cost and private forks are
    almost always a bad idea

    View Slide

  56. View Slide

  57. BE A GOOD CITIZEN

    View Slide

  58. HAVE FUN
    !"#

    View Slide

  59. Thank you.
    @marcosero
    • Working Effectively with Legacy Code by Michael Feathers
    • Utter Disregard for Git Commit History by Zach Holman
    http://zachholman.com/posts/git-commit-history/
    • Destroy All Software screencast by Gary Bernhardt
    https://www.destroyallsoftware.com/screencasts
    • Isn't That Code Dead? by David Schnepper
    https://www.youtube.com/watch?v=29UXzfQWOhQ

    View Slide