We all have to deal with the scarcest resource in development teams: time. This often leads to compromises and shortcuts when writing code. The result is what is called technical debt: the difference between how the code should have been and how it is.
Strategies for managing technical debt are many but all require an investment of time and energy, proportional to the amount of debt to be repaid.
Is this really the only way?
Rector is a tool capable of automating a wide range of refactorings, allowing us to speed up the most tedious manual operations. In this talk we will see how, exploring
- rector's basic principles
- predefined rules, configurable rules, sets of rules
- how to write custom rules
3. ● Spreaker is a podcast platform
● Within Spreaker, podcasts can be
hosted, distributed, monetized,
discovered, and listened to
● Part of iHeartMedia family since
2020
4. 🤓 Expert teams can tame it, choosing willingly
to accumulate it
→ trade off cleaner solution with a good
enough one
Tech Debt
🐥 Green teams accumulate it unconsciously
→ let's try this and that
Never saw a project without it 🙄
5. The mere fact that
we are writing code
exposes us to tech debt
Tech Debt
-> Language Evolves
-> Libraries evolve
-> Frameworks evolve
-> Things are (re)discovered
6. How can we deal with it?
Invest 🕒 and ⚡
to repay the debt
😫 Sometimes it is hard
to justify the investment
🤔 Is there a way to get away
with it?
Tech Debt
7. Performs automated refactorings on a codebase
It provides a list of predefined rectors, aka rules, refactorings you can choose
to apply on your codebase, via a rector.php config file. E.g.
- Change a property access with a method call
from $obj->property to $obj->method()
- Substitute class invocation with another one
from Banana::method() to Apple::anotherMethod()
Rector
8. Provided a ton of rules out of the box
- Code style/quality
- Manipulate properties/methods
- Upgrade language version
- Upgrade framework version
Rector
https://github.com/rectorphp/rector/blob/main/docs/rector_rules_overview.md
9. Why do I need it?
-> Regexp are not enough?
-> Search and replace is not enough?
Rectors parses the code, so it can perform complex manipulation. For this
reason it is also unaffected by code formatting (spaces, newlines, …)
Rector
10. Installation/configuration
$ composer require rector/rector --dev
If you create custom rules, configure composer.json to enable autoload
"autoload-dev": {
"psr-4": {
"UtilsRector": "tools/php/rector/src",
"UtilsRectorTests": "tools/php/rector/tests"
}
}
11. Installation/configuration
Create an empty rector.php file in the project root directory
$ vendor/bin/rector init
Change rector.php to specify which directories should be scanned and which
rules should be applied
13. Run
In the project root directory run
$ vendor/bin/rector process
If you want to see a preview of the changes without touching the files
$ vendor/bin/rector process --dry-run
24. 1. Loads configuration from rector.php
2. Iterates all files
3. For each file
a. Preparation phase: parse file, creates AST (array of nodes), add some
metadata
b. Rectify Phase
i. Traverse AST
ii. Check if rectors can be applied to that node
iii. If yse, apply
c. Save/Diff phase
How it works
25. A rule is a PHP class that extends AbstractRector
Implement 3 method
Writing Custom Rules
public function getRuleDefinition(): RuleDefinition
public function getNodeTypes(): array
public function refactor(Node $node): ?Node
45. AST - Abstract Syntax Tree
Intermediate representation of the source code
Machine friendly
Tree structure
Traversing the AST means
traversing the original source code
48. A rule is a PHP class that extends AbstractRector
Implement 3 method
Writing Custom Rules
public function getRuleDefinition(): RuleDefinition
public function getNodeTypes(): array
public function refactor(Node $node): ?Node
49. Look for existing rules that perform similar tasks. Use it as a starting point.
Look for helper classes: classes that perform some heavy lifting for you. E.g
pull up a property
There are plenty:
- ClassDependencyManipulator
- ClassInsertManipulator
- NodeFactory
- ParamAnalyzer
Create a small snippet of code to test it with --dry-run
Start with an existing rule
51. Look for a rule that does something similar to what you need and use it as a
starting point
This part is a bit time consuming, there are multiple ways to achieve the same
result
Don't try to do too much in a single rule, combine multiple rules
Writing Custom Rules: lesson learned
52. Get all the corner cases is hard, Pareto rulez!
NodeDumper is your friend
Create a Dummy snippet for quick testing
Writing Custom Rules: lesson learned
53. Extensions: composer installable set of rules for specific framework/libraries
These are provided out of the box
https://github.com/rectorphp/rector-symfony
https://github.com/rectorphp/rector-doctrine
https://github.com/rectorphp/rector-phpunit
Extensions