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 Command 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 Command, and based on these observations, apply Extract Interface, too.
1 | <?php namespace Tarsana\Command; |
||
17 | class Command { |
||
18 | |||
19 | protected $name; |
||
20 | protected $version; |
||
21 | protected $description; |
||
22 | |||
23 | protected $syntax; |
||
24 | protected $descriptions; |
||
25 | |||
26 | protected $options; |
||
27 | protected $args; |
||
28 | |||
29 | protected $action; |
||
30 | protected $commands; |
||
31 | |||
32 | protected $console; |
||
33 | protected $fs; |
||
34 | protected $templatesLoader; |
||
35 | |||
36 | public static function create(callable $action = null) { |
||
42 | |||
43 | public function __construct() |
||
56 | |||
57 | /** |
||
58 | * name getter and setter. |
||
59 | * |
||
60 | * @param string |
||
61 | * @return mixed |
||
62 | */ |
||
63 | View Code Duplication | public function name(string $value = null) |
|
71 | |||
72 | /** |
||
73 | * version getter and setter. |
||
74 | * |
||
75 | * @param string |
||
76 | * @return mixed |
||
77 | */ |
||
78 | public function version(string $value = null) |
||
86 | |||
87 | /** |
||
88 | * description getter and setter. |
||
89 | * |
||
90 | * @param string |
||
91 | * @return mixed |
||
92 | */ |
||
93 | View Code Duplication | public function description(string $value = null) |
|
101 | |||
102 | /** |
||
103 | * descriptions getter and setter. |
||
104 | * |
||
105 | * @param string |
||
106 | * @return mixed |
||
107 | */ |
||
108 | public function descriptions(array $value = null) |
||
116 | |||
117 | /** |
||
118 | * syntax getter and setter. |
||
119 | * |
||
120 | * @param string|null $syntax |
||
121 | * @return Syntax|self |
||
122 | */ |
||
123 | public function syntax(string $syntax = null) |
||
131 | |||
132 | /** |
||
133 | * options getter and setter. |
||
134 | * |
||
135 | * @param array |
||
136 | * @return mixed |
||
137 | */ |
||
138 | public function options(array $options = null) |
||
150 | |||
151 | /** |
||
152 | * option getter. |
||
153 | * |
||
154 | * @param string |
||
155 | * @return mixed |
||
156 | */ |
||
157 | public function option(string $name) |
||
163 | |||
164 | /** |
||
165 | * args getter and setter. |
||
166 | * |
||
167 | * @param stdClass |
||
168 | * @return mixed |
||
169 | */ |
||
170 | public function args(\stdClass $value = null) |
||
178 | |||
179 | /** |
||
180 | * console getter and setter. |
||
181 | * |
||
182 | * @param ConsoleInterface |
||
183 | * @return mixed |
||
184 | */ |
||
185 | public function console(ConsoleInterface $value = null) |
||
196 | |||
197 | /** |
||
198 | * fs getter and setter. |
||
199 | * |
||
200 | * @param Tarsana\IO\Filesystem|string |
||
201 | * @return mixed |
||
202 | */ |
||
203 | public function fs($value = null) |
||
216 | |||
217 | /** |
||
218 | * templatesLoader getter and setter. |
||
219 | * |
||
220 | * @param Tarsana\Command\Interfaces\Template\TemplateLoaderInterface |
||
221 | * @return mixed |
||
222 | */ |
||
223 | public function templatesLoader(TemplateLoaderInterface $value = null) |
||
231 | |||
232 | public function templatesPath(string $path, string $cachePath = null) { |
||
236 | |||
237 | public function template(string $name) { |
||
242 | |||
243 | /** |
||
244 | * action getter and setter. |
||
245 | * |
||
246 | * @param callable |
||
247 | * @return mixed |
||
248 | */ |
||
249 | View Code Duplication | public function action(callable $value = null) |
|
257 | |||
258 | public function command(string $name, Command $command = null) |
||
268 | |||
269 | protected function setupSubCommands() |
||
274 | |||
275 | public function describe(string $name, string $description = null) |
||
293 | |||
294 | public function run(array $args = null, array $options = [], bool $rawArgs = true) |
||
329 | |||
330 | public function clear() |
||
337 | |||
338 | public function parseArguments(array $args) |
||
355 | |||
356 | protected function handleError(\Exception $e) { |
||
360 | |||
361 | protected function init() {} |
||
363 | |||
364 | } |
||
365 |
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.