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 Widget 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 Widget, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
21 | abstract class Widget extends HtmlDoubleElement { |
||
22 | use FieldAsTrait,FormTrait; |
||
23 | |||
24 | /** |
||
25 | * @var string classname |
||
26 | */ |
||
27 | protected $_model; |
||
28 | protected $_modelInstance; |
||
29 | /** |
||
30 | * @var InstanceViewer |
||
31 | */ |
||
32 | protected $_instanceViewer; |
||
33 | /** |
||
34 | * @var HtmlMenu |
||
35 | */ |
||
36 | protected $_toolbar; |
||
37 | /** |
||
38 | * @var PositionInTable |
||
39 | */ |
||
40 | protected $_toolbarPosition; |
||
41 | |||
42 | /** |
||
43 | * @var boolean |
||
44 | */ |
||
45 | protected $_edition; |
||
46 | |||
47 | /** |
||
48 | * @var HtmlForm |
||
49 | */ |
||
50 | protected $_form; |
||
51 | |||
52 | protected $_generated; |
||
53 | |||
54 | |||
55 | public function __construct($identifier,$model,$modelInstance=NULL) { |
||
67 | |||
68 | protected function _init($instanceViewer,$contentKey,$content,$edition){ |
||
74 | |||
75 | protected function _getFieldIdentifier($prefix,$name=""){ |
||
78 | |||
79 | protected function _getFieldName($index){ |
||
82 | |||
83 | protected function _getFieldCaption($index){ |
||
86 | |||
87 | abstract protected function _setToolbarPosition($table,$captions=NULL); |
||
88 | |||
89 | public function show($modelInstance){ |
||
92 | |||
93 | public function getModel() { |
||
96 | |||
97 | public function setModel($_model) { |
||
101 | |||
102 | public function getInstanceViewer() { |
||
105 | |||
106 | public function setInstanceViewer($_instanceViewer) { |
||
110 | |||
111 | abstract public function getHtmlComponent(); |
||
112 | |||
113 | public function setAttached($value=true){ |
||
116 | |||
117 | public function setColor($color){ |
||
120 | |||
121 | |||
122 | public function setCaptions($captions){ |
||
126 | |||
127 | public function setFields($fields){ |
||
131 | |||
132 | public function addField($field){ |
||
136 | |||
137 | public function addMessage($attributes=NULL,$fieldName="message"){ |
||
142 | |||
143 | public function addErrorMessage(){ |
||
146 | |||
147 | public function insertField($index,$field){ |
||
151 | |||
152 | public function insertInField($index,$field){ |
||
156 | |||
157 | public function setValueFunction($index,$callback){ |
||
161 | |||
162 | public function setIdentifierFunction($callback){ |
||
166 | |||
167 | /** |
||
168 | * @return \Ajax\semantic\html\collections\menus\HtmlMenu |
||
169 | */ |
||
170 | public function getToolbar(){ |
||
176 | |||
177 | /** |
||
178 | * Adds a new element in toolbar |
||
179 | * @param mixed $element |
||
180 | * @param callable $callback function to call on $element |
||
181 | * @return \Ajax\common\html\HtmlDoubleElement |
||
182 | */ |
||
183 | public function addInToolbar($element,$callback=NULL){ |
||
197 | |||
198 | /** |
||
199 | * @param string $caption |
||
200 | * @param string $icon |
||
201 | * @param callable $callback function($element) |
||
202 | * @return \Ajax\common\html\HtmlDoubleElement |
||
203 | */ |
||
204 | public function addItemInToolbar($caption,$icon=NULL,$callback=NULL){ |
||
210 | |||
211 | /** |
||
212 | * @param array $items |
||
213 | * @param callable $callback function($element) |
||
214 | * @return \Ajax\common\Widget |
||
215 | */ |
||
216 | public function addItemsInToolbar(array $items,$callback=NULL){ |
||
228 | |||
229 | /** |
||
230 | * @param string $value |
||
231 | * @param array $items |
||
232 | * @param callable $callback function($element) |
||
233 | * @return \Ajax\common\html\HtmlDoubleElement |
||
234 | */ |
||
235 | View Code Duplication | public function addDropdownInToolbar($value,$items,$callback=NULL){ |
|
242 | |||
243 | /** |
||
244 | * @param string $caption |
||
245 | * @param string $cssStyle |
||
246 | * @param callable $callback function($element) |
||
247 | * @return \Ajax\common\html\HtmlDoubleElement |
||
248 | */ |
||
249 | public function addButtonInToolbar($caption,$cssStyle=null,$callback=NULL){ |
||
253 | |||
254 | /** |
||
255 | * @param array $captions |
||
256 | * @param boolean $asIcon |
||
257 | * @param callable $callback function($element) |
||
258 | * @return \Ajax\common\html\HtmlDoubleElement |
||
259 | */ |
||
260 | public function addButtonsInToolbar(array $captions,$asIcon=false,$callback=NULL){ |
||
264 | |||
265 | /** |
||
266 | * @param string $caption |
||
267 | * @param string $icon |
||
268 | * @param boolean $before |
||
269 | * @param boolean $labeled |
||
270 | * @return \Ajax\common\html\HtmlDoubleElement |
||
271 | */ |
||
272 | public function addLabelledIconButtonInToolbar($caption,$icon,$before=true,$labeled=false){ |
||
277 | |||
278 | public function addSubmitInToolbar($identifier,$value,$cssStyle=NULL,$url=NULL,$responseElement=NULL,$parameters=NULL){ |
||
283 | |||
284 | /** |
||
285 | * Defines a callback function to call for modifying captions |
||
286 | * function parameters are $captions: the captions to modify and $instance: the active model instance |
||
287 | * @param callable $captionCallback |
||
288 | * @return Widget |
||
289 | */ |
||
290 | public function setCaptionCallback($captionCallback) { |
||
294 | |||
295 | /** |
||
296 | * Makes the input fields editable |
||
297 | * @param boolean $_edition |
||
298 | * @return \Ajax\common\Widget |
||
299 | */ |
||
300 | public function setEdition($_edition=true) { |
||
304 | |||
305 | /** |
||
306 | * Defines the default function which displays fields value |
||
307 | * @param callable $defaultValueFunction function parameters are : $name : the field name, $value : the field value ,$index : the field index, $instance : the active instance of model |
||
308 | * @return \Ajax\common\Widget |
||
309 | */ |
||
310 | public function setDefaultValueFunction($defaultValueFunction){ |
||
314 | |||
315 | /** |
||
316 | * @param string|boolean $disable |
||
317 | * @return string |
||
318 | */ |
||
319 | public function jsDisabled($disable=true){ |
||
322 | |||
323 | /** |
||
324 | * @param string $caption |
||
325 | * @param callable $callback function($element) |
||
326 | * @return \Ajax\common\html\HtmlDoubleElement |
||
327 | */ |
||
328 | public function addEditButtonInToolbar($caption,$callback=NULL){ |
||
335 | |||
336 | public function setToolbar(HtmlMenu $_toolbar) { |
||
340 | |||
341 | public function setToolbarPosition($_toolbarPosition) { |
||
345 | |||
346 | public function getForm() { |
||
353 | |||
354 | public function run(JsUtils $js){ |
||
361 | |||
362 | protected function runForm(JsUtils $js){ |
||
369 | |||
370 | protected function _compileForm(){ |
||
378 | |||
379 | public function setValidationParams(array $_validationParams) { |
||
383 | } |
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.