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 HttpApi 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 HttpApi, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
14 | class HttpApi extends AbstractApi |
||
15 | { |
||
16 | const AHGORA_BASE_URL = 'https://www.ahgora.com.br'; |
||
17 | const AHGORA_COMPANY_URL = '%s/externo/index/%s'; |
||
18 | const AHGORA_LOGIN_URL = '%s/externo/login'; |
||
19 | const AHGORA_PUNCHS_URL = '%s/externo/batidas/%s-%s'; |
||
20 | |||
21 | /** @var \Katapoka\Ahgora\Contracts\IHttpClient */ |
||
22 | private $httpClient; |
||
23 | /** @var string */ |
||
24 | private $password; |
||
25 | /** @var string */ |
||
26 | private $companyId; |
||
27 | /** @var string */ |
||
28 | private $username; |
||
29 | /** @var bool */ |
||
30 | private $loggedIn = false; |
||
31 | /** @var HtmlPageParser */ |
||
32 | private $htmlPageParser; |
||
33 | |||
34 | /** |
||
35 | * Api constructor. |
||
36 | * |
||
37 | * @param IHttpClient $httpClient |
||
38 | */ |
||
39 | 1 | public function __construct(IHttpClient $httpClient) |
|
45 | |||
46 | /** |
||
47 | * Set the company id of the ahgora system. |
||
48 | * |
||
49 | * @param string $companyId |
||
50 | * |
||
51 | * @return $this |
||
52 | */ |
||
53 | public function setCompanyId($companyId) |
||
60 | |||
61 | /** |
||
62 | * Set the username of the employee, from the company set at the setCompanyId. |
||
63 | * |
||
64 | * @param string $username |
||
65 | * |
||
66 | * @return $this |
||
67 | */ |
||
68 | public function setUsername($username) |
||
75 | |||
76 | /** |
||
77 | * Set the password of the employee, from the company set at the setCompanyId. |
||
78 | * |
||
79 | * @param string $password |
||
80 | * |
||
81 | * @return $this |
||
82 | */ |
||
83 | public function setPassword($password) |
||
90 | |||
91 | /** |
||
92 | * Try to execute the login on the page. |
||
93 | * To execute some actions the user needs to be loggedin. |
||
94 | * After a successful login, the status loggedin is saved as true. |
||
95 | * |
||
96 | * @return bool Returns true if the login was successful and false otherwise |
||
97 | */ |
||
98 | public function doLogin() |
||
116 | |||
117 | /** |
||
118 | * Get the punches at the given parameters. |
||
119 | * |
||
120 | * @param int|null $month The month you want to get the punches - Must be between 01 and 12 (both included) |
||
121 | * @param int|null $year The year you want to get the punches |
||
122 | * |
||
123 | * @return array |
||
124 | */ |
||
125 | public function getPunches($month = null, $year = null) |
||
139 | |||
140 | /** |
||
141 | * Get the punches from some given day. |
||
142 | * |
||
143 | * @param int $day |
||
144 | * @param int $month |
||
145 | * @param int $year |
||
146 | * |
||
147 | * @return mixed |
||
148 | */ |
||
149 | View Code Duplication | public function getPunchesFromDay($day, $month, $year) |
|
168 | |||
169 | /** |
||
170 | * Gets the employee name. |
||
171 | * |
||
172 | * @return string |
||
173 | */ |
||
174 | public function getEmployeeName() |
||
178 | |||
179 | /** |
||
180 | * Gets the employer name. |
||
181 | * |
||
182 | * @return string |
||
183 | */ |
||
184 | public function getEmployeeRole() |
||
188 | |||
189 | /** |
||
190 | * Get the employer department. |
||
191 | * |
||
192 | * @return string |
||
193 | */ |
||
194 | public function getDepartment() |
||
198 | |||
199 | /** |
||
200 | * Retrive all the punches for the given string. |
||
201 | * |
||
202 | * @param string $punchesStr |
||
203 | * |
||
204 | * @return array |
||
205 | */ |
||
206 | private function parsePunches($punchesStr) |
||
215 | |||
216 | /** |
||
217 | * Execute the login on the server and returns the server response. |
||
218 | * |
||
219 | * @return IHttpResponse |
||
220 | */ |
||
221 | private function executeLogin() |
||
229 | |||
230 | /** |
||
231 | * Check if the company has external access on the Ahgora system. |
||
232 | * |
||
233 | * @return bool |
||
234 | */ |
||
235 | private function checkAccessEnabled() |
||
241 | |||
242 | /** |
||
243 | * Check the return of the login action. |
||
244 | * How it works: If statusCode 200 and no body, login ok, otherwise, login failed. |
||
245 | * Should return a json with property "r" with "error" and "text" with the message |
||
246 | * |
||
247 | * @param IHttpResponse $response |
||
248 | * |
||
249 | * @return bool |
||
250 | */ |
||
251 | private function checkLoginStatus(IHttpResponse $response) |
||
261 | |||
262 | /** |
||
263 | * Check if the response can be decoded as json, has the property r and r is 'success'. |
||
264 | * |
||
265 | * @param IHttpResponse $response |
||
266 | * |
||
267 | * @return bool |
||
268 | */ |
||
269 | private function getResponseLoginStatus(IHttpResponse $response) |
||
281 | |||
282 | /** |
||
283 | * Safely set if the user is loggedin or not. |
||
284 | * Did a separate method do eventually trigger events, if necessary. |
||
285 | * |
||
286 | * @param bool $loggedIn |
||
287 | * |
||
288 | * @return $this |
||
289 | */ |
||
290 | private function setLoggedIn($loggedIn = true) |
||
301 | |||
302 | /** |
||
303 | * Build the company url string. |
||
304 | * |
||
305 | * @return string |
||
306 | */ |
||
307 | private function companyUrl() |
||
314 | |||
315 | /** |
||
316 | * Build the login url. |
||
317 | * |
||
318 | * @return string |
||
319 | */ |
||
320 | private function loginUrl() |
||
327 | |||
328 | /** |
||
329 | * Get the built punchesUrl with the given month and year. |
||
330 | * |
||
331 | * @param int $month |
||
332 | * @param int $year |
||
333 | * |
||
334 | * @return string |
||
335 | */ |
||
336 | private function punchesUrl($month, $year) |
||
348 | |||
349 | /** |
||
350 | * Make the request to the punches page of the requested time period. |
||
351 | * |
||
352 | * @param int $month |
||
353 | * @param int $year |
||
354 | * |
||
355 | * @return IHttpResponse |
||
356 | */ |
||
357 | private function getPunchesPage($month, $year) |
||
361 | |||
362 | /** |
||
363 | * Get the punches from the given response of the punches page. |
||
364 | * |
||
365 | * @param IHttpResponse $punchesPageResponse |
||
366 | * |
||
367 | * @return array |
||
368 | */ |
||
369 | private function getPunchesFromPage(IHttpResponse $punchesPageResponse) |
||
381 | |||
382 | private function parsePunchesPage(IHttpResponse $punchesPageResponse) |
||
394 | |||
395 | /** |
||
396 | * Convert the date string and the datepunch array to an array of DateTime's. |
||
397 | * |
||
398 | * @param string $date |
||
399 | * @param array $punches |
||
400 | * |
||
401 | * @return \DateTime[] |
||
402 | */ |
||
403 | private function createPunchesDate($date, array $punches = []) |
||
412 | } |
||
413 |
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.