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 RequestParameters 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 RequestParameters, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
23 | class RequestParameters |
||
24 | { |
||
25 | const DEFAULT_PAGE = 1; |
||
26 | const DEFAULT_MAX_RESULTS = 25; |
||
27 | |||
28 | /** |
||
29 | * Start date. |
||
30 | * |
||
31 | * @var DateTime|null |
||
32 | */ |
||
33 | protected $startDate; |
||
34 | |||
35 | /** |
||
36 | * End date. |
||
37 | * |
||
38 | * @var DateTime|null |
||
39 | */ |
||
40 | protected $endDate; |
||
41 | |||
42 | /** |
||
43 | * Query for text search. |
||
44 | * |
||
45 | * @var string|null |
||
46 | */ |
||
47 | protected $query; |
||
48 | |||
49 | /** |
||
50 | * Page. |
||
51 | * |
||
52 | * @var int |
||
53 | */ |
||
54 | protected $page = self::DEFAULT_PAGE; |
||
55 | |||
56 | /** |
||
57 | * Max results per page. |
||
58 | * |
||
59 | * @var int |
||
60 | */ |
||
61 | protected $maxResults = self::DEFAULT_MAX_RESULTS; |
||
62 | |||
63 | /** |
||
64 | * Include fields list. These fields will be set in your packages or items. |
||
65 | * |
||
66 | * @var array|null |
||
67 | */ |
||
68 | protected $includeFields; |
||
69 | |||
70 | /** |
||
71 | * Exclude fields lists. These fields won't be set in your packages or items. |
||
72 | * |
||
73 | * @var array|null |
||
74 | */ |
||
75 | protected $excludeFields; |
||
76 | |||
77 | /** |
||
78 | * Mapping array, which links correct parameter name for API with proper |
||
79 | * method. |
||
80 | * |
||
81 | * @var string[] |
||
82 | */ |
||
83 | protected $propertyMapping = array( |
||
84 | 'start_date' => 'getStartDate', |
||
85 | 'end_date' => 'getEndDate', |
||
86 | 'q' => 'getQuery', |
||
87 | 'page' => 'getPage', |
||
88 | 'max_results' => 'getMaxResults', |
||
89 | 'include_fields' => 'getIncludeFields', |
||
90 | 'exclude_fields' => 'getExcludeFields', |
||
91 | ); |
||
92 | |||
93 | /** |
||
94 | * Returns start date. |
||
95 | * |
||
96 | * @return DateTime|null |
||
97 | */ |
||
98 | public function getStartDate() |
||
102 | |||
103 | /** |
||
104 | * Sets start date. Will accept a string formatted 'yyyy-mm-dd' or DateTime |
||
105 | * object. |
||
106 | * |
||
107 | * @param string|DateTime|null $startDate |
||
108 | */ |
||
109 | View Code Duplication | public function setStartDate($startDate) |
|
123 | |||
124 | /** |
||
125 | * Returns end date. |
||
126 | * |
||
127 | * @return DateTime|null |
||
128 | */ |
||
129 | public function getEndDate() |
||
133 | |||
134 | /** |
||
135 | * Sets end date. Will accept string formatted 'yyyy-mm-dd' or DateTIme |
||
136 | * object. |
||
137 | * |
||
138 | * @param string|DateTime|null $endDate |
||
139 | */ |
||
140 | View Code Duplication | public function setEndDate($endDate) |
|
154 | |||
155 | /** |
||
156 | * Returns text query. |
||
157 | * |
||
158 | * @return string |
||
159 | */ |
||
160 | public function getQuery() |
||
164 | |||
165 | /** |
||
166 | * Sets query parameters. |
||
167 | * |
||
168 | * @param string|null $query |
||
169 | */ |
||
170 | public function setQuery($query) |
||
180 | |||
181 | /** |
||
182 | * Returns page number. |
||
183 | * |
||
184 | * @return int |
||
185 | */ |
||
186 | public function getPage() |
||
190 | |||
191 | /** |
||
192 | * Sets page number. If null is supplied, resets to class default. |
||
193 | * |
||
194 | * @param int|null $page |
||
195 | */ |
||
196 | View Code Duplication | public function setPage($page) |
|
210 | |||
211 | /** |
||
212 | * Returns maximum results per page. |
||
213 | * |
||
214 | * @return int |
||
215 | */ |
||
216 | public function getMaxResults() |
||
220 | |||
221 | /** |
||
222 | * Sets maximum results per page. If null is supplied, resets to class |
||
223 | * default. |
||
224 | * |
||
225 | * @param int|nul $maxResults |
||
226 | */ |
||
227 | View Code Duplication | public function setMaxResults($maxResults) |
|
241 | |||
242 | /** |
||
243 | * Returns include fields. |
||
244 | * |
||
245 | * @return array |
||
246 | */ |
||
247 | public function getIncludeFields() |
||
251 | |||
252 | /** |
||
253 | * Sets include fields. |
||
254 | * |
||
255 | * @param array|null $includeFields |
||
256 | */ |
||
257 | View Code Duplication | public function setIncludeFields($includeFields) |
|
271 | |||
272 | /** |
||
273 | * Gets exclude fields. |
||
274 | * |
||
275 | * @return array |
||
276 | */ |
||
277 | public function getExcludeFields() |
||
281 | |||
282 | /** |
||
283 | * Sets exclude fields |
||
284 | * |
||
285 | * @param array|null |
||
286 | */ |
||
287 | View Code Duplication | public function setExcludeFields($excludeFields) |
|
301 | |||
302 | /** |
||
303 | * Validate date parameter input and converts to DateTime. |
||
304 | * |
||
305 | * @param string|DateTime $date When string format yyyy-mm-dd should be used |
||
306 | * |
||
307 | * @return DateTime |
||
308 | */ |
||
309 | private function validateDate($date) |
||
323 | |||
324 | /** |
||
325 | * Arguments of type string and array are valid. String will be split on , |
||
326 | * and converted to an array. |
||
327 | * |
||
328 | * @param string|array $value |
||
329 | * |
||
330 | * @return array |
||
331 | */ |
||
332 | private function validateStringOrArray($value) |
||
342 | |||
343 | /** |
||
344 | * Validates if value is numeric. |
||
345 | * |
||
346 | * @param string|int $value |
||
347 | * |
||
348 | * @return int |
||
349 | */ |
||
350 | private function validateNumeric($value) |
||
360 | |||
361 | /** |
||
362 | * Returns all properties either as an array or http query string. |
||
363 | * |
||
364 | * @param boolean $buildHttpQuery Build query from array |
||
365 | * |
||
366 | * @return mixed[]|string |
||
367 | */ |
||
368 | public function getAllParameters($buildHttpQuery = false) |
||
385 | } |
||
386 |
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.