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 AtBpost 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 AtBpost, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
19 | class AtBpost extends National |
||
20 | { |
||
21 | /** @var string */ |
||
22 | protected $product = Product::PRODUCT_NAME_BPACK_AT_BPOST; |
||
23 | |||
24 | /** @var string */ |
||
25 | private $pugoId; |
||
26 | |||
27 | /** @var string */ |
||
28 | private $pugoName; |
||
29 | |||
30 | /** @var \Bpost\BpostApiClient\Bpost\Order\PugoAddress */ |
||
31 | private $pugoAddress; |
||
32 | |||
33 | /** @var string */ |
||
34 | private $receiverName; |
||
35 | |||
36 | /** @var string */ |
||
37 | private $receiverCompany; |
||
38 | |||
39 | /** @var string */ |
||
40 | protected $requestedDeliveryDate; |
||
41 | |||
42 | /** @var ShopHandlingInstruction */ |
||
43 | private $shopHandlingInstruction; |
||
44 | |||
45 | /** |
||
46 | * @param string $product Possible values are: bpack@bpost |
||
47 | * @throws BpostInvalidValueException |
||
48 | */ |
||
49 | 3 | View Code Duplication | public function setProduct($product) |
57 | |||
58 | /** |
||
59 | * @return array |
||
60 | */ |
||
61 | 3 | public static function getPossibleProductValues() |
|
67 | |||
68 | /** |
||
69 | * @param \Bpost\BpostApiClient\Bpost\Order\PugoAddress $pugoAddress |
||
70 | */ |
||
71 | 3 | public function setPugoAddress($pugoAddress) |
|
75 | |||
76 | /** |
||
77 | * @return \Bpost\BpostApiClient\Bpost\Order\PugoAddress |
||
78 | */ |
||
79 | 3 | public function getPugoAddress() |
|
83 | |||
84 | /** |
||
85 | * @param string $pugoId |
||
86 | */ |
||
87 | 3 | public function setPugoId($pugoId) |
|
91 | |||
92 | /** |
||
93 | * @return string |
||
94 | */ |
||
95 | 3 | public function getPugoId() |
|
99 | |||
100 | /** |
||
101 | * @param string $pugoName |
||
102 | */ |
||
103 | 3 | public function setPugoName($pugoName) |
|
107 | |||
108 | /** |
||
109 | * @return string |
||
110 | */ |
||
111 | 3 | public function getPugoName() |
|
115 | |||
116 | /** |
||
117 | * @param string $receiverCompany |
||
118 | */ |
||
119 | 3 | public function setReceiverCompany($receiverCompany) |
|
123 | |||
124 | /** |
||
125 | * @return string |
||
126 | */ |
||
127 | 3 | public function getReceiverCompany() |
|
131 | |||
132 | /** |
||
133 | * @param string $receiverName |
||
134 | */ |
||
135 | 3 | public function setReceiverName($receiverName) |
|
139 | |||
140 | /** |
||
141 | * @return string |
||
142 | */ |
||
143 | 3 | public function getReceiverName() |
|
147 | |||
148 | /** |
||
149 | * @return string |
||
150 | */ |
||
151 | 3 | public function getRequestedDeliveryDate() |
|
155 | |||
156 | /** |
||
157 | * @param string $requestedDeliveryDate |
||
158 | */ |
||
159 | 3 | public function setRequestedDeliveryDate($requestedDeliveryDate) |
|
163 | |||
164 | /** |
||
165 | * @return string |
||
166 | */ |
||
167 | 2 | public function getShopHandlingInstruction() |
|
174 | |||
175 | /** |
||
176 | * @param string $shopHandlingInstruction |
||
177 | */ |
||
178 | 1 | public function setShopHandlingInstruction($shopHandlingInstruction) |
|
182 | |||
183 | /** |
||
184 | * Return the object as an array for usage in the XML |
||
185 | * |
||
186 | * @param \DomDocument $document |
||
187 | * @param string $prefix |
||
188 | * @param string $type |
||
189 | * @return \DomElement |
||
190 | */ |
||
191 | 2 | public function toXML(\DOMDocument $document, $prefix = null, $type = null) |
|
227 | |||
228 | /** |
||
229 | * @param \DOMDocument $document |
||
230 | * @param \DOMElement $typeElement |
||
231 | * @param string $prefix |
||
232 | */ |
||
233 | 2 | protected function addToXmlRequestedDeliveryDate(\DOMDocument $document, \DOMElement $typeElement, $prefix) |
|
241 | |||
242 | 2 | private function addToXmlShopHandlingInstruction(\DOMDocument $document, \DOMElement $typeElement, $prefix) |
|
250 | |||
251 | /** |
||
252 | * @param \SimpleXMLElement $xml |
||
253 | * |
||
254 | * @return AtBpost |
||
255 | * @throws BpostInvalidValueException |
||
256 | * @throws BpostNotImplementedException |
||
257 | */ |
||
258 | 1 | public static function createFromXML(\SimpleXMLElement $xml) |
|
344 | } |
||
345 |
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.