Complex classes like AbstractEntity 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 AbstractEntity, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
23 | abstract class AbstractEntity extends MutableObject implements |
||
24 | EntityInterface, |
||
25 | \JsonSerializable, |
||
26 | \IteratorAggregate, |
||
27 | \ArrayAccess, |
||
28 | ValueInterface, |
||
29 | PublishableInterface |
||
30 | { |
||
31 | /** |
||
32 | * Field format declares how entity must process magic setters and getters. Available values: |
||
33 | * camelCase, tableize. |
||
34 | */ |
||
35 | const FIELD_FORMAT = 'camelCase'; |
||
36 | |||
37 | /** |
||
38 | * Field mutators. |
||
39 | */ |
||
40 | const MUTATOR_GETTER = 'getter'; |
||
41 | const MUTATOR_SETTER = 'setter'; |
||
42 | const MUTATOR_ACCESSOR = 'accessor'; |
||
43 | |||
44 | /** |
||
45 | * @var array |
||
46 | */ |
||
47 | private $fields = []; |
||
48 | |||
49 | /** |
||
50 | * @param array $fields |
||
51 | */ |
||
52 | public function __construct(array $fields = []) |
||
57 | |||
58 | /** |
||
59 | * Routes user function in format of (get|set)FieldName into (get|set)Field(fieldName, value). |
||
60 | * |
||
61 | * @see getFeld() |
||
62 | * @see setField() |
||
63 | * |
||
64 | * @param string $method |
||
65 | * @param array $arguments |
||
66 | * |
||
67 | * @return $this|mixed|null|AccessorInterface |
||
68 | * |
||
69 | * @throws EntityException |
||
70 | */ |
||
71 | public function __call(string $method, array $arguments) |
||
113 | |||
114 | /** |
||
115 | * {@inheritdoc} |
||
116 | */ |
||
117 | public function hasField(string $name): bool |
||
121 | |||
122 | /** |
||
123 | * {@inheritdoc} |
||
124 | * |
||
125 | * @param bool $filter If false, associated field setter or accessor will be ignored. |
||
126 | * |
||
127 | * @throws AccessorExceptionInterface |
||
128 | */ |
||
129 | public function setField(string $name, $value, bool $filter = true) |
||
174 | |||
175 | /** |
||
176 | * {@inheritdoc} |
||
177 | * |
||
178 | * @param bool $filter If false, associated field getter will be ignored. |
||
179 | * |
||
180 | * @throws AccessorExceptionInterface |
||
181 | */ |
||
182 | public function getField(string $name, $default = null, bool $filter = true) |
||
211 | |||
212 | /** |
||
213 | * {@inheritdoc} |
||
214 | * |
||
215 | * @see $fillable |
||
216 | * @see $secured |
||
217 | * @see isFillable() |
||
218 | * |
||
219 | * @param array|\Traversable $fields |
||
220 | * @param bool $all Fill all fields including non fillable. |
||
221 | * |
||
222 | * @return $this |
||
223 | * |
||
224 | * @throws AccessorExceptionInterface |
||
225 | */ |
||
226 | public function setFields($fields = [], bool $all = false) |
||
244 | |||
245 | /** |
||
246 | * @return array |
||
247 | */ |
||
248 | protected function getKeys(): array |
||
252 | |||
253 | /** |
||
254 | * {@inheritdoc} |
||
255 | * |
||
256 | * Every getter and accessor will be applied/constructed if filter argument set to true. |
||
257 | * |
||
258 | * @param bool $filter |
||
259 | * |
||
260 | * @throws AccessorExceptionInterface |
||
261 | */ |
||
262 | public function getFields(bool $filter = true): array |
||
271 | |||
272 | /** |
||
273 | * @param mixed $offset |
||
274 | * |
||
275 | * @return bool |
||
276 | */ |
||
277 | public function __isset($offset) |
||
281 | |||
282 | /** |
||
283 | * @param mixed $offset |
||
284 | * |
||
285 | * @return mixed |
||
286 | */ |
||
287 | public function __get($offset) |
||
291 | |||
292 | /** |
||
293 | * @param mixed $offset |
||
294 | * @param mixed $value |
||
295 | */ |
||
296 | public function __set($offset, $value) |
||
300 | |||
301 | /** |
||
302 | * @param mixed $offset |
||
303 | */ |
||
304 | public function __unset($offset) |
||
308 | |||
309 | /** |
||
310 | * {@inheritdoc} |
||
311 | */ |
||
312 | public function offsetExists($offset) |
||
316 | |||
317 | /** |
||
318 | * {@inheritdoc} |
||
319 | */ |
||
320 | public function offsetGet($offset) |
||
324 | |||
325 | /** |
||
326 | * {@inheritdoc} |
||
327 | */ |
||
328 | public function offsetSet($offset, $value) |
||
332 | |||
333 | /** |
||
334 | * {@inheritdoc} |
||
335 | */ |
||
336 | public function offsetUnset($offset) |
||
340 | |||
341 | /** |
||
342 | * {@inheritdoc} |
||
343 | */ |
||
344 | public function getIterator(): \Iterator |
||
348 | |||
349 | /** |
||
350 | * Serialize entity data into plain array. |
||
351 | * |
||
352 | * @return array |
||
353 | * |
||
354 | * @throws AccessorExceptionInterface |
||
355 | */ |
||
356 | public function serializeData() |
||
369 | |||
370 | /** |
||
371 | * Alias for serializeData. |
||
372 | * |
||
373 | * @return array |
||
374 | */ |
||
375 | public function toArray(): array |
||
379 | |||
380 | /** |
||
381 | * {@inheritdoc} |
||
382 | * |
||
383 | * By default use publicFields to be json serialized. |
||
384 | */ |
||
385 | public function jsonSerialize() |
||
389 | |||
390 | /** |
||
391 | * Destruct data entity. |
||
392 | */ |
||
393 | public function __destruct() |
||
397 | |||
398 | /** |
||
399 | * Check if field is fillable. |
||
400 | * |
||
401 | * @param string $field |
||
402 | * |
||
403 | * @return bool |
||
404 | */ |
||
405 | abstract protected function isFillable(string $field): bool; |
||
406 | |||
407 | /** |
||
408 | * Get mutator associated with given field. |
||
409 | * |
||
410 | * @param string $field |
||
411 | * @param string $type See MUTATOR_* constants |
||
412 | * |
||
413 | * @return mixed |
||
414 | */ |
||
415 | abstract protected function getMutator(string $field, string $type); |
||
416 | |||
417 | /** |
||
418 | * Create instance of field accessor. |
||
419 | * |
||
420 | * @param string $accessor |
||
421 | * @param mixed $value |
||
422 | * |
||
423 | * @return AccessorInterface |
||
424 | * |
||
425 | * @throws AccessorExceptionInterface |
||
426 | */ |
||
427 | protected function createAccessor(string $accessor, $value): AccessorInterface |
||
431 | |||
432 | /** |
||
433 | * Reset every field value. |
||
434 | */ |
||
435 | protected function flushValues() |
||
439 | |||
440 | /** |
||
441 | * Create entity by passing fields thought setFields method |
||
442 | * |
||
443 | * @param array $fields |
||
444 | * |
||
445 | * @return AbstractEntity |
||
446 | * |
||
447 | * @event created($entity) |
||
448 | */ |
||
449 | public static function create($fields = []) |
||
459 | } |
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.