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 BlockInterpreter 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 BlockInterpreter, and based on these observations, apply Extract Interface, too.
1 | <?php namespace Limoncello\Validation\Execution; |
||
31 | final class BlockInterpreter |
||
32 | { |
||
33 | /** |
||
34 | * @param mixed $input |
||
35 | * @param array $serializedBlocks |
||
36 | * @param ContextStorageInterface $context |
||
37 | * @param CaptureAggregatorInterface $captures |
||
38 | * @param ErrorAggregatorInterface $errors |
||
39 | * |
||
40 | * @return void |
||
41 | * |
||
42 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
43 | */ |
||
44 | public static function execute( |
||
58 | |||
59 | /** |
||
60 | * @param int[] $indexes |
||
61 | * @param array $blocks |
||
62 | * @param ContextStorageInterface $context |
||
63 | * @param ErrorAggregatorInterface $errors |
||
64 | * |
||
65 | * @return void |
||
66 | * |
||
67 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
68 | */ |
||
69 | View Code Duplication | public static function executeStarts( |
|
84 | |||
85 | /** |
||
86 | * @param int[] $indexes |
||
87 | * @param array $blocks |
||
88 | * @param ContextStorageInterface $context |
||
89 | * @param ErrorAggregatorInterface $errors |
||
90 | * |
||
91 | * @return void |
||
92 | * |
||
93 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
94 | */ |
||
95 | View Code Duplication | public static function executeEnds( |
|
110 | |||
111 | /** |
||
112 | * @param mixed $input |
||
113 | * @param int $blockIndex |
||
114 | * @param array $blocks |
||
115 | * @param ContextStorageInterface $context |
||
116 | * @param CaptureAggregatorInterface $captures |
||
117 | * @param ErrorAggregatorInterface $errors |
||
118 | * |
||
119 | * @return void |
||
120 | * |
||
121 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
122 | */ |
||
123 | public static function executeBlock( |
||
143 | |||
144 | /** |
||
145 | * @param mixed $input |
||
146 | * @param int $blockIndex |
||
147 | * @param array $blocks |
||
148 | * @param ContextStorageInterface $context |
||
149 | * @param CaptureAggregatorInterface $captures |
||
150 | * |
||
151 | * @return array |
||
152 | * |
||
153 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
154 | */ |
||
155 | private static function executeBlockImpl( |
||
185 | |||
186 | /** |
||
187 | * @param mixed $input |
||
188 | * @param int $blockIndex |
||
189 | * @param array $blocks |
||
190 | * @param ContextStorageInterface $context |
||
191 | * @param CaptureAggregatorInterface $captures |
||
192 | * |
||
193 | * @return array |
||
194 | * |
||
195 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
196 | */ |
||
197 | private static function executeProcedureBlock( |
||
215 | |||
216 | /** |
||
217 | * @param mixed $input |
||
218 | * @param int $blockIndex |
||
219 | * @param array $blocks |
||
220 | * @param ContextStorageInterface $context |
||
221 | * @param CaptureAggregatorInterface $captures |
||
222 | * |
||
223 | * @return array |
||
224 | * |
||
225 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
226 | */ |
||
227 | private static function executeIfBlock( |
||
251 | |||
252 | /** |
||
253 | * @param mixed $input |
||
254 | * @param int $blockIndex |
||
255 | * @param array $blocks |
||
256 | * @param ContextStorageInterface $context |
||
257 | * @param CaptureAggregatorInterface $captures |
||
258 | * |
||
259 | * @return array |
||
260 | * |
||
261 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
262 | */ |
||
263 | View Code Duplication | private static function executeAndBlock( |
|
285 | |||
286 | /** |
||
287 | * @param mixed $input |
||
288 | * @param int $blockIndex |
||
289 | * @param array $blocks |
||
290 | * @param ContextStorageInterface $context |
||
291 | * @param CaptureAggregatorInterface $captures |
||
292 | * |
||
293 | * @return array |
||
294 | * |
||
295 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
296 | * @SuppressWarnings(PHPMD.ElseExpression) |
||
297 | */ |
||
298 | View Code Duplication | private static function executeOrBlock( |
|
321 | |||
322 | /** |
||
323 | * @param array $serializedBlocks |
||
324 | * |
||
325 | * @return array |
||
326 | * |
||
327 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
328 | */ |
||
329 | private static function getBlocks(array $serializedBlocks): array |
||
336 | |||
337 | /** |
||
338 | * @param array $serializedBlocks |
||
339 | * |
||
340 | * @return array |
||
341 | * |
||
342 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
343 | */ |
||
344 | View Code Duplication | private static function getBlocksWithStart(array $serializedBlocks): array |
|
356 | |||
357 | /** |
||
358 | * @param array $serializedBlocks |
||
359 | * |
||
360 | * @return array |
||
361 | * |
||
362 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
363 | */ |
||
364 | View Code Duplication | private static function getBlocksWithEnd(array $serializedBlocks): array |
|
376 | |||
377 | /** |
||
378 | * @param array $block |
||
379 | * |
||
380 | * @return int |
||
381 | * |
||
382 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
383 | */ |
||
384 | private static function getBlockType(array $block): int |
||
392 | |||
393 | /** |
||
394 | * @param array $result |
||
395 | * @param array $block |
||
396 | * @param CaptureAggregatorInterface $captures |
||
397 | * |
||
398 | * @return void |
||
399 | * |
||
400 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
401 | */ |
||
402 | private static function captureSuccessfulBlockResultIfEnabled( |
||
416 | |||
417 | /** |
||
418 | * @param array $procedureBlock |
||
419 | * @param ContextInterface $context |
||
420 | * |
||
421 | * @return array |
||
422 | * |
||
423 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
424 | */ |
||
425 | View Code Duplication | private static function executeProcedureStart(array $procedureBlock, ContextInterface $context): array |
|
435 | |||
436 | /** |
||
437 | * @param array $procedureBlock |
||
438 | * @param ContextInterface $context |
||
439 | * |
||
440 | * @return array |
||
441 | * |
||
442 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
443 | */ |
||
444 | View Code Duplication | private static function executeProcedureEnd(array $procedureBlock, ContextInterface $context): array |
|
454 | |||
455 | /** |
||
456 | * @param array $errorsInfo |
||
457 | * @param ContextStorageInterface $context |
||
458 | * @param ErrorAggregatorInterface $errors |
||
459 | * |
||
460 | * @return void |
||
461 | */ |
||
462 | private static function addBlockErrors( |
||
478 | |||
479 | /** |
||
480 | * @param array $blocks |
||
481 | * |
||
482 | * @return bool |
||
483 | * |
||
484 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
485 | */ |
||
486 | private static function debugCheckLooksLikeBlocksArray(array $blocks): bool |
||
499 | |||
500 | /** |
||
501 | * @param array $blockIndexes |
||
502 | * @param array $blockList |
||
503 | * @param int $blockType |
||
504 | * |
||
505 | * @return bool |
||
506 | * |
||
507 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
508 | */ |
||
509 | private static function debugCheckBlocksExist(array $blockIndexes, array $blockList, int $blockType): bool |
||
521 | |||
522 | /** |
||
523 | * @param array $block |
||
524 | * |
||
525 | * @return bool |
||
526 | */ |
||
527 | private static function debugHasKnownBlockType(array $block): bool |
||
543 | } |
||
544 |
Late static binding only has effect in subclasses. A
final
class cannot be extended anymore so late static binding cannot occurr. Consider replacingstatic::
withself::
.To learn more about late static binding, please refer to the PHP core documentation.