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 DeCaptchaAbstract 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 DeCaptchaAbstract, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
10 | abstract class DeCaptchaAbstract implements DeCaptchaInterface |
||
11 | { |
||
12 | const RESPONSE_TYPE_STRING = 1; |
||
13 | const RESPONSE_TYPE_JSON = 2; |
||
14 | |||
15 | const ACTION_FIELDS = 1; |
||
16 | const ACTION_URI = 2; |
||
17 | const ACTION_METHOD = 3; |
||
18 | const ACTION_JSON = 4; |
||
19 | |||
20 | const ACTION_METHOD_POST = 1; |
||
21 | const ACTION_METHOD_GET = 2; |
||
22 | |||
23 | const DECODE_FORMAT = 1; |
||
24 | const DECODE_ACTION = 2; |
||
25 | const DECODE_SEPARATOR = 3; |
||
26 | const DECODE_PARAMS = 4; |
||
27 | const DECODE_PARAM_SETTING_MARKER = 5; |
||
28 | |||
29 | const PARAM_FIELD_TYPE_STRING = 1; |
||
30 | const PARAM_FIELD_TYPE_INTEGER = 2; |
||
31 | const PARAM_FIELD_TYPE_MIX = 3; |
||
32 | const PARAM_FIELD_TYPE_OBJECT = 4; |
||
33 | const PARAM_FIELD_TYPE_BOOLEAN = 5; |
||
34 | const PARAM_FIELD_TYPE_FLOAT = 6; |
||
35 | |||
36 | const PARAM_SLUG_DEFAULT = 1; |
||
37 | const PARAM_SLUG_TYPE = 2; |
||
38 | const PARAM_SLUG_REQUIRE = 3; |
||
39 | const PARAM_SLUG_SPEC = 4; |
||
40 | const PARAM_SLUG_VARIABLE = 5; |
||
41 | const PARAM_SLUG_CODING = 6; |
||
42 | const PARAM_SLUG_NOTWIKI = 7; |
||
43 | const PARAM_SLUG_ENUM = 8; |
||
44 | const PARAM_SLUG_WIKI = 9; |
||
45 | |||
46 | const PARAM_SLUG_CODING_BASE64 = 1; |
||
47 | |||
48 | const PARAM_SPEC_API_KEY = -1; |
||
49 | const PARAM_SPEC_FILE = -2; |
||
50 | const PARAM_SPEC_CAPTCHA = -3; |
||
51 | const PARAM_SPEC_CODE = -4; |
||
52 | |||
53 | /** |
||
54 | * Сервис на который будем загружать капчу. |
||
55 | * |
||
56 | * @var string |
||
57 | */ |
||
58 | protected $host; |
||
59 | protected $scheme = 'http'; |
||
60 | protected $errorLang = DeCaptchaErrors::LANG_EN; |
||
61 | protected $lastRunTime = null; |
||
62 | /** @var DeCaptchaErrors */ |
||
63 | protected $errorObject; |
||
64 | protected $causeAnError = false; |
||
65 | |||
66 | protected $limit = []; |
||
67 | protected $paramsSpec = []; |
||
68 | protected $params = []; |
||
69 | protected $limitSettings = []; |
||
70 | protected $decodeSettings = []; |
||
71 | protected $actions = []; |
||
72 | protected $paramsNames = []; |
||
73 | |||
74 | protected function resetLimits() |
||
80 | |||
81 | /** |
||
82 | * @param $action |
||
83 | * |
||
84 | * @return bool |
||
85 | */ |
||
86 | protected function limitHasNotYetEnded($action) |
||
90 | |||
91 | /** |
||
92 | 3 | * @param $action |
|
93 | * @param $data |
||
94 | 3 | * |
|
95 | 1 | * @throws DeCaptchaErrors |
|
96 | 1 | * |
|
97 | 3 | * @return array |
|
98 | */ |
||
99 | 3 | protected function decodeResponse($action, $data) |
|
139 | |||
140 | /** |
||
141 | * @param $errorLang |
||
142 | */ |
||
143 | public function setErrorLang($errorLang) |
||
147 | |||
148 | /** |
||
149 | * Узнаём путь до файла |
||
150 | * Если передана ссылка, то скачиваем и кладём во временную директорию. |
||
151 | * |
||
152 | 1 | * @param string $fileName |
|
153 | 1 | * |
|
154 | * @throws Exception |
||
155 | * |
||
156 | * @return string |
||
157 | */ |
||
158 | protected function getFilePath($fileName) |
||
177 | |||
178 | /** |
||
179 | * @param $action |
||
180 | * |
||
181 | * @return string |
||
182 | */ |
||
183 | protected function getActionUrl($action) |
||
187 | 1 | ||
188 | 1 | /** |
|
189 | 1 | * @return string |
|
190 | 1 | */ |
|
191 | 1 | protected function getBaseUrl() |
|
195 | |||
196 | /** |
||
197 | * @param $params |
||
198 | */ |
||
199 | public function setParams($params) |
||
207 | |||
208 | /** |
||
209 | * @param $param |
||
210 | * @param $value |
||
211 | */ |
||
212 | public function setParam($param, $value) |
||
216 | |||
217 | /** |
||
218 | * @param $param |
||
219 | * @param $spec |
||
220 | * @param $coding |
||
221 | * |
||
222 | * @return \CURLFile|mixed|null|string |
||
223 | */ |
||
224 | public function getParamSpec($param, $spec = null, $coding = null) |
||
253 | |||
254 | /** |
||
255 | * @param $action |
||
256 | * @param $field |
||
257 | * |
||
258 | * @throws DeCaptchaErrors |
||
259 | * |
||
260 | * @return array |
||
261 | */ |
||
262 | protected function getParams($action, $field = null) |
||
316 | |||
317 | /** |
||
318 | * @param string $action |
||
319 | * |
||
320 | * @return string |
||
321 | */ |
||
322 | protected function getResponse($action) |
||
331 | |||
332 | /** |
||
333 | * Задержка выполнения. |
||
334 | * |
||
335 | * @param int $delay Количество секунд |
||
336 | * @param \Closure|null $callback |
||
337 | * |
||
338 | * @return mixed |
||
339 | */ |
||
340 | protected function executionDelayed($delay = 0, $callback = null) |
||
351 | |||
352 | /** |
||
353 | * @param string $url |
||
354 | * @param array $data |
||
355 | * @param bool $isPost |
||
356 | * @param bool $isJson |
||
357 | * |
||
358 | * @throws DeCaptchaErrors |
||
359 | * |
||
360 | * @return string |
||
361 | */ |
||
362 | protected function curlResponse($url, $data, $isPost = true, $isJson = false) |
||
401 | |||
402 | abstract public function getCode(); |
||
403 | |||
404 | abstract public function getError(); |
||
405 | } |
||
406 |
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.