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 Type 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 Type, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
8 | class Type implements Contracts\Type |
||
9 | { |
||
10 | private $convention; |
||
11 | private $properties = []; |
||
12 | private $indexes = []; |
||
13 | private $types = []; |
||
14 | |||
15 | private $manager; |
||
16 | private $space; |
||
17 | private $spaceId; |
||
18 | private $name; |
||
19 | |||
20 | 35 | public function __construct(Contracts\Manager $manager, $name, array $properties, array $types, array $indexes) |
|
31 | |||
32 | 35 | public function getSpace() |
|
40 | |||
41 | 35 | public function getSpaceId() |
|
45 | |||
46 | 35 | public function getManager() |
|
50 | |||
51 | 35 | public function getName() |
|
55 | |||
56 | 35 | public function addIndex($properties, array $arguments = null) |
|
57 | { |
||
58 | 35 | $properties = (array) $properties; |
|
59 | 35 | foreach ($properties as $property) { |
|
60 | 35 | if (!$this->hasProperty($property)) { |
|
61 | 35 | throw new LogicException("Unknown property $property for ".$this->name); |
|
62 | } |
||
63 | } |
||
64 | |||
65 | 35 | $schema = $this->manager->getSchema(); |
|
66 | |||
67 | 35 | $indexName = implode('_', $properties); |
|
68 | |||
69 | 35 | if ($schema->hasIndex($this->getName(), $indexName)) { |
|
70 | 1 | throw new LogicException("Index $indexName already exists!"); |
|
71 | } |
||
72 | |||
73 | 35 | if (!$arguments) { |
|
74 | 35 | $arguments = []; |
|
75 | } |
||
76 | |||
77 | 35 | if (!array_key_exists('parts', $arguments) || !count($arguments['parts'])) { |
|
78 | 35 | $arguments['parts'] = []; |
|
79 | 35 | foreach ($properties as $property) { |
|
80 | 35 | $arguments['parts'][] = array_search($property, $this->properties) + 1; |
|
81 | 35 | $arguments['parts'][] = $this->convention->getTarantoolType($this->types[$property]); |
|
82 | } |
||
83 | } |
||
84 | |||
85 | 35 | $num = $schema->createIndex($this->getName(), $indexName, $arguments); |
|
86 | 35 | $this->indexes[$num] = $properties; |
|
87 | |||
88 | 35 | return $this; |
|
89 | } |
||
90 | |||
91 | /** |
||
92 | * @param $property name |
||
93 | * |
||
94 | * @return Type |
||
95 | */ |
||
96 | 35 | public function addProperty($name, $type = null) |
|
116 | |||
117 | 35 | public function hasProperty($name) |
|
121 | |||
122 | 35 | public function getProperties() |
|
126 | |||
127 | 2 | public function getPropertyType($property) |
|
131 | |||
132 | 7 | public function setPropertyType($property, $type) |
|
154 | |||
155 | 1 | public function removeProperty($name) |
|
169 | |||
170 | 5 | public function reference(Contracts\Type $foreign, $property = null) |
|
182 | |||
183 | 35 | public function isReference($property) |
|
187 | |||
188 | 4 | public function getReferenceProperty(Contracts\Type $type) |
|
205 | |||
206 | 1 | public function getReferences() |
|
218 | |||
219 | 35 | public function getRequiredProperties() |
|
234 | |||
235 | 1 | public function getIndex($num) |
|
239 | |||
240 | 1 | public function dropIndex($num) |
|
243 | |||
244 | 1 | public function getIndexes() |
|
248 | |||
249 | 35 | public function findIndex($query) |
|
274 | |||
275 | 35 | public function getIndexTuple($index, $params) |
|
286 | |||
287 | 35 | public function getCompleteTuple($input) |
|
316 | |||
317 | 35 | View Code Duplication | public function getTuple($input) |
328 | |||
329 | 35 | View Code Duplication | public function fromTuple($input) |
340 | |||
341 | 35 | public function encodeProperty($name, $value) |
|
345 | |||
346 | 35 | public function decodeProperty($name, $value) |
|
350 | } |
||
351 |
It seems like the method you are trying to call exists only in some of the possible types.
Let’s take a look at an example:
Available Fixes
Add an additional type-check:
Only allow a single type to be passed if the variable comes from a parameter: