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 Model 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 Model, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
25 | abstract class Model extends Component |
||
26 | { |
||
27 | |||
28 | use ModelRecordBehavior; |
||
29 | |||
30 | /** |
||
31 | * @var BaseModel[] |
||
32 | */ |
||
33 | protected $_cacheAll; |
||
34 | |||
35 | /** |
||
36 | * @var BaseModel[] |
||
37 | */ |
||
38 | protected $_cacheById = []; |
||
39 | |||
40 | |||
41 | /******************************************* |
||
42 | * MODEL CLASSES |
||
43 | *******************************************/ |
||
44 | |||
45 | /** |
||
46 | * @return string |
||
47 | */ |
||
48 | public abstract static function modelClass(): string; |
||
49 | |||
50 | /** |
||
51 | * @return string |
||
52 | */ |
||
53 | public static function modelClassInstance(): string |
||
57 | |||
58 | /******************************************* |
||
59 | * CREATE |
||
60 | *******************************************/ |
||
61 | |||
62 | /** |
||
63 | * @param array $config |
||
64 | * @param string|null $toScenario |
||
65 | * @throws InvalidConfigException |
||
66 | * @return BaseModel |
||
67 | */ |
||
68 | View Code Duplication | public function create($config = [], string $toScenario = null): BaseModel |
|
91 | |||
92 | /** |
||
93 | * @param Record $record |
||
94 | * @param string|null $toScenario |
||
95 | * @throws InvalidConfigException |
||
96 | * @return BaseModel |
||
97 | */ |
||
98 | protected function createFromRecord(Record $record, string $toScenario = null): BaseModel |
||
117 | |||
118 | /******************************************* |
||
119 | * FIND/GET ALL |
||
120 | *******************************************/ |
||
121 | |||
122 | /** |
||
123 | * @param string $toScenario |
||
124 | * @return BaseModel[] |
||
125 | */ |
||
126 | View Code Duplication | public function findAll(string $toScenario = null) |
|
150 | |||
151 | /** |
||
152 | * @param string $toScenario |
||
153 | * @return BaseModel[] |
||
154 | * @throws ModelNotFoundException |
||
155 | */ |
||
156 | public function getAll(string $toScenario = null): array |
||
168 | |||
169 | /******************************************* |
||
170 | * FIND/GET |
||
171 | *******************************************/ |
||
172 | |||
173 | /** |
||
174 | * @param $identifier |
||
175 | * @param string $toScenario |
||
176 | * @return Model|null |
||
177 | */ |
||
178 | public function find($identifier, string $toScenario = null) |
||
204 | |||
205 | /** |
||
206 | * @param $identifier |
||
207 | * @param string $toScenario |
||
208 | * @return BaseModel |
||
209 | * @throws ModelNotFoundException |
||
210 | */ |
||
211 | public function get($identifier, string $toScenario = null): BaseModel |
||
224 | |||
225 | /******************************************* |
||
226 | * FIND/GET BY ID |
||
227 | *******************************************/ |
||
228 | |||
229 | /** |
||
230 | * @param int $id |
||
231 | * @param string|null $toScenario |
||
232 | * @return BaseModel|null |
||
233 | */ |
||
234 | View Code Duplication | public function findById(int $id, string $toScenario = null) |
|
259 | |||
260 | /** |
||
261 | * @param int $id |
||
262 | * @param string|null $toScenario |
||
263 | * @return BaseModel |
||
264 | * @throws ModelNotFoundException |
||
265 | */ |
||
266 | View Code Duplication | public function getById(int $id, string $toScenario = null): BaseModel |
|
279 | |||
280 | /** |
||
281 | * @param int $id |
||
282 | * @param string|null $toScenario |
||
283 | * @return BaseModel|null |
||
284 | */ |
||
285 | View Code Duplication | public function freshFindById(int $id, string $toScenario = null) |
|
299 | |||
300 | /** |
||
301 | * @param int $id |
||
302 | * @param string|null $toScenario |
||
303 | * @return BaseModel |
||
304 | * @throws ModelNotFoundException |
||
305 | */ |
||
306 | View Code Duplication | public function freshGetById(int $id, string $toScenario = null): BaseModel |
|
318 | |||
319 | /******************************************* |
||
320 | * FIND/GET BY QUERY |
||
321 | *******************************************/ |
||
322 | |||
323 | /** |
||
324 | * @param QueryInterface $query |
||
325 | * @param string $toScenario |
||
326 | * @return BaseModel[] |
||
327 | */ |
||
328 | View Code Duplication | public function findAllByQuery(QueryInterface $query, string $toScenario = null): array |
|
340 | |||
341 | /** |
||
342 | * @param QueryInterface $query |
||
343 | * @param string $toScenario |
||
344 | * @return BaseModel|null |
||
345 | */ |
||
346 | View Code Duplication | public function findByQuery(QueryInterface $query, string $toScenario = null) |
|
357 | |||
358 | /******************************************* |
||
359 | * FIND/GET BY CONDITION |
||
360 | *******************************************/ |
||
361 | |||
362 | /** |
||
363 | * @param $condition |
||
364 | * @param string $toScenario |
||
365 | * @return BaseModel[] |
||
366 | */ |
||
367 | public function findAllByCondition($condition, string $toScenario = null): array |
||
384 | |||
385 | /** |
||
386 | * @param $condition |
||
387 | * @param string $toScenario |
||
388 | * @return BaseModel[] |
||
389 | * @throws ModelNotFoundException |
||
390 | */ |
||
391 | public function getAllByCondition($condition, string $toScenario = null): array |
||
403 | |||
404 | /** |
||
405 | * @param $condition |
||
406 | * @param string $toScenario |
||
407 | * @return BaseModel|null |
||
408 | */ |
||
409 | View Code Duplication | public function findByCondition($condition, string $toScenario = null) |
|
420 | |||
421 | /** |
||
422 | * @param $condition |
||
423 | * @param string $toScenario |
||
424 | * @return BaseModel |
||
425 | * @throws ModelNotFoundException |
||
426 | */ |
||
427 | public function getByCondition($condition, string $toScenario = null): BaseModel |
||
439 | |||
440 | /******************************************* |
||
441 | * FIND/GET BY CRITERIA |
||
442 | *******************************************/ |
||
443 | |||
444 | /** |
||
445 | * @param $criteria |
||
446 | * @param string $toScenario |
||
447 | * @return BaseModel[] |
||
448 | */ |
||
449 | View Code Duplication | public function findAllByCriteria($criteria, string $toScenario = null): array |
|
467 | |||
468 | /** |
||
469 | * @param $criteria |
||
470 | * @param string $toScenario |
||
471 | * @return BaseModel[] |
||
472 | * @throws ModelNotFoundException |
||
473 | */ |
||
474 | public function getAllByCriteria($criteria, string $toScenario = null): array |
||
486 | |||
487 | /** |
||
488 | * @param $criteria |
||
489 | * @param string $toScenario |
||
490 | * @return BaseModel|null |
||
491 | */ |
||
492 | View Code Duplication | public function findByCriteria($criteria, string $toScenario = null) |
|
503 | |||
504 | /** |
||
505 | * @param $criteria |
||
506 | * @param string $toScenario |
||
507 | * @return BaseModel |
||
508 | * @throws ModelNotFoundException |
||
509 | */ |
||
510 | public function getByCriteria($criteria, string $toScenario = null): BaseModel |
||
522 | |||
523 | |||
524 | /******************************************* |
||
525 | * FIND/GET BY RECORD |
||
526 | *******************************************/ |
||
527 | |||
528 | /** |
||
529 | * @param Record $record |
||
530 | * @param string $toScenario |
||
531 | * @return BaseModel |
||
532 | */ |
||
533 | View Code Duplication | public function findByRecord(Record $record, string $toScenario = null): BaseModel |
|
550 | |||
551 | /** |
||
552 | * @param Record $record |
||
553 | * @param string $toScenario |
||
554 | * @return BaseModel |
||
555 | */ |
||
556 | public function getByRecord(Record $record, string $toScenario = null): BaseModel |
||
560 | |||
561 | |||
562 | /******************************************* |
||
563 | * CACHE |
||
564 | *******************************************/ |
||
565 | |||
566 | /** |
||
567 | * @param $identifier |
||
568 | * @return BaseModel|null |
||
569 | */ |
||
570 | View Code Duplication | public function findCache($identifier) |
|
586 | |||
587 | /** |
||
588 | * Find an existing cache by ID |
||
589 | * |
||
590 | * @param $id |
||
591 | * @return BaseModel|null |
||
592 | */ |
||
593 | public function findCacheById(int $id) |
||
606 | |||
607 | /** |
||
608 | * Identify whether in cache by ID |
||
609 | * |
||
610 | * @param $id |
||
611 | * @return bool |
||
612 | */ |
||
613 | protected function isCachedById(int $id) |
||
617 | |||
618 | /** |
||
619 | * @param BaseModel $model |
||
620 | * @return $this |
||
621 | */ |
||
622 | protected function cacheById(BaseModel $model) |
||
636 | |||
637 | /** |
||
638 | * @param Record $record |
||
639 | * @return BaseModel|null |
||
640 | */ |
||
641 | public function findCacheByRecord(Record $record) |
||
653 | |||
654 | /** |
||
655 | * @param BaseModel $model |
||
656 | * @return static |
||
657 | */ |
||
658 | public function addToCache(BaseModel $model) |
||
665 | |||
666 | |||
667 | /******************************************* |
||
668 | * EXCEPTIONS |
||
669 | *******************************************/ |
||
670 | |||
671 | /** |
||
672 | * @throws ModelNotFoundException |
||
673 | */ |
||
674 | protected function notFoundException() |
||
684 | |||
685 | /** |
||
686 | * @param int|null $id |
||
687 | * @throws ModelNotFoundException |
||
688 | */ |
||
689 | protected function notFoundByIdException(int $id = null) |
||
700 | |||
701 | /** |
||
702 | * @param null $criteria |
||
703 | * @throws ModelNotFoundException |
||
704 | */ |
||
705 | protected function notFoundByCriteriaException($criteria = null) |
||
716 | |||
717 | /** |
||
718 | * @param null $condition |
||
719 | * @throws ModelNotFoundException |
||
720 | */ |
||
721 | protected function notFoundByConditionException($condition = null) |
||
732 | |||
733 | } |
||
734 |