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 Plan 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 Plan, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
35 | class Plan |
||
36 | { |
||
37 | /** |
||
38 | * List of tables to be created |
||
39 | * |
||
40 | * @var \Phinx\Db\Plan\NewTable[] |
||
41 | */ |
||
42 | protected $tableCreates = []; |
||
43 | |||
44 | /** |
||
45 | * List of table updates |
||
46 | * |
||
47 | * @var \Phinx\Db\Plan\AlterTable[] |
||
48 | */ |
||
49 | protected $tableUpdates = []; |
||
50 | |||
51 | /** |
||
52 | * List of table removals or renames |
||
53 | * |
||
54 | * @var \Phinx\Db\Plan\AlterTable[] |
||
55 | */ |
||
56 | protected $tableMoves = []; |
||
57 | |||
58 | /** |
||
59 | * List of index additions or removals |
||
60 | * |
||
61 | * @var \Phinx\Db\Plan\AlterTable[] |
||
62 | */ |
||
63 | protected $indexes = []; |
||
64 | |||
65 | /** |
||
66 | * List of constraint additions or removals |
||
67 | * |
||
68 | * @var \Phinx\Db\Plan\AlterTable[] |
||
69 | */ |
||
70 | protected $constraints = []; |
||
71 | |||
72 | /** |
||
73 | * List of dropped columns |
||
74 | * |
||
75 | * @var \Phinx\Db\Plan\AlterTable[] |
||
76 | */ |
||
77 | protected $columnRemoves = []; |
||
78 | |||
79 | /** |
||
80 | * Constructor |
||
81 | * |
||
82 | * @param \Phinx\Db\Plan\Intent $intent All the actions that should be executed |
||
83 | */ |
||
84 | public function __construct(Intent $intent) |
||
88 | |||
89 | /** |
||
90 | * Parses the given Intent and creates the separate steps to execute |
||
91 | * |
||
92 | * @param \Phinx\Db\Action\Action[] $actions The actions to use for the plan |
||
93 | * |
||
94 | * @return void |
||
95 | */ |
||
96 | protected function createPlan($actions) |
||
105 | |||
106 | /** |
||
107 | * Returns a nested list of all the steps to execute |
||
108 | * |
||
109 | * @return \Phinx\Db\Plan\AlterTable[][] |
||
110 | */ |
||
111 | View Code Duplication | protected function updatesSequence() |
|
121 | |||
122 | /** |
||
123 | * Returns a nested list of all the steps to execute in inverse order |
||
124 | * |
||
125 | * @return \Phinx\Db\Plan\AlterTable[][] |
||
126 | */ |
||
127 | View Code Duplication | protected function inverseUpdatesSequence() |
|
137 | |||
138 | /** |
||
139 | * Executes this plan using the given AdapterInterface |
||
140 | * |
||
141 | * @param \Phinx\Db\Adapter\AdapterInterface $executor The executor object for the plan |
||
142 | * |
||
143 | * @return void |
||
144 | */ |
||
145 | View Code Duplication | public function execute(AdapterInterface $executor) |
|
157 | |||
158 | /** |
||
159 | * Executes the inverse plan (rollback the actions) with the given AdapterInterface:w |
||
160 | * |
||
161 | * @param \Phinx\Db\Adapter\AdapterInterface $executor The executor object for the plan |
||
162 | * |
||
163 | * @return void |
||
164 | */ |
||
165 | View Code Duplication | public function executeInverse(AdapterInterface $executor) |
|
177 | |||
178 | /** |
||
179 | * Deletes certain actions from the plan if they are found to be conflicting or redundant. |
||
180 | * |
||
181 | * @return void |
||
182 | */ |
||
183 | protected function resolveConflicts() |
||
248 | |||
249 | /** |
||
250 | * Deletes all actions related to the given table and keeps the |
||
251 | * rest |
||
252 | * |
||
253 | * @param \Phinx\Db\Table\Table $table The table to find in the list of actions |
||
254 | * @param \Phinx\Db\Plan\AlterTable[] $actions The actions to transform |
||
255 | * |
||
256 | * @return \Phinx\Db\Plan\AlterTable[] The list of actions without actions for the given table |
||
257 | */ |
||
258 | protected function forgetTable(Table $table, $actions) |
||
270 | |||
271 | /** |
||
272 | * Finds all DropForeignKey actions in an AlterTable and moves |
||
273 | * all conflicting DropIndex action in `$this->indexes` into the |
||
274 | * given AlterTable. |
||
275 | * |
||
276 | * @param \Phinx\Db\Plan\AlterTable $alter The collection of actions to inspect |
||
277 | * |
||
278 | * @return \Phinx\Db\Plan\AlterTable The updated AlterTable object. This function |
||
279 | * has the side effect of changing the `$this->indexes` property. |
||
280 | */ |
||
281 | protected function remapContraintAndIndexConflicts(AlterTable $alter) |
||
301 | |||
302 | /** |
||
303 | * Deletes any DropIndex actions for the given table and exact columns |
||
304 | * |
||
305 | * @param \Phinx\Db\Table\Table $table The table to find in the list of actions |
||
306 | * @param string[] $columns The column names to match |
||
307 | * @param \Phinx\Db\Plan\AlterTable[] $actions The actions to transform |
||
308 | * |
||
309 | * @return array A tuple containing the list of actions without actions for dropping the index |
||
310 | * and a list of drop index actions that were removed. |
||
311 | */ |
||
312 | View Code Duplication | protected function forgetDropIndex(Table $table, array $columns, array $actions) |
|
334 | |||
335 | /** |
||
336 | * Deletes any RemoveColumn actions for the given table and exact columns |
||
337 | * |
||
338 | * @param \Phinx\Db\Table\Table $table The table to find in the list of actions |
||
339 | * @param string[] $columns The column names to match |
||
340 | * @param \Phinx\Db\Plan\AlterTable[] $actions The actions to transform |
||
341 | * |
||
342 | * @return array A tuple containing the list of actions without actions for removing the column |
||
343 | * and a list of remove column actions that were removed. |
||
344 | */ |
||
345 | View Code Duplication | protected function forgetRemoveColumn(Table $table, array $columns, array $actions) |
|
367 | |||
368 | /** |
||
369 | * Collects all table creation actions from the given intent |
||
370 | * |
||
371 | * @param \Phinx\Db\Action\Action[] $actions The actions to parse |
||
372 | * |
||
373 | * @return void |
||
374 | */ |
||
375 | protected function gatherCreates($actions) |
||
400 | |||
401 | /** |
||
402 | * Collects all alter table actions from the given intent |
||
403 | * |
||
404 | * @param \Phinx\Db\Action\Action[] $actions The actions to parse |
||
405 | * |
||
406 | * @return void |
||
407 | */ |
||
408 | protected function gatherUpdates($actions) |
||
437 | |||
438 | /** |
||
439 | * Collects all alter table drop and renames from the given intent |
||
440 | * |
||
441 | * @param \Phinx\Db\Action\Action[] $actions The actions to parse |
||
442 | * @return void |
||
443 | */ |
||
444 | protected function gatherTableMoves($actions) |
||
465 | |||
466 | /** |
||
467 | * Collects all index creation and drops from the given intent |
||
468 | * |
||
469 | * @param \Phinx\Db\Action\Action[] $actions The actions to parse |
||
470 | * |
||
471 | * @return void |
||
472 | */ |
||
473 | protected function gatherIndexes($actions) |
||
492 | |||
493 | /** |
||
494 | * Collects all foreign key creation and drops from the given intent |
||
495 | * |
||
496 | * @param \Phinx\Db\Action\Action[] $actions The actions to parse |
||
497 | * |
||
498 | * @return void |
||
499 | */ |
||
500 | protected function gatherConstraints($actions) |
||
516 | } |
||
517 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.