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 AbstractRenderer 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 AbstractRenderer, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
14 | abstract class AbstractRenderer implements RendererInterface |
||
15 | { |
||
16 | /** |
||
17 | * @var array |
||
18 | */ |
||
19 | protected $options = []; |
||
20 | |||
21 | /** |
||
22 | * @var string |
||
23 | */ |
||
24 | protected $title; |
||
25 | |||
26 | /** |
||
27 | * @var Cache\Storage\StorageInterface |
||
28 | */ |
||
29 | protected $cache; |
||
30 | |||
31 | /** |
||
32 | * @var string |
||
33 | */ |
||
34 | protected $cacheId; |
||
35 | |||
36 | /** |
||
37 | * @var Paginator |
||
38 | */ |
||
39 | protected $paginator; |
||
40 | |||
41 | /** |
||
42 | * @var \ZfcDatagrid\Column\AbstractColumn[] |
||
43 | */ |
||
44 | protected $columns = []; |
||
45 | |||
46 | /** |
||
47 | * @var \ZfcDataGrid\Column\Style\AbstractStyle[] |
||
48 | */ |
||
49 | protected $rowStyles = []; |
||
50 | |||
51 | /** |
||
52 | * @var array |
||
53 | */ |
||
54 | protected $sortConditions = null; |
||
55 | |||
56 | /** |
||
57 | * @var Filter[] |
||
58 | */ |
||
59 | protected $filters = null; |
||
60 | |||
61 | /** |
||
62 | * @var int |
||
63 | */ |
||
64 | protected $currentPageNumber = null; |
||
65 | |||
66 | /** |
||
67 | * @var array |
||
68 | */ |
||
69 | protected $data = []; |
||
70 | |||
71 | /** |
||
72 | * @var MvcEvent |
||
73 | */ |
||
74 | protected $mvcEvent; |
||
75 | |||
76 | /** |
||
77 | * @var ViewModel |
||
78 | */ |
||
79 | protected $viewModel; |
||
80 | |||
81 | /** |
||
82 | * @var string |
||
83 | */ |
||
84 | protected $template; |
||
85 | |||
86 | /** |
||
87 | * @var string |
||
88 | */ |
||
89 | protected $templateToolbar; |
||
90 | |||
91 | /** |
||
92 | * @var array |
||
93 | */ |
||
94 | protected $toolbarTemplateVariables = []; |
||
95 | |||
96 | /** |
||
97 | * @var Translator |
||
98 | */ |
||
99 | protected $translator; |
||
100 | |||
101 | public function setOptions(array $options) |
||
105 | |||
106 | /** |
||
107 | * @return array |
||
108 | */ |
||
109 | public function getOptions() |
||
113 | |||
114 | /** |
||
115 | * @return array |
||
116 | */ |
||
117 | public function getOptionsRenderer() |
||
126 | |||
127 | /** |
||
128 | * @param ViewModel $viewModel |
||
129 | */ |
||
130 | public function setViewModel(ViewModel $viewModel) |
||
134 | |||
135 | /** |
||
136 | * @return \Zend\View\Model\ViewModel |
||
137 | */ |
||
138 | public function getViewModel() |
||
142 | |||
143 | /** |
||
144 | * Set the view template. |
||
145 | * |
||
146 | * @param string $name |
||
147 | */ |
||
148 | public function setTemplate($name) |
||
152 | |||
153 | /** |
||
154 | * Get the view template name. |
||
155 | * |
||
156 | * @return string |
||
157 | */ |
||
158 | public function getTemplate() |
||
166 | |||
167 | /** |
||
168 | * Get the default template path (if there is no own set). |
||
169 | * |
||
170 | * @param string $type layout or toolbar |
||
171 | * |
||
172 | * @return string |
||
173 | * |
||
174 | * @throws \Exception |
||
175 | */ |
||
176 | private function getTemplatePathDefault($type = 'layout') |
||
191 | |||
192 | /** |
||
193 | * Set the toolbar view template name. |
||
194 | * |
||
195 | * @param string $name |
||
196 | */ |
||
197 | public function setToolbarTemplate($name) |
||
201 | |||
202 | /** |
||
203 | * @return string |
||
204 | * |
||
205 | * @throws \Exception |
||
206 | */ |
||
207 | public function getToolbarTemplate() |
||
215 | |||
216 | /** |
||
217 | * Set the toolbar view template variables. |
||
218 | * |
||
219 | * @param array $variables |
||
220 | */ |
||
221 | public function setToolbarTemplateVariables(array $variables) |
||
225 | |||
226 | /** |
||
227 | * Get the toolbar template variables. |
||
228 | * |
||
229 | * @return array |
||
230 | */ |
||
231 | public function getToolbarTemplateVariables() |
||
235 | |||
236 | /** |
||
237 | * Paginator is here to retreive the totalItemCount, count pages, current page |
||
238 | * NOT FOR THE ACTUAL DATA!!!! |
||
239 | * |
||
240 | * @param \Zend\Paginator\Paginator $paginator |
||
241 | */ |
||
242 | public function setPaginator(Paginator $paginator) |
||
246 | |||
247 | /** |
||
248 | * @return \Zend\Paginator\Paginator |
||
249 | */ |
||
250 | public function getPaginator() |
||
254 | |||
255 | /** |
||
256 | * Set the columns. |
||
257 | * |
||
258 | * @param array $columns |
||
259 | */ |
||
260 | public function setColumns(array $columns) |
||
264 | |||
265 | /** |
||
266 | * Get all columns. |
||
267 | * |
||
268 | * @return \ZfcDatagrid\Column\AbstractColumn[] |
||
269 | */ |
||
270 | public function getColumns() |
||
274 | |||
275 | /** |
||
276 | * @param \ZfcDataGrid\Column\Style\AbstractStyle[] $rowStyles |
||
277 | */ |
||
278 | public function setRowStyles($rowStyles = []) |
||
282 | |||
283 | /** |
||
284 | * @return \ZfcDataGrid\Column\Style\AbstractStyle[] |
||
285 | */ |
||
286 | public function getRowStyles() |
||
290 | |||
291 | /** |
||
292 | * Calculate the sum of the displayed column width to 100%. |
||
293 | * |
||
294 | * @param array $columns |
||
295 | */ |
||
296 | protected function calculateColumnWidthPercent(array $columns) |
||
313 | |||
314 | /** |
||
315 | * The prepared data. |
||
316 | * |
||
317 | * @param array $data |
||
318 | */ |
||
319 | public function setData(array $data) |
||
323 | |||
324 | /** |
||
325 | * @return array |
||
326 | */ |
||
327 | public function getData() |
||
331 | |||
332 | /** |
||
333 | * @return array |
||
334 | */ |
||
335 | public function getCacheData() |
||
339 | |||
340 | /** |
||
341 | * @throws \Exception |
||
342 | * |
||
343 | * @return array|false |
||
344 | */ |
||
345 | private function getCacheSortConditions() |
||
354 | |||
355 | /** |
||
356 | * @throws \Exception |
||
357 | * |
||
358 | * @return array|false |
||
359 | */ |
||
360 | private function getCacheFilters() |
||
369 | |||
370 | /** |
||
371 | * Not used ATM... |
||
372 | * |
||
373 | * @see \ZfcDatagrid\Renderer\RendererInterface::setMvcEvent() |
||
374 | */ |
||
375 | public function setMvcEvent(MvcEvent $mvcEvent) |
||
379 | |||
380 | /** |
||
381 | * Not used ATM... |
||
382 | * |
||
383 | * @return MvcEvent |
||
384 | */ |
||
385 | public function getMvcEvent() |
||
389 | |||
390 | /** |
||
391 | * @return \Zend\Stdlib\RequestInterface |
||
392 | */ |
||
393 | public function getRequest() |
||
397 | |||
398 | /** |
||
399 | * @param Translator $translator |
||
400 | * |
||
401 | * @throws \InvalidArgumentException |
||
402 | */ |
||
403 | View Code Duplication | public function setTranslator($translator) |
|
411 | |||
412 | /** |
||
413 | * @return \Zend\I18n\Translator\Translator |
||
414 | */ |
||
415 | public function getTranslator() |
||
419 | |||
420 | /** |
||
421 | * @param $string |
||
422 | * |
||
423 | * @return string |
||
424 | */ |
||
425 | public function translate($string) |
||
429 | |||
430 | /** |
||
431 | * Set the title. |
||
432 | * |
||
433 | * @param string $title |
||
434 | */ |
||
435 | public function setTitle($title) |
||
439 | |||
440 | /** |
||
441 | * @return string |
||
442 | */ |
||
443 | public function getTitle() |
||
447 | |||
448 | /** |
||
449 | * @param Cache\Storage\StorageInterface $cache |
||
450 | */ |
||
451 | public function setCache(Cache\Storage\StorageInterface $cache) |
||
455 | |||
456 | /** |
||
457 | * @return Cache\Storage\StorageInterface |
||
458 | */ |
||
459 | public function getCache() |
||
463 | |||
464 | /** |
||
465 | * @param string $cacheId |
||
466 | */ |
||
467 | public function setCacheId($cacheId) |
||
471 | |||
472 | /** |
||
473 | * @return string |
||
474 | */ |
||
475 | public function getCacheId() |
||
479 | |||
480 | /** |
||
481 | * Set the sort conditions explicit (e.g. |
||
482 | * from a custom form). |
||
483 | * |
||
484 | * @param array $sortConditions |
||
485 | */ |
||
486 | public function setSortConditions(array $sortConditions) |
||
500 | |||
501 | /** |
||
502 | * @return array |
||
503 | */ |
||
504 | View Code Duplication | public function getSortConditions() |
|
521 | |||
522 | /** |
||
523 | * Get the default sort conditions defined for the columns. |
||
524 | * |
||
525 | * @return array |
||
526 | */ |
||
527 | public function getSortConditionsDefault() |
||
548 | |||
549 | /** |
||
550 | * Set filters explicit (e.g. |
||
551 | * from a custom form). |
||
552 | * |
||
553 | * @param array $filters |
||
554 | */ |
||
555 | public function setFilters(array $filters) |
||
565 | |||
566 | /** |
||
567 | * @return Filter[] |
||
568 | */ |
||
569 | View Code Duplication | public function getFilters() |
|
586 | |||
587 | /** |
||
588 | * Get the default filter conditions defined for the columns. |
||
589 | * |
||
590 | * @return Filter[] |
||
591 | */ |
||
592 | public function getFiltersDefault() |
||
609 | |||
610 | /** |
||
611 | * Set the current page number. |
||
612 | * |
||
613 | * @param int $page |
||
614 | */ |
||
615 | public function setCurrentPageNumber($page) |
||
619 | |||
620 | /** |
||
621 | * Should be implemented for each renderer itself (just default). |
||
622 | * |
||
623 | * @return int |
||
624 | */ |
||
625 | public function getCurrentPageNumber() |
||
633 | |||
634 | /** |
||
635 | * Should be implemented for each renderer itself (just default). |
||
636 | * |
||
637 | * @return int |
||
638 | */ |
||
639 | public function getItemsPerPage($defaultItems = 25) |
||
647 | |||
648 | /** |
||
649 | * VERY UGLY DEPENDECY... |
||
650 | * |
||
651 | * @todo Refactor :-) |
||
652 | * |
||
653 | * @see \ZfcDatagrid\Renderer\RendererInterface::prepareViewModel() |
||
654 | */ |
||
655 | public function prepareViewModel(Datagrid $grid) |
||
714 | |||
715 | /** |
||
716 | * Return the name of the renderer. |
||
717 | * |
||
718 | * @return string |
||
719 | */ |
||
720 | abstract public function getName(); |
||
721 | |||
722 | /** |
||
723 | * Determine if the renderer is for export. |
||
724 | * |
||
725 | * @return bool |
||
726 | */ |
||
727 | abstract public function isExport(); |
||
728 | |||
729 | /** |
||
730 | * Determin if the renderer is HTML |
||
731 | * It can be export + html -> f.x. |
||
732 | * printing for HTML. |
||
733 | * |
||
734 | * @return bool |
||
735 | */ |
||
736 | abstract public function isHtml(); |
||
737 | |||
738 | /** |
||
739 | * Execute all... |
||
740 | * |
||
741 | * @return ViewModel Response\Stream |
||
742 | */ |
||
743 | abstract public function execute(); |
||
744 | } |
||
745 |
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.