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 ForkManager 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 ForkManager, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 19 | class ForkManager implements ExecutableInterface, MemoryLimitManagerDependentInterface, TimeLimitManagerDependentInterface |
||
| 20 | { |
||
| 21 | /** |
||
| 22 | * @var ForkManagerEvent |
||
| 23 | */ |
||
| 24 | private $event; |
||
| 25 | |||
| 26 | /** |
||
| 27 | * @var EventDispatcher |
||
| 28 | */ |
||
| 29 | private $eventDispatcher; |
||
| 30 | |||
| 31 | /** |
||
| 32 | * @var int |
||
| 33 | */ |
||
| 34 | private $maximumNumberOfThreads; |
||
| 35 | |||
| 36 | /** |
||
| 37 | * @var MemoryLimitManager |
||
| 38 | */ |
||
| 39 | private $memoryLimitManager; |
||
| 40 | |||
| 41 | /** |
||
| 42 | * @var int |
||
| 43 | */ |
||
| 44 | private $numberOfMicrosecondsToCheckThreadStatus; |
||
| 45 | |||
| 46 | /** |
||
| 47 | * @var int |
||
| 48 | */ |
||
| 49 | private $processId; |
||
| 50 | |||
| 51 | /** |
||
| 52 | * @var bool |
||
| 53 | */ |
||
| 54 | private $noShutdownSignalReceived; |
||
| 55 | |||
| 56 | /** |
||
| 57 | * @var TaskManager |
||
| 58 | */ |
||
| 59 | private $taskManager; |
||
| 60 | |||
| 61 | /** |
||
| 62 | * @var TimeLimitManager |
||
| 63 | */ |
||
| 64 | private $timeLimitManager; |
||
| 65 | |||
| 66 | /** |
||
| 67 | * @var array |
||
| 68 | */ |
||
| 69 | private $threads; |
||
| 70 | |||
| 71 | /** |
||
| 72 | * @param bool $validateEnvironment |
||
| 73 | * @throws RuntimeException |
||
| 74 | */ |
||
| 75 | public function __construct($validateEnvironment = true) |
||
| 104 | |||
| 105 | /** |
||
| 106 | * @param AbstractTask $task |
||
| 107 | * @return $this |
||
| 108 | */ |
||
| 109 | public function addTask(AbstractTask $task) |
||
| 116 | |||
| 117 | /** |
||
| 118 | * @return EventDispatcher |
||
| 119 | */ |
||
| 120 | public function getEventDispatcher() |
||
| 124 | |||
| 125 | /** |
||
| 126 | * @return MemoryLimitManager |
||
| 127 | */ |
||
| 128 | public function getMemoryLimitManager() |
||
| 132 | |||
| 133 | /** |
||
| 134 | * @return TaskManager |
||
| 135 | */ |
||
| 136 | public function getTaskManager() |
||
| 140 | |||
| 141 | /** |
||
| 142 | * @return TimeLimitManager |
||
| 143 | */ |
||
| 144 | public function getTimeLimitManager() |
||
| 148 | |||
| 149 | /** |
||
| 150 | * @param ForkManagerEvent $event |
||
| 151 | */ |
||
| 152 | public function injectEvent(ForkManagerEvent $event) |
||
| 156 | |||
| 157 | /** |
||
| 158 | * @param EventDispatcher $dispatcher |
||
| 159 | */ |
||
| 160 | public function injectEventDispatcher(EventDispatcher $dispatcher) |
||
| 164 | |||
| 165 | /** |
||
| 166 | * @param MemoryLimitManager $manager |
||
| 167 | */ |
||
| 168 | public function injectMemoryLimitManager(MemoryLimitManager $manager) |
||
| 172 | |||
| 173 | /** |
||
| 174 | * @param TimeLimitManager $manager |
||
| 175 | */ |
||
| 176 | public function injectTimeLimitManager(TimeLimitManager $manager) |
||
| 180 | |||
| 181 | /** |
||
| 182 | * @param TaskManager $manager |
||
| 183 | */ |
||
| 184 | public function injectTaskManager(TaskManager $manager) |
||
| 188 | |||
| 189 | /** |
||
| 190 | * @param int $maximumNumberOfThreads |
||
| 191 | */ |
||
| 192 | public function setMaximumNumberOfThreads($maximumNumberOfThreads) |
||
| 196 | |||
| 197 | /** |
||
| 198 | * @param int $numberOfMicrosecondsToCheckThreadStatus |
||
| 199 | */ |
||
| 200 | public function setNumberOfMicrosecondsToCheckThreadStatus($numberOfMicrosecondsToCheckThreadStatus) |
||
| 204 | |||
| 205 | /** |
||
| 206 | * @throws RuntimeException |
||
| 207 | */ |
||
| 208 | public function execute() |
||
| 285 | |||
| 286 | /** |
||
| 287 | * @return bool |
||
| 288 | */ |
||
| 289 | private function notAllThreadsAreFinished() |
||
| 293 | |||
| 294 | private function updateNumberOfRunningThreads() |
||
| 307 | |||
| 308 | /** |
||
| 309 | * @param AbstractTask $task |
||
| 310 | * @throws RuntimeException |
||
| 311 | */ |
||
| 312 | private function startThread(AbstractTask $task) |
||
| 339 | |||
| 340 | /** |
||
| 341 | * @param $processId |
||
| 342 | * @throws RuntimeException |
||
| 343 | */ |
||
| 344 | private function stopThread($processId) |
||
| 368 | |||
| 369 | /** |
||
| 370 | * @throws RuntimeException |
||
| 371 | * @todo think about the idea to put this in a "HandleMaximumMemoryLimitReachedStrategy" |
||
| 372 | */ |
||
| 373 | private function stopNewestThread() |
||
| 388 | |||
| 389 | /** |
||
| 390 | * @throws RuntimeException |
||
| 391 | */ |
||
| 392 | private function stopAllThreads() |
||
| 398 | |||
| 399 | /** |
||
| 400 | * @param int $processId |
||
| 401 | * @return int |
||
| 402 | * @throws RuntimeException |
||
| 403 | */ |
||
| 404 | private function hasThreadFinished($processId) |
||
| 424 | |||
| 425 | /** |
||
| 426 | * @return int |
||
| 427 | */ |
||
| 428 | private function countNumberOfThreads() |
||
| 432 | |||
| 433 | /** |
||
| 434 | * @return bool |
||
| 435 | */ |
||
| 436 | private function isMaximumNumberOfThreadsReached() |
||
| 440 | |||
| 441 | /** |
||
| 442 | * @return bool |
||
| 443 | */ |
||
| 444 | private function isMaximumMemoryLimitOfWholeThreadsReached() |
||
| 452 | |||
| 453 | /** |
||
| 454 | * @param int $steps |
||
| 455 | */ |
||
| 456 | private function sleep($steps = 1) |
||
| 464 | |||
| 465 | //begin of posix signal handling |
||
| 466 | /** |
||
| 467 | * @param int $signal |
||
| 468 | * @codeCoverageIgnore |
||
| 469 | */ |
||
| 470 | private function signalHandler($signal) |
||
| 486 | |||
| 487 | private function shutdown() |
||
| 496 | |||
| 497 | private function dispatchSignal() |
||
| 501 | |||
| 502 | /** |
||
| 503 | * @param $nameOfSignalHandlerMethod |
||
| 504 | * @throws InvalidArgumentException |
||
| 505 | * @codeCoverageIgnore |
||
| 506 | */ |
||
| 507 | private function setUpSignalHandling($nameOfSignalHandlerMethod) |
||
| 533 | //end of posix signal handling |
||
| 534 | |||
| 535 | /** |
||
| 536 | * @throws RuntimeException |
||
| 537 | */ |
||
| 538 | private function assertMandatoryPropertiesAreSet() |
||
| 556 | |||
| 557 | /** |
||
| 558 | * @param string $source |
||
| 559 | * @param ForkManager $forkManager |
||
| 560 | * @param TaskInterface $task |
||
| 561 | * @return ForkManagerEvent |
||
| 562 | */ |
||
| 563 | private function createNewEvent($source = null, ForkManager $forkManager = null, TaskInterface $task = null) |
||
| 581 | } |