Complex classes like Couchbase 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 Couchbase, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
28 | class Couchbase extends AbstractAdapter implements FlushableInterface |
||
29 | { |
||
30 | /** |
||
31 | * Major version of ext/couchbase. |
||
32 | * |
||
33 | * @var null|int |
||
34 | */ |
||
35 | protected static $extCouchbaseMajorVersion; |
||
36 | |||
37 | /** |
||
38 | * @var CouchbaseResourceManager |
||
39 | */ |
||
40 | protected $resourceManager; |
||
41 | |||
42 | /** |
||
43 | * @var string |
||
44 | */ |
||
45 | protected $resourceId; |
||
46 | |||
47 | /** |
||
48 | * The namespace prefix. |
||
49 | * |
||
50 | * @var string |
||
51 | */ |
||
52 | protected $namespacePrefix = ''; |
||
53 | |||
54 | /** |
||
55 | * Has this instance be initialized. |
||
56 | * |
||
57 | * @var bool |
||
58 | */ |
||
59 | protected $initialized = false; |
||
60 | |||
61 | /** |
||
62 | * Constructor. |
||
63 | * |
||
64 | * @param null|array|\Traversable|CouchbaseOptions $options |
||
65 | * |
||
66 | * @throws Exception\ExceptionInterface |
||
67 | */ |
||
68 | 61 | public function __construct($options = null) |
|
69 | { |
||
70 | 61 | if (static::$extCouchbaseMajorVersion === null) { |
|
71 | 1 | $v = (string) phpversion('couchbase'); |
|
72 | 1 | static::$extCouchbaseMajorVersion = ($v !== '') ? (int) $v[0] : 0; |
|
73 | 1 | } |
|
74 | 61 | if (static::$extCouchbaseMajorVersion < 2) { |
|
75 | throw new Exception\ExtensionNotLoadedException('Need ext/couchbase version >= 2.0.0'); |
||
76 | } |
||
77 | 61 | parent::__construct($options); |
|
78 | // reset initialized flag on update option(s) |
||
79 | 61 | $initialized = &$this->initialized; |
|
80 | 61 | $this->getEventManager()->attach('option', function () use (&$initialized) { |
|
81 | 61 | $initialized = false; |
|
82 | 61 | }); |
|
83 | 61 | } |
|
84 | |||
85 | /** |
||
86 | * Flush the whole storage. |
||
87 | * |
||
88 | * @return bool |
||
89 | */ |
||
90 | 61 | public function flush() |
|
96 | |||
97 | /** |
||
98 | * Internal method to store an item. |
||
99 | * |
||
100 | * @param string $normalizedKey |
||
101 | * @param mixed $value |
||
102 | * |
||
103 | * @return bool |
||
104 | * |
||
105 | * @throws Exception\ExceptionInterface |
||
106 | */ |
||
107 | 32 | protected function internalSetItem(&$normalizedKey, &$value) |
|
124 | |||
125 | /** |
||
126 | * Initialize the internal memcached resource. |
||
127 | * |
||
128 | * @return \CouchbaseBucket |
||
129 | */ |
||
130 | 61 | protected function getCouchbaseResource() |
|
153 | |||
154 | /** |
||
155 | * Get options. |
||
156 | * |
||
157 | * @return CouchbaseOptions |
||
158 | * |
||
159 | * @see setOptions() |
||
160 | */ |
||
161 | 61 | public function getOptions() |
|
169 | |||
170 | /** |
||
171 | * Set options. |
||
172 | * |
||
173 | * @param array|\Traversable|CouchbaseOptions $options |
||
174 | * |
||
175 | * @return \CouchbaseCluster |
||
176 | * |
||
177 | * @see getOptions() |
||
178 | */ |
||
179 | 61 | public function setOptions($options) |
|
187 | |||
188 | /** |
||
189 | * Get expiration time by ttl. |
||
190 | * |
||
191 | * Some storage commands involve sending an expiration value (relative to |
||
192 | * an item or to an operation requested by the client) to the server. In |
||
193 | * all such cases, the actual value sent may either be Unix time (number of |
||
194 | * seconds since January 1, 1970, as an integer), or a number of seconds |
||
195 | * starting from current time. In the latter case, this number of seconds |
||
196 | * may not exceed 60*60*24*30 (number of seconds in 30 days); if the |
||
197 | * expiration value is larger than that, the server will consider it to be |
||
198 | * real Unix time value rather than an offset from current time. |
||
199 | * |
||
200 | * @return int |
||
201 | */ |
||
202 | 43 | protected function expirationTime() |
|
211 | |||
212 | /** |
||
213 | * Add an item. |
||
214 | * |
||
215 | * @param string $normalizedKey |
||
216 | * @param mixed $value |
||
217 | * |
||
218 | * @return bool |
||
219 | * |
||
220 | * @throws Exception\ExceptionInterface |
||
221 | */ |
||
222 | 3 | protected function internalAddItem(&$normalizedKey, &$value) |
|
237 | |||
238 | /** |
||
239 | * @param array $normalizedKeyValuePairs |
||
240 | * |
||
241 | * @return array|mixed |
||
242 | * |
||
243 | * @throws Exception\RuntimeException |
||
244 | */ |
||
245 | 1 | protected function internalAddItems(array &$normalizedKeyValuePairs) |
|
261 | |||
262 | /** |
||
263 | * @param array $normalizedKeyValuePairs |
||
264 | * |
||
265 | * @return array |
||
266 | */ |
||
267 | 7 | protected function namespacesKeyValuePairs(array &$normalizedKeyValuePairs) |
|
278 | |||
279 | /** |
||
280 | * @param $result |
||
281 | */ |
||
282 | 4 | protected function filterErrors(&$result) |
|
294 | |||
295 | /** |
||
296 | * @param array $result |
||
297 | */ |
||
298 | 5 | protected function removeNamespacePrefix(&$result) |
|
307 | |||
308 | /** |
||
309 | * Internal method to store multiple items. |
||
310 | * |
||
311 | * @param array $normalizedKeyValuePairs |
||
312 | * |
||
313 | * @return array Array of not stored keys |
||
314 | * |
||
315 | * @throws Exception\ExceptionInterface |
||
316 | */ |
||
317 | 6 | protected function internalSetItems(array &$normalizedKeyValuePairs) |
|
327 | |||
328 | /** |
||
329 | * Internal method to remove an item. |
||
330 | * |
||
331 | * @param string $normalizedKey |
||
332 | * |
||
333 | * @return bool |
||
334 | * |
||
335 | * @throws Exception\ExceptionInterface |
||
336 | */ |
||
337 | 3 | protected function internalRemoveItem(&$normalizedKey) |
|
350 | |||
351 | /** |
||
352 | * Internal method to remove multiple items. |
||
353 | * |
||
354 | * @param array $normalizedKeys |
||
355 | * |
||
356 | * @return array Array of not removed keys |
||
357 | * |
||
358 | * @throws Exception\ExceptionInterface |
||
359 | */ |
||
360 | 3 | protected function internalRemoveItems(array &$normalizedKeys) |
|
376 | |||
377 | 6 | protected function namespacesKeys(array &$normalizedKeys) |
|
383 | |||
384 | /** |
||
385 | * Internal method to set an item only if token matches. |
||
386 | * |
||
387 | * @param mixed $token |
||
388 | * @param string $normalizedKey |
||
389 | * @param mixed $value |
||
390 | * |
||
391 | * @return bool |
||
392 | * |
||
393 | * @throws Exception\ExceptionInterface |
||
394 | * |
||
395 | * @see getItem() |
||
396 | * @see setItem() |
||
397 | */ |
||
398 | 1 | protected function internalCheckAndSetItem(&$token, &$normalizedKey, &$value) |
|
399 | { |
||
400 | 1 | $memc = $this->getCouchbaseResource(); |
|
401 | 1 | $key = $this->namespacePrefix.$normalizedKey; |
|
402 | 1 | $success = null; |
|
403 | 1 | $this->internalGetItem($key, $success, $token); |
|
404 | |||
405 | try { |
||
406 | 1 | $memc->replace($key, $value, ['cas' => $token, 'expiry' => $this->expirationTime()]); |
|
407 | 1 | $result = true; |
|
408 | 1 | } catch (\CouchbaseException $e) { |
|
409 | 1 | if ($e->getCode() === \COUCHBASE_KEY_EEXISTS |
|
410 | 1 | || $e->getCode() === \COUCHBASE_KEY_ENOENT |
|
411 | 1 | ) { |
|
412 | 1 | return false; |
|
413 | } |
||
414 | throw new Exception\RuntimeException($e); |
||
415 | } |
||
416 | |||
417 | 1 | return $result; |
|
418 | } |
||
419 | |||
420 | /** |
||
421 | * Internal method to get an item. |
||
422 | * |
||
423 | * @param string $normalizedKey |
||
424 | * @param bool $success |
||
425 | * @param mixed $casToken |
||
426 | * |
||
427 | * @return mixed Data on success, null on failure |
||
428 | * |
||
429 | * @throws Exception\ExceptionInterface |
||
430 | */ |
||
431 | 20 | protected function internalGetItem(&$normalizedKey, &$success = null, &$casToken = null) |
|
452 | |||
453 | /** |
||
454 | * Internal method to set an item only if token matches. |
||
455 | * |
||
456 | * @param string $normalizedKey |
||
457 | * @param mixed $value |
||
458 | * |
||
459 | * @return bool |
||
460 | * |
||
461 | * @throws Exception\ExceptionInterface |
||
462 | */ |
||
463 | 3 | protected function internalReplaceItem(&$normalizedKey, &$value) |
|
477 | |||
478 | /** |
||
479 | * Internal method to touch an item. |
||
480 | * |
||
481 | * @param string &$normalizedKey Key which will be touched |
||
482 | * |
||
483 | * @return bool |
||
484 | * |
||
485 | * @throws Exception\RuntimeException |
||
486 | */ |
||
487 | 2 | protected function internalTouchItem(&$normalizedKey) |
|
488 | { |
||
489 | 2 | $redis = $this->getCouchbaseResource(); |
|
490 | try { |
||
491 | 2 | $ttl = $this->getOptions()->getTtl(); |
|
492 | 2 | $redis->touch($this->namespacePrefix.$normalizedKey, $ttl); |
|
493 | 2 | } catch (\CouchbaseException $e) { |
|
494 | 1 | if ($e->getCode() === \COUCHBASE_KEY_EEXISTS |
|
495 | 1 | || $e->getCode() === \COUCHBASE_KEY_ENOENT |
|
496 | 1 | ) { |
|
497 | 1 | return false; |
|
498 | } |
||
499 | throw new Exception\RuntimeException($e); |
||
500 | } |
||
501 | |||
502 | 1 | return true; |
|
503 | } |
||
504 | |||
505 | /** |
||
506 | * Internal method to test if an item exists. |
||
507 | * |
||
508 | * @param string $normalizedKey |
||
509 | * |
||
510 | * @return bool |
||
511 | * |
||
512 | * @throws Exception\ExceptionInterface |
||
513 | */ |
||
514 | 17 | protected function internalHasItem(&$normalizedKey) |
|
531 | |||
532 | /** |
||
533 | * Internal method to test multiple items. |
||
534 | * |
||
535 | * @param array $normalizedKeys |
||
536 | * |
||
537 | * @return array Array of found keys |
||
538 | * |
||
539 | * @throws Exception\ExceptionInterface |
||
540 | */ |
||
541 | 3 | protected function internalHasItems(array &$normalizedKeys) |
|
566 | |||
567 | /** |
||
568 | * Internal method to get multiple items. |
||
569 | * |
||
570 | * @param array $normalizedKeys |
||
571 | * |
||
572 | * @return array Associative array of keys and values |
||
573 | * |
||
574 | * @throws Exception\ExceptionInterface |
||
575 | */ |
||
576 | 4 | protected function internalGetItems(array &$normalizedKeys) |
|
609 | |||
610 | /** |
||
611 | * Internal method to increment an item. |
||
612 | * |
||
613 | * @param string $normalizedKey |
||
614 | * @param int $value |
||
615 | * |
||
616 | * @return int|bool The new value on success, false on failure |
||
617 | * |
||
618 | * @throws Exception\ExceptionInterface |
||
619 | */ |
||
620 | 3 | protected function internalIncrementItem(&$normalizedKey, &$value) |
|
641 | |||
642 | /** |
||
643 | * Internal method to decrement an item. |
||
644 | * |
||
645 | * @param string $normalizedKey |
||
646 | * @param int $value |
||
647 | * |
||
648 | * @return int|bool The new value on success, false on failure |
||
649 | * |
||
650 | * @throws Exception\ExceptionInterface |
||
651 | */ |
||
652 | 2 | protected function internalDecrementItem(&$normalizedKey, &$value) |
|
674 | |||
675 | /** |
||
676 | * Internal method to get capabilities of this adapter. |
||
677 | * |
||
678 | * @return Capabilities |
||
679 | */ |
||
680 | 15 | protected function internalGetCapabilities() |
|
713 | } |
||
714 |