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...
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
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
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?
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;
Framework "Magic" class User { public function setPasswordAttribute($value) { $this->attributes['password'] = Hash::make($value); } public function getPasswordAttribute($value) { return 'HIDDEN'; } }
Framework "Magic" class Post { public function scopePopular($query) { return $query->where('votes', '>', 100); } } $posts = Post::popular()->get(); // scopePopular()
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'); //... }
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; } }
class User { public function canPublishPost() { if ($this->isAwesome()) { if($this->type == 'zombie') { tombstone('2017-10-31', 'cmgmyr'); //... } //... } //... } }
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() ...
class User { public function canPublishPost() { if ($this->isAwesome()) { if($this->type == 'zombie') { tombstone('2017-10-31', 'cmgmyr'); //... } //... } //... } }
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!!!
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(); } }