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 Sanitize 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 Sanitize, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
21 | class Sanitize implements Filter\FilterInterface |
||
22 | { |
||
23 | /** |
||
24 | * Character(s) used to replace delimiters |
||
25 | * |
||
26 | * @var string |
||
27 | */ |
||
28 | protected $delimiterReplacement; |
||
29 | |||
30 | /** |
||
31 | * Word delimiters which are replaced by spaceReplacement string |
||
32 | * |
||
33 | * @var array |
||
34 | */ |
||
35 | protected $wordDelimiters = [' ', '.', '\\', '/', '-', '_']; |
||
36 | |||
37 | /** |
||
38 | * Which characters are not replaced |
||
39 | * |
||
40 | * @var array |
||
41 | */ |
||
42 | protected $notReplacedChars = []; |
||
43 | |||
44 | /** |
||
45 | * @var Transliteration |
||
46 | */ |
||
47 | protected $transliteration; |
||
48 | |||
49 | /** |
||
50 | * @var Filter\StringTrim |
||
51 | */ |
||
52 | protected $stringTrim; |
||
53 | |||
54 | /** |
||
55 | * @var Filter\StringToLower |
||
56 | */ |
||
57 | protected $stringToLower; |
||
58 | |||
59 | /** |
||
60 | * |
||
61 | * @param string $delimiterReplacement |
||
62 | * @param string|array $wordDelimiters |
||
63 | */ |
||
64 | public function __construct($delimiterReplacement = '-', $wordDelimiters = null) |
||
71 | |||
72 | /** |
||
73 | * Returns $value filtered to valid URL |
||
74 | * |
||
75 | * @param string $s |
||
76 | * @return string |
||
77 | */ |
||
78 | public function filter($s) |
||
96 | |||
97 | /** |
||
98 | * @return Transliteration |
||
99 | */ |
||
100 | public function getTransliteration() |
||
107 | |||
108 | /** |
||
109 | * @param Transliteration $transliteration |
||
110 | * @return $this |
||
111 | */ |
||
112 | public function setTransliteration(Transliteration $transliteration) |
||
117 | |||
118 | /** |
||
119 | * @return Filter\StringTrim |
||
120 | */ |
||
121 | public function getStringTrim() |
||
128 | |||
129 | /** |
||
130 | * @param Filter\StringTrim $stringTrim |
||
131 | * @return $this |
||
132 | */ |
||
133 | public function setStringTrim(Filter\StringTrim $stringTrim) |
||
138 | |||
139 | /** |
||
140 | * @return Filter\StringToLower |
||
141 | */ |
||
142 | public function getStringToLower() |
||
150 | |||
151 | /** |
||
152 | * @param Filter\StringToLower $stringToLower |
||
153 | * @return $this |
||
154 | */ |
||
155 | public function setStringToLower(Filter\StringToLower $stringToLower) |
||
160 | |||
161 | /** |
||
162 | * @param string|array $notReplaced |
||
163 | * @return $this |
||
164 | * @throws Exception\RuntimeException |
||
165 | */ |
||
166 | View Code Duplication | public function addNotReplacedChars($notReplaced) |
|
184 | |||
185 | /** |
||
186 | * Returns chars which are not replaced |
||
187 | * |
||
188 | * @return array |
||
189 | */ |
||
190 | public function getNotReplacedChars() |
||
194 | |||
195 | /** |
||
196 | * Remove not replaced character |
||
197 | * |
||
198 | * @param string|array $notReplaced |
||
199 | * @return $this |
||
200 | * @throws Exception\RuntimeException |
||
201 | */ |
||
202 | View Code Duplication | public function removeNotReplacedChar($notReplaced) |
|
228 | |||
229 | /** |
||
230 | * Returns the delimiterReplacement option |
||
231 | * |
||
232 | * @return string |
||
233 | */ |
||
234 | public function getDelimiterReplacement() |
||
238 | |||
239 | /** |
||
240 | * Sets the delimiterReplacement option |
||
241 | * |
||
242 | * @param string $delimiterReplacement |
||
243 | * @return $this |
||
244 | */ |
||
245 | public function setDelimiterReplacement($delimiterReplacement) |
||
250 | |||
251 | /** |
||
252 | * Returns word delimiters array |
||
253 | * |
||
254 | * @return array |
||
255 | */ |
||
256 | public function getWordDelimiters() |
||
260 | |||
261 | /** |
||
262 | * Add word delimiter |
||
263 | * |
||
264 | * @param string|array $delimiter |
||
265 | * @return $this |
||
266 | * @throws Exception\RuntimeException |
||
267 | */ |
||
268 | View Code Duplication | public function addWordDelimiter($delimiter) |
|
286 | |||
287 | /** |
||
288 | * Remove word delimiter |
||
289 | * |
||
290 | * @param string|array $delimiters |
||
291 | * @return $this |
||
292 | * @throws Exception\RuntimeException |
||
293 | */ |
||
294 | View Code Duplication | public function removeWordDelimiter($delimiters) |
|
320 | |||
321 | /** |
||
322 | * Replace delimiters with another string |
||
323 | * |
||
324 | * @param string $s |
||
325 | * @return string |
||
326 | */ |
||
327 | private function replaceDelimiters($s) |
||
344 | |||
345 | /** |
||
346 | * To special chars |
||
347 | * |
||
348 | * @param string $s |
||
349 | * @return string |
||
350 | */ |
||
351 | private function trimSpecialsChars($s) |
||
360 | |||
361 | /** |
||
362 | * Replace double delimiter with single one |
||
363 | * |
||
364 | * @param string $s |
||
365 | * @return string |
||
366 | */ |
||
367 | private function replaceDoubleDelimiterReplacementWithSingle($s) |
||
375 | |||
376 | /** |
||
377 | * Trim dashes on beginning/end of the string |
||
378 | * |
||
379 | * @param string $s |
||
380 | * @return string |
||
381 | */ |
||
382 | private function trimStartAndEndSpaceReplacement($s) |
||
386 | } |
||
387 |
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.