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 AbstractForm 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 AbstractForm, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
17 | abstract class AbstractForm implements FormInterface |
||
18 | { |
||
19 | const ENC_TYPE_MULTIPART_FORM_DATA = 'multipart/form-data'; |
||
20 | const ENC_TYPE_URL_ENCODED = 'application/x-www-form-urlencoded'; |
||
21 | const ENC_TYPE_TEXT_PLAIN = 'text/plain'; |
||
22 | |||
23 | const METHOD_POST = 'post'; |
||
24 | const METHOD_GET = 'get'; |
||
25 | |||
26 | /** @var FieldCollection $fieldCollection */ |
||
27 | private $fieldCollection; |
||
28 | |||
29 | /** @var FormRendererInterface */ |
||
30 | private $formRenderer; |
||
31 | |||
32 | /** @var array $errorMessages */ |
||
33 | private $errorMessages; |
||
34 | |||
35 | /** @var bool $displayErrors */ |
||
36 | private $displayErrors; |
||
37 | |||
38 | use HasAttributesTrait; |
||
39 | |||
40 | /** |
||
41 | * AbstractForm constructor. |
||
42 | * @param $name |
||
43 | */ |
||
44 | 47 | public function __construct($name) |
|
45 | { |
||
46 | 47 | $this->fieldCollection = new FieldCollection(); |
|
47 | 47 | $this->formRenderer = new FormRenderer(); |
|
48 | 47 | $this->attributes = [ |
|
49 | 47 | 'name' => $name, |
|
50 | 47 | 'method' => self::METHOD_POST, |
|
51 | ]; |
||
52 | 47 | $this->displayErrors = false; |
|
53 | 47 | $this->init(); |
|
54 | 47 | } |
|
55 | |||
56 | abstract public function init(); |
||
57 | |||
58 | /** |
||
59 | * @return bool |
||
60 | */ |
||
61 | 8 | public function isValid() |
|
73 | |||
74 | /** |
||
75 | * @param FieldCollection $fields |
||
76 | */ |
||
77 | 8 | private function validateFields(FieldCollection $fields) |
|
87 | |||
88 | /** |
||
89 | * @param FieldInterface $field |
||
90 | */ |
||
91 | 8 | private function checkFieldForErrors(FieldInterface $field) |
|
97 | |||
98 | 8 | View Code Duplication | public function checkDynamicFormsForErrors(FieldInterface $field) |
110 | |||
111 | /** |
||
112 | * @return array |
||
113 | */ |
||
114 | 4 | public function getValues() |
|
126 | |||
127 | /** |
||
128 | * @param array $data |
||
129 | * @return $this |
||
130 | */ |
||
131 | 5 | public function populate(array $data) |
|
139 | |||
140 | /** |
||
141 | * @param array $dynamicForms |
||
142 | * @param array $data |
||
143 | */ |
||
144 | private function populateDynamicForms(array $dynamicForms, array $data) |
||
152 | |||
153 | /** |
||
154 | * @param FieldCollection $fields |
||
155 | * @param array $data |
||
156 | */ |
||
157 | 5 | private function populateFields(FieldCollection $fields, array $data) |
|
165 | |||
166 | /** |
||
167 | * @param FieldInterface $field |
||
168 | * @param array $data |
||
169 | */ |
||
170 | 5 | View Code Duplication | private function populateField(FieldInterface $field, array $data) |
181 | |||
182 | /** |
||
183 | * @param string $name |
||
184 | * @return FieldInterface|null |
||
185 | */ |
||
186 | 2 | public function getField($name) |
|
190 | |||
191 | /** |
||
192 | * @return FieldCollection |
||
193 | */ |
||
194 | 30 | public function getFields() |
|
198 | |||
199 | /** |
||
200 | * @param FieldInterface $field |
||
201 | * @return $this |
||
202 | */ |
||
203 | 38 | public function addField(FieldInterface $field) |
|
208 | |||
209 | /** |
||
210 | * @return string |
||
211 | */ |
||
212 | 28 | public function render() |
|
216 | |||
217 | /** |
||
218 | * @param $url |
||
219 | * @return $this |
||
220 | */ |
||
221 | 2 | public function setAction($url) |
|
226 | |||
227 | /** |
||
228 | * @return string |
||
229 | */ |
||
230 | 2 | public function getAction() |
|
234 | |||
235 | /** |
||
236 | * @return string |
||
237 | */ |
||
238 | 29 | public function getId() |
|
242 | |||
243 | /** |
||
244 | * @param string $id |
||
245 | * @return $this |
||
246 | */ |
||
247 | 2 | public function setId($id) |
|
252 | |||
253 | /** |
||
254 | * @param $encType |
||
255 | * @return $this |
||
256 | */ |
||
257 | 2 | public function setEncType($encType) |
|
262 | |||
263 | /** |
||
264 | * @return string |
||
265 | */ |
||
266 | 1 | public function getEncType() |
|
270 | |||
271 | /** |
||
272 | * @param string $method |
||
273 | * @return FormInterface |
||
274 | */ |
||
275 | 2 | public function setMethod($method) |
|
280 | |||
281 | /** |
||
282 | * @return string |
||
283 | */ |
||
284 | 29 | public function getMethod() |
|
288 | |||
289 | /** |
||
290 | * @param $class |
||
291 | * @return FormInterface |
||
292 | */ |
||
293 | 2 | public function setClass($class) |
|
298 | |||
299 | /** |
||
300 | * @return string |
||
301 | */ |
||
302 | 2 | public function getClass() |
|
306 | |||
307 | /** |
||
308 | * @return boolean |
||
309 | */ |
||
310 | 29 | public function isDisplayErrors() |
|
314 | |||
315 | /** |
||
316 | * @param boolean $displayErrors |
||
317 | * @return AbstractForm |
||
318 | */ |
||
319 | 3 | public function setDisplayErrors($displayErrors) |
|
324 | |||
325 | /** |
||
326 | * @param FormRendererInterface $renderer |
||
327 | * @return AbstractForm |
||
328 | */ |
||
329 | 2 | public function setFormRenderer(FormRendererInterface $renderer) |
|
334 | |||
335 | 6 | public function moveUploadedFiles() |
|
344 | |||
345 | /** |
||
346 | * @param FieldInterface $field |
||
347 | * @return bool |
||
348 | */ |
||
349 | 6 | public function moveFileIfUploadField(FieldInterface $field) |
|
357 | } |
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.