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 NewsManager 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 NewsManager, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
23 | class NewsManager extends AbstractManager |
||
24 | { |
||
25 | use CategoryTrait; |
||
26 | |||
27 | /** @var NewsInterface $currentNews The current news. */ |
||
28 | protected $currentNews; |
||
29 | |||
30 | /** @var integer $currentPage The current Page. */ |
||
31 | protected $currentPage; |
||
32 | |||
33 | /** @var integer $numPerPage News by page. */ |
||
34 | protected $numPerPage = 0; |
||
35 | |||
36 | /** @var integer $numPage How many pages. */ |
||
37 | protected $numPage; |
||
38 | |||
39 | /** @var boolean $pageCycle Does the pager can cycle indefinitely. */ |
||
40 | protected $entryCycle = false; |
||
41 | |||
42 | /** @var NewsInterface $nextNews */ |
||
43 | protected $nextNews; |
||
44 | |||
45 | /** @var NewsInterface $prevNews */ |
||
46 | protected $prevNews; |
||
47 | |||
48 | /** @var integer $page */ |
||
49 | protected $page = 0; |
||
50 | |||
51 | /** @var integer $category */ |
||
52 | protected $category = 0; |
||
53 | |||
54 | /** @var NewsInterface[] $all All the news. */ |
||
55 | protected $all = []; |
||
56 | |||
57 | /** @var NewsInterface[] $entries The news collection. */ |
||
58 | protected $entries = []; |
||
59 | |||
60 | /** @var NewsInterface[] $archive The archive news collection. */ |
||
61 | protected $archive = []; |
||
62 | |||
63 | /** @var NewsInterface $entry A news. */ |
||
64 | protected $entry; |
||
65 | |||
66 | /** @var object $objType The news object model. */ |
||
67 | protected $objType; |
||
68 | |||
69 | /** @var string $featIdent The config ident for featured news. */ |
||
70 | protected $featIdent; |
||
71 | |||
72 | /** @var NewsInterface[] $featList The config ident for featured news. */ |
||
73 | protected $featList = []; |
||
74 | |||
75 | /** @var NewsLoader $loader The news loader provider. */ |
||
76 | protected $loader; |
||
77 | |||
78 | /** |
||
79 | * @var array |
||
80 | */ |
||
81 | protected $categoryItem = []; |
||
82 | |||
83 | /** |
||
84 | * NewsManager constructor. |
||
85 | * @param array $data The Data. |
||
86 | * @throws Exception When $data index is not set. |
||
87 | */ |
||
88 | View Code Duplication | public function __construct(array $data) |
|
107 | |||
108 | /** |
||
109 | * To be displayed news list. |
||
110 | * @return mixed The news collection. |
||
111 | */ |
||
112 | View Code Duplication | public function entries() |
|
135 | |||
136 | /** |
||
137 | * @param integer|null $id The news id. |
||
138 | * @return mixed |
||
139 | */ |
||
140 | View Code Duplication | public function entry($id = null) |
|
153 | |||
154 | /** |
||
155 | * All available news. |
||
156 | * @return NewsInterface[]|Collection The news collection. |
||
157 | */ |
||
158 | public function all() |
||
168 | |||
169 | /** |
||
170 | * @return CategoryInterface[]|Collection The category collection. |
||
171 | */ |
||
172 | View Code Duplication | public function loadCategoryItems() |
|
180 | |||
181 | /** |
||
182 | * @param integer $id The category id. |
||
183 | * @return CategoryInterface |
||
184 | */ |
||
185 | public function categoryItem($id) |
||
195 | |||
196 | /** |
||
197 | * @return mixed |
||
198 | * @param array $options The options for the collection loader. |
||
199 | * @throws Exception When featured news ident is not valid. |
||
200 | */ |
||
201 | View Code Duplication | public function featList(array $options = []) |
|
257 | |||
258 | /** |
||
259 | * @return NewsInterface[]|Collection |
||
260 | */ |
||
261 | View Code Duplication | public function archive() |
|
286 | |||
287 | /** |
||
288 | * Get the latest news. |
||
289 | * @return NewsInterface|array The latest news. |
||
290 | */ |
||
291 | View Code Duplication | public function latest() |
|
302 | |||
303 | /** |
||
304 | * @return mixed The previous news |
||
305 | */ |
||
306 | public function prev() |
||
314 | |||
315 | /** |
||
316 | * @return mixed The next news |
||
317 | */ |
||
318 | public function next() |
||
326 | |||
327 | /** |
||
328 | * @return float|int The current news index page ident. |
||
329 | */ |
||
330 | View Code Duplication | public function currentPage() |
|
353 | |||
354 | // ========================================================================== |
||
355 | // GETTERS |
||
356 | // ========================================================================== |
||
357 | |||
358 | /** |
||
359 | * @return mixed |
||
360 | */ |
||
361 | public function currentNews() |
||
369 | |||
370 | /** |
||
371 | * @return integer |
||
372 | */ |
||
373 | public function numPerPage() |
||
377 | |||
378 | /** |
||
379 | * @return boolean |
||
380 | */ |
||
381 | public function entryCycle() |
||
385 | |||
386 | /** |
||
387 | * Amount of news (total) |
||
388 | * @return integer How many news? |
||
389 | */ |
||
390 | public function numNews() |
||
394 | |||
395 | /** |
||
396 | * The total amount of pages. |
||
397 | * @return float |
||
398 | */ |
||
399 | View Code Duplication | public function numPages() |
|
416 | |||
417 | /** |
||
418 | * Is there a pager. |
||
419 | * @return boolean |
||
420 | */ |
||
421 | public function hasPager() |
||
425 | |||
426 | /** |
||
427 | * @return integer |
||
428 | */ |
||
429 | public function page() |
||
433 | |||
434 | /** |
||
435 | * @return integer |
||
436 | */ |
||
437 | public function category() |
||
441 | |||
442 | /** |
||
443 | * @return mixed |
||
444 | */ |
||
445 | public function objType() |
||
449 | |||
450 | /** |
||
451 | * @return mixed |
||
452 | */ |
||
453 | public function featIdent() |
||
457 | |||
458 | /** |
||
459 | * @return NewsLoader |
||
460 | */ |
||
461 | public function loader() |
||
465 | |||
466 | // ========================================================================== |
||
467 | // SETTERS |
||
468 | // ========================================================================== |
||
469 | |||
470 | /** |
||
471 | * @param mixed $currentNews The current news context. |
||
472 | * @return self . |
||
473 | */ |
||
474 | public function setCurrentNews($currentNews) |
||
480 | |||
481 | /** |
||
482 | * @param integer $numPerPage The number of news per page. |
||
483 | * @return self |
||
484 | */ |
||
485 | public function setNumPerPage($numPerPage) |
||
491 | |||
492 | /** |
||
493 | * @param boolean $entryCycle Next and Prev cycles indefinitely. |
||
494 | * @return self |
||
495 | */ |
||
496 | public function setEntryCycle($entryCycle) |
||
502 | |||
503 | /** |
||
504 | * @param integer $page The page number to load. |
||
505 | * @return self |
||
506 | */ |
||
507 | public function setPage($page) |
||
513 | |||
514 | /** |
||
515 | * @param integer $category The current news category. |
||
516 | * @return self |
||
517 | */ |
||
518 | public function setCategory($category) |
||
524 | |||
525 | /** |
||
526 | * @param mixed $objType The object type. |
||
527 | * @return self |
||
528 | */ |
||
529 | public function setObjType($objType) |
||
535 | |||
536 | /** |
||
537 | * @param mixed $featIdent The featured list ident. |
||
538 | * @return self |
||
539 | */ |
||
540 | public function setFeatIdent($featIdent) |
||
546 | |||
547 | /** |
||
548 | * @param NewsLoader $loader The news loader provider. |
||
549 | * @return self |
||
550 | */ |
||
551 | public function setLoader(NewsLoader $loader) |
||
557 | |||
558 | // ========================================================================== |
||
559 | // UTILS |
||
560 | // ========================================================================== |
||
561 | |||
562 | /** |
||
563 | * Set the Prev and Next news |
||
564 | * @return $this |
||
565 | */ |
||
566 | View Code Duplication | public function setPrevNext() |
|
615 | } |
||
616 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.