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 Update 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 Update, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
10 | class Update |
||
11 | { |
||
12 | |||
13 | private $arr_files; |
||
14 | |||
15 | private $files_dates = []; |
||
16 | |||
17 | private $restore_files = []; |
||
18 | |||
19 | /** |
||
20 | * update server |
||
21 | * @var string |
||
22 | */ |
||
23 | private $US = 'http://upd.imagecms.net/'; |
||
24 | |||
25 | /** |
||
26 | * path to update server |
||
27 | * @var string |
||
28 | */ |
||
29 | private $pathUS; |
||
30 | |||
31 | /** |
||
32 | * папки, які не враховувати при обновлені |
||
33 | * @var array |
||
34 | */ |
||
35 | private $distinctDirs = [ |
||
36 | '.', |
||
37 | '..', |
||
38 | '.git', |
||
39 | 'uploads', |
||
40 | 'cache', |
||
41 | 'templates', |
||
42 | 'tests', |
||
43 | 'captcha', |
||
44 | 'nbproject', |
||
45 | 'uploads_site', |
||
46 | 'backups', |
||
47 | 'cmlTemp', |
||
48 | ]; |
||
49 | |||
50 | /** |
||
51 | * файли, які не враховувати при обновлені |
||
52 | * @var array |
||
53 | */ |
||
54 | private $distinctFiles = [ |
||
55 | 'md5.txt', |
||
56 | '.htaccess', |
||
57 | 'config.php' |
||
58 | ]; |
||
59 | |||
60 | /** |
||
61 | * instance of ci |
||
62 | * @var MY_Controller |
||
63 | */ |
||
64 | public $ci; |
||
65 | |||
66 | /** |
||
67 | * SoapClient |
||
68 | * @var SoapClient |
||
69 | */ |
||
70 | public $client; |
||
71 | |||
72 | /** |
||
73 | * |
||
74 | * @var array |
||
75 | */ |
||
76 | public $settings; |
||
77 | |||
78 | public function __construct() { |
||
85 | |||
86 | /** |
||
87 | * check new Version |
||
88 | * @return mixed |
||
89 | * @throws Exception |
||
90 | */ |
||
91 | public function getStatus() { |
||
105 | |||
106 | /** |
||
107 | * getting hash from setting |
||
108 | * @return array |
||
109 | * @throws Exception |
||
110 | */ |
||
111 | public function getHashSum() { |
||
130 | |||
131 | public function getUpdate() { |
||
144 | |||
145 | /** |
||
146 | * |
||
147 | * @param string $file |
||
148 | * @return string |
||
149 | */ |
||
150 | public function getOldMD5File($file = 'md5.txt') { |
||
154 | |||
155 | /** |
||
156 | * zipping files |
||
157 | * @param array $files |
||
158 | * @return bool |
||
159 | * @throws Exception |
||
160 | */ |
||
161 | public function add_to_ZIP($files = []) { |
||
190 | |||
191 | /** |
||
192 | * @throws Exception |
||
193 | */ |
||
194 | public function createBackUp() { |
||
218 | |||
219 | /** |
||
220 | * restore file to zip |
||
221 | * @param string $file |
||
222 | * @param mixed|string $destination |
||
223 | * @return bool |
||
224 | * @throws Exception |
||
225 | */ |
||
226 | public function restoreFromZIP($file, $destination = FCPATH) { |
||
247 | |||
248 | /** |
||
249 | * Бере контрольні суми файлів текущих файлів і файлів старої теперішньої версії |
||
250 | * Записує іх у відповідні файли з настройок, як серіалізований масив ключ - шлях до файлу, значення - контрольна сума |
||
251 | * запускати два рази переоприділивши $this->path_parse |
||
252 | * $this->path_parse = realpath('') текущі. |
||
253 | * $this->path_parse = rtrim($this->dir_old_upd, '\') |
||
254 | * @param null|string $directory |
||
255 | * @return array |
||
256 | */ |
||
257 | public function parse_md5($directory = null) { |
||
278 | |||
279 | /** |
||
280 | * database backup |
||
281 | * @return string |
||
282 | */ |
||
283 | public function db_backup() { |
||
293 | |||
294 | /** |
||
295 | * database restore |
||
296 | * @param string $file |
||
297 | * @return boolean |
||
298 | */ |
||
299 | public function db_restore($file) { |
||
311 | |||
312 | /** |
||
313 | * Create restore files list |
||
314 | * @return boolean|array |
||
315 | */ |
||
316 | public function restore_files_list() { |
||
343 | |||
344 | /** |
||
345 | * remove dir recursive |
||
346 | * @param string $dir - path to directory |
||
347 | */ |
||
348 | public function removeDirRec($dir) { |
||
359 | |||
360 | /** |
||
361 | * db update |
||
362 | * @param string $file_name |
||
363 | * @return boolean |
||
364 | */ |
||
365 | public function db_update($file_name = 'sql_19-08-2013_17.16.14.txt') { |
||
374 | |||
375 | /** |
||
376 | * ganerate sql query from file |
||
377 | * @param string $file |
||
378 | * @return boolean |
||
379 | */ |
||
380 | public function query_from_file($file) { |
||
395 | |||
396 | public function get_files_dates() { |
||
404 | |||
405 | /** |
||
406 | * @param bool|string $param |
||
407 | * @return string |
||
408 | */ |
||
409 | public function getSettings($param = false) { |
||
422 | |||
423 | /** |
||
424 | * |
||
425 | * @param array $settings |
||
426 | * @return bool |
||
427 | */ |
||
428 | public function setSettings($settings) { |
||
443 | |||
444 | } |
Let’s assume that you have a directory layout like this:
and let’s assume the following content of
Bar.php
:If both files
OtherDir/Foo.php
andSomeDir/Foo.php
are loaded in the same runtime, you will see a PHP error such as the following:PHP Fatal error: Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php
However, as
OtherDir/Foo.php
does not necessarily have to be loaded and the error is only triggered if it is loaded beforeOtherDir/Bar.php
, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias: