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 ChannelComposite 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 ChannelComposite, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
17 | class ChannelComposite extends BaseEventEmitter implements ChannelCompositeInterface |
||
18 | { |
||
19 | use LoopAwareTrait; |
||
20 | |||
21 | /** |
||
22 | * @var string |
||
23 | */ |
||
24 | protected $name; |
||
25 | |||
26 | /** |
||
27 | * @var ChannelInterface[]|ChannelCompositeInterface[] |
||
28 | */ |
||
29 | protected $buses; |
||
30 | |||
31 | /** |
||
32 | * @var RouterCompositeInterface |
||
33 | */ |
||
34 | protected $router; |
||
35 | |||
36 | /** |
||
37 | * @var EventListener[][] |
||
38 | */ |
||
39 | protected $events; |
||
40 | |||
41 | /** |
||
42 | * @var string |
||
43 | */ |
||
44 | protected $seed; |
||
45 | |||
46 | /** |
||
47 | * @var int |
||
48 | */ |
||
49 | protected $counter; |
||
50 | |||
51 | /** |
||
52 | * @param string $name |
||
53 | * @param ChannelInterface[]|ChannelCompositeInterface[] $buses |
||
54 | * @param RouterCompositeInterface $router |
||
55 | * @param LoopInterface $loop |
||
56 | */ |
||
57 | 79 | public function __construct($name, $buses = [], RouterCompositeInterface $router, LoopInterface $loop) |
|
72 | |||
73 | /** |
||
74 | * |
||
75 | */ |
||
76 | 2 | public function __destruct() |
|
91 | |||
92 | /** |
||
93 | * @override |
||
94 | * @inheritDoc |
||
95 | */ |
||
96 | 3 | public function existsBus($name) |
|
100 | |||
101 | /** |
||
102 | * @override |
||
103 | * @inheritDoc |
||
104 | */ |
||
105 | 2 | View Code Duplication | public function getBus($name) |
114 | |||
115 | /** |
||
116 | * @override |
||
117 | * @inheritDoc |
||
118 | */ |
||
119 | 18 | public function setBus($name, $channel) |
|
132 | |||
133 | /** |
||
134 | * @override |
||
135 | * @inheritDoc |
||
136 | */ |
||
137 | 2 | public function removeBus($name) |
|
152 | |||
153 | /** |
||
154 | * @override |
||
155 | * @inheritDoc |
||
156 | */ |
||
157 | 2 | public function getBuses() |
|
161 | |||
162 | /** |
||
163 | * @override |
||
164 | * @inheritDoc |
||
165 | */ |
||
166 | 3 | public function getName() |
|
170 | |||
171 | /** |
||
172 | * @override |
||
173 | * @inheritDoc |
||
174 | */ |
||
175 | 1 | public function getModel() |
|
179 | |||
180 | /** |
||
181 | * @override |
||
182 | * @inheritDoc |
||
183 | */ |
||
184 | 1 | public function getRouter() |
|
188 | |||
189 | /** |
||
190 | * @override |
||
191 | * @inheritDoc |
||
192 | */ |
||
193 | 1 | public function getInput() |
|
197 | |||
198 | /** |
||
199 | * @override |
||
200 | * @inheritDoc |
||
201 | */ |
||
202 | 1 | public function getOutput() |
|
206 | |||
207 | /** |
||
208 | * @override |
||
209 | * @inheritDoc |
||
210 | */ |
||
211 | 4 | View Code Duplication | public function createProtocol($message = null) |
224 | |||
225 | /** |
||
226 | * @override |
||
227 | * @inheritDoc |
||
228 | */ |
||
229 | 1 | public function onStart(callable $handler) |
|
233 | |||
234 | /** |
||
235 | * @override |
||
236 | * @inheritDoc |
||
237 | */ |
||
238 | 1 | public function onStop(callable $handler) |
|
242 | |||
243 | /** |
||
244 | * @override |
||
245 | * @inheritDoc |
||
246 | */ |
||
247 | 1 | public function onConnect(callable $handler) |
|
251 | |||
252 | /** |
||
253 | * @override |
||
254 | * @inheritDoc |
||
255 | */ |
||
256 | 1 | public function onDisconnect(callable $handler) |
|
260 | |||
261 | /** |
||
262 | * @override |
||
263 | * @inheritDoc |
||
264 | */ |
||
265 | 1 | public function onInput(callable $handler) |
|
269 | |||
270 | /** |
||
271 | * @override |
||
272 | * @inheritDoc |
||
273 | */ |
||
274 | 1 | public function onOutput(callable $handler) |
|
278 | |||
279 | /** |
||
280 | * @override |
||
281 | * @inheritDoc |
||
282 | */ |
||
283 | 1 | public function start() |
|
292 | |||
293 | /** |
||
294 | * @override |
||
295 | * @inheritDoc |
||
296 | */ |
||
297 | 1 | public function stop() |
|
306 | |||
307 | /** |
||
308 | * @override |
||
309 | * @inheritDoc |
||
310 | */ |
||
311 | 2 | View Code Duplication | public function send($name, $message, $flags = Channel::MODE_DEFAULT, callable $success = null, callable $failure = null, callable $cancel = null, $timeout = 0.0) |
320 | |||
321 | /** |
||
322 | * @override |
||
323 | * @inheritDoc |
||
324 | */ |
||
325 | 2 | View Code Duplication | public function push($name, $message, $flags = Channel::MODE_DEFAULT, callable $success = null, callable $failure = null, callable $cancel = null, $timeout = 0.0) |
334 | |||
335 | /** |
||
336 | * @override |
||
337 | * @inheritDoc |
||
338 | */ |
||
339 | 5 | View Code Duplication | public function sendAsync($name, $message, $flags = Channel::MODE_DEFAULT) |
352 | |||
353 | /** |
||
354 | * @override |
||
355 | * @inheritDoc |
||
356 | */ |
||
357 | 5 | View Code Duplication | public function pushAsync($name, $message, $flags = Channel::MODE_DEFAULT) |
370 | |||
371 | /** |
||
372 | * @override |
||
373 | * @inheritDoc |
||
374 | */ |
||
375 | 5 | View Code Duplication | public function sendRequest($name, $message, $flags = Channel::MODE_DEFAULT, callable $success = null, callable $failure = null, callable $cancel = null, $timeout = 0.0) |
388 | |||
389 | /** |
||
390 | * @override |
||
391 | * @inheritDoc |
||
392 | */ |
||
393 | 5 | View Code Duplication | public function pushRequest($name, $message, $flags = Channel::MODE_DEFAULT, callable $success = null, callable $failure = null, callable $cancel = null, $timeout = 0.0) |
406 | |||
407 | /** |
||
408 | * @override |
||
409 | * @inheritDoc |
||
410 | */ |
||
411 | 1 | public function receive($sender, ProtocolInterface $protocol) |
|
418 | |||
419 | /** |
||
420 | * @override |
||
421 | * @inheritDoc |
||
422 | */ |
||
423 | 1 | public function pull($sender, ProtocolInterface $protocol) |
|
427 | |||
428 | /** |
||
429 | * @override |
||
430 | * @inheritDoc |
||
431 | */ |
||
432 | 2 | public function isStarted() |
|
443 | |||
444 | /** |
||
445 | * @override |
||
446 | * @inheritDoc |
||
447 | */ |
||
448 | 2 | public function isStopped() |
|
459 | |||
460 | /** |
||
461 | * @override |
||
462 | * @inheritDoc |
||
463 | */ |
||
464 | 3 | public function isConnected($name) |
|
481 | |||
482 | /** |
||
483 | * @override |
||
484 | * @inheritDoc |
||
485 | */ |
||
486 | 2 | View Code Duplication | public function getConnected() |
497 | |||
498 | /** |
||
499 | * @override |
||
500 | * @inheritDoc |
||
501 | */ |
||
502 | 2 | View Code Duplication | public function filterConnected($pattern) |
513 | |||
514 | /** |
||
515 | * @param string $name |
||
516 | * @param ProtocolInterface $message |
||
517 | * @param int $flags |
||
518 | * @return bool |
||
519 | */ |
||
520 | 1 | View Code Duplication | protected function handleSendAsync($name, $message, $flags = Channel::MODE_DEFAULT) |
533 | |||
534 | /** |
||
535 | * @param string $name |
||
536 | * @param ProtocolInterface $message |
||
537 | * @param int $flags |
||
538 | * @return bool |
||
539 | */ |
||
540 | 2 | protected function handlePushAsync($name, $message, $flags = Channel::MODE_DEFAULT) |
|
577 | |||
578 | /** |
||
579 | * @param string $name |
||
580 | * @param string|ProtocolInterface $message |
||
581 | * @param int $flags |
||
582 | * @param callable|null $success |
||
583 | * @param callable|null $failure |
||
584 | * @param callable|null $cancel |
||
585 | * @param float $timeout |
||
586 | * @return bool[] |
||
587 | */ |
||
588 | 1 | protected function handleSendRequest($name, $message, $flags = Channel::MODE_DEFAULT, callable $success = null, callable $failure = null, callable $cancel = null, $timeout = 0.0) |
|
592 | |||
593 | /** |
||
594 | * @param string $name |
||
595 | * @param string|ProtocolInterface $message |
||
596 | * @param int $flags |
||
597 | * @param callable|null $success |
||
598 | * @param callable|null $failure |
||
599 | * @param callable|null $cancel |
||
600 | * @param float $timeout |
||
601 | * @return bool |
||
602 | */ |
||
603 | 2 | protected function handlePushRequest($name, $message, $flags = Channel::MODE_DEFAULT, callable $success = null, callable $failure = null, callable $cancel = null, $timeout = 0.0) |
|
640 | |||
641 | /** |
||
642 | * @internal |
||
643 | * @param string $sender |
||
644 | * @param ProtocolInterface $protocol |
||
645 | */ |
||
646 | public function handleReceive($sender, ProtocolInterface $protocol) |
||
650 | |||
651 | /** |
||
652 | * @return string |
||
653 | */ |
||
654 | 7 | protected function genID() |
|
658 | |||
659 | /** |
||
660 | * @return float |
||
661 | */ |
||
662 | 5 | protected function getTime() |
|
666 | |||
667 | /** |
||
668 | * @return int |
||
669 | */ |
||
670 | 9 | View Code Duplication | protected function getNextSuffix() |
680 | |||
681 | /** |
||
682 | * @param ProtocolInterface|null|string|string[] $message |
||
683 | * @return ProtocolInterface |
||
684 | */ |
||
685 | 5 | protected function createMessageProtocol($message) |
|
703 | |||
704 | /** |
||
705 | * @param mixed|mixed[]|null $in |
||
706 | * @param mixed|mixed[]|null $out |
||
707 | * @param callable $combinator |
||
708 | * @return mixed|mixed[] |
||
709 | */ |
||
710 | 6 | private function combine($in, $out, callable $combinator) |
|
736 | } |
||
737 |
This check looks for assignments to scalar types that may be of the wrong type.
To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.