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 RequestParser 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 RequestParser, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
9 | class RequestParser { |
||
|
|||
10 | const SORT_ASCENDING = 'ascending'; |
||
11 | const SORT_DESCENDING = 'descending'; |
||
12 | |||
13 | /** @var array */ |
||
14 | protected static $defaults = [ |
||
15 | /** |
||
16 | * reformat the include query parameter paths to nested arrays |
||
17 | * this allows easier processing on each step of the chain |
||
18 | */ |
||
19 | 'useNestedIncludePaths' => true, |
||
20 | |||
21 | /** |
||
22 | * reformat the sort query parameter paths to separate the sort order |
||
23 | * this allows easier processing of sort orders and field names |
||
24 | */ |
||
25 | 'useAnnotatedSortFields' => true, |
||
26 | ]; |
||
27 | /** @var string */ |
||
28 | private $selfLink = ''; |
||
29 | /** @var array */ |
||
30 | private $queryParameters = []; |
||
31 | /** @var array */ |
||
32 | private $document = []; |
||
33 | |||
34 | /** |
||
35 | * @param string $selfLink the uri used to make this request {@see getSelfLink()} |
||
36 | * @param array $queryParameters all query parameters defined by the specification |
||
37 | * @param array $document the request jsonapi document |
||
38 | */ |
||
39 | public function __construct($selfLink='', array $queryParameters=[], array $document=[]) { |
||
44 | |||
45 | /** |
||
46 | * @return self |
||
47 | */ |
||
48 | public static function fromSuperglobals() { |
||
72 | |||
73 | /** |
||
74 | * @param ServerRequestInterface|RequestInterface $request |
||
75 | * @return self |
||
76 | */ |
||
77 | public static function fromPsrRequest(RequestInterface $request) { |
||
101 | |||
102 | /** |
||
103 | * the full link used to make this request |
||
104 | * |
||
105 | * this is not a bare self link of a resource and includes query parameters if used |
||
106 | * |
||
107 | * @return string |
||
108 | */ |
||
109 | public function getSelfLink() { |
||
112 | |||
113 | /** |
||
114 | * @return boolean |
||
115 | */ |
||
116 | public function hasIncludePaths() { |
||
119 | |||
120 | /** |
||
121 | * returns a nested array based on the path, or the raw paths |
||
122 | * |
||
123 | * the nested format allows easier processing on each step of the chain |
||
124 | * the raw format allows for custom processing |
||
125 | * |
||
126 | * @param array $options optional {@see RequestParser::$defaults} |
||
127 | * @return string[]|array |
||
128 | */ |
||
129 | public function getIncludePaths(array $options=[]) { |
||
152 | |||
153 | /** |
||
154 | * @param string $type |
||
155 | * @return boolean |
||
156 | */ |
||
157 | public function hasSparseFieldset($type) { |
||
160 | |||
161 | /** |
||
162 | * @param string $type |
||
163 | * @return string[] |
||
164 | */ |
||
165 | public function getSparseFieldset($type) { |
||
172 | |||
173 | /** |
||
174 | * @return boolean |
||
175 | */ |
||
176 | public function hasSortFields() { |
||
179 | |||
180 | /** |
||
181 | * returns an array with sort order annotations, or the raw sort fields with minus signs |
||
182 | * |
||
183 | * the annotated format allows easier processing of sort orders and field names |
||
184 | * the raw format allows for custom processing |
||
185 | * |
||
186 | * @todo return some kind of SortFieldObject |
||
187 | * |
||
188 | * @param array $options optional {@see RequestParser::$defaults} |
||
189 | * @return string[]|array[] { |
||
190 | * @var string $field the sort field, without any minus sign for descending sort order |
||
191 | * @var string $order one of the RequestParser::SORT_* constants |
||
192 | * } |
||
193 | */ |
||
194 | public function getSortFields(array $options=[]) { |
||
219 | |||
220 | /** |
||
221 | * @return boolean |
||
222 | */ |
||
223 | public function hasPagination() { |
||
226 | |||
227 | /** |
||
228 | * @todo return some kind of PaginatorObject which recognizes the strategy of pagination used |
||
229 | * e.g. page-based, offset-based, cursor-based, or unknown |
||
230 | * |
||
231 | * @return array |
||
232 | */ |
||
233 | public function getPagination() { |
||
236 | |||
237 | /** |
||
238 | * @return boolean |
||
239 | */ |
||
240 | public function hasFilter() { |
||
243 | |||
244 | /** |
||
245 | * @return array |
||
246 | */ |
||
247 | public function getFilter() { |
||
250 | |||
251 | /** |
||
252 | * @param string $attributeName |
||
253 | * @return boolean |
||
254 | */ |
||
255 | View Code Duplication | public function hasAttribute($attributeName) { |
|
265 | |||
266 | /** |
||
267 | * @param string $attributeName |
||
268 | * @return mixed |
||
269 | */ |
||
270 | public function getAttribute($attributeName) { |
||
273 | |||
274 | /** |
||
275 | * @param string $relationshipName |
||
276 | * @return boolean |
||
277 | */ |
||
278 | View Code Duplication | public function hasRelationship($relationshipName) { |
|
288 | |||
289 | /** |
||
290 | * @todo return some kind of read-only ResourceIdentifierObject |
||
291 | * |
||
292 | * @param string $relationshipName |
||
293 | * @return array |
||
294 | */ |
||
295 | public function getRelationship($relationshipName) { |
||
298 | |||
299 | /** |
||
300 | * @param string $metaKey |
||
301 | * @return boolean |
||
302 | */ |
||
303 | public function hasMeta($metaKey) { |
||
313 | |||
314 | /** |
||
315 | * @param string $metaKey |
||
316 | * @return mixed |
||
317 | */ |
||
318 | public function getMeta($metaKey) { |
||
321 | |||
322 | /** |
||
323 | * @return array |
||
324 | */ |
||
325 | public function getDocument() { |
||
328 | } |
||
329 |