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 ElementWrapper 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 ElementWrapper, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
45 | class ElementWrapper |
||
46 | { |
||
47 | /** |
||
48 | * Wrapped element. |
||
49 | * |
||
50 | * @var Element |
||
51 | */ |
||
52 | private $_element; |
||
53 | |||
54 | /** |
||
55 | * Constructor |
||
56 | * |
||
57 | * @param Element $el |
||
58 | */ |
||
59 | 77 | public function __construct(Element $el) { |
|
62 | |||
63 | /** |
||
64 | * Compatibility method to dispatch calls to wrapped element. |
||
65 | * |
||
66 | * @deprecated Use <code>as*</code> accessor methods to ensure strict type |
||
67 | * @param string $mtd Method name |
||
68 | * @param array $args Arguments |
||
69 | * @return mixed |
||
70 | */ |
||
71 | public function __call($mtd, array $args) { |
||
74 | |||
75 | /** |
||
76 | * Get the wrapped element as an abstract type. |
||
77 | * |
||
78 | * @return ElementBase |
||
79 | */ |
||
80 | 1 | public function asElement() { |
|
83 | |||
84 | /** |
||
85 | * Get the wrapped element as a context specific tagged type. |
||
86 | * |
||
87 | * @throws \UnexpectedValueException |
||
88 | * @return TaggedType |
||
89 | */ |
||
90 | 2 | public function asTagged() { |
|
97 | |||
98 | /** |
||
99 | * Get the wrapped element as a boolean type. |
||
100 | * |
||
101 | * @throws \UnexpectedValueException |
||
102 | * @return Boolean |
||
103 | */ |
||
104 | 4 | View Code Duplication | public function asBoolean() { |
111 | |||
112 | /** |
||
113 | * Get the wrapped element as an integer type. |
||
114 | * |
||
115 | * @throws \UnexpectedValueException |
||
116 | * @return Integer |
||
117 | */ |
||
118 | 2 | View Code Duplication | public function asInteger() { |
125 | |||
126 | /** |
||
127 | * Get the wrapped element as a bit string type. |
||
128 | * |
||
129 | * @throws \UnexpectedValueException |
||
130 | * @return BitString |
||
131 | */ |
||
132 | 2 | View Code Duplication | public function asBitString() { |
139 | |||
140 | /** |
||
141 | * Get the wrapped element as an octet string type. |
||
142 | * |
||
143 | * @throws \UnexpectedValueException |
||
144 | * @return OctetString |
||
145 | */ |
||
146 | 2 | View Code Duplication | public function asOctetString() { |
153 | |||
154 | /** |
||
155 | * Get the wrapped element as a null type. |
||
156 | * |
||
157 | * @throws \UnexpectedValueException |
||
158 | * @return NullType |
||
159 | */ |
||
160 | 7 | View Code Duplication | public function asNull() { |
167 | |||
168 | /** |
||
169 | * Get the wrapped element as an object identifier type. |
||
170 | * |
||
171 | * @throws \UnexpectedValueException |
||
172 | * @return ObjectIdentifier |
||
173 | */ |
||
174 | 2 | View Code Duplication | public function asObjectIdentifier() { |
182 | |||
183 | /** |
||
184 | * Get the wrapped element as an object descriptor type. |
||
185 | * |
||
186 | * @throws \UnexpectedValueException |
||
187 | * @return ObjectDescriptor |
||
188 | */ |
||
189 | 2 | View Code Duplication | public function asObjectDescriptor() { |
197 | |||
198 | /** |
||
199 | * Get the wrapped element as a real type. |
||
200 | * |
||
201 | * @throws \UnexpectedValueException |
||
202 | * @return Real |
||
203 | */ |
||
204 | 2 | View Code Duplication | public function asReal() { |
211 | |||
212 | /** |
||
213 | * Get the wrapped element as an enumerated type. |
||
214 | * |
||
215 | * @throws \UnexpectedValueException |
||
216 | * @return Enumerated |
||
217 | */ |
||
218 | 2 | View Code Duplication | public function asEnumerated() { |
225 | |||
226 | /** |
||
227 | * Get the wrapped element as a UTF8 string type. |
||
228 | * |
||
229 | * @throws \UnexpectedValueException |
||
230 | * @return UTF8String |
||
231 | */ |
||
232 | 2 | View Code Duplication | public function asUTF8String() { |
239 | |||
240 | /** |
||
241 | * Get the wrapped element as a relative OID type. |
||
242 | * |
||
243 | * @throws \UnexpectedValueException |
||
244 | * @return RelativeOID |
||
245 | */ |
||
246 | 2 | View Code Duplication | public function asRelativeOID() { |
253 | |||
254 | /** |
||
255 | * Get the wrapped element as a sequence type. |
||
256 | * |
||
257 | * @throws \UnexpectedValueException |
||
258 | * @return Sequence |
||
259 | */ |
||
260 | 2 | View Code Duplication | public function asSequence() { |
267 | |||
268 | /** |
||
269 | * Get the wrapped element as a set type. |
||
270 | * |
||
271 | * @throws \UnexpectedValueException |
||
272 | * @return Set |
||
273 | */ |
||
274 | 2 | View Code Duplication | public function asSet() { |
281 | |||
282 | /** |
||
283 | * Get the wrapped element as a numeric string type. |
||
284 | * |
||
285 | * @throws \UnexpectedValueException |
||
286 | * @return NumericString |
||
287 | */ |
||
288 | 2 | View Code Duplication | public function asNumericString() { |
295 | |||
296 | /** |
||
297 | * Get the wrapped element as a printable string type. |
||
298 | * |
||
299 | * @throws \UnexpectedValueException |
||
300 | * @return PrintableString |
||
301 | */ |
||
302 | 2 | View Code Duplication | public function asPrintableString() { |
309 | |||
310 | /** |
||
311 | * Get the wrapped element as a T61 string type. |
||
312 | * |
||
313 | * @throws \UnexpectedValueException |
||
314 | * @return T61String |
||
315 | */ |
||
316 | 2 | View Code Duplication | public function asT61String() { |
323 | |||
324 | /** |
||
325 | * Get the wrapped element as a videotex string type. |
||
326 | * |
||
327 | * @throws \UnexpectedValueException |
||
328 | * @return VideotexString |
||
329 | */ |
||
330 | 2 | View Code Duplication | public function asVideotexString() { |
337 | |||
338 | /** |
||
339 | * Get the wrapped element as a IA6 string type. |
||
340 | * |
||
341 | * @throws \UnexpectedValueException |
||
342 | * @return IA5String |
||
343 | */ |
||
344 | 2 | View Code Duplication | public function asIA5String() { |
351 | |||
352 | /** |
||
353 | * Get the wrapped element as an UTC time type. |
||
354 | * |
||
355 | * @throws \UnexpectedValueException |
||
356 | * @return UTCTime |
||
357 | */ |
||
358 | 2 | View Code Duplication | public function asUTCTime() { |
365 | |||
366 | /** |
||
367 | * Get the wrapped element as a generalized time type. |
||
368 | * |
||
369 | * @throws \UnexpectedValueException |
||
370 | * @return GeneralizedTime |
||
371 | */ |
||
372 | 2 | View Code Duplication | public function asGeneralizedTime() { |
379 | |||
380 | /** |
||
381 | * Get the wrapped element as a graphic string type. |
||
382 | * |
||
383 | * @throws \UnexpectedValueException |
||
384 | * @return GraphicString |
||
385 | */ |
||
386 | 2 | View Code Duplication | public function asGraphicString() { |
393 | |||
394 | /** |
||
395 | * Get the wrapped element as a visible string type. |
||
396 | * |
||
397 | * @throws \UnexpectedValueException |
||
398 | * @return VisibleString |
||
399 | */ |
||
400 | 2 | View Code Duplication | public function asVisibleString() { |
407 | |||
408 | /** |
||
409 | * Get the wrapped element as a general string type. |
||
410 | * |
||
411 | * @throws \UnexpectedValueException |
||
412 | * @return GeneralString |
||
413 | */ |
||
414 | 2 | View Code Duplication | public function asGeneralString() { |
421 | |||
422 | /** |
||
423 | * Get the wrapped element as a universal string type. |
||
424 | * |
||
425 | * @throws \UnexpectedValueException |
||
426 | * @return UniversalString |
||
427 | */ |
||
428 | 2 | View Code Duplication | public function asUniversalString() { |
435 | |||
436 | /** |
||
437 | * Get the wrapped element as a character string type. |
||
438 | * |
||
439 | * @throws \UnexpectedValueException |
||
440 | * @return CharacterString |
||
441 | */ |
||
442 | 2 | View Code Duplication | public function asCharacterString() { |
449 | |||
450 | /** |
||
451 | * Get the wrapped element as a BMP string type. |
||
452 | * |
||
453 | * @throws \UnexpectedValueException |
||
454 | * @return BMPString |
||
455 | */ |
||
456 | 2 | View Code Duplication | public function asBMPString() { |
463 | |||
464 | /** |
||
465 | * Get the wrapped element as any string type. |
||
466 | * |
||
467 | * @throws \UnexpectedValueException |
||
468 | * @return StringType |
||
469 | */ |
||
470 | 2 | View Code Duplication | public function asString() { |
477 | |||
478 | /** |
||
479 | * Get the wrapped element as any time type. |
||
480 | * |
||
481 | * @throws \UnexpectedValueException |
||
482 | * @return TimeType |
||
483 | */ |
||
484 | 2 | View Code Duplication | public function asTime() { |
491 | |||
492 | /** |
||
493 | * Generate message for exceptions thrown by <code>as*</code> methods. |
||
494 | * |
||
495 | * @param int $tag Type tag of the expected element |
||
496 | * @return string |
||
497 | */ |
||
498 | 29 | private function _generateExceptionMessage($tag) { |
|
502 | |||
503 | /** |
||
504 | * Get textual description of the wrapped element for debugging purposes. |
||
505 | * |
||
506 | * @return string |
||
507 | */ |
||
508 | 30 | private function _typeDescriptorString() { |
|
516 | } |
||
517 |
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.