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 AbstractCollection 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 AbstractCollection, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
16 | abstract class AbstractCollection extends Arrayy implements CollectionInterface |
||
17 | { |
||
18 | /** |
||
19 | * The type of elements stored in this collection. |
||
20 | * |
||
21 | * @var string |
||
22 | */ |
||
23 | private $collectionType; |
||
24 | |||
25 | /** |
||
26 | * Constructs a collection object of the specified type, optionally with the |
||
27 | * specified data. |
||
28 | * |
||
29 | * @param mixed $data |
||
30 | * <p> |
||
31 | * The initial items to store in the collection. |
||
32 | * </p> |
||
33 | * @param string $iteratorClass |
||
34 | * @param bool $checkForMissingPropertiesInConstructorAndType |
||
35 | */ |
||
36 | 15 | public function __construct( |
|
67 | |||
68 | /** |
||
69 | * @return static[] |
||
70 | */ |
||
71 | 6 | public function getCollection(): array |
|
75 | |||
76 | /** |
||
77 | * The type (FQCN) associated with this collection. |
||
78 | * |
||
79 | * @return string |
||
80 | */ |
||
81 | abstract public function getType(): string; |
||
82 | |||
83 | /** |
||
84 | * Merge current items and items of given collections into a new one. |
||
85 | * |
||
86 | * @param static ...$collections The collections to merge. |
||
87 | * |
||
88 | * @throws \InvalidArgumentException if any of the given collections are not of the same type |
||
89 | * |
||
90 | * @return static |
||
91 | */ |
||
92 | 1 | public function merge(CollectionInterface ...$collections): CollectionInterface |
|
104 | |||
105 | /** |
||
106 | * Assigns a value to the specified offset + check the type. |
||
107 | * |
||
108 | * @param int|string|null $offset |
||
109 | * @param mixed $value |
||
110 | */ |
||
111 | 1 | public function offsetSet($offset, $value) |
|
125 | |||
126 | /** |
||
127 | * Prepend a (key) + value to the current array. |
||
128 | * |
||
129 | * @param mixed $value |
||
130 | * @param mixed $key |
||
131 | * |
||
132 | * @return static |
||
133 | * <p>(Mutable) Return this Arrayy object, with the prepended value.</p> |
||
134 | */ |
||
135 | 3 | View Code Duplication | public function prepend($value, $key = null): Arrayy |
149 | |||
150 | /** |
||
151 | * Append a (key) + value to the current array. |
||
152 | * |
||
153 | * @param mixed $value |
||
154 | * @param mixed $key |
||
155 | * |
||
156 | * @return static |
||
157 | * <p>(Mutable) Return this Arrayy object, with the appended values.</p> |
||
158 | */ |
||
159 | 4 | View Code Duplication | public function append($value, $key = null): Arrayy |
173 | |||
174 | /** |
||
175 | * Returns the values from given property or method. |
||
176 | * |
||
177 | * @param string $keyOrPropertyOrMethod the property or method name to filter by |
||
178 | * |
||
179 | * @throws \InvalidArgumentException if property or method is not defined |
||
180 | * |
||
181 | * @return array |
||
182 | */ |
||
183 | 1 | public function column(string $keyOrPropertyOrMethod): array |
|
194 | |||
195 | /** |
||
196 | * Returns a collection of matching items. |
||
197 | * |
||
198 | * @param string $keyOrPropertyOrMethod the property or method to evaluate |
||
199 | * @param mixed $value the value to match |
||
200 | * |
||
201 | * @throws \InvalidArgumentException if property or method is not defined |
||
202 | * |
||
203 | * @return static |
||
204 | */ |
||
205 | 1 | public function where(string $keyOrPropertyOrMethod, $value): CollectionInterface |
|
218 | |||
219 | /** |
||
220 | * Internal mechanic of set method. |
||
221 | * |
||
222 | * @param string|null $key |
||
223 | * @param mixed $value |
||
224 | * @param bool $checkPropertiesAndType |
||
225 | * |
||
226 | * @return bool |
||
227 | */ |
||
228 | 12 | protected function internalSet($key, $value, $checkPropertiesAndType = true): bool |
|
244 | |||
245 | /** |
||
246 | * @param mixed $value |
||
247 | */ |
||
248 | 14 | private function checkTypeWrapper($value) |
|
256 | |||
257 | /** |
||
258 | * Extracts the value of the given property or method from the object. |
||
259 | * |
||
260 | * @param Arrayy $object the object to extract the value from |
||
261 | * @param string $keyOrPropertyOrMethod the property or method for which the |
||
262 | * value should be extracted |
||
263 | * |
||
264 | * @throws \InvalidArgumentException if the method or property is not defined |
||
265 | * |
||
266 | * @return mixed the value extracted from the specified property or method |
||
267 | */ |
||
268 | 2 | private function extractValue(Arrayy $object, string $keyOrPropertyOrMethod) |
|
292 | |||
293 | /** |
||
294 | * Returns `true` if value is of the specified type. |
||
295 | * |
||
296 | * @param string $type the type to check the value against |
||
297 | * @param mixed $value the value to check |
||
298 | * |
||
299 | * @return bool |
||
300 | */ |
||
301 | 14 | private function checkType(string $type, $value) |
|
335 | |||
336 | /** |
||
337 | * @param mixed $value |
||
338 | * |
||
339 | * @return string |
||
340 | * |
||
341 | * @noinspection ReturnTypeCanBeDeclaredInspection |
||
342 | */ |
||
343 | 6 | private function valueToString($value) |
|
373 | } |
||
374 |
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.