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 Organizer 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 Organizer, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
33 | class Organizer extends EventSourcedAggregateRoot implements UpdateableWithCdbXmlInterface, LabelAwareAggregateRoot |
||
34 | { |
||
35 | /** |
||
36 | * The actor id. |
||
37 | * |
||
38 | * @var string |
||
39 | */ |
||
40 | protected $actorId; |
||
41 | |||
42 | /** |
||
43 | * @var Language |
||
44 | */ |
||
45 | private $mainLanguage; |
||
46 | |||
47 | /** |
||
48 | * @var Url |
||
49 | */ |
||
50 | private $website; |
||
51 | |||
52 | /** |
||
53 | * @var Title[] |
||
54 | */ |
||
55 | private $titles; |
||
56 | |||
57 | /** |
||
58 | * @var Address[]|null |
||
59 | */ |
||
60 | private $addresses; |
||
61 | |||
62 | /** |
||
63 | * @var ContactPoint |
||
64 | */ |
||
65 | private $contactPoint; |
||
66 | |||
67 | /** |
||
68 | * @var LabelCollection|Label[] |
||
69 | */ |
||
70 | private $labels; |
||
71 | |||
72 | /** |
||
73 | * {@inheritdoc} |
||
74 | */ |
||
75 | public function getAggregateRootId() |
||
79 | |||
80 | public function __construct() |
||
89 | |||
90 | /** |
||
91 | * Import from UDB2. |
||
92 | * |
||
93 | * @param string $actorId |
||
94 | * The actor id. |
||
95 | * @param string $cdbXml |
||
96 | * The cdb xml. |
||
97 | * @param string $cdbXmlNamespaceUri |
||
98 | * The cdb xml namespace uri. |
||
99 | * |
||
100 | * @return Organizer |
||
101 | * The actor. |
||
102 | */ |
||
103 | public static function importFromUDB2( |
||
119 | |||
120 | /** |
||
121 | * Factory method to create a new Organizer. |
||
122 | * |
||
123 | * @param string $id |
||
124 | * @param Language $mainLanguage |
||
125 | * @param Url $website |
||
126 | * @param Title $title |
||
127 | * @return Organizer |
||
128 | */ |
||
129 | public static function create( |
||
143 | |||
144 | /** |
||
145 | * @inheritdoc |
||
146 | */ |
||
147 | public function updateWithCdbXml($cdbXml, $cdbXmlNamespaceUri) |
||
157 | |||
158 | /** |
||
159 | * @param Url $website |
||
160 | */ |
||
161 | public function updateWebsite(Url $website) |
||
172 | |||
173 | /** |
||
174 | * @param Title $title |
||
175 | * @param Language $language |
||
176 | */ |
||
177 | public function updateTitle( |
||
198 | |||
199 | /** |
||
200 | * @param Address $address |
||
201 | * @param Language $language |
||
202 | */ |
||
203 | View Code Duplication | public function updateAddress( |
|
224 | |||
225 | /** |
||
226 | * @param ContactPoint $contactPoint |
||
227 | */ |
||
228 | public function updateContactPoint(ContactPoint $contactPoint) |
||
236 | |||
237 | /** |
||
238 | * @inheritdoc |
||
239 | */ |
||
240 | public function addLabel(Label $label) |
||
246 | |||
247 | /** |
||
248 | * @inheritdoc |
||
249 | */ |
||
250 | public function removeLabel(Label $label) |
||
256 | |||
257 | /** |
||
258 | * @param Labels $labels |
||
259 | */ |
||
260 | public function importLabels(Labels $labels) |
||
315 | |||
316 | public function delete() |
||
322 | |||
323 | /** |
||
324 | * Apply the organizer created event. |
||
325 | * @param OrganizerCreated $organizerCreated |
||
326 | */ |
||
327 | protected function applyOrganizerCreated(OrganizerCreated $organizerCreated) |
||
335 | |||
336 | /** |
||
337 | * Apply the organizer created event. |
||
338 | * @param OrganizerCreatedWithUniqueWebsite $organizerCreated |
||
339 | */ |
||
340 | protected function applyOrganizerCreatedWithUniqueWebsite(OrganizerCreatedWithUniqueWebsite $organizerCreated) |
||
350 | |||
351 | /** |
||
352 | * @param OrganizerImportedFromUDB2 $organizerImported |
||
353 | * @throws \CultureFeed_Cdb_ParseException |
||
354 | */ |
||
355 | protected function applyOrganizerImportedFromUDB2( |
||
372 | |||
373 | /** |
||
374 | * @param OrganizerUpdatedFromUDB2 $organizerUpdatedFromUDB2 |
||
375 | * @throws \CultureFeed_Cdb_ParseException |
||
376 | */ |
||
377 | protected function applyOrganizerUpdatedFromUDB2( |
||
391 | |||
392 | /** |
||
393 | * @param WebsiteUpdated $websiteUpdated |
||
394 | */ |
||
395 | protected function applyWebsiteUpdated(WebsiteUpdated $websiteUpdated) |
||
399 | |||
400 | /** |
||
401 | * @param TitleUpdated $titleUpdated |
||
402 | */ |
||
403 | protected function applyTitleUpdated(TitleUpdated $titleUpdated) |
||
407 | |||
408 | /** |
||
409 | * @param TitleTranslated $titleTranslated |
||
410 | */ |
||
411 | protected function applyTitleTranslated(TitleTranslated $titleTranslated) |
||
415 | |||
416 | /** |
||
417 | * @param AddressUpdated $addressUpdated |
||
418 | */ |
||
419 | protected function applyAddressUpdated(AddressUpdated $addressUpdated) |
||
423 | |||
424 | /** |
||
425 | * @param AddressTranslated $addressTranslated |
||
426 | */ |
||
427 | protected function applyAddressTranslated(AddressTranslated $addressTranslated) |
||
431 | |||
432 | /** |
||
433 | * @param ContactPointUpdated $contactPointUpdated |
||
434 | */ |
||
435 | protected function applyContactPointUpdated(ContactPointUpdated $contactPointUpdated) |
||
439 | |||
440 | /** |
||
441 | * @param LabelAdded $labelAdded |
||
442 | */ |
||
443 | protected function applyLabelAdded(LabelAdded $labelAdded) |
||
447 | |||
448 | /** |
||
449 | * @param LabelRemoved $labelRemoved |
||
450 | */ |
||
451 | protected function applyLabelRemoved(LabelRemoved $labelRemoved) |
||
455 | |||
456 | /** |
||
457 | * @param \CultureFeed_Cdb_Item_Actor $actor |
||
458 | * @return null|Title |
||
459 | */ |
||
460 | private function getTitle(\CultureFeed_Cdb_Item_Actor $actor) |
||
474 | |||
475 | /** |
||
476 | * @param Title $title |
||
477 | * @param Language $language |
||
478 | */ |
||
479 | private function setTitle(Title $title, Language $language) |
||
483 | |||
484 | /** |
||
485 | * @param Title $title |
||
486 | * @param Language $language |
||
487 | * @return bool |
||
488 | */ |
||
489 | private function isTitleChanged(Title $title, Language $language) |
||
494 | |||
495 | /** |
||
496 | * @param Address $address |
||
497 | * @param Language $language |
||
498 | */ |
||
499 | private function setAddress(Address $address, Language $language) |
||
503 | |||
504 | /** |
||
505 | * @param Address $address |
||
506 | * @param Language $language |
||
507 | * @return bool |
||
508 | */ |
||
509 | private function isAddressChanged(Address $address, Language $language) |
||
514 | } |
||
515 |
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.