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 Server 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 Server, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
21 | class Server implements ServerInterface |
||
22 | { |
||
23 | /** |
||
24 | * a Checker instance. |
||
25 | * |
||
26 | * @var \WebHelper\Parser\Parser\Checker |
||
27 | */ |
||
28 | private $checker; |
||
29 | |||
30 | /** |
||
31 | * The filesystem path where the web server is installed. |
||
32 | * |
||
33 | * It has to be an absolute path. |
||
34 | * |
||
35 | * Apache httpd server does not accept a relative prefix path at compilation. |
||
36 | * Nginx does, but this is a very risky practice... |
||
37 | * So relative prefix path in nginx configuration will not be considered |
||
38 | * |
||
39 | * @var string |
||
40 | */ |
||
41 | private $prefix = ''; |
||
42 | |||
43 | /** |
||
44 | * The string to match as a starting multi-line directive. |
||
45 | * |
||
46 | * @var string |
||
47 | */ |
||
48 | private $startMultiLine = ''; |
||
49 | |||
50 | /** |
||
51 | * The string to match as an ending multi-line directive. |
||
52 | * |
||
53 | * @var string |
||
54 | */ |
||
55 | private $endMultiLine = ''; |
||
56 | |||
57 | /** |
||
58 | * The string to match a simple directive. |
||
59 | * |
||
60 | * @var string |
||
61 | */ |
||
62 | private $simpleDirective = ''; |
||
63 | |||
64 | /** |
||
65 | * The string to match an inclusion directive. |
||
66 | * |
||
67 | * @var string |
||
68 | */ |
||
69 | private $inclusionDirective = ''; |
||
70 | |||
71 | /** |
||
72 | * binaries that can be used to control the webserver. |
||
73 | * |
||
74 | * @var array |
||
75 | */ |
||
76 | private $binaries = []; |
||
77 | |||
78 | /** |
||
79 | * the parameter string to use to detect version and config file. |
||
80 | * |
||
81 | * @var string |
||
82 | */ |
||
83 | private $detectionParameter = ''; |
||
84 | |||
85 | /** |
||
86 | * The ordered list of methods to apply before convertion. |
||
87 | * |
||
88 | * @var array |
||
89 | */ |
||
90 | private $beforeMethods = []; |
||
91 | |||
92 | /** |
||
93 | * The ordered list of methods to apply after convertion. |
||
94 | * |
||
95 | * @var array |
||
96 | */ |
||
97 | private $afterMethods = []; |
||
98 | |||
99 | /** |
||
100 | * The simple directive syntax when dumped. |
||
101 | * |
||
102 | * @var string |
||
103 | */ |
||
104 | private $dumperSimpleDirective = ''; |
||
105 | |||
106 | /** |
||
107 | * The starting block directive syntax when dumped. |
||
108 | * |
||
109 | * @var string |
||
110 | */ |
||
111 | private $dumperStartDirective = ''; |
||
112 | |||
113 | /** |
||
114 | * The ending block directive syntax when dumped. |
||
115 | * |
||
116 | * @var string |
||
117 | */ |
||
118 | private $dumperEndDirective = ''; |
||
119 | |||
120 | /** |
||
121 | * Sets the Checker instance. |
||
122 | * |
||
123 | * @param Checker $checker a Checker instance |
||
124 | */ |
||
125 | 32 | public function setChecker(Checker $checker) |
|
131 | |||
132 | /** |
||
133 | * Confirms if the server instance has valid parameters. |
||
134 | * |
||
135 | * @return bool true if all parameters are initialized, false otherwise |
||
136 | */ |
||
137 | 2 | public function isValid() |
|
146 | |||
147 | /** |
||
148 | * Getter for the prefix. |
||
149 | * |
||
150 | * @return string the filesystem path where the web server is installed |
||
151 | */ |
||
152 | 4 | public function getPrefix() |
|
156 | |||
157 | /** |
||
158 | * Sets the prefix of a server instance. |
||
159 | * |
||
160 | * @throws ServerException if the prefix is invalid |
||
161 | * |
||
162 | * @param string $prefix the filesystem path where the web server is installed |
||
163 | */ |
||
164 | 11 | public function setPrefix($prefix) |
|
181 | |||
182 | /** |
||
183 | * Gets the regexp that will match the starting block directives. |
||
184 | * |
||
185 | * @return string the regexp that will match the starting block directives |
||
186 | */ |
||
187 | 8 | public function getStartMultiLine() |
|
191 | |||
192 | /** |
||
193 | * Sets the regexp that will match the starting block directives. |
||
194 | * |
||
195 | * @param string $startMultiLine the regexp that will match the starting block directives |
||
196 | */ |
||
197 | 13 | public function setStartMultiLine($startMultiLine) |
|
210 | |||
211 | /** |
||
212 | * Gets the regexp that will match the ending block directives. |
||
213 | * |
||
214 | * @return string the regexp that will match the ending block directives |
||
215 | */ |
||
216 | 8 | public function getEndMultiLine() |
|
220 | |||
221 | /** |
||
222 | * Sets the regexp that will match the ending block directives. |
||
223 | * |
||
224 | * @param string $endMultiLine the regexp that will match the ending block directives |
||
225 | */ |
||
226 | 10 | View Code Duplication | public function setEndMultiLine($endMultiLine) |
246 | |||
247 | /** |
||
248 | * Gets the regexp that will match the simple directives. |
||
249 | * |
||
250 | * @return string the regexp that will match the simple directives |
||
251 | */ |
||
252 | 8 | public function getSimpleDirective() |
|
256 | |||
257 | /** |
||
258 | * Sets the regexp that will match the simple directives. |
||
259 | * |
||
260 | * @param string $simpleDirective the regexp that will match the simple directives |
||
261 | */ |
||
262 | 13 | public function setSimpleDirective($simpleDirective) |
|
275 | |||
276 | /** |
||
277 | * Gets the regexp that will match the inclusion directives. |
||
278 | * |
||
279 | * @return string the regexp that will match the inclusion directives |
||
280 | */ |
||
281 | 7 | public function getInclusionDirective() |
|
285 | |||
286 | /** |
||
287 | * Sets the regexp that will match the inclusion directives. |
||
288 | * |
||
289 | * @param string $inclusionDirective the regexp that will match the inclusion directives |
||
290 | */ |
||
291 | 9 | View Code Duplication | public function setInclusionDirective($inclusionDirective) |
311 | |||
312 | /** |
||
313 | * Confirms if a directive matcher is a valid regex. |
||
314 | * |
||
315 | * @param string $directive the directive matcher to check |
||
316 | * @param string $message1 message exception if the matcher is not a string |
||
317 | * @param string $message2 message exception if the matcher is not a valid regex |
||
318 | * |
||
319 | * @throws ServerException if the directive matcher is invalid |
||
320 | * |
||
321 | * @return bool true if the directive matcher is valid |
||
322 | */ |
||
323 | 19 | private function isValidDirective($directive, $message1, $message2) |
|
341 | |||
342 | /** |
||
343 | * Gets the list of binaries that can be run to analyze. |
||
344 | * |
||
345 | * @return array the list of binaries that can be run |
||
346 | */ |
||
347 | 1 | public function getBinaries() |
|
351 | |||
352 | /** |
||
353 | * Sets the list of binaries that can be run to analyze. |
||
354 | * |
||
355 | * @param array $binaries list of controlers |
||
356 | */ |
||
357 | 8 | public function setBinaries(array $binaries) |
|
363 | |||
364 | /** |
||
365 | * Gets the parameter string to use to detect version and config file. |
||
366 | * |
||
367 | * @return string parameter string |
||
368 | */ |
||
369 | 1 | public function getDetectionParameter() |
|
373 | |||
374 | /** |
||
375 | * Sets the parameter string to use to detect version and config file. |
||
376 | * |
||
377 | * @param string $parameter parameter string |
||
378 | */ |
||
379 | 8 | public function setDetectionParameter($parameter = '') |
|
385 | |||
386 | /** |
||
387 | * Gets the ordered list of methods to apply before the config file turns into an array. |
||
388 | * |
||
389 | * @return array the ordered list of methods to apply before convertion |
||
390 | */ |
||
391 | 14 | public function getBeforeMethods() |
|
395 | |||
396 | /** |
||
397 | * Sets the ordered list of methods to apply before the config file turns into an array. |
||
398 | * |
||
399 | * @param array $methods the ordered list of methods to apply before convertion |
||
400 | */ |
||
401 | 13 | public function setBeforeMethods(array $methods) |
|
407 | |||
408 | /** |
||
409 | * Gets the ordered list of methods to apply after the config file has turned into an array. |
||
410 | * |
||
411 | * @return array the ordered list of methods to apply after convertion |
||
412 | */ |
||
413 | 14 | public function getAfterMethods() |
|
417 | |||
418 | /** |
||
419 | * Sets the ordered list of methods to apply after the config file has turned into an array. |
||
420 | * |
||
421 | * @param array $methods the ordered list of methods to apply after convertion |
||
422 | */ |
||
423 | 13 | public function setAfterMethods(array $methods) |
|
429 | |||
430 | /** |
||
431 | * Gets the simple directive syntax when dumped. |
||
432 | * |
||
433 | * @return string the simple directive syntax when dumped |
||
434 | */ |
||
435 | 1 | public function getDumperSimpleDirective() |
|
439 | |||
440 | /** |
||
441 | * Gets the starting block directive syntax when dumped. |
||
442 | * |
||
443 | * @return string the starting block directive syntax when dumped |
||
444 | */ |
||
445 | 1 | public function getDumperStartDirective() |
|
449 | |||
450 | /** |
||
451 | * Gets the ending block directive syntax when dumped. |
||
452 | * |
||
453 | * @return string the ending block directive syntax when dumped |
||
454 | */ |
||
455 | 1 | public function getDumperEndDirective() |
|
459 | |||
460 | /** |
||
461 | * Sets the simple directive syntax when dumped. |
||
462 | * |
||
463 | * @param string $simpleDirective the simple directive syntax when dumped |
||
464 | */ |
||
465 | 8 | public function setDumperSimpleDirective($simpleDirective) |
|
471 | |||
472 | /** |
||
473 | * Sets the starting block directive syntax when dumped. |
||
474 | * |
||
475 | * @param string $startMultiLine the starting block directive syntax when dumped |
||
476 | */ |
||
477 | 8 | public function setDumperStartDirective($startMultiLine) |
|
483 | |||
484 | /** |
||
485 | * Sets the ending block directive syntax when dumped. |
||
486 | * |
||
487 | * @param string $endMultiLine the ending block directive syntax when dumped |
||
488 | */ |
||
489 | 8 | public function setDumperEndDirective($endMultiLine) |
|
495 | } |
||
496 |
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.