Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like RemoveBraces often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use RemoveBraces, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 16 | class RemoveBraces extends AbstractPass |
||
| 17 | { |
||
| 18 | /** |
||
| 19 | * @var array Offsets of braces that need to be preserved (offsets used as keys) |
||
| 20 | */ |
||
| 21 | protected $preservedBraces; |
||
| 22 | |||
| 23 | /** |
||
| 24 | * {@inheritdoc} |
||
| 25 | */ |
||
| 26 | 39 | protected function optimizeStream() |
|
| 45 | |||
| 46 | /** |
||
| 47 | * Test whether the given structure's braces can be removed |
||
| 48 | * |
||
| 49 | * @param array $structure |
||
| 50 | * @return bool |
||
| 51 | */ |
||
| 52 | 35 | protected function canRemoveBracesFrom(array $structure) |
|
| 56 | |||
| 57 | /** |
||
| 58 | * Test whether the token at current offset is a control structure |
||
| 59 | * |
||
| 60 | * NOTE: we ignore T_DO since the braces are not optional |
||
| 61 | * |
||
| 62 | * @return bool |
||
| 63 | */ |
||
| 64 | 39 | protected function isControlStructure() |
|
| 68 | |||
| 69 | /** |
||
| 70 | * Test whether the token at current offset is an open curly brace |
||
| 71 | * |
||
| 72 | * @return bool |
||
| 73 | */ |
||
| 74 | 35 | protected function isCurlyOpen() |
|
| 78 | |||
| 79 | /** |
||
| 80 | * Test whether current token is followed by a function or class-related declaration |
||
| 81 | * |
||
| 82 | * @return bool |
||
| 83 | */ |
||
| 84 | 37 | protected function isFollowedByDeclaraction() |
|
| 96 | |||
| 97 | /** |
||
| 98 | * Optimize given T_ELSE structure |
||
| 99 | * |
||
| 100 | * @param array $structure |
||
| 101 | * @return void |
||
| 102 | */ |
||
| 103 | 21 | protected function optimizeElse(array $structure) |
|
| 118 | |||
| 119 | /** |
||
| 120 | * Optimize given structure and the other structures it contains |
||
| 121 | * |
||
| 122 | * @param array $structure |
||
| 123 | * @return void |
||
| 124 | */ |
||
| 125 | 35 | protected function optimizeStructure(array $structure) |
|
| 143 | |||
| 144 | /** |
||
| 145 | * Optimize a list of parsed structures |
||
| 146 | * |
||
| 147 | * @param array[] $structures |
||
| 148 | * @return void |
||
| 149 | */ |
||
| 150 | 39 | protected function optimizeStructures(array $structures) |
|
| 157 | |||
| 158 | /** |
||
| 159 | * Parse the control structure starting at current offset |
||
| 160 | * |
||
| 161 | * @return array|false |
||
| 162 | */ |
||
| 163 | 39 | protected function parseControlStructure() |
|
| 232 | |||
| 233 | /** |
||
| 234 | * Mark the offset of right braces that must be preserved |
||
| 235 | * |
||
| 236 | * Works by counting the number of consecutive braces between the starting point and the next |
||
| 237 | * non-brace token. If the next token is a T_ELSE or T_ELSEIF and it does not immediately follow |
||
| 238 | * current brace then its branch belongs to another conditional, which means the brace must be |
||
| 239 | * preserved |
||
| 240 | * |
||
| 241 | * @param integer $offset Offset of the first closing brace |
||
| 242 | * @return void |
||
| 243 | */ |
||
| 244 | 31 | protected function markPreservedBraces($offset) |
|
| 269 | |||
| 270 | /** |
||
| 271 | * Remove braces from given structure |
||
| 272 | * |
||
| 273 | * @param array $structure |
||
| 274 | * @return void |
||
| 275 | */ |
||
| 276 | 31 | protected function removeBraces(array $structure) |
|
| 302 | |||
| 303 | /** |
||
| 304 | * Remove the whitespace before given offset, if possible |
||
| 305 | * |
||
| 306 | * @return void |
||
| 307 | */ |
||
| 308 | 31 | protected function removeWhitespaceBefore($offset) |
|
| 321 | |||
| 322 | /** |
||
| 323 | * Skip the condition of a control structure |
||
| 324 | * |
||
| 325 | * @return void |
||
| 326 | */ |
||
| 327 | 39 | protected function skipParenthesizedExpression() |
|
| 358 | |||
| 359 | /** |
||
| 360 | * Remove one tab's worth of indentation off a range of PHP tokens |
||
| 361 | * |
||
| 362 | * @param integer $start Offset of the first token to unindent |
||
| 363 | * @param integer $end Offset of the last token to unindent |
||
| 364 | * @return void |
||
| 365 | */ |
||
| 366 | 7 | protected function unindentBlock($start, $end) |
|
| 382 | } |