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 AbstractEnhancedProvider 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 AbstractEnhancedProvider, and based on these observations, apply Extract Interface, too.
1 | <?php namespace Comodojo\SimpleCache\Providers; |
||
33 | abstract class AbstractEnhancedProvider |
||
34 | extends AbstractProvider |
||
35 | implements EnhancedSimpleCacheInterface { |
||
36 | |||
37 | use StatefulTrait; |
||
38 | use NamespaceTrait; |
||
39 | |||
40 | protected $driver; |
||
41 | |||
42 | protected $default_properties = []; |
||
43 | |||
44 | protected $properties; |
||
45 | |||
46 | private $queue = []; |
||
47 | |||
48 | 145 | View Code Duplication | public function __construct(array $properties = [], LoggerInterface $logger = null) { |
57 | |||
58 | 54 | public function getProperties() { |
|
63 | |||
64 | 68 | public function get($key, $default = null) { |
|
65 | |||
66 | 68 | if ( KeyValidator::validateKey($key) === false ) { |
|
67 | throw new InvalidSimpleCacheArgumentException('Invalid key provided'); |
||
68 | } |
||
69 | |||
70 | try { |
||
71 | |||
72 | 68 | $data = $this->driver->get($key, $this->getNamespace()); |
|
73 | |||
74 | 68 | } catch (Exception $e) { |
|
75 | |||
76 | 36 | $this->setState(self::CACHE_ERROR, $e->getMessage()); |
|
77 | $data = null; |
||
78 | |||
79 | } |
||
80 | |||
81 | 68 | if ( $data === null ) return $default; |
|
82 | |||
83 | 46 | return unserialize($data); |
|
84 | |||
85 | } |
||
86 | |||
87 | 79 | public function set($key, $value, $ttl = null) { |
|
88 | |||
89 | 79 | if ( KeyValidator::validateKey($key) === false ) { |
|
90 | throw new InvalidSimpleCacheArgumentException('Invalid key provided'); |
||
91 | } |
||
92 | |||
93 | 79 | if ( $value === null ) { |
|
94 | 5 | throw new InvalidSimpleCacheArgumentException('Cannot cache a null value'); |
|
95 | } |
||
96 | |||
97 | $real_ttl; |
||
98 | |||
99 | 74 | View Code Duplication | if ( $ttl == null || $ttl == 0 ) $real_ttl = 0; |
100 | 20 | else if ( $ttl instanceof DateInterval ) $real_ttl = $ttl->format('%s'); |
|
101 | 20 | else $real_ttl = intval($ttl); |
|
102 | |||
103 | try { |
||
104 | |||
105 | 74 | $data = $this->driver->set($key, $this->getNamespace(), serialize($value), $real_ttl); |
|
106 | |||
107 | 74 | } catch (Exception $e) { |
|
108 | |||
109 | $this->setState(self::CACHE_ERROR, $e->getMessage()); |
||
110 | $data = false; |
||
111 | |||
112 | } |
||
113 | |||
114 | 74 | return $data; |
|
115 | |||
116 | } |
||
117 | |||
118 | 12 | View Code Duplication | public function delete($key) { |
119 | |||
120 | 12 | if ( KeyValidator::validateKey($key) === false ) { |
|
121 | throw new InvalidSimpleCacheArgumentException('Invalid key provided'); |
||
122 | } |
||
123 | |||
124 | try { |
||
125 | |||
126 | 12 | $data = $this->driver->delete($key, $this->getNamespace()); |
|
127 | |||
128 | 12 | } catch (Exception $e) { |
|
129 | |||
130 | $this->setState(self::CACHE_ERROR, $e->getMessage()); |
||
131 | $data = false; |
||
132 | |||
133 | } |
||
134 | |||
135 | 12 | return $data; |
|
136 | |||
137 | } |
||
138 | |||
139 | 6 | public function clear() { |
|
140 | |||
141 | try { |
||
142 | |||
143 | 6 | $data = $this->driver->clear(); |
|
144 | |||
145 | 6 | } catch (Exception $e) { |
|
146 | |||
147 | $this->setState(self::CACHE_ERROR, $e->getMessage()); |
||
148 | $data = false; |
||
149 | |||
150 | } |
||
151 | |||
152 | 6 | return $data; |
|
153 | |||
154 | } |
||
155 | |||
156 | 6 | public function getMultiple($keys, $default = null) { |
|
157 | |||
158 | 6 | if ( !is_array($keys) && !($keys instanceof Traversable) ) { |
|
159 | throw new InvalidSimpleCacheArgumentException('Invalid keys provided'); |
||
160 | } |
||
161 | |||
162 | 6 | foreach ( $keys as $key ) { |
|
163 | 6 | if ( KeyValidator::validateKey($key) === false ) { |
|
164 | throw new InvalidSimpleCacheArgumentException('Invalid key provided'); |
||
165 | } |
||
166 | 6 | } |
|
167 | |||
168 | try { |
||
169 | |||
170 | 6 | $data = $this->driver->getMultiple($keys, $this->getNamespace()); |
|
171 | |||
172 | 6 | } catch (Exception $e) { |
|
173 | |||
174 | $this->setState(self::CACHE_ERROR, $e->getMessage()); |
||
175 | $data = array_combine($keys, array_fill(0, count($keys), null)); |
||
176 | |||
177 | } |
||
178 | |||
179 | 6 | return array_map(function($value) use($default) { |
|
180 | 6 | if ( $value === null ) return $default; |
|
181 | 5 | return unserialize($value); |
|
182 | 6 | }, $data); |
|
183 | |||
184 | } |
||
185 | |||
186 | 6 | public function setMultiple($values, $ttl = null) { |
|
187 | |||
188 | 6 | if ( !is_array($values) && !($values instanceof Traversable) ) { |
|
189 | throw new InvalidSimpleCacheArgumentException('Invalid keys provided'); |
||
190 | } |
||
191 | |||
192 | 6 | $real_values = []; |
|
193 | |||
194 | 6 | foreach ( $values as $key => $value ) { |
|
195 | 6 | if ( KeyValidator::validateKey($key) === false ) { |
|
196 | throw new InvalidSimpleCacheArgumentException('Invalid key provided'); |
||
197 | } |
||
198 | 6 | if ( $value === null ) { |
|
199 | throw new InvalidSimpleCacheArgumentException('Cannot cache a null value'); |
||
200 | } |
||
201 | 6 | $real_values[$key] = serialize($value); |
|
202 | 6 | } |
|
203 | |||
204 | $real_ttl; |
||
205 | |||
206 | 6 | View Code Duplication | if ( $ttl == null || $ttl == 0 ) $real_ttl = 0; |
207 | else if ( $ttl instanceof DateInterval ) $real_ttl = $ttl->format('%s'); |
||
208 | else $real_ttl = intval($ttl); |
||
209 | |||
210 | try { |
||
211 | |||
212 | 6 | $data = $this->driver->setMultiple($real_values, $this->getNamespace(), $real_ttl); |
|
213 | |||
214 | 6 | } catch (Exception $e) { |
|
215 | |||
216 | $this->setState(self::CACHE_ERROR, $e->getMessage()); |
||
217 | $data = false; |
||
218 | |||
219 | } |
||
220 | |||
221 | 6 | return $data; |
|
222 | |||
223 | } |
||
224 | |||
225 | 6 | public function deleteMultiple($keys) { |
|
226 | |||
227 | 6 | if ( !is_array($keys) && !($keys instanceof Traversable) ) { |
|
228 | throw new InvalidSimpleCacheArgumentException('Invalid keys provided'); |
||
229 | } |
||
230 | |||
231 | 6 | foreach ( $keys as $key ) { |
|
232 | 6 | if ( KeyValidator::validateKey($key) === false ) { |
|
233 | throw new InvalidSimpleCacheArgumentException('Invalid key provided'); |
||
234 | } |
||
235 | 6 | } |
|
236 | |||
237 | try { |
||
238 | |||
239 | 6 | $data = $this->driver->deleteMultiple($keys, $this->getNamespace()); |
|
240 | |||
241 | 6 | } catch (Exception $e) { |
|
242 | |||
243 | $this->setState(self::CACHE_ERROR, $e->getMessage()); |
||
244 | $data = false; |
||
245 | |||
246 | } |
||
247 | |||
248 | 6 | return $data; |
|
249 | |||
250 | } |
||
251 | |||
252 | 29 | View Code Duplication | public function has($key) { |
253 | |||
254 | 29 | if ( KeyValidator::validateKey($key) === false ) { |
|
255 | throw new InvalidSimpleCacheArgumentException('Invalid key provided'); |
||
256 | } |
||
257 | |||
258 | try { |
||
259 | |||
260 | 29 | $data = $this->driver->has($key, $this->getNamespace()); |
|
261 | |||
262 | 29 | } catch (Exception $e) { |
|
263 | |||
264 | $this->setState(self::CACHE_ERROR, $e->getMessage()); |
||
265 | $data = false; |
||
266 | |||
267 | } |
||
268 | |||
269 | 29 | return $data; |
|
270 | |||
271 | } |
||
272 | |||
273 | abstract public function getStats(); |
||
274 | |||
275 | 6 | View Code Duplication | public function clearNamespace() { |
276 | |||
277 | try { |
||
278 | |||
279 | 6 | $data = $this->driver->clear($this->getNamespace()); |
|
280 | |||
281 | 6 | } catch (Exception $e) { |
|
282 | |||
283 | $this->setState(self::CACHE_ERROR, $e->getMessage()); |
||
284 | $data = false; |
||
285 | |||
286 | } |
||
287 | |||
288 | 6 | return $data; |
|
289 | |||
290 | } |
||
291 | |||
292 | 108 | View Code Duplication | public function test() { |
311 | |||
312 | } |
||
313 |