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 Order 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 Order, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 21 | class Order implements OrderInterface |
||
| 22 | { |
||
| 23 | use TimestampableTrait; |
||
| 24 | |||
| 25 | /** |
||
| 26 | * @var mixed |
||
| 27 | */ |
||
| 28 | protected $id; |
||
| 29 | |||
| 30 | /** |
||
| 31 | * @var \DateTime |
||
| 32 | */ |
||
| 33 | protected $completedAt; |
||
| 34 | |||
| 35 | /** |
||
| 36 | * @var string |
||
| 37 | */ |
||
| 38 | protected $number; |
||
| 39 | |||
| 40 | /** |
||
| 41 | * @var string |
||
| 42 | */ |
||
| 43 | protected $notes; |
||
| 44 | |||
| 45 | /** |
||
| 46 | * @var Collection|OrderItemInterface[] |
||
| 47 | */ |
||
| 48 | protected $items; |
||
| 49 | |||
| 50 | /** |
||
| 51 | * @var int |
||
| 52 | */ |
||
| 53 | protected $itemsTotal = 0; |
||
| 54 | |||
| 55 | /** |
||
| 56 | * @var Collection|AdjustmentInterface[] |
||
| 57 | */ |
||
| 58 | protected $adjustments; |
||
| 59 | |||
| 60 | /** |
||
| 61 | * @var Collection|CommentInterface[] |
||
| 62 | */ |
||
| 63 | protected $comments; |
||
| 64 | |||
| 65 | /** |
||
| 66 | * @var Collection|IdentityInterface[] |
||
| 67 | */ |
||
| 68 | protected $identities; |
||
| 69 | |||
| 70 | /** |
||
| 71 | * @var int |
||
| 72 | */ |
||
| 73 | protected $adjustmentsTotal = 0; |
||
| 74 | |||
| 75 | /** |
||
| 76 | * Calculated total. |
||
| 77 | * Items total + adjustments total. |
||
| 78 | * |
||
| 79 | * @var int |
||
| 80 | */ |
||
| 81 | protected $total = 0; |
||
| 82 | |||
| 83 | /** |
||
| 84 | * @var string |
||
| 85 | */ |
||
| 86 | protected $state = OrderInterface::STATE_CART; |
||
| 87 | |||
| 88 | public function __construct() |
||
| 96 | |||
| 97 | /** |
||
| 98 | * {@inheritdoc} |
||
| 99 | */ |
||
| 100 | public function getId() |
||
| 104 | |||
| 105 | /** |
||
| 106 | * {@inheritdoc} |
||
| 107 | */ |
||
| 108 | public function isCompleted() |
||
| 112 | |||
| 113 | /** |
||
| 114 | * {@inheritdoc} |
||
| 115 | */ |
||
| 116 | public function complete() |
||
| 120 | |||
| 121 | /** |
||
| 122 | * {@inheritdoc} |
||
| 123 | */ |
||
| 124 | public function getCompletedAt() |
||
| 128 | |||
| 129 | /** |
||
| 130 | * {@inheritdoc} |
||
| 131 | */ |
||
| 132 | public function setCompletedAt(\DateTime $completedAt = null) |
||
| 136 | |||
| 137 | /** |
||
| 138 | * {@inheritdoc} |
||
| 139 | */ |
||
| 140 | public function getNumber() |
||
| 144 | |||
| 145 | /** |
||
| 146 | * {@inheritdoc} |
||
| 147 | */ |
||
| 148 | public function setNumber($number) |
||
| 152 | |||
| 153 | /** |
||
| 154 | * {@inheritdoc} |
||
| 155 | */ |
||
| 156 | public function getNotes() |
||
| 160 | |||
| 161 | /** |
||
| 162 | * {@inheritdoc} |
||
| 163 | */ |
||
| 164 | public function setNotes($notes) |
||
| 168 | |||
| 169 | /** |
||
| 170 | * {@inheritdoc} |
||
| 171 | */ |
||
| 172 | public function getSequenceType() |
||
| 176 | |||
| 177 | /** |
||
| 178 | * {@inheritdoc} |
||
| 179 | */ |
||
| 180 | public function getItems() |
||
| 184 | |||
| 185 | /** |
||
| 186 | * {@inheritdoc} |
||
| 187 | */ |
||
| 188 | public function clearItems() |
||
| 194 | |||
| 195 | /** |
||
| 196 | * {@inheritdoc} |
||
| 197 | */ |
||
| 198 | public function countItems() |
||
| 202 | |||
| 203 | /** |
||
| 204 | * {@inheritdoc} |
||
| 205 | */ |
||
| 206 | View Code Duplication | public function addItem(OrderItemInterface $item) |
|
| 218 | |||
| 219 | /** |
||
| 220 | * {@inheritdoc} |
||
| 221 | */ |
||
| 222 | View Code Duplication | public function removeItem(OrderItemInterface $item) |
|
| 231 | |||
| 232 | /** |
||
| 233 | * {@inheritdoc} |
||
| 234 | */ |
||
| 235 | public function hasItem(OrderItemInterface $item) |
||
| 239 | |||
| 240 | /** |
||
| 241 | * {@inheritdoc} |
||
| 242 | */ |
||
| 243 | public function getItemsTotal() |
||
| 247 | |||
| 248 | /** |
||
| 249 | * {@inheritdoc} |
||
| 250 | */ |
||
| 251 | public function recalculateItemsTotal() |
||
| 260 | |||
| 261 | /** |
||
| 262 | * {@inheritdoc} |
||
| 263 | */ |
||
| 264 | public function getComments() |
||
| 268 | |||
| 269 | /** |
||
| 270 | * {@inheritdoc} |
||
| 271 | */ |
||
| 272 | public function addComment(CommentInterface $comment) |
||
| 279 | |||
| 280 | /** |
||
| 281 | * {@inheritdoc} |
||
| 282 | */ |
||
| 283 | public function removeComment(CommentInterface $comment) |
||
| 290 | |||
| 291 | /** |
||
| 292 | * {@inheritdoc} |
||
| 293 | */ |
||
| 294 | public function getTotal() |
||
| 298 | |||
| 299 | /** |
||
| 300 | * {@inheritdoc} |
||
| 301 | */ |
||
| 302 | public function setState($state) |
||
| 306 | |||
| 307 | /** |
||
| 308 | * {@inheritdoc} |
||
| 309 | */ |
||
| 310 | public function getState() |
||
| 314 | |||
| 315 | /** |
||
| 316 | * {@inheritdoc} |
||
| 317 | */ |
||
| 318 | public function getTotalQuantity() |
||
| 328 | |||
| 329 | /** |
||
| 330 | * {@inheritdoc} |
||
| 331 | */ |
||
| 332 | public function isEmpty() |
||
| 336 | |||
| 337 | /** |
||
| 338 | * {@inheritdoc} |
||
| 339 | */ |
||
| 340 | public function addIdentity(IdentityInterface $identity) |
||
| 348 | |||
| 349 | /** |
||
| 350 | * {@inheritdoc} |
||
| 351 | */ |
||
| 352 | public function hasIdentity(IdentityInterface $identity) |
||
| 356 | |||
| 357 | /** |
||
| 358 | * {@inheritdoc} |
||
| 359 | */ |
||
| 360 | public function getIdentities() |
||
| 364 | |||
| 365 | /** |
||
| 366 | * {@inheritdoc} |
||
| 367 | */ |
||
| 368 | public function removeIdentity(IdentityInterface $identity) |
||
| 375 | |||
| 376 | /** |
||
| 377 | * {@inheritdoc} |
||
| 378 | */ |
||
| 379 | View Code Duplication | public function getAdjustments($type = null) |
|
| 389 | |||
| 390 | /** |
||
| 391 | * {@inheritdoc} |
||
| 392 | */ |
||
| 393 | View Code Duplication | public function getAdjustmentsRecursively($type = null) |
|
| 402 | |||
| 403 | /** |
||
| 404 | * {@inheritdoc} |
||
| 405 | */ |
||
| 406 | View Code Duplication | public function addAdjustment(AdjustmentInterface $adjustment) |
|
| 414 | |||
| 415 | /** |
||
| 416 | * {@inheritdoc} |
||
| 417 | */ |
||
| 418 | View Code Duplication | public function removeAdjustment(AdjustmentInterface $adjustment) |
|
| 426 | |||
| 427 | /** |
||
| 428 | * {@inheritdoc} |
||
| 429 | */ |
||
| 430 | public function hasAdjustment(AdjustmentInterface $adjustment) |
||
| 434 | |||
| 435 | /** |
||
| 436 | * {@inheritdoc} |
||
| 437 | */ |
||
| 438 | View Code Duplication | public function getAdjustmentsTotal($type = null) |
|
| 453 | |||
| 454 | /** |
||
| 455 | * {@inheritdoc} |
||
| 456 | */ |
||
| 457 | View Code Duplication | public function getAdjustmentsTotalRecursively($type = null) |
|
| 468 | |||
| 469 | /** |
||
| 470 | * {@inheritdoc} |
||
| 471 | */ |
||
| 472 | public function removeAdjustments($type) |
||
| 482 | |||
| 483 | /** |
||
| 484 | * {@inheritdoc} |
||
| 485 | */ |
||
| 486 | public function removeAdjustmentsRecursively($type = null) |
||
| 493 | |||
| 494 | /** |
||
| 495 | * {@inheritdoc} |
||
| 496 | */ |
||
| 497 | View Code Duplication | public function recalculateAdjustmentsTotal() |
|
| 509 | |||
| 510 | /** |
||
| 511 | * Calculate total. |
||
| 512 | * Items total + Adjustments total. |
||
| 513 | */ |
||
| 514 | protected function recalculateTotal() |
||
| 522 | |||
| 523 | /** |
||
| 524 | * @param AdjustmentInterface $adjustment |
||
| 525 | */ |
||
| 526 | protected function addToAdjustmentsTotal(AdjustmentInterface $adjustment) |
||
| 533 | |||
| 534 | /** |
||
| 535 | * @param AdjustmentInterface $adjustment |
||
| 536 | */ |
||
| 537 | protected function subtractFromAdjustmentsTotal(AdjustmentInterface $adjustment) |
||
| 544 | } |
||
| 545 |
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.