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 TreeNode 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 TreeNode, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
31 | class TreeNode implements \Countable |
||
32 | { |
||
33 | /** |
||
34 | * @var integer Information associated to that node. |
||
35 | * Bits of order 0 and 1 are reserved for the existence of left and right tree. |
||
36 | * Other bits are for the balance |
||
37 | * |
||
38 | * @since 1.0.0 |
||
39 | */ |
||
40 | private $information = 0; |
||
41 | |||
42 | /** |
||
43 | * @var TreeNode Left|Predecessor node |
||
44 | * |
||
45 | * @since 1.0.0 |
||
46 | */ |
||
47 | private $left; |
||
48 | |||
49 | /** |
||
50 | * @var TreeNode Right|Successor node |
||
51 | * |
||
52 | * @since 1.0.0 |
||
53 | */ |
||
54 | private $right; |
||
55 | |||
56 | /** |
||
57 | * @var mixed Node key |
||
58 | * |
||
59 | * @since 1.0.0 |
||
60 | */ |
||
61 | private $key; |
||
62 | |||
63 | /** |
||
64 | * @var mixed Node value |
||
65 | * |
||
66 | * @since 1.0.0 |
||
67 | */ |
||
68 | public $value; |
||
69 | |||
70 | /** |
||
71 | * Create a node |
||
72 | * |
||
73 | * @param mixed $key The node key |
||
74 | * @param mixed $value The node value |
||
75 | * |
||
76 | * @return A new node |
||
77 | * |
||
78 | * @since 1.0.0 |
||
79 | */ |
||
80 | public static function create($key, $value) |
||
84 | |||
85 | /** |
||
86 | * Constructor |
||
87 | * |
||
88 | * @param mixed $key The node key |
||
89 | * @param mixed $value The node value |
||
90 | * @param TreeNode $predecessor The left node |
||
91 | * @param TreeNode $successor The right node |
||
92 | * |
||
93 | * @since 1.0.0 |
||
94 | */ |
||
95 | protected function __construct($key, $value, $predecessor = null, $successor = null) |
||
102 | |||
103 | /** |
||
104 | * Magic get method |
||
105 | * |
||
106 | * @param string $property The node property |
||
107 | * |
||
108 | * @return mixed The value associated to the property |
||
109 | * |
||
110 | * @throws \RuntimeException If the property is undefined |
||
111 | * |
||
112 | * @since 1.0.0 |
||
113 | */ |
||
114 | public function __get($property) |
||
134 | |||
135 | /** |
||
136 | * Get the first node |
||
137 | * |
||
138 | * @return the first node |
||
139 | * |
||
140 | * @since 1.0.0 |
||
141 | */ |
||
142 | public function first() |
||
153 | |||
154 | /** |
||
155 | * Get the last node |
||
156 | * |
||
157 | * @return the last node |
||
158 | * |
||
159 | * @since 1.0.0 |
||
160 | */ |
||
161 | public function last() |
||
172 | |||
173 | /** |
||
174 | * Get the predecessor |
||
175 | * |
||
176 | * @return the predecessor node |
||
177 | * |
||
178 | * @since 1.0.0 |
||
179 | */ |
||
180 | View Code Duplication | public function predecessor() |
|
198 | |||
199 | /** |
||
200 | * Get the successor |
||
201 | * |
||
202 | * @return the successor node |
||
203 | * |
||
204 | * @since 1.0.0 |
||
205 | */ |
||
206 | View Code Duplication | public function successor() |
|
224 | |||
225 | /** |
||
226 | * Count the number of key/value pair |
||
227 | * |
||
228 | * @return integer |
||
229 | * |
||
230 | * @since 1.0.0 |
||
231 | */ |
||
232 | public function count() |
||
248 | |||
249 | /** |
||
250 | * Get the node for a key |
||
251 | * |
||
252 | * @param mixed $key The key |
||
253 | * @param Callable $comparator The comparator function |
||
254 | * @param integer $type The operation type |
||
255 | * -2 for the greatest key lesser than the given key |
||
256 | * -1 for the greatest key lesser than or equal to the given key |
||
257 | * 0 for the given key |
||
258 | * +1 for the lowest key greater than or equal to the given key |
||
259 | * +2 for the lowest key greater than the given key |
||
260 | * |
||
261 | * @return mixed The node or null if not found |
||
262 | * |
||
263 | * @since 1.0.0 |
||
264 | */ |
||
265 | public function find($key, $comparator, $type = 0) |
||
333 | |||
334 | /** |
||
335 | * Rotate the node to the left |
||
336 | * |
||
337 | * @return TreeNode The rotated node |
||
338 | * |
||
339 | * @since 1.0.0 |
||
340 | */ |
||
341 | View Code Duplication | private function _rotateLeft() |
|
372 | |||
373 | /** |
||
374 | * Rotate the node to the right |
||
375 | * |
||
376 | * @return TreeNode The rotated node |
||
377 | * |
||
378 | * @since 1.0.0 |
||
379 | */ |
||
380 | View Code Duplication | private function _rotateRight() |
|
411 | |||
412 | /** |
||
413 | * Increment the balance of the node |
||
414 | * |
||
415 | * @return TreeNode $this or a rotated version of $this |
||
416 | * |
||
417 | * @since 1.0.0 |
||
418 | */ |
||
419 | View Code Duplication | private function _incBalance() |
|
435 | |||
436 | /** |
||
437 | * Decrement the balance of the node |
||
438 | * |
||
439 | * @return TreeNode $this or a rotated version of $this |
||
440 | * |
||
441 | * @since 1.0.0 |
||
442 | */ |
||
443 | View Code Duplication | private function _decBalance() |
|
459 | |||
460 | /** |
||
461 | * Insert a key/value pair |
||
462 | * |
||
463 | * @param mixed $key The key |
||
464 | * @param mixed $value The value |
||
465 | * @param Callable $comparator The comparator function |
||
466 | * |
||
467 | * @return TreeNode The new root |
||
468 | * |
||
469 | * @since 1.0.0 |
||
470 | */ |
||
471 | public function insert($key, $value, $comparator) |
||
521 | |||
522 | /** |
||
523 | * Pull up the left most node of a node |
||
524 | * |
||
525 | * @return TreeNode The new root |
||
526 | * |
||
527 | * @since 1.0.0 |
||
528 | */ |
||
529 | private function _pullUpLeftMost() |
||
573 | |||
574 | /** |
||
575 | * Remove a key |
||
576 | * |
||
577 | * @param mixed $key The key |
||
578 | * @param Callable $comparator The comparator function |
||
579 | * |
||
580 | * @return TreeNode The new root |
||
581 | * |
||
582 | * @since 1.0.0 |
||
583 | */ |
||
584 | public function remove($key, $comparator) |
||
661 | } |
||
662 |
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.