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 Request 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 Request, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
9 | class Request |
||
10 | { |
||
11 | /** |
||
12 | * @var string $requestUri Request URI from $_SERVER. |
||
13 | * @var string $scriptName Scriptname from $_SERVER, actual scriptname part. |
||
14 | * @var string $path Scriptname from $_SERVER, path-part. |
||
15 | */ |
||
16 | private $requestUri; |
||
17 | private $scriptName; |
||
18 | private $path; |
||
19 | |||
20 | |||
21 | |||
22 | /** |
||
23 | * @var string $route The route. |
||
24 | * @var array $routeParts The route as an array. |
||
25 | */ |
||
26 | private $route; |
||
27 | private $routeParts; |
||
28 | |||
29 | |||
30 | |||
31 | /** |
||
32 | * @var string $currentUrl Current url. |
||
33 | * @var string $siteUrl Url to this site, http://dbwebb.se. |
||
34 | * @var string $baseUrl Url to root dir, |
||
35 | * siteUrl . /some/installation/directory/. |
||
36 | */ |
||
37 | private $currentUrl; |
||
38 | private $siteUrl; |
||
39 | private $baseUrl; |
||
40 | |||
41 | |||
42 | |||
43 | /** |
||
44 | * @var string $server Mapped to $_SERVER. |
||
45 | * @var string $get Mapped to $_GET. |
||
46 | * @var string $post Mapped to $_POST. |
||
47 | * @var string $body Mapped to request body, defaults to php://input. |
||
48 | */ |
||
49 | private $server; |
||
50 | private $get; |
||
51 | private $post; |
||
52 | private $body; |
||
53 | |||
54 | |||
55 | |||
56 | /** |
||
57 | * Constructor. |
||
58 | */ |
||
59 | 27 | public function __construct() |
|
63 | |||
64 | |||
65 | |||
66 | /** |
||
67 | * Read info from the globals. |
||
68 | * |
||
69 | * @param array $globals use to initiate globals with values. |
||
70 | * |
||
71 | * @return void |
||
72 | */ |
||
73 | 27 | public function setGlobals($globals = []) |
|
87 | |||
88 | |||
89 | |||
90 | /** |
||
91 | * Init the request class by reading information from the request. |
||
92 | * |
||
93 | * @return $this |
||
94 | */ |
||
95 | 10 | public function init() |
|
116 | |||
117 | |||
118 | |||
119 | /** |
||
120 | * Get site url including scheme, host and port. |
||
121 | * |
||
122 | * @return string |
||
123 | */ |
||
124 | 4 | public function getSiteUrl() |
|
128 | |||
129 | |||
130 | |||
131 | /** |
||
132 | * Get base url including site url and path to current index.php. |
||
133 | * |
||
134 | * @return string |
||
135 | */ |
||
136 | 4 | public function getBaseUrl() |
|
140 | |||
141 | |||
142 | |||
143 | /** |
||
144 | * Get script name, index.php or other. |
||
145 | * |
||
146 | * @return string |
||
147 | */ |
||
148 | public function getScriptName() |
||
152 | |||
153 | |||
154 | |||
155 | /** |
||
156 | * Get route path parts in an array. |
||
157 | * |
||
158 | * @return array with route in its parts |
||
159 | */ |
||
160 | public function getRouteParts() |
||
164 | |||
165 | |||
166 | |||
167 | /** |
||
168 | * Get route path as a string. |
||
169 | * |
||
170 | * @return string as the current extracted route |
||
171 | */ |
||
172 | 6 | public function getRoute() |
|
176 | |||
177 | |||
178 | |||
179 | /** |
||
180 | * Get the request method. |
||
181 | * |
||
182 | * @return string as the request method |
||
183 | */ |
||
184 | 5 | public function getMethod() |
|
188 | |||
189 | |||
190 | |||
191 | /** |
||
192 | * Extract the part containing the route. |
||
193 | * |
||
194 | * @todo Should be private, or useful in test? |
||
195 | * |
||
196 | * @return string as the current extracted route |
||
197 | */ |
||
198 | 10 | public function extractRoute() |
|
238 | |||
239 | |||
240 | |||
241 | /** |
||
242 | * Get the current url. |
||
243 | * |
||
244 | * @param boolean $queryString attach query string, default is true. |
||
245 | * |
||
246 | * @return string as current url. |
||
247 | */ |
||
248 | 25 | public function getCurrentUrl($queryString = true) |
|
277 | |||
278 | |||
279 | |||
280 | /** |
||
281 | * Get a value from the _SERVER array and use default if it is not set. |
||
282 | * |
||
283 | * @param string $key to check if it exists in the $_SERVER variable |
||
284 | * @param string $default value to return as default |
||
285 | * |
||
286 | * @return mixed |
||
287 | */ |
||
288 | 26 | public function getServer($key, $default = null) |
|
292 | |||
293 | |||
294 | |||
295 | /** |
||
296 | * Set variable in the server array. |
||
297 | * |
||
298 | * @param mixed $key the key an the , or an key-value array |
||
299 | * @param string $value the value of the key |
||
300 | * |
||
301 | * @return self |
||
302 | */ |
||
303 | 19 | View Code Duplication | public function setServer($key, $value = null) |
312 | |||
313 | |||
314 | |||
315 | /** |
||
316 | * Check if the value from the _GET array exists. |
||
317 | * |
||
318 | * @param string $key to check if it exists in the $_GET variable |
||
319 | * |
||
320 | * @return boolean |
||
321 | */ |
||
322 | public function hasGet($key) |
||
326 | |||
327 | |||
328 | |||
329 | /** |
||
330 | * Get a value from the _GET array and use default if it is not set. |
||
331 | * |
||
332 | * @param string $key to check if it exists in the $_GET variable |
||
333 | * @param string $default value to return as default |
||
334 | * |
||
335 | * @return mixed |
||
336 | */ |
||
337 | 1 | public function getGet($key, $default = null) |
|
341 | |||
342 | |||
343 | |||
344 | /** |
||
345 | * Set variable in the get array. |
||
346 | * |
||
347 | * @param mixed $key the key an the , or an key-value array |
||
348 | * @param string $value the value of the key |
||
349 | * |
||
350 | * @return self |
||
351 | */ |
||
352 | 1 | View Code Duplication | public function setGet($key, $value = null) |
361 | |||
362 | |||
363 | |||
364 | /** |
||
365 | * Get a value from the _POST array and use default if it is not set. |
||
366 | * |
||
367 | * @param string $key to check if it exists in the $_POST variable |
||
368 | * @param string $default value to return as default |
||
369 | * |
||
370 | * @return mixed |
||
371 | */ |
||
372 | public function getPost($key = null, $default = null) |
||
380 | |||
381 | |||
382 | |||
383 | /** |
||
384 | * Set the request body (useful for unit testing). |
||
385 | * |
||
386 | * @return self |
||
387 | */ |
||
388 | public function setBody($body) |
||
392 | |||
393 | |||
394 | |||
395 | /** |
||
396 | * Get the request body. |
||
397 | * |
||
398 | * @return mixed |
||
399 | */ |
||
400 | public function getBody() |
||
406 | |||
407 | |||
408 | |||
409 | /** |
||
410 | * Get the request body from the HTTP request and treat it as |
||
411 | * JSON data. |
||
412 | * |
||
413 | * @throws Anax\Request\Exception when request body is invalid JSON. |
||
414 | * |
||
415 | * @return mixed as the JSON converted content. |
||
416 | */ |
||
417 | public function getBodyAsJson() |
||
425 | } |
||
426 |
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.