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 DrushDriver 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 DrushDriver, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
13 | class DrushDriver extends BaseDriver { |
||
14 | /** |
||
15 | * Store a drush alias for tests requiring shell access. |
||
16 | * |
||
17 | * @var string |
||
18 | */ |
||
19 | public $alias; |
||
20 | |||
21 | /** |
||
22 | * Stores the root path to a Drupal installation. |
||
23 | * |
||
24 | * This is an alternative to using drush aliases. |
||
25 | * |
||
26 | * @var string |
||
27 | */ |
||
28 | public $root; |
||
29 | |||
30 | /** |
||
31 | * Store the path to drush binary. |
||
32 | * |
||
33 | * @var string |
||
34 | */ |
||
35 | public $binary; |
||
36 | |||
37 | /** |
||
38 | * Track bootstrapping. |
||
39 | * |
||
40 | * @var bool |
||
41 | */ |
||
42 | private $bootstrapped = FALSE; |
||
43 | |||
44 | /** |
||
45 | * Random generator. |
||
46 | * |
||
47 | * @var \Drupal\Component\Utility\Random |
||
48 | */ |
||
49 | private $random; |
||
50 | |||
51 | /** |
||
52 | * Global arguments or options for drush commands. |
||
53 | * |
||
54 | * @var string |
||
55 | */ |
||
56 | private $arguments = ''; |
||
57 | |||
58 | /** |
||
59 | * Tracks legacy drush. |
||
60 | * |
||
61 | * @var bool |
||
62 | */ |
||
63 | protected static $isLegacyDrush; |
||
64 | |||
65 | /** |
||
66 | * Set drush alias or root path. |
||
67 | * |
||
68 | * @param string $alias |
||
69 | * A drush alias. |
||
70 | * @param string $root_path |
||
71 | * The root path of the Drupal install. This is an alternative to using |
||
72 | * aliases. |
||
73 | * @param string $binary |
||
74 | * The path to the drush binary. |
||
75 | * @param \Drupal\Component\Utility\Random $random |
||
76 | * Random generator. |
||
77 | * |
||
78 | * @throws \Drupal\Driver\Exception\BootstrapException |
||
79 | * Thrown when a required parameter is missing. |
||
80 | */ |
||
81 | public function __construct($alias = NULL, $root_path = NULL, $binary = 'drush', Random $random = NULL) { |
||
102 | |||
103 | /** |
||
104 | * {@inheritdoc} |
||
105 | */ |
||
106 | public function getRandom() { |
||
109 | |||
110 | /** |
||
111 | * {@inheritdoc} |
||
112 | */ |
||
113 | public function bootstrap() { |
||
128 | |||
129 | /** |
||
130 | * Determine if drush is a legacy version. |
||
131 | * |
||
132 | * @return bool |
||
133 | * Returns TRUE if drush is older than drush 9. |
||
134 | */ |
||
135 | protected function isLegacyDrush() { |
||
147 | |||
148 | /** |
||
149 | * {@inheritdoc} |
||
150 | */ |
||
151 | public function isBootstrapped() { |
||
154 | |||
155 | /** |
||
156 | * {@inheritdoc} |
||
157 | */ |
||
158 | public function userCreate(\stdClass $user) { |
||
176 | |||
177 | /** |
||
178 | * Parse user id from drush user-information output. |
||
179 | */ |
||
180 | protected function parseUserId($info) { |
||
189 | |||
190 | /** |
||
191 | * {@inheritdoc} |
||
192 | */ |
||
193 | public function userDelete(\stdClass $user) { |
||
201 | |||
202 | /** |
||
203 | * {@inheritdoc} |
||
204 | */ |
||
205 | public function userAddRole(\stdClass $user, $role) { |
||
212 | |||
213 | /** |
||
214 | * {@inheritdoc} |
||
215 | */ |
||
216 | public function fetchWatchdog($count = 10, $type = NULL, $severity = NULL) { |
||
224 | |||
225 | /** |
||
226 | * {@inheritdoc} |
||
227 | */ |
||
228 | public function clearCache($type = 'all') { |
||
241 | |||
242 | /** |
||
243 | * {@inheritdoc} |
||
244 | */ |
||
245 | public function clearStaticCaches() { |
||
249 | |||
250 | /** |
||
251 | * Decodes JSON object returned by Drush. |
||
252 | * |
||
253 | * It will clean up any junk that may have appeared before or after the |
||
254 | * JSON object. This can happen with remote Drush aliases. |
||
255 | * |
||
256 | * @param string $output |
||
257 | * The output from Drush. |
||
258 | * |
||
259 | * @return object |
||
260 | * The decoded JSON object. |
||
261 | */ |
||
262 | protected function decodeJsonObject($output) { |
||
269 | |||
270 | /** |
||
271 | * {@inheritdoc} |
||
272 | */ |
||
273 | View Code Duplication | public function createEntity($entity_type, \StdClass $entity) { |
|
282 | |||
283 | /** |
||
284 | * {@inheritdoc} |
||
285 | */ |
||
286 | View Code Duplication | public function entityDelete($entity_type, \StdClass $entity) { |
|
294 | |||
295 | /** |
||
296 | * {@inheritdoc} |
||
297 | */ |
||
298 | public function createNode($node) { |
||
311 | |||
312 | /** |
||
313 | * {@inheritdoc} |
||
314 | */ |
||
315 | public function nodeDelete($node) { |
||
318 | |||
319 | /** |
||
320 | * {@inheritdoc} |
||
321 | */ |
||
322 | public function createTerm(\stdClass $term) { |
||
330 | |||
331 | /** |
||
332 | * {@inheritdoc} |
||
333 | */ |
||
334 | public function termDelete(\stdClass $term) { |
||
337 | |||
338 | /** |
||
339 | * {@inheritdoc} |
||
340 | */ |
||
341 | public function isField($entity_type, $field_name) { |
||
357 | |||
358 | /** |
||
359 | * Sets common drush arguments or options. |
||
360 | * |
||
361 | * @param string $arguments |
||
362 | * Global arguments to add to every drush command. |
||
363 | */ |
||
364 | public function setArguments($arguments) { |
||
367 | |||
368 | /** |
||
369 | * Get common drush arguments. |
||
370 | */ |
||
371 | public function getArguments() { |
||
374 | |||
375 | /** |
||
376 | * Parse arguments into a string. |
||
377 | * |
||
378 | * @param array $arguments |
||
379 | * An array of argument/option names to values. |
||
380 | * |
||
381 | * @return string |
||
382 | * The parsed arguments. |
||
383 | */ |
||
384 | protected static function parseArguments(array $arguments) { |
||
396 | |||
397 | /** |
||
398 | * Execute a drush command. |
||
399 | */ |
||
400 | public function drush($command, array $arguments = [], array $options = []) { |
||
436 | |||
437 | /** |
||
438 | * {@inheritdoc} |
||
439 | */ |
||
440 | public function processBatch() { |
||
444 | |||
445 | /** |
||
446 | * {@inheritdoc} |
||
447 | */ |
||
448 | public function runCron() { |
||
451 | |||
452 | /** |
||
453 | * Run Drush commands dynamically from a DrupalContext. |
||
454 | */ |
||
455 | public function __call($name, $arguments) { |
||
458 | |||
459 | } |
||
460 |
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.