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 VocabularyConfig 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 VocabularyConfig, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
6 | class VocabularyConfig extends BaseConfig |
||
7 | { |
||
8 | private $plugins; |
||
9 | private $pluginParameters; |
||
10 | private $languageOrderCache = array(); |
||
11 | |||
12 | const DEFAULT_PROPERTY_ORDER = array("rdf:type", "dc:isReplacedBy", |
||
13 | "skos:definition", "skos:broader", "isothes:broaderGeneric", |
||
14 | "isothes:broaderPartitive", "isothes:broaderInstantial", |
||
15 | "skos:narrower", "isothes:narrowerGeneric", "isothes:narrowerPartitive", |
||
16 | "isothes:narrowerInstantial", "skos:related", "skos:altLabel", |
||
17 | "skos:note", "skos:scopeNote", "skos:historyNote", "rdfs:comment", |
||
18 | "dc11:source", "dc:source", "skosmos:memberOf", "skosmos:memberOfArray"); |
||
19 | |||
20 | const ISO25964_PROPERTY_ORDER = array("rdf:type", "dc:isReplacedBy", |
||
21 | // ISO 25964 allows placing all text fields (inc. SN and DEF) together |
||
22 | // so we will do that, except for HN, which is clearly administrative |
||
23 | "skos:note", "skos:scopeNote", "skos:definition", "rdfs:comment", |
||
24 | "dc11:source", "dc:source", "skos:altLabel", "skos:broader", |
||
25 | "isothes:broaderGeneric", "isothes:broaderPartitive", |
||
26 | "isothes:broaderInstantial", "skos:narrower", "isothes:narrowerGeneric", |
||
27 | "isothes:narrowerPartitive", "isothes:narrowerInstantial", |
||
28 | "skos:related", "skos:historyNote", "skosmos:memberOf", |
||
29 | "skosmos:memberOfArray"); |
||
30 | |||
31 | public function __construct($resource, $globalPlugins=array()) |
||
70 | |||
71 | /** |
||
72 | * Get the SPARQL endpoint URL for this vocabulary |
||
73 | * |
||
74 | * @return string endpoint URL |
||
75 | */ |
||
76 | View Code Duplication | public function getSparqlEndpoint() |
|
87 | |||
88 | /** |
||
89 | * Get the SPARQL graph URI for this vocabulary |
||
90 | * |
||
91 | * @return string|null graph URI |
||
92 | */ |
||
93 | public function getSparqlGraph() |
||
102 | |||
103 | /** |
||
104 | * Get the SPARQL dialect for this vocabulary |
||
105 | * |
||
106 | * @return string|null dialect name |
||
107 | */ |
||
108 | public function getSparqlDialect() |
||
117 | |||
118 | /** |
||
119 | * Get the default language of this vocabulary |
||
120 | * @return string default language, e.g. 'en' |
||
121 | */ |
||
122 | |||
123 | public function getDefaultLanguage() |
||
138 | |||
139 | /** |
||
140 | * Whether the alphabetical index is small enough to be shown all at once. |
||
141 | * @return boolean true if all concepts can be shown at once. |
||
142 | */ |
||
143 | public function getAlphabeticalFull() |
||
147 | |||
148 | /** |
||
149 | * Returns a short name for a vocabulary if configured. If that has not been set |
||
150 | * using vocabId as a fallback. |
||
151 | * @return string |
||
152 | */ |
||
153 | public function getShortName() |
||
162 | |||
163 | /** |
||
164 | * Get the vocabulary feedback e-mail address and return it. |
||
165 | * |
||
166 | * @return string e-mail address or null if not defined. |
||
167 | */ |
||
168 | public function getFeedbackRecipient() |
||
173 | |||
174 | /** |
||
175 | * Returns the human readable vocabulary title. |
||
176 | * @return string the title of the vocabulary |
||
177 | */ |
||
178 | public function getTitle($lang = null) |
||
182 | |||
183 | /** |
||
184 | * Returns a boolean value set in the config.ttl config. |
||
185 | * @return boolean |
||
186 | */ |
||
187 | public function sortByNotation() |
||
191 | |||
192 | /** |
||
193 | * Returns a boolean value set in the config.ttl config. |
||
194 | * @return boolean |
||
195 | */ |
||
196 | public function showChangeList() |
||
200 | |||
201 | /** |
||
202 | * get the URLs from which the vocabulary data can be downloaded |
||
203 | * @return array Array with MIME type as key, URL as value |
||
204 | */ |
||
205 | public function getDataURLs() |
||
247 | |||
248 | /** |
||
249 | * Returns the main Concept Scheme URI of that Vocabulary, |
||
250 | * or null if not set. |
||
251 | * @return string concept scheme URI or null |
||
252 | */ |
||
253 | |||
254 | public function getMainConceptSchemeURI() |
||
263 | |||
264 | /** |
||
265 | * Returns the class URI used for concept groups in this vocabulary, |
||
266 | * or null if not set. |
||
267 | * @return string group class URI or null |
||
268 | */ |
||
269 | |||
270 | public function getGroupClassURI() |
||
279 | |||
280 | /** |
||
281 | * Returns the class URI used for thesaurus arrays in this vocabulary, |
||
282 | * or null if not set. |
||
283 | * @return string array class URI or null |
||
284 | */ |
||
285 | |||
286 | public function getArrayClassURI() |
||
295 | |||
296 | /** |
||
297 | * Returns custom properties displayed on the search page if configured. |
||
298 | * @return array array class URI or null |
||
299 | */ |
||
300 | |||
301 | View Code Duplication | public function getAdditionalSearchProperties() |
|
316 | |||
317 | /** |
||
318 | * Queries whether the property should be shown with all the label language variations. |
||
319 | * @param string $property |
||
320 | * @return boolean |
||
321 | */ |
||
322 | public function hasMultiLingualProperty($property) |
||
339 | |||
340 | /** |
||
341 | * Returns a boolean value set in the config.ttl config. |
||
342 | * @return boolean |
||
343 | */ |
||
344 | public function getShowHierarchy() |
||
348 | |||
349 | /** |
||
350 | * Returns a boolean value set in the config.ttl config. |
||
351 | * @return boolean |
||
352 | */ |
||
353 | public function showConceptSchemesInHierarchy() |
||
357 | |||
358 | /** |
||
359 | * Returns a boolean value set in the config.ttl config. |
||
360 | * @return boolean defaults to true if fetching hasn't been explicitly denied. |
||
361 | */ |
||
362 | public function getExternalResourcesLoading() |
||
366 | |||
367 | /** |
||
368 | * Returns a boolean value set in the config.ttl config. |
||
369 | * @return boolean |
||
370 | */ |
||
371 | public function getShowLangCodes() |
||
375 | |||
376 | /** |
||
377 | * Returns a boolean value set in the config.ttl config. |
||
378 | * @return boolean |
||
379 | */ |
||
380 | public function searchByNotation() |
||
384 | |||
385 | /** |
||
386 | * Returns skosmos:marcSourcecode value set in config.ttl. |
||
387 | * @return string marcsource name |
||
388 | */ |
||
389 | public function getMarcSourceCode($lang = null) |
||
393 | |||
394 | /** |
||
395 | * Returns a boolean value set in the config.ttl config. |
||
396 | * @return array array of concept class URIs (can be empty) |
||
397 | */ |
||
398 | public function getIndexClasses() |
||
402 | |||
403 | /** |
||
404 | * Returns skosmos:externalProperty values set in the config.ttl config. |
||
405 | * @return array array of external property URIs (can be empty) |
||
406 | */ |
||
407 | public function getExtProperties() |
||
411 | |||
412 | /** |
||
413 | * Get the languages supported by this vocabulary |
||
414 | * @return array languages supported by this vocabulary (as language tag strings) |
||
415 | */ |
||
416 | public function getLanguages() |
||
428 | |||
429 | /** |
||
430 | * Returns the plugin parameters |
||
431 | * @return string plugin parameters or null |
||
432 | */ |
||
433 | public function getPluginParameters() { |
||
436 | |||
437 | /** |
||
438 | * Returns the vocabulary default sidebar view. |
||
439 | * @return string name of the view |
||
440 | */ |
||
441 | public function getDefaultSidebarView() |
||
460 | |||
461 | /** |
||
462 | * Extracts the vocabulary id string from the baseuri of the vocabulary. |
||
463 | * @return string identifier eg. 'mesh'. |
||
464 | */ |
||
465 | public function getId() |
||
479 | |||
480 | public function getShowStatistics() { |
||
483 | |||
484 | public function getPlugins() |
||
488 | |||
489 | /** |
||
490 | * Returns the property/properties used for visualizing concept hierarchies. |
||
491 | * @return array array class URI or null |
||
492 | */ |
||
493 | |||
494 | View Code Duplication | public function getHierarchyProperty() |
|
509 | |||
510 | /** |
||
511 | * Returns a boolean value set in the config.ttl config. |
||
512 | * @return boolean |
||
513 | */ |
||
514 | public function showNotation() |
||
518 | |||
519 | /** |
||
520 | * Returns a boolean value set in the config.ttl config. |
||
521 | * @return boolean |
||
522 | */ |
||
523 | public function showAlphabeticalIndex() |
||
527 | |||
528 | /** |
||
529 | * Returns the alphabetical list qualifier in this vocabulary, |
||
530 | * or null if not set. |
||
531 | * @return EasyRdf\Resource|null alphabetical list qualifier resource or null |
||
532 | */ |
||
533 | public function getAlphabeticalListQualifier() |
||
537 | |||
538 | /** |
||
539 | * Returns a boolean value set in the config.ttl config. |
||
540 | * @return boolean |
||
541 | */ |
||
542 | public function getShowDeprecated() |
||
546 | |||
547 | /** |
||
548 | * Returns the vocabulary dc:type value(s) with their labels and uris, if set in the vocabulary configuration. |
||
549 | * @return array of objects or an empty array |
||
550 | */ |
||
551 | public function getTypes($lang = null) |
||
562 | |||
563 | /** |
||
564 | * Returns an array of fallback languages that is ordered by priority and |
||
565 | * defined in the vocabulary configuration as a collection. |
||
566 | * Additionally, the chosen content language is inserted with the highest priority |
||
567 | * and the vocab default language is inserted with the lowest priority. |
||
568 | * @param string $clang |
||
569 | * @return array of language code strings |
||
570 | */ |
||
571 | public function getLanguageOrder($clang) |
||
595 | |||
596 | /** |
||
597 | * @return boolean |
||
598 | */ |
||
599 | public function isUseModifiedDate() |
||
603 | |||
604 | /** |
||
605 | * @return array |
||
606 | */ |
||
607 | public function getPropertyOrder() |
||
635 | } |
||
636 |
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.