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 AnswerApi 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 AnswerApi, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
24 | final class AnswerApi |
||
25 | { |
||
26 | const URL = 'answers/'; |
||
27 | const QUERY_PARAMS = [ |
||
28 | 'order' => 'desc', |
||
29 | 'sort' => 'activity', |
||
30 | 'site' => 'stackoverflow', |
||
31 | 'filter' => Http::FILTER_ALL, |
||
32 | ]; |
||
33 | |||
34 | /** |
||
35 | * The authentication. |
||
36 | * |
||
37 | * @var Authentication|null |
||
38 | */ |
||
39 | private $authentication; |
||
40 | |||
41 | /** |
||
42 | * Constructor. |
||
43 | * |
||
44 | * @param Authentication|null $anAuthentication The authentication |
||
45 | */ |
||
46 | public function __construct(Authentication $anAuthentication = null) |
||
50 | |||
51 | /** |
||
52 | * Get all answers on the site. |
||
53 | * |
||
54 | * More info: http://api.stackexchange.com/docs/answers |
||
55 | * |
||
56 | * @param array $params QueryString parameter(s) |
||
57 | * @param bool $serialize Checks if the result will be serialize or not, by default is true |
||
58 | * |
||
59 | * @return array |
||
|
|||
60 | */ |
||
61 | View Code Duplication | public function all(array $params = ['site' => 'stackoverflow'], $serialize = true) |
|
75 | |||
76 | /** |
||
77 | * Get answers identified by a set of ids. |
||
78 | * |
||
79 | * More info: http://api.stackexchange.com/docs/answers-by-ids |
||
80 | * |
||
81 | * @param string|array $ids Array which contains the ids delimited by semicolon, or a simple id |
||
82 | * @param array $params QueryString parameter(s) |
||
83 | * @param bool $serialize Checks if the result will be serialize or not, by default is true |
||
84 | * |
||
85 | * @return array|Answer |
||
86 | */ |
||
87 | public function getOfIds($ids, array $params = ['site' => 'stackoverflow'], $serialize = true) |
||
101 | |||
102 | /** |
||
103 | * Casts an accept vote on the given answer. |
||
104 | * |
||
105 | * More info: https://api.stackexchange.com/docs/accept-answer |
||
106 | * |
||
107 | * @param string $id The id of question |
||
108 | * @param array $params QueryString parameter(s) |
||
109 | * @param bool $serialize Checks if the result will be serialize or not, by default is true |
||
110 | * |
||
111 | * @throws \Exception when the auth is null |
||
112 | * |
||
113 | * @return Answer |
||
114 | */ |
||
115 | public function accept($id, array $params = self::QUERY_PARAMS, $serialize = true) |
||
126 | |||
127 | /** |
||
128 | * Undoes an accept vote on the given answer. |
||
129 | * |
||
130 | * More info: https://api.stackexchange.com/docs/undo-accept-answer |
||
131 | * |
||
132 | * @param string $id The id of question |
||
133 | * @param array $params QueryString parameter(s) |
||
134 | * @param bool $serialize Checks if the result will be serialize or not, by default is true |
||
135 | * |
||
136 | * @throws \Exception when the auth is null |
||
137 | * |
||
138 | * @return Answer |
||
139 | */ |
||
140 | public function undoAccept($id, array $params = self::QUERY_PARAMS, $serialize = true) |
||
151 | |||
152 | /** |
||
153 | * Deletes an answer. |
||
154 | * |
||
155 | * More info: https://api.stackexchange.com/docs/delete-answer |
||
156 | * |
||
157 | * @param string $id The id of question |
||
158 | * @param array $params QueryString parameter(s) |
||
159 | * @param bool $serialize Checks if the result will be serialize or not, by default is true |
||
160 | * |
||
161 | * @throws \Exception when the auth is null |
||
162 | * |
||
163 | * @return Answer |
||
164 | */ |
||
165 | public function delete($id, array $params = self::QUERY_PARAMS, $serialize = true) |
||
176 | |||
177 | /** |
||
178 | * Downvotes an answer. |
||
179 | * |
||
180 | * More info: https://api.stackexchange.com/docs/downvote-answer |
||
181 | * |
||
182 | * @param string $id The id of question |
||
183 | * @param array $params QueryString parameter(s) |
||
184 | * @param bool $serialize Checks if the result will be serialize or not, by default is true |
||
185 | * |
||
186 | * @throws \Exception when the auth is null |
||
187 | * |
||
188 | * @return Answer |
||
189 | */ |
||
190 | public function downvote($id, array $params = self::QUERY_PARAMS, $serialize = true) |
||
201 | |||
202 | /** |
||
203 | * Undoes an downvote on an answer. |
||
204 | * |
||
205 | * More info: https://api.stackexchange.com/docs/undo-downvote-answer |
||
206 | * |
||
207 | * @param string $id The id of question |
||
208 | * @param array $params QueryString parameter(s) |
||
209 | * @param bool $serialize Checks if the result will be serialize or not, by default is true |
||
210 | * |
||
211 | * @throws \Exception when the auth is null |
||
212 | * |
||
213 | * @return Answer |
||
214 | */ |
||
215 | public function undoDownvote($id, array $params = self::QUERY_PARAMS, $serialize = true) |
||
226 | |||
227 | /** |
||
228 | * Edit an existing answer. |
||
229 | * |
||
230 | * More info: https://api.stackexchange.com/docs/edit-answer |
||
231 | * |
||
232 | * @param string $id The id of question |
||
233 | * @param string $body The body of the answer |
||
234 | * @param array $params QueryString parameter(s) |
||
235 | * @param bool $serialize Checks if the result will be serialize or not, by default is true |
||
236 | * |
||
237 | * @throws \Exception when the auth is null |
||
238 | * |
||
239 | * @return Answer |
||
240 | */ |
||
241 | View Code Duplication | public function update($id, $body, array $params = self::QUERY_PARAMS, $serialize = true) |
|
252 | |||
253 | /** |
||
254 | * Upvotes an answer. |
||
255 | * |
||
256 | * More info: https://api.stackexchange.com/docs/upvote-answer |
||
257 | * |
||
258 | * @param string $id The id of question |
||
259 | * @param array $params QueryString parameter(s) |
||
260 | * @param bool $serialize Checks if the result will be serialize or not, by default is true |
||
261 | * |
||
262 | * @throws \Exception when the auth is null |
||
263 | * |
||
264 | * @return Answer |
||
265 | */ |
||
266 | public function upvote($id, array $params = self::QUERY_PARAMS, $serialize = true) |
||
277 | |||
278 | /** |
||
279 | * Undoes an upvote on an answer. |
||
280 | * |
||
281 | * More info: https://api.stackexchange.com/docs/undo-upvote-answer |
||
282 | * |
||
283 | * @param string $id The id of question |
||
284 | * @param array $params QueryString parameter(s) |
||
285 | * @param bool $serialize Checks if the result will be serialize or not, by default is true |
||
286 | * |
||
287 | * @throws \Exception when the auth is null |
||
288 | * |
||
289 | * @return Answer |
||
290 | */ |
||
291 | public function undoUpvote($id, array $params = self::QUERY_PARAMS, $serialize = true) |
||
302 | |||
303 | /** |
||
304 | * Casts a flag against the answer identified by id. |
||
305 | * |
||
306 | * More info: https://api.stackexchange.com/docs/create-answer-flag |
||
307 | * |
||
308 | * @param string $id The id of question |
||
309 | * @param array $params QueryString parameter(s) |
||
310 | * @param bool $serialize Checks if the result will be serialize or not, by default is true |
||
311 | * |
||
312 | * @throws \Exception when the auth is null |
||
313 | * |
||
314 | * @return Answer |
||
315 | */ |
||
316 | public function addFlag($id, array $params = self::QUERY_PARAMS, $serialize = true) |
||
327 | |||
328 | /** |
||
329 | * Gets the answers to a set of questions identified in id. |
||
330 | * |
||
331 | * More info: https://api.stackexchange.com/docs/answers-on-questions |
||
332 | * |
||
333 | * @param string|array $ids Array which contains the ids delimited by semicolon, or a simple id |
||
334 | * @param array $params QueryString parameter(s) |
||
335 | * @param bool $serialize Checks if the result will be serialize or not, by default is true |
||
336 | * |
||
337 | * @return array|Answer |
||
338 | */ |
||
339 | public function getOfQuestionIds($ids, array $params = ['site' => 'stackoverflow'], $serialize = true) |
||
353 | |||
354 | /** |
||
355 | * Create a new answer on the given question. |
||
356 | * |
||
357 | * More info: https://api.stackexchange.com/docs/create-answer |
||
358 | * |
||
359 | * @param string $id The id of question |
||
360 | * @param string $body The body of the answer |
||
361 | * @param array $params QueryString parameter(s) |
||
362 | * @param bool $serialize Checks if the result will be serialize or not, by default is true |
||
363 | * |
||
364 | * @throws \Exception when the auth is null |
||
365 | * |
||
366 | * @return Answer |
||
367 | */ |
||
368 | View Code Duplication | public function addOfQuestionId($id, $body, array $params = self::QUERY_PARAMS, $serialize = true) |
|
381 | |||
382 | /** |
||
383 | * Render an answer given it's body and the question it's on. |
||
384 | * |
||
385 | * More info: https://api.stackexchange.com/docs/render-answer |
||
386 | * |
||
387 | * @param string $id The id of question |
||
388 | * @param string $body The body of the answer |
||
389 | * @param array $params QueryString parameter(s) |
||
390 | * @param bool $serialize Checks if the result will be serialize or not, by default is true |
||
391 | * |
||
392 | * @throws \Exception when the auth is null |
||
393 | * |
||
394 | * @return Answer |
||
395 | */ |
||
396 | public function render($id, $body, array $params = ['site' => 'stackoverflow'], $serialize = true) |
||
412 | |||
413 | /** |
||
414 | * Returns the answers the users in {ids} have posted. |
||
415 | * |
||
416 | * More info: https://api.stackexchange.com/docs/answers-on-users |
||
417 | * |
||
418 | * @param string|array $ids Array which contains the ids delimited by semicolon, or a simple id |
||
419 | * @param array $params QueryString parameter(s) |
||
420 | * @param bool $serialize Checks if the result will be serialize or not, by default is true |
||
421 | * |
||
422 | * @return array|Answer |
||
423 | */ |
||
424 | View Code Duplication | public function getOfUserIds($ids, array $params = ['site' => 'stackoverflow'], $serialize = true) |
|
438 | |||
439 | /** |
||
440 | * Returns the answers owned by the user associated with the given access_token. |
||
441 | * |
||
442 | * More info: https://api.stackexchange.com/docs/me-answers |
||
443 | * |
||
444 | * @param array $params QueryString parameter(s) |
||
445 | * @param bool $serialize Checks if the result will be serialize or not, by default is true |
||
446 | * |
||
447 | * @throws \Exception when the auth is null |
||
448 | * |
||
449 | * @return array|Answer |
||
450 | */ |
||
451 | View Code Duplication | public function myAnswers(array $params = self::QUERY_PARAMS, $serialize = true) |
|
462 | |||
463 | /** |
||
464 | * Returns the top 30 answers a user has posted in response to questions with the given tags. |
||
465 | * |
||
466 | * More info: https://api.stackexchange.com/docs/top-user-answers-in-tags |
||
467 | * |
||
468 | * @param string $userId The user id |
||
469 | * @param string|array $tags Array which contains the $tags delimited by semicolon, or a simple tag |
||
470 | * @param array $params QueryString parameter(s) |
||
471 | * @param bool $serialize Checks if the result will be serialize or not, by default is true |
||
472 | * |
||
473 | * @return array|Answer |
||
474 | */ |
||
475 | View Code Duplication | public function getTopOfUserAndTags($userId, $tags, array $params = ['site' => 'stackoverflow'], $serialize = true) |
|
489 | |||
490 | /** |
||
491 | * Returns the top 30 answers the user associated with the given |
||
492 | * access_token has posted in response to questions with the given tags. |
||
493 | * |
||
494 | * More info: https://api.stackexchange.com/docs/me-tags-top-answers |
||
495 | * |
||
496 | * @param string|array $tags Array which contains the tags delimited by semicolon, or a simple tag |
||
497 | * @param array $params QueryString parameter(s) |
||
498 | * @param bool $serialize Checks if the result will be serialize or not, by default is true |
||
499 | * |
||
500 | * @throws \Exception when the auth is null |
||
501 | * |
||
502 | * @return array|Answer |
||
503 | */ |
||
504 | public function myTopAnswersOfTags($tags, array $params = self::QUERY_PARAMS, $serialize = true) |
||
516 | } |
||
517 |
This check compares the return type specified in the
@return
annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.If the return type contains the type array, this check recommends the use of a more specific type like
String[]
orarray<String>
.