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 VueJs 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 VueJs, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
17 | class VueJs extends Extractor implements ExtractorInterface, ExtractorMultiInterface |
||
18 | { |
||
19 | public static $options = [ |
||
20 | 'constants' => [], |
||
21 | |||
22 | 'functions' => [ |
||
23 | 'gettext' => 'gettext', |
||
24 | '__' => 'gettext', |
||
25 | 'ngettext' => 'ngettext', |
||
26 | 'n__' => 'ngettext', |
||
27 | 'pgettext' => 'pgettext', |
||
28 | 'p__' => 'pgettext', |
||
29 | 'dgettext' => 'dgettext', |
||
30 | 'd__' => 'dgettext', |
||
31 | 'dngettext' => 'dngettext', |
||
32 | 'dn__' => 'dngettext', |
||
33 | 'dpgettext' => 'dpgettext', |
||
34 | 'dp__' => 'dpgettext', |
||
35 | 'npgettext' => 'npgettext', |
||
36 | 'np__' => 'npgettext', |
||
37 | 'dnpgettext' => 'dnpgettext', |
||
38 | 'dnp__' => 'dnpgettext', |
||
39 | 'noop' => 'noop', |
||
40 | 'noop__' => 'noop', |
||
41 | ], |
||
42 | ]; |
||
43 | |||
44 | /** |
||
45 | * @inheritDoc |
||
46 | * @throws Exception |
||
47 | */ |
||
48 | View Code Duplication | public static function fromFileMultiple($file, array $translations, array $options = []) |
|
55 | |||
56 | /** |
||
57 | * @inheritdoc |
||
58 | * @throws Exception |
||
59 | */ |
||
60 | public static function fromString($string, Translations $translations, array $options = []) |
||
64 | |||
65 | /** |
||
66 | * @inheritDoc |
||
67 | * @throws Exception |
||
68 | */ |
||
69 | public static function fromStringMultiple($string, array $translations, array $options = []) |
||
140 | |||
141 | /** |
||
142 | * Extracts script tag contents using regex instead of DOM operations. |
||
143 | * If we parse using DOM, some contents may change, for example, tags within strings will be stripped |
||
144 | * |
||
145 | * @param $string |
||
146 | * @return bool|string |
||
147 | */ |
||
148 | private static function extractScriptTag($string) |
||
156 | |||
157 | /** |
||
158 | * @param string $html |
||
159 | * @return DOMDocument |
||
160 | */ |
||
161 | private static function convertHtmlToDom($html) |
||
172 | |||
173 | /** |
||
174 | * Extract translations from script part |
||
175 | * |
||
176 | * @param string $scriptContents Only script tag contents, not the whole template |
||
177 | * @param Translations|Translations[] $translations One or multiple domain Translation objects |
||
178 | * @param array $options |
||
179 | * @param int $lineOffset Number of lines the script is offset in the vue template file |
||
180 | * @throws Exception |
||
181 | */ |
||
182 | private static function getScriptTranslationsFromString( |
||
192 | |||
193 | /** |
||
194 | * Parse template to extract all translations (element content and dynamic element attributes) |
||
195 | * |
||
196 | * @param DOMNode $dom |
||
197 | * @param Translations|Translations[] $translations One or multiple domain Translation objects |
||
198 | * @param array $options |
||
199 | * @param int $lineOffset Line number where the template part starts in the vue file |
||
200 | * @throws Exception |
||
201 | */ |
||
202 | private static function getTemplateTranslations( |
||
220 | |||
221 | /** |
||
222 | * @param array $options |
||
223 | * @param DOMNode $dom |
||
224 | * @param Translations|Translations[] $translations |
||
225 | */ |
||
226 | private static function getTagTranslations(array $options, DOMNode $dom, $translations) |
||
281 | |||
282 | /** |
||
283 | * Extract JS expressions from element attribute bindings (excluding text within elements) |
||
284 | * For example: <span :title="__('extract this')"> skip element content </span> |
||
285 | * |
||
286 | * @param array $options |
||
287 | * @param DOMNode $dom |
||
288 | * @return string JS code |
||
289 | */ |
||
290 | private static function getTemplateAttributeFakeJs(array $options, DOMNode $dom) |
||
310 | |||
311 | /** |
||
312 | * Loop DOM element recursively and parse out all dynamic vue attributes which are basically JS expressions |
||
313 | * |
||
314 | * @param array $attributePrefixes List of attribute prefixes we parse as JS (may contain translations) |
||
315 | * @param DOMNode $dom |
||
316 | * @param array $expressionByLine [lineNumber => [jsExpression, ..], ..] |
||
317 | * @return array [lineNumber => [jsExpression, ..], ..] |
||
318 | */ |
||
319 | private static function getVueAttributeExpressions( |
||
353 | |||
354 | /** |
||
355 | * Check if this attribute name should be parsed for translations |
||
356 | * |
||
357 | * @param string $attributeName |
||
358 | * @param string[] $attributePrefixes |
||
359 | * @return bool |
||
360 | */ |
||
361 | private static function isAttributeMatching($attributeName, $attributePrefixes) |
||
370 | |||
371 | /** |
||
372 | * Extract JS expressions from within template elements (excluding attributes) |
||
373 | * For example: <span :title="skip attributes"> {{__("extract element content")}} </span> |
||
374 | * |
||
375 | * @param DOMNode $dom |
||
376 | * @return string JS code |
||
377 | */ |
||
378 | private static function getTemplateFakeJs(DOMNode $dom) |
||
392 | |||
393 | /** |
||
394 | * Match JS expressions in a template line |
||
395 | * |
||
396 | * @param string $line |
||
397 | * @return string[] |
||
398 | */ |
||
399 | private static function parseOneTemplateLine($line) |
||
417 | } |
||
418 |
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.