Complex classes like CacheAbstract 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 CacheAbstract, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
9 | abstract class CacheAbstract { |
||
10 | /** |
||
11 | * Controls debug on html page for all Cache backends. |
||
12 | * @var boolean |
||
13 | */ |
||
14 | public static $debugOnPage = false; |
||
15 | |||
16 | /** |
||
17 | * Controls debug to a file |
||
18 | * @var string the file name, or null if file debug is off. |
||
19 | */ |
||
20 | public static $debugLogFile = null; |
||
21 | |||
22 | /** |
||
23 | * Is this cache enabled? |
||
24 | * @var boolean $enabled |
||
25 | */ |
||
26 | protected $enabled = true; |
||
27 | |||
28 | /** |
||
29 | * Holds recursive data for start()/end(). Array of CacheData |
||
30 | * |
||
31 | * @var array |
||
32 | */ |
||
33 | private $loopdata = array(); |
||
34 | |||
35 | private $inloop = 0; |
||
36 | protected $lifetime = 0; |
||
37 | |||
38 | /** |
||
39 | * This is a namespace string to avoid clashes with other instances of this application. |
||
40 | * Initialize it to a unique string. If you are not running multiple instances, ignore. |
||
41 | * |
||
42 | * @var string |
||
43 | */ |
||
44 | protected $namespace = ""; |
||
45 | |||
46 | /** |
||
47 | * Array for basic cache profiling. Keys are CacheLogEnum, values are counters. |
||
48 | * |
||
49 | * @var array |
||
50 | */ |
||
51 | static protected $summary = array( |
||
52 | CacheLogEnum::ACCESSED => 0, |
||
53 | CacheLogEnum::MISSED => 0, |
||
54 | CacheLogEnum::DELETED => 0, |
||
55 | CacheLogEnum::CLEANED => 0, |
||
56 | CacheLogEnum::SAVED => 0, |
||
57 | CacheLogEnum::PREFETCHED => 0, |
||
58 | ); |
||
59 | |||
60 | /** |
||
61 | * Stores cache log for debugging. |
||
62 | * @var array |
||
63 | */ |
||
64 | protected $cache_log = array(); |
||
65 | |||
66 | /** |
||
67 | * Is log enabled? Log can take a lot of RAM, so only turn this on when |
||
68 | * profiling. |
||
69 | * @var boolean $should_log |
||
70 | */ |
||
71 | protected $should_log = false; |
||
72 | |||
73 | /** |
||
74 | * Returns basic cache statistics. See $summary. |
||
75 | * |
||
76 | * @return array() |
||
77 | */ |
||
78 | public static function getLogSummary() { |
||
81 | |||
82 | public static function resetLogSummary() { |
||
92 | |||
93 | /** |
||
94 | * |
||
95 | * @param boolean $b |
||
96 | * @return CacheAbstract |
||
97 | */ |
||
98 | public function setLog($b) { |
||
102 | |||
103 | /** |
||
104 | * Returns a cache |
||
105 | * |
||
106 | * @param string $backend |
||
107 | * @throws Cachearium\Exceptions\CacheInvalidBackendException |
||
108 | * @return CacheAbstract |
||
109 | */ |
||
110 | public static function factory($backend) { |
||
117 | |||
118 | /** |
||
119 | * Clears all cache classes. |
||
120 | * @codeCoverageIgnore |
||
121 | */ |
||
122 | public static function clearAll() { |
||
135 | |||
136 | /** |
||
137 | * Enable this cache |
||
138 | * |
||
139 | * @return CacheAbstract this |
||
140 | */ |
||
141 | final public function setEnabled($b) { |
||
150 | |||
151 | /** |
||
152 | * Enable this cache |
||
153 | * |
||
154 | * @return CacheAbstract this |
||
155 | */ |
||
156 | public function enable() { |
||
160 | |||
161 | /** |
||
162 | * Disable this cache |
||
163 | * |
||
164 | * @return CacheAbstract |
||
165 | */ |
||
166 | public function disable() { |
||
170 | |||
171 | /** |
||
172 | * @return True if cache is enabled, working and storing/retrieving data. |
||
173 | */ |
||
174 | public function isEnabled() { |
||
177 | |||
178 | /** |
||
179 | * |
||
180 | * @param number $lifetime 0 for infinite |
||
181 | */ |
||
182 | public function setDefaultLifetime($lifetime = 0) { |
||
185 | |||
186 | public function getDefaultLifetime() { |
||
189 | |||
190 | /** |
||
191 | * @param string $name An optional namespace. |
||
192 | */ |
||
193 | public function setNamespace($name) { |
||
197 | |||
198 | /** |
||
199 | * @return string |
||
200 | */ |
||
201 | public function getNamespace() { |
||
204 | |||
205 | /** |
||
206 | * Get cached entry. |
||
207 | * |
||
208 | * @param $k |
||
209 | * @return mixed |
||
210 | * @throws Cachearium\Exceptions\NotCachedException |
||
211 | */ |
||
212 | abstract public function get(CacheKey $k); |
||
213 | |||
214 | /** |
||
215 | * Same as get(), but expanded parameters. |
||
216 | * |
||
217 | * @param string $base |
||
218 | * @param string $id |
||
219 | * @param mixed $sub |
||
220 | * @return mixed |
||
221 | * @throws Cachearium\Exceptions\NotCachedException |
||
222 | * @see getK |
||
223 | */ |
||
224 | public function getP($base, $id, $sub = null) { |
||
227 | |||
228 | /** |
||
229 | * Same as get, but assumes data was stored with a CacheData object |
||
230 | * and will treat it accordingly. |
||
231 | * |
||
232 | * @param CacheKey $k |
||
233 | * @return CacheData |
||
234 | * @throws Cachearium\Exceptions\NotCachedException |
||
235 | */ |
||
236 | public function getData(CacheKey $k) { |
||
243 | |||
244 | /** |
||
245 | * Same as getData(), but expanded parameters. |
||
246 | * |
||
247 | * @see getData() |
||
248 | * @param string $base |
||
249 | * @param string $id |
||
250 | * @param mixed $sub |
||
251 | */ |
||
252 | public function getDataP($base, $id, $sub = null) { |
||
255 | |||
256 | /** |
||
257 | * Gets data from multiple cache keys at once |
||
258 | * |
||
259 | * Backends may override this to provide an efficient implementation over multiple |
||
260 | * calls to get(). |
||
261 | * |
||
262 | * @param array $cacheid List of cache keys |
||
263 | * @param callable $callback if present will be called for any \NotCachedExceptions. |
||
264 | * Callback should have this signature: (CacheAbstract $c, CacheKey $k) |
||
265 | * @return array:mixed array with data, using same keys as cacheid. Keys not |
||
266 | * found in cache won't be present, but no exception will be thrown |
||
267 | */ |
||
268 | public function getMulti(array $cacheid, $callback = null) { |
||
283 | |||
284 | /** |
||
285 | * Increment a variable. Backend deals with this, but in general this is atomic. |
||
286 | * Backend must only guarantee that the increment is made, but the final value |
||
287 | * may not be current + $value due to concurrent accesses. |
||
288 | * |
||
289 | * @param integer $value |
||
290 | * @param CacheKey $k |
||
291 | * @param integer $default If key is not in cache, this value is returned. |
||
292 | * @return integer |
||
293 | */ |
||
294 | abstract public function increment($value, CacheKey $k, $default = 0); |
||
295 | |||
296 | /** |
||
297 | * Invalidates a dependency index. If the index does not exist it is created. |
||
298 | * @param CacheKey $k |
||
299 | */ |
||
300 | public function invalidate(CacheKey $k) { |
||
303 | |||
304 | /** |
||
305 | * Saves data in cache. |
||
306 | * |
||
307 | * @param mixed $data Data to save in cache |
||
308 | * @param CacheKey $k |
||
309 | * @param integer $lifetime The lifetime in sceonds, although it is up to the implementation whether |
||
310 | * it is respected or not. |
||
311 | * @return boolean true if no problem |
||
312 | */ |
||
313 | abstract public function store($data, CacheKey $k, $lifetime = 0); |
||
314 | |||
315 | /** |
||
316 | * Same as store() but expanded parameters |
||
317 | * |
||
318 | * @param mixed $data |
||
319 | * @param string $base |
||
320 | * @param string $sub |
||
321 | * @param string $id |
||
322 | * @param number $lifetime |
||
323 | * @return boolean true if no problem |
||
324 | * @see store() |
||
325 | */ |
||
326 | public function storeP($data, $base, $id, $sub = null, $lifetime = 0) { |
||
329 | |||
330 | /** |
||
331 | * Same as store() but expanded parameters |
||
332 | * |
||
333 | * @param CacheData $data |
||
334 | * @param number $lifetime |
||
335 | * @return boolean true if no problem |
||
336 | * @see store() |
||
337 | */ |
||
338 | public function storeData(CacheData $data, $lifetime = 0) { |
||
341 | |||
342 | /** |
||
343 | * Deletes an entry from the cache |
||
344 | * |
||
345 | * @param CacheKey $k |
||
346 | * @return boolean |
||
347 | */ |
||
348 | abstract public function delete(CacheKey $k); |
||
349 | |||
350 | /** |
||
351 | * @see delete() |
||
352 | * @param string $base |
||
353 | * @param string $id |
||
354 | * @param mixed $sub |
||
355 | */ |
||
356 | public function deleteP($base, $id, $sub = null) { |
||
359 | |||
360 | /** |
||
361 | * Cleans cache: all entries with a certain $base and $id in the $key |
||
362 | * are deleted. |
||
363 | * |
||
364 | * @param CacheKey $k |
||
365 | * @return boolean true if no problem |
||
366 | */ |
||
367 | public function clean(CacheKey $k) { |
||
370 | |||
371 | /** |
||
372 | * Cleans cache: all entries with a certain $base and $id |
||
373 | * |
||
374 | * @return boolean true if no problem |
||
375 | */ |
||
376 | abstract public function cleanP($base, $id); |
||
377 | |||
378 | /** |
||
379 | * Clears entire cache. Use sparingly. |
||
380 | */ |
||
381 | abstract public function clear(); |
||
382 | |||
383 | /** |
||
384 | * Prefetches data which will be used. This avoids multiple trips to the cache |
||
385 | * server if they can be avoided. |
||
386 | * |
||
387 | * Backend may ignore this call and implement a noop. |
||
388 | * |
||
389 | * @param array $data array(0 => CacheKey, ...) |
||
390 | */ |
||
391 | abstract public function prefetch($data); |
||
392 | |||
393 | /** |
||
394 | * Generates a report for this backend |
||
395 | * |
||
396 | * @codeCoverageIgnore |
||
397 | */ |
||
398 | abstract public function report(); |
||
399 | |||
400 | /** |
||
401 | * Starts a cache if it doesn't exist, or outputs the data and returns true. |
||
402 | * Calls extraSub(). |
||
403 | * |
||
404 | * @param CacheKey $k |
||
405 | * @param string $lifetime The lifetime, in seconds |
||
406 | * @param boolean $print if True echoes the data |
||
407 | * @param boolean $fail if false throws an exception if something happens, such |
||
408 | * as not cached |
||
409 | * @return boolean|string True if cached |
||
410 | * @review |
||
411 | */ |
||
412 | public function start(CacheKey $k, $lifetime = null, $print = true, $fail = false) { |
||
417 | |||
418 | /** |
||
419 | * @see recursiveStart() |
||
420 | */ |
||
421 | public function recursiveStartP($base, $id, $sub = null, $lifetime = null, $print = true, $fail = false) { |
||
424 | |||
425 | /** |
||
426 | * @see start() |
||
427 | */ |
||
428 | public function startP($base, $id, $sub = null, $lifetime = null, $print = true, $fail = false) { |
||
431 | |||
432 | /** |
||
433 | * start() using a callable. Same as start()/c()/end(). |
||
434 | * |
||
435 | * @param CacheKey $k |
||
436 | * @param callable $c A callable. Whatever it prints will be cached. |
||
437 | * @param array $cparams parameters for the callback, optional |
||
438 | * @param integer $lifetime |
||
439 | */ |
||
440 | public function startCallback(CacheKey $k, callable $c, array $cparams = [], $lifetime = null) { |
||
448 | |||
449 | /** |
||
450 | * Appends a callback to the current start()/end() cache |
||
451 | * |
||
452 | * Callbacks are always called at runtime, their result is never cached at |
||
453 | * this level. You may cache it in the callback, of course. |
||
454 | * |
||
455 | * @param function $callback |
||
456 | * @return boolean |
||
457 | * @review |
||
458 | */ |
||
459 | public function appendCallback(callable $callback) { |
||
477 | |||
478 | /** |
||
479 | * Returns a key given parameters. This is up to storage and different |
||
480 | * values may be returned for the same parameters, as storages are likely |
||
481 | * to use key-based cache expiration. |
||
482 | * |
||
483 | * @param CacheKey $k |
||
484 | */ |
||
485 | abstract protected function hashKey(CacheKey $k); |
||
486 | |||
487 | protected function keyFromDeps(CacheKey $k, $deps) { |
||
495 | |||
496 | /** |
||
497 | * Get extra sub |
||
498 | * @param unknown $sub |
||
499 | */ |
||
500 | private function extraSub(&$sub) { |
||
512 | |||
513 | public function newstart(CacheKey $k, $lifetime = null, $fail = false) { |
||
552 | |||
553 | public function newEnd($print = true) { |
||
608 | |||
609 | /** |
||
610 | * Prints HTML for cache debug probes -> opens tag |
||
611 | * |
||
612 | * @param string $key |
||
613 | * @param CacheData $cachedata |
||
614 | * @param string $type |
||
615 | * @codeCoverageIgnore |
||
616 | */ |
||
617 | protected function printProbeStart($key, CacheData $cachedata, $type) { |
||
627 | |||
628 | /** |
||
629 | * Prints HTML for cache debug probes -> closes tag |
||
630 | * |
||
631 | * @param string $key |
||
632 | * @param CacheData $cachedata |
||
633 | * @SuppressWarnings(PHPMD.UnusedFormalParameter) |
||
634 | * @codeCoverageIgnore |
||
635 | */ |
||
636 | protected function printProbeEnd($key, CacheData $cachedata) { |
||
639 | |||
640 | /** |
||
641 | * |
||
642 | * @param CacheKey $k |
||
643 | * @param integer $lifetime if null uses the class default |
||
644 | * @param boolean $print |
||
645 | * @param boolean $fail if true throws a NotCachedException if not cached. |
||
646 | * @throws Cachearium\Exceptions\NotCachedException |
||
647 | * @throws Cachearium\Exceptions\CacheKeyClashException |
||
648 | * @return string The cached item as a string or false if not cached. |
||
649 | */ |
||
650 | public function recursiveStart(CacheKey $k, $lifetime = null, $print = true, $fail = false) { |
||
749 | |||
750 | /** |
||
751 | * |
||
752 | * @param boolean $print |
||
753 | * @throws \Cachearium\Exceptions\CacheStoreFailure |
||
754 | * @return string The string. If $print == true the string is printed as well. |
||
755 | */ |
||
756 | public function recursiveEnd($print = true) { |
||
811 | |||
812 | /** |
||
813 | * Ends the cache start(). |
||
814 | * @see recursiveEnd() |
||
815 | */ |
||
816 | public function end($print = true) { |
||
819 | |||
820 | /* |
||
821 | * DEBUG |
||
822 | */ |
||
823 | |||
824 | /** |
||
825 | * High level log for testing and debugging |
||
826 | * |
||
827 | * @codeCoverageIgnore |
||
828 | */ |
||
829 | public static function logHigh($message) { |
||
834 | |||
835 | /** |
||
836 | * Logs cache accesses for debugging |
||
837 | * |
||
838 | * @param string $status CacheLogEnum constant |
||
839 | * @param CacheKey $k The message to print. |
||
840 | * @param integer $lifetime |
||
841 | * @codeCoverageIgnore |
||
842 | */ |
||
843 | protected function log($status, CacheKey $k, $lifetime = 0) { |
||
863 | |||
864 | /** |
||
865 | * Dumps a short HTML summary of the cache hits/misses |
||
866 | * @codeCoverageIgnore |
||
867 | */ |
||
868 | public static function dumpSummary() { |
||
875 | |||
876 | /** |
||
877 | * Renders CSS for live view debugging of cached data. |
||
878 | * @codeCoverageIgnore |
||
879 | */ |
||
880 | public static function cssDebug() { |
||
927 | |||
928 | |||
929 | /** |
||
930 | * Extensive footer debug code. Shows which parts of the HTML were |
||
931 | * cached or missed visually. Great! |
||
932 | * @codeCoverageIgnore |
||
933 | */ |
||
934 | public static function footerDebug() { |
||
1003 | } |
||
1004 |
This check looks for the
else
branches ofif
statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.These
else
branches can be removed.could be turned into
This is much more concise to read.