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 DriverAbstract 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 DriverAbstract, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
28 | abstract class DriverAbstract implements ExtendedCacheItemPoolInterface |
||
29 | { |
||
30 | const DRIVER_CHECK_FAILURE = '%s is not installed or misconfigured, cannot continue.'; |
||
31 | const DRIVER_TAGS_KEY_PREFIX = '_TAG_'; |
||
32 | const DRIVER_DATA_WRAPPER_INDEX = 'd'; |
||
33 | const DRIVER_TIME_WRAPPER_INDEX = 't'; |
||
34 | const DRIVER_TAGS_WRAPPER_INDEX = 'g'; |
||
35 | |||
36 | /** |
||
37 | * @var array |
||
38 | */ |
||
39 | public $extension_dir = '_extensions'; |
||
40 | |||
41 | /** |
||
42 | * @var array |
||
43 | */ |
||
44 | public $tmp = []; |
||
45 | |||
46 | /** |
||
47 | * @var array default options, this will be merge to Driver's Options |
||
48 | */ |
||
49 | public $config = []; |
||
50 | |||
51 | /** |
||
52 | * @var bool |
||
53 | */ |
||
54 | public $fallback = false; |
||
55 | |||
56 | /** |
||
57 | * @var mixed Instance of driver service |
||
58 | */ |
||
59 | public $instance; |
||
60 | |||
61 | |||
62 | public function __destruct() |
||
69 | |||
70 | /** |
||
71 | * @param $keyword |
||
72 | * @return string |
||
73 | */ |
||
74 | protected function encodeFilename($keyword) |
||
75 | { |
||
76 | // return trim(trim(preg_replace('/[^a-zA-Z0-9]+/', '_', $keyword), '_')); |
||
|
|||
77 | // return rtrim(base64_encode($keyword), '='); |
||
78 | return md5($keyword); |
||
79 | } |
||
80 | |||
81 | /** |
||
82 | * @param $config_name |
||
83 | * @param string $value |
||
84 | */ |
||
85 | public function setup($config_name, $value = '') |
||
86 | { |
||
87 | /** |
||
88 | * Config for class |
||
89 | */ |
||
90 | if (is_array($config_name)) { |
||
91 | $this->config = array_merge($this->config, $config_name); |
||
92 | } else { |
||
93 | $this->config[ $config_name ] = $value; |
||
94 | } |
||
95 | } |
||
96 | |||
97 | |||
98 | /** |
||
99 | * @param $file |
||
100 | * @return string |
||
101 | * @throws \Exception |
||
102 | */ |
||
103 | protected function readfile($file) |
||
104 | { |
||
105 | if (function_exists('file_get_contents')) { |
||
106 | return file_get_contents($file); |
||
107 | } else { |
||
108 | $string = ''; |
||
109 | |||
110 | $file_handle = @fopen($file, 'r'); |
||
111 | if (!$file_handle) { |
||
112 | throw new phpFastCacheDriverException("Can't Read File", 96); |
||
113 | |||
114 | } |
||
115 | while (!feof($file_handle)) { |
||
116 | $line = fgets($file_handle); |
||
117 | $string .= $line; |
||
118 | } |
||
119 | fclose($file_handle); |
||
120 | |||
121 | return $string; |
||
122 | } |
||
123 | } |
||
124 | |||
125 | /** |
||
126 | * Encode data types such as object/array |
||
127 | * for driver that does not support |
||
128 | * non-scalar value |
||
129 | * @param $data |
||
130 | * @return string |
||
131 | */ |
||
132 | protected function encode($data) |
||
133 | { |
||
134 | return serialize($data); |
||
135 | } |
||
136 | |||
137 | /** |
||
138 | * Decode data types such as object/array |
||
139 | * for driver that does not support |
||
140 | * non-scalar value |
||
141 | * @param $value |
||
142 | * @return mixed |
||
143 | */ |
||
144 | protected function decode($value) |
||
145 | { |
||
146 | $x = @unserialize($value); |
||
147 | if ($x == false) { |
||
148 | return $value; |
||
149 | } else { |
||
150 | return $x; |
||
151 | } |
||
152 | } |
||
153 | |||
154 | /** |
||
155 | * Check phpModules or CGI |
||
156 | * @return bool |
||
157 | */ |
||
158 | protected function isPHPModule() |
||
159 | { |
||
160 | if (PHP_SAPI === 'apache2handler') { |
||
161 | return true; |
||
162 | } else { |
||
163 | if (strpos(PHP_SAPI, 'handler') !== false) { |
||
164 | return true; |
||
165 | } |
||
166 | } |
||
167 | |||
168 | return false; |
||
169 | } |
||
170 | |||
171 | |||
172 | /** |
||
173 | * @param $class |
||
174 | * @return bool |
||
175 | */ |
||
176 | protected function isExistingDriver($class) |
||
177 | { |
||
178 | return class_exists("\\phpFastCache\\Drivers\\{$class}"); |
||
179 | } |
||
180 | |||
181 | |||
182 | /** |
||
183 | * @param $tag |
||
184 | * @return string |
||
185 | */ |
||
186 | protected function _getTagName($tag) |
||
187 | { |
||
188 | return "__tag__" . $tag; |
||
189 | } |
||
190 | |||
191 | /** |
||
192 | * @param \phpFastCache\Cache\ExtendedCacheItemInterface $item |
||
193 | * @return array |
||
194 | */ |
||
195 | public function driverPreWrap(ExtendedCacheItemInterface $item) |
||
203 | |||
204 | /** |
||
205 | * @param array $wrapper |
||
206 | * @return mixed |
||
207 | */ |
||
208 | public function driverUnwrapData(array $wrapper) |
||
212 | |||
213 | /** |
||
214 | * @param array $wrapper |
||
215 | * @return mixed |
||
216 | */ |
||
217 | public function driverUnwrapTags(array $wrapper) |
||
221 | |||
222 | |||
223 | /** |
||
224 | * @param array $wrapper |
||
225 | * @return \DateTime |
||
226 | */ |
||
227 | public function driverUnwrapTime(array $wrapper) |
||
231 | |||
232 | /** |
||
233 | * @return string |
||
234 | */ |
||
235 | public function getDriverName() |
||
241 | |||
242 | /** |
||
243 | * @param \phpFastCache\Cache\ExtendedCacheItemInterface $item |
||
244 | * @return bool |
||
245 | */ |
||
246 | public function driverWriteTags(ExtendedCacheItemInterface $item) |
||
303 | |||
304 | /** |
||
305 | * @param $key |
||
306 | * @return string |
||
307 | */ |
||
308 | public function getTagKey($key) |
||
312 | |||
313 | /** |
||
314 | * @param $key |
||
315 | * @return string |
||
316 | */ |
||
317 | public function getTagKeys(array $keys) |
||
325 | |||
326 | /** |
||
327 | * @param string $tagName |
||
328 | * @return \phpFastCache\Cache\ExtendedCacheItemInterface[] |
||
329 | * @throws InvalidArgumentException |
||
330 | */ |
||
331 | public function getItemsByTag($tagName) |
||
346 | |||
347 | /** |
||
348 | * @param array $tagNames |
||
349 | * @return \phpFastCache\Cache\ExtendedCacheItemInterface[] |
||
350 | * @throws InvalidArgumentException |
||
351 | */ |
||
352 | public function getItemsByTags(array $tagNames) |
||
361 | |||
362 | /** |
||
363 | * @param string $tagName |
||
364 | * @return bool|null |
||
365 | * @throws InvalidArgumentException |
||
366 | */ |
||
367 | public function deleteItemsByTag($tagName) |
||
383 | |||
384 | /** |
||
385 | * @param array $tagNames |
||
386 | * @return bool|null |
||
387 | * @throws InvalidArgumentException |
||
388 | */ |
||
389 | View Code Duplication | public function deleteItemsByTags(array $tagNames) |
|
1 ignored issue
–
show
|
|||
390 | { |
||
391 | $return = null; |
||
401 | |||
402 | /** |
||
403 | * @inheritdoc |
||
404 | */ |
||
405 | View Code Duplication | public function incrementItemsByTag($tagName, $step = 1) |
|
417 | |||
418 | /** |
||
419 | * @inheritdoc |
||
420 | */ |
||
421 | View Code Duplication | public function incrementItemsByTags(array $tagNames, $step = 1) |
|
434 | |||
435 | /** |
||
436 | * @inheritdoc |
||
437 | */ |
||
438 | View Code Duplication | public function decrementItemsByTag($tagName, $step = 1) |
|
450 | |||
451 | /** |
||
452 | * @inheritdoc |
||
453 | */ |
||
454 | View Code Duplication | public function decrementItemsByTags(array $tagNames, $step = 1) |
|
467 | |||
468 | /** |
||
469 | * @inheritdoc |
||
470 | */ |
||
471 | View Code Duplication | public function appendItemsByTag($tagName, $data) |
|
483 | |||
484 | /** |
||
485 | * @inheritdoc |
||
486 | */ |
||
487 | View Code Duplication | public function appendItemsByTags(array $tagNames, $data) |
|
500 | |||
501 | /** |
||
502 | * @inheritdoc |
||
503 | */ |
||
504 | View Code Duplication | public function prependItemsByTag($tagName, $data) |
|
516 | |||
517 | /** |
||
518 | * @inheritdoc |
||
519 | */ |
||
520 | View Code Duplication | public function prependItemsByTags(array $tagNames, $data) |
|
533 | |||
534 | /** |
||
535 | * Abstract Drivers Methods |
||
536 | */ |
||
537 | |||
538 | /** |
||
539 | * @param string $key |
||
540 | * @return array [ |
||
541 | * 'd' => 'THE ITEM DATA' |
||
542 | * 't' => 'THE ITEM DATE EXPIRATION' |
||
543 | * 'g' => 'THE ITEM TAGS' |
||
544 | * ] |
||
545 | * |
||
546 | */ |
||
547 | abstract public function driverRead($key); |
||
548 | |||
549 | /** |
||
550 | * @param \Psr\Cache\CacheItemInterface $item |
||
551 | * @return mixed |
||
552 | */ |
||
553 | abstract public function driverWrite(CacheItemInterface $item); |
||
554 | |||
555 | /** |
||
556 | * @return bool |
||
557 | */ |
||
558 | abstract public function driverClear(); |
||
559 | |||
560 | /** |
||
561 | * @return bool |
||
562 | */ |
||
563 | abstract public function driverConnect(); |
||
564 | |||
565 | /** |
||
566 | * @param \Psr\Cache\CacheItemInterface $item |
||
567 | * @return bool |
||
568 | */ |
||
569 | abstract public function driverDelete(CacheItemInterface $item); |
||
570 | |||
571 | /** |
||
572 | * @param \Psr\Cache\CacheItemInterface $item |
||
573 | * @return bool |
||
574 | */ |
||
575 | abstract public function driverIsHit(CacheItemInterface $item); |
||
576 | |||
577 | } |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.