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 SchemaProvider 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 SchemaProvider, and based on these observations, apply Extract Interface, too.
1 | <?php namespace Neomerx\JsonApi\Schema; |
||
31 | abstract class SchemaProvider implements SchemaProviderInterface |
||
32 | { |
||
33 | /** Links information */ |
||
34 | const LINKS = DocumentInterface::KEYWORD_LINKS; |
||
35 | |||
36 | /** Linked data key. */ |
||
37 | const DATA = DocumentInterface::KEYWORD_DATA; |
||
38 | |||
39 | /** Relationship meta */ |
||
40 | const META = DocumentInterface::KEYWORD_META; |
||
41 | |||
42 | /** If 'self' URL should be shown. */ |
||
43 | const SHOW_SELF = 'showSelf'; |
||
44 | |||
45 | /** If 'related' URL should be shown. */ |
||
46 | const SHOW_RELATED = 'related'; |
||
47 | |||
48 | /** If data should be shown in relationships. */ |
||
49 | const SHOW_DATA = 'showData'; |
||
50 | |||
51 | /** |
||
52 | * @var string |
||
53 | */ |
||
54 | protected $resourceType; |
||
55 | |||
56 | /** |
||
57 | * @var string Must end with '/' |
||
58 | */ |
||
59 | protected $selfSubUrl; |
||
60 | |||
61 | /** |
||
62 | * @var bool |
||
63 | */ |
||
64 | protected $isShowAttributesInIncluded = true; |
||
1 ignored issue
–
show
|
|||
65 | |||
66 | /** |
||
67 | * @var SchemaFactoryInterface |
||
68 | */ |
||
69 | private $factory; |
||
70 | |||
71 | /** |
||
72 | * @var ContainerInterface |
||
73 | */ |
||
74 | private $container; |
||
75 | |||
76 | /** |
||
77 | * @param SchemaFactoryInterface $factory |
||
78 | * @param ContainerInterface $container |
||
79 | */ |
||
80 | 62 | public function __construct(SchemaFactoryInterface $factory, ContainerInterface $container) |
|
81 | { |
||
82 | 62 | $isOk = (is_string($this->resourceType) === true && empty($this->resourceType) === false); |
|
83 | 62 | if ($isOk === false) { |
|
84 | 1 | throw new InvalidArgumentException(T::t('Resource type is not set for Schema \'%s\'.', [static::class])); |
|
85 | } |
||
86 | |||
87 | 61 | if ($this->selfSubUrl === null) { |
|
88 | 57 | $this->selfSubUrl = '/' . $this->resourceType . '/'; |
|
89 | 57 | } else { |
|
90 | $isOk = |
||
91 | 5 | is_string($this->selfSubUrl) === true && |
|
92 | 5 | empty($this->selfSubUrl) === false && |
|
93 | 5 | $this->selfSubUrl[0] === '/' && |
|
94 | 5 | $this->selfSubUrl[strlen($this->selfSubUrl) - 1] == '/'; |
|
95 | |||
96 | 5 | if ($isOk === false) { |
|
97 | 1 | $message = T::t('\'Self\' sub-url set incorrectly for Schema \'%s\'.', [static::class]); |
|
98 | 1 | throw new InvalidArgumentException($message); |
|
99 | } |
||
100 | } |
||
101 | |||
102 | 60 | $this->factory = $factory; |
|
103 | 60 | $this->container = $container; |
|
104 | 60 | } |
|
105 | |||
106 | /** |
||
107 | * @inheritdoc |
||
108 | */ |
||
109 | 57 | public function getResourceType() |
|
113 | |||
114 | /** |
||
115 | * @inheritdoc |
||
116 | */ |
||
117 | 49 | public function getSelfSubUrl($resource = null) |
|
121 | |||
122 | /** |
||
123 | * @inheritdoc |
||
124 | */ |
||
125 | 47 | public function getSelfSubLink($resource) |
|
129 | |||
130 | /** |
||
131 | * @inheritdoc |
||
132 | */ |
||
133 | 4 | public function getRelationshipSelfLink($resource, $name, $meta = null, $treatAsHref = false) |
|
139 | |||
140 | /** |
||
141 | * @inheritdoc |
||
142 | */ |
||
143 | 4 | public function getRelationshipRelatedLink($resource, $name, $meta = null, $treatAsHref = false) |
|
149 | |||
150 | /** |
||
151 | * @inheritdoc |
||
152 | */ |
||
153 | 53 | public function getPrimaryMeta($resource) |
|
157 | |||
158 | /** |
||
159 | * @inheritdoc |
||
160 | */ |
||
161 | 29 | public function getLinkageMeta($resource) |
|
165 | |||
166 | /** |
||
167 | * @inheritdoc |
||
168 | */ |
||
169 | 19 | public function getInclusionMeta($resource) |
|
173 | |||
174 | /** |
||
175 | * @inheritdoc |
||
176 | */ |
||
177 | 30 | public function getRelationshipsPrimaryMeta($resource) |
|
181 | |||
182 | /** |
||
183 | * @inheritdoc |
||
184 | */ |
||
185 | 16 | public function getRelationshipsInclusionMeta($resource) |
|
189 | |||
190 | /** |
||
191 | * @inheritdoc |
||
192 | */ |
||
193 | 19 | public function isShowAttributesInIncluded() |
|
197 | |||
198 | /** |
||
199 | * Get resource links. |
||
200 | * |
||
201 | * @param object $resource |
||
202 | * @param bool $isPrimary |
||
203 | * @param array $includeRelationships A list of relationships that will be included as full resources. |
||
204 | * |
||
205 | * @return array |
||
206 | */ |
||
207 | 8 | public function getRelationships($resource, $isPrimary, array $includeRelationships) |
|
213 | |||
214 | /** |
||
215 | * @inheritdoc |
||
216 | */ |
||
217 | 51 | public function createResourceObject($resource, $isOriginallyArrayed, $attributeKeysFilter = null) |
|
221 | |||
222 | /** |
||
223 | * @inheritdoc |
||
224 | */ |
||
225 | 51 | public function getRelationshipObjectIterator($resource, $isPrimary, array $includeRelationships) |
|
231 | |||
232 | /** |
||
233 | * @inheritdoc |
||
234 | */ |
||
235 | 26 | public function getIncludePaths() |
|
239 | |||
240 | /** |
||
241 | * @inheritdoc |
||
242 | */ |
||
243 | 47 | public function getResourceLinks($resource) |
|
251 | |||
252 | /** |
||
253 | * @inheritdoc |
||
254 | */ |
||
255 | 16 | public function getIncludedResourceLinks($resource) |
|
259 | |||
260 | /** |
||
261 | * @param object $resource |
||
262 | * @param string $name |
||
263 | * |
||
264 | * @return string |
||
265 | */ |
||
266 | 4 | protected function getRelationshipSelfUrl($resource, $name) |
|
272 | |||
273 | /** |
||
274 | * @param object $resource |
||
275 | * @param string $name |
||
276 | * |
||
277 | * @return string |
||
278 | */ |
||
279 | 4 | protected function getRelationshipRelatedUrl($resource, $name) |
|
285 | |||
286 | /** |
||
287 | * @param string $subHref |
||
288 | * @param null|mixed $meta |
||
289 | * @param bool $treatAsHref |
||
290 | * |
||
291 | * @return LinkInterface |
||
292 | */ |
||
293 | 49 | protected function createLink($subHref, $meta = null, $treatAsHref = false) |
|
297 | |||
298 | /** |
||
299 | * @param object $resource |
||
300 | * @param string $relationshipName |
||
301 | * @param array $description |
||
302 | * @param bool $isShowSelf |
||
303 | * @param bool $isShowRelated |
||
304 | * |
||
305 | * @return array <string,LinkInterface> |
||
306 | */ |
||
307 | 40 | protected function readLinks($resource, $relationshipName, array $description, $isShowSelf, $isShowRelated) |
|
319 | |||
320 | /** |
||
321 | * @param object $resource |
||
322 | * @param string $name |
||
323 | * @param array $desc |
||
324 | * |
||
325 | * @return RelationshipObjectInterface |
||
326 | */ |
||
327 | 40 | protected function createRelationshipObject($resource, $name, array $desc) |
|
338 | |||
339 | /** |
||
340 | * @param array $array |
||
341 | * @param string $key |
||
342 | * @param mixed $default |
||
343 | * |
||
344 | * @return mixed |
||
345 | */ |
||
346 | 40 | private function getValue(array $array, $key, $default = null) |
|
350 | } |
||
351 |
Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.