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 BinaryTreeAbstract 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 BinaryTreeAbstract, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
8 | abstract class BinaryTreeAbstract implements TreeInterface { |
||
9 | protected $root; |
||
10 | protected $size; |
||
11 | |||
12 | /** |
||
13 | * Checks if the tree is empty. |
||
14 | * |
||
15 | * @return boolean true if is empty, else false. |
||
16 | */ |
||
17 | public function empty() { |
||
20 | |||
21 | /** |
||
22 | * Returns the tree size. |
||
23 | * |
||
24 | * @return int the length |
||
25 | */ |
||
26 | public function size() { |
||
29 | |||
30 | public function put($key, $data){} |
||
32 | |||
33 | /** |
||
34 | * Retrieve the data stored in the tree. |
||
35 | * |
||
36 | * @param int|string $key the key to identify the data. |
||
37 | * @return mixed |
||
38 | */ |
||
39 | public function get($key){ |
||
57 | |||
58 | /** |
||
59 | * Returns the root node. |
||
60 | * |
||
61 | * @return DataStructures\Trees\Nodes\BSTNode|null the root node. |
||
62 | */ |
||
63 | public function getRoot(){ |
||
66 | |||
67 | /** |
||
68 | * Looks for the node with the given key. |
||
69 | * |
||
70 | * @param int|string $key the key used to look for. |
||
71 | * @return bool true if was found. |
||
72 | */ |
||
73 | public function exists($key){ |
||
96 | |||
97 | /** |
||
98 | * Method that retrieves true if found a node with the specified key. |
||
99 | * It's the recursive version of exists method and it's used internally |
||
100 | * for traverse through a root node. |
||
101 | * |
||
102 | * @param DataStructures\Trees\Nodes\BSTNode|null $node the root node. |
||
103 | * @param int|string $key the key used to look for. |
||
104 | * @return bool true if exists a node with that key. |
||
105 | */ |
||
106 | private function _exists($node, $key) : bool { |
||
119 | |||
120 | public function floor($key){} |
||
122 | |||
123 | /** |
||
124 | * Gets the node with the minimum key. The most left and more bottom. |
||
125 | * |
||
126 | * @return DataStructures\Trees\Nodes\BSTNode|null the minum node or |
||
127 | * null if the tree is empty. |
||
128 | */ |
||
129 | public function min() { |
||
145 | |||
146 | /** |
||
147 | * Gets the node with the maximum key. The most right and more bottom. |
||
148 | * |
||
149 | * @return DataStructures\Trees\Nodes\BSTNode|null the maximum node or |
||
150 | * null if the tree is empty. |
||
151 | */ |
||
152 | public function max() { |
||
168 | |||
169 | /** |
||
170 | * Returns the minimum node from a given node in position X. |
||
171 | * |
||
172 | * @param DataStructures\Trees\Nodes\BSTNode $node the start point. |
||
173 | * @return DataStructures\Trees\Nodes\BSTNode|null the minimum node. |
||
174 | */ |
||
175 | View Code Duplication | private function getMinNode(BinaryNodeInterface $node = null) { |
|
186 | |||
187 | /** |
||
188 | * Returns the maximum node from a given node in position X. |
||
189 | * |
||
190 | * @param DataStructures\Trees\Nodes\BSTNode $node the start point. |
||
191 | * @return DataStructures\Trees\Nodes\BSTNode|null the maximum node. |
||
192 | */ |
||
193 | View Code Duplication | private function getMaxNode(BinaryNodeInterface $node = null) { |
|
204 | |||
205 | /** |
||
206 | * Deletes the node with the minimum key and returns it. The most left and more bottom. |
||
207 | * |
||
208 | * @param DataStructures\Trees\Nodes\BSTNode|null if null takes the root. |
||
209 | * @return DataStructures\Trees\Nodes\BSTNode|null the minimum node or |
||
210 | * null if the tree is empty. |
||
211 | */ |
||
212 | View Code Duplication | public function deleteMin(BinaryNodeInterface $node = null) { |
|
220 | |||
221 | /** |
||
222 | * Deletes the node with the maximum key and returns it. The most right and more bottom. |
||
223 | * |
||
224 | * @param DataStructures\Trees\Nodes\BSTNode|null if null takes the root. |
||
225 | * @return DataStructures\Trees\Nodes\BSTNode|null the maximum node or |
||
226 | * null if the tree is empty. |
||
227 | */ |
||
228 | View Code Duplication | public function deleteMax(BinaryNodeInterface $node = null) { |
|
236 | |||
237 | /** |
||
238 | * Deletes the selected node if is not null and returns the node |
||
239 | * that replaces the deleted node. Also decrease the size of tree. |
||
240 | * |
||
241 | * @param DataStructures\Trees\Nodes\BSTNode|null The node to be deleted. |
||
242 | * @return the node that replaces the deleted. |
||
243 | */ |
||
244 | protected abstract function _delete(BinaryNodeInterface &$node); |
||
245 | |||
246 | /** |
||
247 | * Replaces the node n to remove a new one k and links k with the parent |
||
248 | * of n. |
||
249 | * |
||
250 | * @param DataStructures\Trees\Nodes\BSTNode $nodeToReplace the node to remove. |
||
251 | * @param DataStructures\Trees\Nodes\BSTNode|null $newNode the newNode |
||
252 | * to link with the $nodeToReplace parent. |
||
253 | * @return DataStructures\Trees\Nodes\BSTNode the new linked node. |
||
254 | */ |
||
255 | protected function replace(&$nodeToReplace, &$newNode) { |
||
270 | |||
271 | public function delete($key){} |
||
272 | |||
273 | /** |
||
274 | * Retrieves the node with the specified key. |
||
275 | * |
||
276 | * @param int|string $key the key used to store. |
||
277 | * @return DataStructures\Trees\Nodes\BSTNode|null the node or null. |
||
278 | */ |
||
279 | public function search($key) { |
||
301 | |||
302 | /** |
||
303 | * Returns true if is leaf the node. |
||
304 | * |
||
305 | * @param DataStructures\Trees\Nodes\BSTNode|null $node default to null. |
||
306 | * @return true if is leaf the node, is not null and their subtrees has no |
||
307 | * pointers to successors. |
||
308 | */ |
||
309 | public function isLeaf($node) { // BinaryTreeNode |
||
312 | |||
313 | /** |
||
314 | * Checks if a node is root. New nodes that does not point to any other node |
||
315 | * also are called a root node. |
||
316 | * |
||
317 | * @param DataStructures\Trees\Nodes\BSTNode|null $node default to null. |
||
318 | * @return true if is root the node, is not null and their subtrees has no |
||
319 | * pointers to successors. |
||
320 | */ |
||
321 | public function isRoot($node) { |
||
324 | |||
325 | /** |
||
326 | * Binds to count() method. This is equal to make $this->tree->size(). |
||
327 | * |
||
328 | * @return integer the tree size. 0 if it is empty. |
||
329 | */ |
||
330 | public function count() { |
||
333 | } |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.