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 |
||
19 | class Request implements LoggerAwareInterface |
||
20 | { |
||
21 | const URI = 'https://secure.gaug.es/'; |
||
22 | |||
23 | /** @var null|ClientInterface */ |
||
24 | private $client; |
||
25 | |||
26 | /** @var HandlerStack */ |
||
27 | private $handlerStack; |
||
28 | |||
29 | /** @var null|LoggerInterface */ |
||
30 | private $logger; |
||
31 | |||
32 | /** @var string */ |
||
33 | private $logLevel; |
||
34 | |||
35 | /** @var MessageFormatter */ |
||
36 | private $messageFormatter; |
||
37 | |||
38 | /** @var array */ |
||
39 | private $options; |
||
40 | |||
41 | /** @var string */ |
||
42 | protected $token; |
||
43 | |||
44 | /** |
||
45 | * Constructor |
||
46 | * |
||
47 | * @param string $token Your API token |
||
48 | * @param array $options See Guzzle documentation (proxy, etc.) |
||
49 | */ |
||
50 | 26 | public function __construct(string $token, array $options = array()) |
|
64 | |||
65 | /** |
||
66 | * Getter for the HTTP client. |
||
67 | * |
||
68 | * @return Client |
||
69 | */ |
||
70 | 23 | protected function getHttpClient() : Client |
|
89 | |||
90 | /** |
||
91 | * Setter for the Guzzle HandlerStack |
||
92 | */ |
||
93 | 25 | public function setHandlerStack(HandlerStack $handlerStack) |
|
97 | |||
98 | 26 | public function setLogger(LoggerInterface $logger) |
|
102 | |||
103 | 25 | public function setLogLevel(string $logLevel) |
|
119 | |||
120 | /** |
||
121 | * Setter for the Guzzle MessageFormatter |
||
122 | */ |
||
123 | 26 | public function setMessageFormatter(MessageFormatter $messageFormatter) |
|
127 | |||
128 | /** |
||
129 | * Get Your Information |
||
130 | * |
||
131 | * Returns your information. |
||
132 | * |
||
133 | * @return Response |
||
134 | */ |
||
135 | 2 | public function me() : Response |
|
139 | |||
140 | /** |
||
141 | * Update Your Information |
||
142 | * |
||
143 | * Updates and returns your information with the updates applied. |
||
144 | * |
||
145 | * @param string $first_name Your first name. (Optional) |
||
146 | * @param string $last_name Your last name. (Optional) |
||
147 | * |
||
148 | * @return Response |
||
149 | */ |
||
150 | 1 | public function updateMe(string $first_name = null, string $last_name = null) : Response |
|
163 | |||
164 | /** |
||
165 | * API Client List |
||
166 | * |
||
167 | * Returns an array of your API clients. |
||
168 | * |
||
169 | * @return Response |
||
170 | */ |
||
171 | 1 | public function listClients() : Response |
|
175 | |||
176 | /** |
||
177 | * Creating an API Client |
||
178 | * |
||
179 | * Creates an API client, which can be used to authenticate against |
||
180 | * the Gaug.es API. |
||
181 | * |
||
182 | * @param string $description Short description for the key (Optional) |
||
183 | * |
||
184 | * @return Response |
||
185 | */ |
||
186 | 1 | View Code Duplication | public function createClient(string $description = null) : Response |
195 | |||
196 | /** |
||
197 | * Delete an API Client |
||
198 | * |
||
199 | * Permanently deletes an API client key. |
||
200 | * |
||
201 | * @param string $id |
||
202 | * |
||
203 | * @return Response |
||
204 | */ |
||
205 | 1 | public function deleteClient(string $id) : Response |
|
209 | |||
210 | /** |
||
211 | * Gauges List |
||
212 | * |
||
213 | * Returns an array of your gauges, with recent traffic included. |
||
214 | * |
||
215 | * @param int $page Page number (Optional) |
||
216 | * |
||
217 | * @return Response |
||
218 | */ |
||
219 | 1 | View Code Duplication | public function listGauges(int $page = null) : Response |
228 | |||
229 | /** |
||
230 | * Create a New Gauge |
||
231 | * |
||
232 | * Creates a gauge. |
||
233 | * |
||
234 | * @param string $title |
||
235 | * @param string|\DateTimeZone $tz |
||
236 | * @param string $allowedHosts (Optional) |
||
237 | * |
||
238 | * @return Response |
||
239 | */ |
||
240 | 1 | View Code Duplication | public function createGauge(string $title, $tz, string $allowedHosts = null) : Response |
256 | |||
257 | /** |
||
258 | * Gauge Detail |
||
259 | * |
||
260 | * Gets details for a gauge. |
||
261 | * |
||
262 | * @param string $id |
||
263 | * |
||
264 | * @return Response |
||
265 | */ |
||
266 | 1 | public function gaugeDetail(string $id) : Response |
|
270 | |||
271 | /** |
||
272 | * Update a Gauge |
||
273 | * |
||
274 | * Updates and returns a gauge with the updates applied. |
||
275 | * |
||
276 | * @param string $id |
||
277 | * @param string $title |
||
278 | * @param string|\DateTimeZone $tz |
||
279 | * @param string $allowedHosts (Optional) |
||
280 | * |
||
281 | * @return Response |
||
282 | */ |
||
283 | 1 | View Code Duplication | public function updateGauge(string $id, string $title, $tz, string $allowedHosts = null) : Response |
299 | |||
300 | /** |
||
301 | * Delete a Gauge |
||
302 | * |
||
303 | * Permanently deletes a gauge. |
||
304 | * |
||
305 | * @param string $id |
||
306 | * |
||
307 | * @return Response |
||
308 | */ |
||
309 | 1 | public function deleteGauge(string $id) : Response |
|
313 | |||
314 | /** |
||
315 | * List Shares |
||
316 | * |
||
317 | * Lists the people that have access to a Gauge. |
||
318 | * |
||
319 | * @param string $id |
||
320 | * |
||
321 | * @return Response |
||
322 | */ |
||
323 | 1 | public function listShares(string $id) : Response |
|
327 | |||
328 | /** |
||
329 | * Share a Gauge |
||
330 | * |
||
331 | * Shares gauge with a person by their email. Any valid email will work |
||
332 | * and will receive an invite even if there is no existing Gauges user |
||
333 | * with that email. |
||
334 | * |
||
335 | * @param string $id |
||
336 | * @param string $email |
||
337 | * |
||
338 | * @return Response |
||
339 | */ |
||
340 | 1 | public function shareGauge(string $id, string $email) : Response |
|
348 | |||
349 | /** |
||
350 | * Top Content |
||
351 | * |
||
352 | * Gets top content for a gauge, paginated. |
||
353 | * |
||
354 | * @param string $id |
||
355 | * @param string|\DateTime $date (Optional) Date in format YYYY-MM-DD |
||
356 | * @param string $group (Optional) Either "day" or "month". Default is "day". |
||
357 | * @param int $page (Optional) |
||
358 | * |
||
359 | * @return Response |
||
360 | */ |
||
361 | 2 | public function topContent(string $id, $date = null, string $group = null, int $page = null) : Response |
|
381 | |||
382 | /** |
||
383 | * Un-share Gauge |
||
384 | * |
||
385 | * @param string $id |
||
386 | * @param string $user_id |
||
387 | * |
||
388 | * @return Response |
||
389 | */ |
||
390 | 1 | public function unshareGauge(string $id, string $user_id) : Response |
|
394 | |||
395 | /** |
||
396 | * Top Referrers |
||
397 | * |
||
398 | * Gets top referrers for a gauge, paginated. |
||
399 | * |
||
400 | * @param string $id |
||
401 | * @param string|\DateTime $date (Optional) Date in format YYYY-MM-DD |
||
402 | * @param int $page (Optional) |
||
403 | * |
||
404 | * @return Response |
||
405 | */ |
||
406 | 1 | View Code Duplication | public function topReferrers(string $id, $date = null, int $page = null) : Response |
415 | |||
416 | /** |
||
417 | * Traffic |
||
418 | * |
||
419 | * Gets traffic for a gauge. |
||
420 | * |
||
421 | * @param string $id |
||
422 | * @param string|\DateTime $date (Optional) Date in format YYYY-MM-DD |
||
423 | * |
||
424 | * @return Response |
||
425 | */ |
||
426 | 1 | public function traffic(string $id, $date = null) : Response |
|
430 | |||
431 | /** |
||
432 | * Browser Resolutions |
||
433 | * |
||
434 | * Gets browsers heights, browser widths, and screen widths for a gauge. |
||
435 | * |
||
436 | * @param string $id |
||
437 | * @param string|\DateTime $date (Optional) Date in format YYYY-MM-DD |
||
438 | * |
||
439 | * @return Response |
||
440 | */ |
||
441 | 1 | public function browserResolutions(string $id, $date = null) : Response |
|
445 | |||
446 | /** |
||
447 | * Technology |
||
448 | * |
||
449 | * Gets browsers and platforms for a gauge. |
||
450 | * |
||
451 | * @param string $id |
||
452 | * @param string|\DateTime $date (Optional) Date in format YYYY-MM-DD |
||
453 | * |
||
454 | * @return Response |
||
455 | */ |
||
456 | 1 | public function technology(string $id, $date = null) : Response |
|
460 | |||
461 | /** |
||
462 | * Search Terms |
||
463 | * |
||
464 | * Gets search terms for a gauge, paginated. |
||
465 | * |
||
466 | * @param string $id |
||
467 | * @param string|\DateTime $date (Optional) Date in format YYYY-MM-DD |
||
468 | * @param int $page (Optional) |
||
469 | * |
||
470 | * @return Response |
||
471 | */ |
||
472 | 1 | View Code Duplication | public function searchTerms(string $id, $date = null, int $page = null) : Response |
482 | |||
483 | /** |
||
484 | * Search Engines |
||
485 | * |
||
486 | * Gets search engines for a gauge. |
||
487 | * |
||
488 | * @param string $id |
||
489 | * @param string|\DateTime $date (Optional) Date in format YYYY-MM-DD |
||
490 | * |
||
491 | * @return Response |
||
492 | */ |
||
493 | 1 | public function searchEngines(string $id, $date = null) : Response |
|
497 | |||
498 | /** |
||
499 | * Locations |
||
500 | * |
||
501 | * Gets locations for a gauge. |
||
502 | * |
||
503 | * @param string $id |
||
504 | * @param string|\DateTime $date (Optional) Date in format YYYY-MM-DD |
||
505 | * |
||
506 | * @return Response |
||
507 | */ |
||
508 | 1 | public function locations(string $id, $date = null) : Response |
|
512 | |||
513 | /** |
||
514 | * Browser stats |
||
515 | * |
||
516 | * Get the browser statistics in a format used with the browserlist module. |
||
517 | * (See https://github.com/ai/browserslist) |
||
518 | * |
||
519 | * @param string $id |
||
520 | * @param string|\DateTime $date (Optional) Date in format YYYY-MM-DD |
||
521 | * |
||
522 | * @return Response |
||
523 | */ |
||
524 | 1 | public function browserStats(string $id, $date = null) : Response |
|
528 | |||
529 | /** |
||
530 | * Make the actual gauges API call. |
||
531 | * |
||
532 | * @param string $method [GET|POST|PUT|DELETE] |
||
533 | * @param string $path |
||
534 | * @param array $params |
||
535 | * |
||
536 | * @return Response |
||
537 | */ |
||
538 | 23 | protected function makeApiCall(string $method, string $path, array $params = array()) : Response |
|
553 | |||
554 | 10 | private function formatDateParameter($date = null) : array |
|
567 | } |
||
568 |
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.