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 MethodBodyBuilder 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 MethodBodyBuilder, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
17 | class MethodBodyBuilder |
||
18 | { |
||
19 | /** |
||
20 | * @var Body |
||
21 | */ |
||
22 | private $methodBody; |
||
23 | |||
24 | /** |
||
25 | * @var string |
||
26 | */ |
||
27 | private $baseUrl; |
||
28 | |||
29 | /** |
||
30 | * Request method |
||
31 | * |
||
32 | * @var string |
||
33 | */ |
||
34 | private $requestMethod; |
||
35 | |||
36 | /** |
||
37 | * Request uri |
||
38 | * |
||
39 | * @var string |
||
40 | */ |
||
41 | private $uri; |
||
42 | |||
43 | /** |
||
44 | * Array of query parameters |
||
45 | * |
||
46 | * @var array |
||
47 | */ |
||
48 | private $queries = []; |
||
49 | |||
50 | /** |
||
51 | * Variable name of query map argument |
||
52 | * |
||
53 | * @var string |
||
54 | */ |
||
55 | private $queryMap; |
||
56 | |||
57 | /** |
||
58 | * Request headers |
||
59 | * |
||
60 | * @var array |
||
61 | */ |
||
62 | private $headers = []; |
||
63 | |||
64 | /** |
||
65 | * A string of php code to describe how to create the body |
||
66 | * |
||
67 | * @var string |
||
68 | */ |
||
69 | private $body; |
||
70 | |||
71 | /** |
||
72 | * An array of body parts |
||
73 | * |
||
74 | * @var array |
||
75 | */ |
||
76 | private $bodyParts = []; |
||
77 | |||
78 | /** |
||
79 | * True if the body is an object |
||
80 | * |
||
81 | * @var bool |
||
82 | */ |
||
83 | private $bodyIsObject = false; |
||
84 | |||
85 | /** |
||
86 | * True if the body is an optional paramter |
||
87 | * |
||
88 | * @var bool |
||
89 | */ |
||
90 | private $bodyIsOptional = false; |
||
91 | |||
92 | /** |
||
93 | * The default body value |
||
94 | * |
||
95 | * @var mixed |
||
96 | */ |
||
97 | private $bodyDefaultValue; |
||
98 | |||
99 | /** |
||
100 | * True if the body implements \JsonSerializable |
||
101 | * |
||
102 | * @var boolean |
||
103 | */ |
||
104 | private $bodyIsJsonSerializable; |
||
105 | |||
106 | /** |
||
107 | * True if the body is an array |
||
108 | * |
||
109 | * @var bool |
||
110 | */ |
||
111 | private $bodyIsArray = false; |
||
112 | |||
113 | /** |
||
114 | * If we should json encode the body |
||
115 | * |
||
116 | * @var bool |
||
117 | */ |
||
118 | private $jsonEncode = false; |
||
119 | |||
120 | /** |
||
121 | * If the body should be sent form urlencoded |
||
122 | * |
||
123 | * @var bool |
||
124 | */ |
||
125 | private $formUrlEncoded = false; |
||
126 | |||
127 | /** |
||
128 | * If the body should be sent as multipart |
||
129 | * |
||
130 | * @var bool |
||
131 | */ |
||
132 | private $multipartEncoded = false; |
||
133 | |||
134 | /** |
||
135 | * Method return type |
||
136 | * |
||
137 | * @var string |
||
138 | */ |
||
139 | private $returnType = 'array'; |
||
140 | |||
141 | /** |
||
142 | * JMS Serializer serialization context |
||
143 | * |
||
144 | * @var array |
||
145 | */ |
||
146 | private $serializationContext = []; |
||
147 | |||
148 | /** |
||
149 | * JMS Serializer deserialization attributes |
||
150 | * |
||
151 | * @var array |
||
152 | */ |
||
153 | private $deserializationContext = []; |
||
154 | |||
155 | /** |
||
156 | * Request callback variable name |
||
157 | * |
||
158 | * @var string |
||
159 | */ |
||
160 | private $callback; |
||
161 | |||
162 | /** |
||
163 | * Async callback is optional |
||
164 | * |
||
165 | * @var bool |
||
166 | */ |
||
167 | private $callbackOptional = false; |
||
168 | |||
169 | /** |
||
170 | * Boundary Id for multipart requests |
||
171 | * |
||
172 | * @var string |
||
173 | */ |
||
174 | private $boundaryId; |
||
175 | |||
176 | /** |
||
177 | * Constructor |
||
178 | */ |
||
179 | public function __construct() |
||
183 | |||
184 | /** |
||
185 | * @param string $baseUrl |
||
186 | */ |
||
187 | public function setBaseUrl($baseUrl) |
||
191 | |||
192 | /** |
||
193 | * @param string $requestMethod |
||
194 | */ |
||
195 | public function setRequestMethod($requestMethod) |
||
199 | |||
200 | /** |
||
201 | * @param string $uri |
||
202 | */ |
||
203 | public function setUri($uri) |
||
207 | |||
208 | /** |
||
209 | * @param array $queries |
||
210 | */ |
||
211 | public function setQueries(array $queries) |
||
215 | |||
216 | /** |
||
217 | * @param string $queryMap |
||
218 | */ |
||
219 | public function setQueryMap($queryMap) |
||
223 | |||
224 | /** |
||
225 | * @param array $headers |
||
226 | */ |
||
227 | public function setHeaders(array $headers) |
||
231 | |||
232 | /** |
||
233 | * @param string $body |
||
234 | */ |
||
235 | public function setBody($body) |
||
239 | |||
240 | /** |
||
241 | * @param array $bodyParts |
||
242 | */ |
||
243 | public function setBodyParts(array $bodyParts) |
||
247 | |||
248 | /** |
||
249 | * @param boolean $bodyIsObject |
||
250 | */ |
||
251 | public function setBodyIsObject($bodyIsObject) |
||
255 | |||
256 | /** |
||
257 | * @param boolean $bodyIsOptional |
||
258 | */ |
||
259 | public function setBodyIsOptional($bodyIsOptional) |
||
263 | |||
264 | /** |
||
265 | * @param mixed $bodyDefaultValue |
||
266 | */ |
||
267 | public function setBodyDefaultValue($bodyDefaultValue) |
||
271 | |||
272 | /** |
||
273 | * @param boolean $bodyIsJsonSerializable |
||
274 | */ |
||
275 | public function setBodyIsJsonSerializable($bodyIsJsonSerializable) |
||
279 | |||
280 | /** |
||
281 | * @param boolean $bodyIsArray |
||
282 | */ |
||
283 | public function setBodyIsArray($bodyIsArray) |
||
287 | |||
288 | /** |
||
289 | * @param boolean $jsonEncode |
||
290 | */ |
||
291 | public function setJsonEncode($jsonEncode) |
||
295 | |||
296 | /** |
||
297 | * @param boolean $formUrlEncoded |
||
298 | */ |
||
299 | public function setFormUrlEncoded($formUrlEncoded) |
||
303 | |||
304 | /** |
||
305 | * @param boolean $multipartEncoded |
||
306 | */ |
||
307 | public function setMultipartEncoded($multipartEncoded) |
||
311 | |||
312 | /** |
||
313 | * @param string $boundaryId |
||
314 | */ |
||
315 | public function setBoundaryId($boundaryId) |
||
319 | |||
320 | /** |
||
321 | * @param string $returnType |
||
322 | */ |
||
323 | public function setReturnType($returnType) |
||
327 | |||
328 | /** |
||
329 | * @param array $serializationContext |
||
330 | */ |
||
331 | public function setSerializationContext(array $serializationContext) |
||
335 | |||
336 | /** |
||
337 | * @param array $deserializationContext |
||
338 | */ |
||
339 | public function setDeserializationContext(array $deserializationContext) |
||
343 | |||
344 | /** |
||
345 | * @param string $callback |
||
346 | */ |
||
347 | public function setCallback($callback) |
||
351 | |||
352 | /** |
||
353 | * @param boolean $callbackOptional |
||
354 | */ |
||
355 | public function setCallbackOptional($callbackOptional) |
||
359 | |||
360 | /** |
||
361 | * Build the method body |
||
362 | * |
||
363 | * @return string |
||
364 | */ |
||
365 | public function build() |
||
377 | |||
378 | /** |
||
379 | * Build the request url |
||
380 | */ |
||
381 | private function createRequestUrl() |
||
411 | |||
412 | /** |
||
413 | * Build the headers |
||
414 | */ |
||
415 | private function createHeaders() |
||
425 | |||
426 | /** |
||
427 | * Build the request body |
||
428 | */ |
||
429 | private function createBody() |
||
449 | |||
450 | /** |
||
451 | * Logic to actually create body |
||
452 | */ |
||
453 | private function doCreateBody() |
||
493 | |||
494 | /** |
||
495 | * Create json body |
||
496 | */ |
||
497 | View Code Duplication | private function createBodyJson() |
|
524 | |||
525 | /** |
||
526 | * Normalize body as array |
||
527 | */ |
||
528 | View Code Duplication | private function createBodyArray() |
|
555 | |||
556 | /** |
||
557 | * Helper method to serialize an object |
||
558 | * |
||
559 | * @param string $contextVar |
||
560 | * @param string $bodyVar |
||
561 | * @param string $object |
||
562 | */ |
||
563 | private function serializeObject($contextVar, $bodyVar, $object) |
||
572 | |||
573 | /** |
||
574 | * Build the response |
||
575 | */ |
||
576 | private function createResponse() |
||
606 | |||
607 | /** |
||
608 | * Build the return |
||
609 | */ |
||
610 | private function createReturns() |
||
652 | |||
653 | /** |
||
654 | * Build the serialization context |
||
655 | * |
||
656 | * @param $contextVar |
||
657 | * @param $context |
||
658 | */ |
||
659 | private function createContext($contextVar, &$context) |
||
683 | |||
684 | /** |
||
685 | * Create a string representation of an array |
||
686 | * |
||
687 | * @param array $array |
||
688 | * @return string |
||
689 | */ |
||
690 | private function arrayToString(array $array) |
||
697 | } |
||
698 |
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.