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

Tombstones, Vampires & Discovering Dead Code

Chris Gmyr
October 19, 2017

Tombstones, Vampires & Discovering Dead Code

Chris Gmyr

October 19, 2017
Tweet

More Decks by Chris Gmyr

Other Decks in Technology

Transcript

  1. Tombstones, Vampires
    &
    Discovering Dead Code

    View Slide

  2. Presented by
    Chris Gmyr
    @cmgmyr

    View Slide

  3. View Slide

  4. View Slide

  5. What are we going to learn?
    → What is technical debt?
    → Efficiently find dead code
    → Remove code with confidence

    View Slide

  6. What is technical debt?
    The implied cost of additional rework caused by
    choosing an easy solution now instead of using a
    better approach.
    If technical debt is not repaid, it accumulates
    'interest', making it harder to implement changes
    later on...

    View Slide

  7. View Slide

  8. What is technical debt?
    ...Technical debt is not necessarily a bad thing, and
    sometimes is required to move projects forward.
    → https://en.wikipedia.org/wiki/Technical_debt

    View Slide

  9. What does technical debt
    look like?

    View Slide

  10. Crowdpac Codebase
    → Laravel 4.2
    → ~300 Classes
    → ~50,000 Logical lines of code
    → 667.13 Average system complexity score
    → (excludes: migrations, tests, views)

    View Slide

  11. View Slide

  12. How do we start paying
    back our technical debt?

    View Slide

  13. Pay back technical debt by
    → remove commented out blocks of code
    → improve your test suite (or start one)
    → refactor code you're currently working on
    → removing dead code

    View Slide

  14. What is "dead code"?
    → not referenced
    → referenced, not executed
    → no longer provides business value

    View Slide

  15. Great, let's
    remove some
    code!

    View Slide

  16. PHP "gotchas"
    → Dynamic language
    → Magic methods
    → Easy to write "bad" code

    View Slide

  17. Variable Functions
    function foo() {
    echo "In foo()
    \n";
    }
    $func = 'foo';
    $func();
    We can't search for references of foo()

    View Slide

  18. Variable Functions
    function displayName($name)
    {
    echo $name;
    }
    $func = 'display' . ucwords($_GET['property']);
    $func($_GET['property_value']);
    How are we easily going to search for displayName() usages?

    View Slide

  19. Magic Methods
    __construct(), __destruct(), __call(), __callStatic(),
    __get(), __set(), __isset(), __unset(), __sleep(),
    __wakeup(), __toString(), __invoke(), __set_state(),
    __clone() and __debugInfo()
    http://php.net/manual/en/language.oop5.magic.php

    View Slide

  20. Magic Methods
    class User
    {
    public function __toString()
    {
    return $this->fullName();
    }
    }
    echo new User('Chris Gmyr');
    echo new User(['full_name' => 'Chris Gmyr']);
    $person = new User([...]); // User::make([...]);
    echo $person;

    View Slide

  21. Framework "Magic"
    class User
    {
    public function setPasswordAttribute($value)
    {
    $this->attributes['password'] = Hash::make($value);
    }
    public function getPasswordAttribute($value)
    {
    return 'HIDDEN';
    }
    }

    View Slide

  22. Framework "Magic"
    User::create([
    'password' => $_POST['password'] // setPasswordAttribute()
    ]);
    $user->password = $_POST['password']; // setPasswordAttribute()
    echo $user->password; // getPasswordAttribute()

    View Slide

  23. Framework "Magic"
    class Post
    {
    public function scopePopular($query)
    {
    return $query->where('votes', '>', 100);
    }
    }
    $posts = Post::popular()->get(); // scopePopular()

    View Slide

  24. Searching for usages is
    inefficient and
    error-prone

    View Slide

  25. Let's try this
    again...

    View Slide

  26. Using tombstones to find
    dead code

    View Slide

  27. What is a tombstone?
    A marker (function) placed inside code that is assumed dead.
    When a tombstone is executed, tracking information is written
    to a log.
    public function reallyOldMethod()
    {
    tombstone('2017-10-31', 'cmgmyr');
    //...
    }

    View Slide

  28. What is a vampire?
    Suspected dead code, marked with a tombstone, that is alive
    echo $user->fullName();
    class User
    {
    public function fullName() // vampire!
    {
    tombstone('2017-10-31', 'cmgmyr'); // remove this
    return $this->first_name . ' ' . $this->last_name;
    }
    }

    View Slide

  29. PHP Implementation
    https://github.com/scheb/tombstone
    function tombstone($date, $author, $label = null) {
    try {
    $trace = TraceProvider::getTraceHere();
    $streamHandler = new StreamHandler(dirname(__DIR__)."/logs/tombstones.log");
    GraveyardProvider::getGraveyard()->addHandler($streamHandler);
    GraveyardProvider::getGraveyard()->tombstone($date, $author, $label, $trace);
    } catch (\Exception $e) {
    //
    }
    }

    View Slide

  30. PHP Implementation
    https://github.com/scheb/tombstone-analyzer

    View Slide

  31. View Slide

  32. Other Tombstone Implementations
    JavaScript
    https://blog.bugsnag.com/javascript-refactoring-with-
    bugsnag-and-tombstones/
    Perl
    http://devblog.nestoria.com/post/115930183873/
    tombstones-for-dead-code

    View Slide

  33. Let's set some
    tombstones!

    View Slide

  34. class Post
    {
    public function publishToMySpace()
    {
    tombstone('2017-10-31', 'cmgmyr');
    //...
    }
    }

    View Slide

  35. View Slide

  36. class User
    {
    public function canPublishPost()
    {
    if ($this->isAwesome()) {
    if($this->type == 'zombie') {
    tombstone('2017-10-31', 'cmgmyr');
    //...
    }
    //...
    }
    //...
    }
    }

    View Slide

  37. Add tombstones to
    suspected dead code

    View Slide

  38. View Slide

  39. ...or ALL code...

    View Slide

  40. View Slide

  41. ...and wait...

    View Slide

  42. Check the logs
    2017-11-01 09:00:00 Vampire detected from tombstone('2017-10-31', 'cmgmyr')
    in User.php on line XXX in canPublishPost()
    ...
    2017-11-02 09:00:00 Vampire detected from tombstone('2017-10-31', 'cmgmyr')
    in User.php on line XXX in canPublishPost()
    ...
    2017-11-03 09:00:00 Vampire detected from tombstone('2017-10-31', 'cmgmyr')
    in User.php on line XXX in canPublishPost()
    ...

    View Slide

  43. class User
    {
    public function canPublishPost()
    {
    if ($this->isAwesome()) {
    if($this->type == 'zombie') {
    tombstone('2017-10-31', 'cmgmyr');
    //...
    }
    //...
    }
    //...
    }
    }

    View Slide

  44. Check the logs
    2017-11-01 09:00:00 Vampire detected from tombstone('2017-10-31', 'cmgmyr')
    in User.php on line XXX in canPublishPost()
    ...
    2017-11-02 09:00:00 Vampire detected from tombstone('2017-10-31', 'cmgmyr')
    in User.php on line XXX in canPublishPost()
    ...
    2017-11-03 09:00:00 Vampire detected from tombstone('2017-10-31', 'cmgmyr')
    in User.php on line XXX in canPublishPost()
    ...
    2017-11-04 ...
    2017-11-05 ...
    2017-11-06 ...
    No more canPublishPost() vampires!!!

    View Slide

  45. class Post
    {
    public function publishToMySpace()
    {
    tombstone('2017-10-31', 'cmgmyr');
    //...
    }
    }

    View Slide

  46. class TombstoneWorkflow
    {
    public function __construct()
    {
    $this->makePlan();
    $this->cleanCode();
    }
    public function cleanCode()
    {
    $this->setTombstones();
    while($this->codebaseHasVampires()) {
    $this->checkLogs();
    $this->removeVampires();
    }
    $this->reviewRemainingTombstones();
    $this->removeDeadCode();
    }
    }

    View Slide

  47. Crowdpac
    2,400 initial tombstones (class methods)
    -750 locally
    -925 staging/production
    ~700 Remaining (30%)

    View Slide

  48. View Slide

  49. Who should utilize tombstones?
    → legacy code
    → complex domain
    → inherited codebase
    → upgrading a codebase

    View Slide

  50. So, why tombstones?
    → Low impact solution
    → Use with dynamic languages
    → High confidence in removing code

    View Slide

  51. Thank you!

    View Slide

  52. Say "Hi"!
    twitter.com/cmgmyr
    github.com/cmgmyr
    chrisgmyr.com

    View Slide