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 YamlFileDriver 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 YamlFileDriver, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
15 | final class YamlFileDriver extends AbstractFileDriver |
||
16 | { |
||
17 | /** |
||
18 | * An in-memory cache of parsed metadata mappings (from file). |
||
19 | * |
||
20 | * @var array |
||
21 | */ |
||
22 | private $mappings = [ |
||
23 | 'model' => [], |
||
24 | 'mixin' => [], |
||
25 | 'embed' => [], |
||
26 | ]; |
||
27 | |||
28 | /** |
||
29 | * {@inheritDoc} |
||
30 | */ |
||
31 | protected function loadMetadataFromFile($type, $file) |
||
62 | |||
63 | /** |
||
64 | * {@inheritDoc} |
||
65 | */ |
||
66 | protected function loadEmbedFromFile($embedName, $file) |
||
76 | |||
77 | /** |
||
78 | * {@inheritDoc} |
||
79 | */ |
||
80 | protected function loadMixinFromFile($mixinName, $file) |
||
90 | |||
91 | /** |
||
92 | * {@inheritDoc} |
||
93 | */ |
||
94 | public function getTypeHierarchy($type, array $types = []) |
||
105 | |||
106 | /** |
||
107 | * {@inheritDoc} |
||
108 | */ |
||
109 | public function getOwnedTypes($type, array $types = []) |
||
136 | |||
137 | /** |
||
138 | * Gets the metadata mapping information from the YAML file. |
||
139 | * |
||
140 | * @param string $metaType The metadata type, either mixin or model. |
||
141 | * @param string $key The metadata key name, either the mixin name or model type. |
||
142 | * @param string $file The YAML file location. |
||
143 | * @return array |
||
144 | * @throws MetadataException |
||
145 | */ |
||
146 | private function getMapping($metaType, $key, $file) |
||
159 | |||
160 | /** |
||
161 | * Sets the entity persistence metadata from the metadata mapping. |
||
162 | * |
||
163 | * @param Metadata\EntityMetadata $metadata |
||
164 | * @param array $mapping |
||
165 | * @return Metadata\EntityMetadata |
||
166 | */ |
||
167 | View Code Duplication | protected function setPersistence(Metadata\EntityMetadata $metadata, array $mapping) |
|
177 | |||
178 | /** |
||
179 | * Sets the entity search metadata from the metadata mapping. |
||
180 | * |
||
181 | * @param Metadata\EntityMetadata $metadata |
||
182 | * @param array $mapping |
||
183 | * @return Metadata\EntityMetadata |
||
184 | */ |
||
185 | View Code Duplication | protected function setSearch(Metadata\EntityMetadata $metadata, array $mapping) |
|
200 | |||
201 | /** |
||
202 | * Sets the entity attribute metadata from the metadata mapping. |
||
203 | * |
||
204 | * @param Metadata\Interfaces\AttributeInterface $metadata |
||
205 | * @param array $attrMapping |
||
206 | * @return Metadata\EntityMetadata |
||
207 | */ |
||
208 | protected function setAttributes(Metadata\Interfaces\AttributeInterface $metadata, array $attrMapping) |
||
259 | |||
260 | /** |
||
261 | * Sets the entity embed metadata from the metadata mapping. |
||
262 | * |
||
263 | * @param Metadata\Interfaces\EmbedInterface $metadata |
||
264 | * @param array $embedMapping |
||
265 | * @return Metadata\EntityMetadata |
||
266 | */ |
||
267 | protected function setEmbeds(Metadata\Interfaces\EmbedInterface $metadata, array $embedMapping) |
||
296 | |||
297 | /** |
||
298 | * Sets creates mixin metadata instances from a set of mixin mappings ands sets them to the entity metadata instance. |
||
299 | * |
||
300 | * @param Metadata\Interfaces\MixinInterface $metadata |
||
301 | * @param array $mixins |
||
302 | * @return Metadata\Interfaces\MixinInterface |
||
303 | */ |
||
304 | protected function setMixins(Metadata\Interfaces\MixinInterface $metadata, array $mixins) |
||
315 | |||
316 | /** |
||
317 | * Sets the entity relationship metadata from the metadata mapping. |
||
318 | * |
||
319 | * @param Metadata\Interfaces\RelationshipInterface $metadata |
||
320 | * @param array $relMapping |
||
321 | * @return Metadata\Interfaces\RelationshipInterface |
||
322 | * @throws RuntimeException If the related entity type was not found. |
||
323 | */ |
||
324 | protected function setRelationships(Metadata\Interfaces\RelationshipInterface $metadata, array $relMapping) |
||
380 | |||
381 | /** |
||
382 | * Determines if a metadata instance is a mixin. |
||
383 | * |
||
384 | * @param Metadata\Interfaces\PropertyInterface $metadata |
||
385 | * @return bool |
||
386 | */ |
||
387 | protected function isMixin(Metadata\Interfaces\PropertyInterface $metadata) |
||
391 | |||
392 | /** |
||
393 | * Sets default values to the metadata mapping array. |
||
394 | * |
||
395 | * @param string $metaType The metadata type, either model or mixin. |
||
396 | * @param mixed $mapping The parsed mapping data. |
||
397 | * @return array |
||
398 | */ |
||
399 | protected function setDefaults($metaType, $mapping) |
||
427 | |||
428 | /** |
||
429 | * Sets a root level default value to a metadata mapping array. |
||
430 | * |
||
431 | * @param string $key |
||
432 | * @param array $mapping |
||
433 | * @return array |
||
434 | */ |
||
435 | private function setRootDefault($key, array $mapping) |
||
442 | |||
443 | /** |
||
444 | * {@inheritDoc} |
||
445 | */ |
||
446 | protected function getExtension() |
||
450 | } |
||
451 |
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.