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 TwitchSDK 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 TwitchSDK, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
18 | class TwitchSDK |
||
19 | { |
||
20 | /** |
||
21 | * @var array|bool |
||
22 | * @todo Create setter and getter with data validation |
||
23 | */ |
||
24 | protected $authConfig = false; |
||
25 | |||
26 | /** @var TwitchRequest */ |
||
27 | protected $request; |
||
28 | |||
29 | /** @var Helper */ |
||
30 | protected $helper; |
||
31 | |||
32 | /** |
||
33 | * TwitchAPI URI's |
||
34 | */ |
||
35 | const URI_USER_FOLLOWS_CHANNEL = '/users/%s/follows/channels'; |
||
36 | const URI_USER_FOLLOW_RELATION = '/users/%s/follows/channels/%s'; |
||
37 | const URI_CHANNEL = 'channels/'; |
||
38 | const URI_CHANNEL_FOLLOWS = 'channels/%s/follows'; |
||
39 | const URI_STREAMS_SEARCH = 'search/streams/'; |
||
40 | const URI_VIDEO = 'videos/'; |
||
41 | const URI_CHAT = 'chat/'; |
||
42 | const URI_CHAT_EMOTICONS = 'chat/emoticons'; |
||
43 | const URI_GAMES_TOP = 'games/top/'; |
||
44 | |||
45 | /** |
||
46 | * TwitchSDK constructor |
||
47 | * @param array $config |
||
48 | * @throws TwitchException |
||
49 | */ |
||
50 | public function __construct(array $config = array()) |
||
67 | |||
68 | /** |
||
69 | * authConfig setter |
||
70 | * @param array $config |
||
71 | * @return TwitchSDK |
||
72 | * @throws TwitchException |
||
73 | */ |
||
74 | public function setAuthConfig(array $config) |
||
84 | |||
85 | /** |
||
86 | * Basic information about the API and authentication status |
||
87 | * @param null $token |
||
88 | * @return \stdClass |
||
89 | * @throws TwitchException |
||
90 | */ |
||
91 | public function status($token = null) |
||
105 | |||
106 | /** |
||
107 | * Get the specified user |
||
108 | * @param $username |
||
109 | * @return \stdClass |
||
110 | * @throws TwitchException |
||
111 | */ |
||
112 | public function userGet($username) |
||
117 | |||
118 | /** |
||
119 | * Get a user's list of followed channels |
||
120 | * @param $user |
||
121 | * @param null $limit |
||
122 | * @param null $offset |
||
123 | * @return \stdClass |
||
124 | * @throws TwitchException |
||
125 | */ |
||
126 | View Code Duplication | public function userFollowChannels($user, $limit = null, $offset = null) |
|
135 | |||
136 | /** |
||
137 | * Get the status of a follow relationship |
||
138 | * @param $user |
||
139 | * @param $channel |
||
140 | * @return \stdClass |
||
141 | * @throws TwitchException |
||
142 | */ |
||
143 | public function userFollowRelationship($user, $channel) |
||
147 | |||
148 | /** |
||
149 | * Set user to follow given channel |
||
150 | * @param $user |
||
151 | * @param $channel |
||
152 | * @param $userToken |
||
153 | * @return \stdClass |
||
154 | * @throws TwitchException |
||
155 | */ |
||
156 | View Code Duplication | public function userFollowChannel($user, $channel, $userToken) |
|
164 | |||
165 | /** |
||
166 | * Set user to unfollow given channel |
||
167 | * @param $user |
||
168 | * @param $channel |
||
169 | * @param $userToken |
||
170 | * @return \stdClass |
||
171 | * @throws TwitchException |
||
172 | */ |
||
173 | View Code Duplication | public function userUnfollowChannel($user, $channel, $userToken) |
|
181 | |||
182 | /** |
||
183 | * Get the specified channel |
||
184 | * @param $channel |
||
185 | * @return \stdClass |
||
186 | * @throws TwitchException |
||
187 | */ |
||
188 | public function channelGet($channel) |
||
192 | |||
193 | /** |
||
194 | * Get the specified team |
||
195 | * @param $teamName |
||
196 | * @return \stdClass |
||
197 | * @throws TwitchException |
||
198 | */ |
||
199 | public function teamGet($teamName) |
||
205 | |||
206 | /** |
||
207 | * Returns a list of active teams |
||
208 | * @param integer $limit |
||
209 | * @param integer $offset |
||
210 | * @return \stdClass |
||
211 | * @throws TwitchException |
||
212 | */ |
||
213 | View Code Duplication | public function teamList($limit = null, $offset = null) |
|
224 | |||
225 | /** |
||
226 | * Get all team members |
||
227 | * @param $teamName |
||
228 | * @return mixed |
||
229 | * @throws TwitchException |
||
230 | */ |
||
231 | public function teamMembersAll($teamName) |
||
235 | |||
236 | /** |
||
237 | * Returns an array of users who follow the specified channel |
||
238 | * @param $channel |
||
239 | * @param null $limit |
||
240 | * @param null $offset |
||
241 | * @return \stdClass |
||
242 | * @throws TwitchException |
||
243 | */ |
||
244 | View Code Duplication | public function channelFollows($channel, $limit = null, $offset = null) |
|
253 | |||
254 | /** |
||
255 | * Get the specified channel's stream |
||
256 | * @param $channel |
||
257 | * @return \stdClass |
||
258 | * @throws TwitchException |
||
259 | */ |
||
260 | public function streamGet($channel) |
||
266 | |||
267 | /** |
||
268 | * Search live streams |
||
269 | * @param $query |
||
270 | * @param null $limit |
||
271 | * @param null $offset |
||
272 | * @return \stdClass |
||
273 | * @throws TwitchException |
||
274 | * @deprecated will be replaced by getStreams() function |
||
275 | */ |
||
276 | View Code Duplication | public function streamSearch($query, $limit = null, $offset = null) |
|
286 | |||
287 | /** |
||
288 | * Summarize streams |
||
289 | * @param null $game |
||
290 | * @param array|null $channels |
||
291 | * @param null $hls |
||
292 | * @return \stdClass |
||
293 | * @throws TwitchException |
||
294 | */ |
||
295 | public function streamsSummarize($game = null, array $channels = null, $hls = null) |
||
311 | |||
312 | /** |
||
313 | * Get featured streams |
||
314 | * @param null $limit |
||
315 | * @param null $offset |
||
316 | * @param null $hls |
||
317 | * @return \stdClass |
||
318 | * @throws TwitchException |
||
319 | */ |
||
320 | public function streamsFeatured($limit = null, $offset = null, $hls = null) |
||
332 | |||
333 | /** |
||
334 | * Get streams by channel |
||
335 | * @param $channels |
||
336 | * @param null $limit |
||
337 | * @param null $offset |
||
338 | * @param null $embeddable |
||
339 | * @param null $hls |
||
340 | * @return \stdClass |
||
341 | * @deprecated will be replaced by getStreams() function |
||
342 | */ |
||
343 | public function streamsByChannels($channels, $limit = null, $offset = null, $embeddable = null, $hls = null) |
||
349 | |||
350 | /** |
||
351 | * Get streams by game |
||
352 | * @param $game |
||
353 | * @param null $limit |
||
354 | * @param null $offset |
||
355 | * @param null $embeddable |
||
356 | * @param null $hls |
||
357 | * @return \stdClass |
||
358 | * @deprecated will be replaced by getStreams() function |
||
359 | */ |
||
360 | public function streamsByGame($game, $limit = null, $offset = null, $embeddable = null, $hls = null) |
||
364 | |||
365 | /** |
||
366 | * Get video |
||
367 | * @param $video |
||
368 | * @return \stdClass |
||
369 | * @throws TwitchException |
||
370 | */ |
||
371 | public function videoGet($video) |
||
375 | |||
376 | /** |
||
377 | * Get videos for a channel |
||
378 | * @param $channel |
||
379 | * @param null $limit |
||
380 | * @param null $offset |
||
381 | * @return \stdClass |
||
382 | * @throws TwitchException |
||
383 | */ |
||
384 | public function videosByChannel($channel, $limit = null, $offset = null) |
||
393 | |||
394 | /** |
||
395 | * Get the specified channel's chat |
||
396 | * @param $channel |
||
397 | * @return \stdClass |
||
398 | * @throws TwitchException |
||
399 | */ |
||
400 | public function chatGet($channel) |
||
404 | |||
405 | /** |
||
406 | * Get a chat's emoticons |
||
407 | * @return \stdClass |
||
408 | * @throws TwitchException |
||
409 | */ |
||
410 | public function chatEmoticons() |
||
414 | |||
415 | /** |
||
416 | * Get top games |
||
417 | * @param null $limit |
||
418 | * @param null $offset |
||
419 | * @return \stdClass |
||
420 | * @throws TwitchException |
||
421 | */ |
||
422 | View Code Duplication | public function gamesTop($limit = null, $offset = null) |
|
431 | |||
432 | /** |
||
433 | * Get HTML code for stream embedding |
||
434 | * @param $channel |
||
435 | * @param int $width |
||
436 | * @param int $height |
||
437 | * @param int $volume |
||
438 | * @return string |
||
439 | */ |
||
440 | View Code Duplication | public function embedStream($channel, $width = 620, $height = 378, $volume = 25) |
|
460 | |||
461 | /** |
||
462 | * Get HTML code for video embedding |
||
463 | * @param $channel |
||
464 | * @param $chapterid |
||
465 | * @param int $width |
||
466 | * @param int $height |
||
467 | * @param int $volume |
||
468 | * @return string |
||
469 | */ |
||
470 | View Code Duplication | public function embedVideo($channel, $chapterid, $width = 400, $height = 300, $volume = 25) |
|
490 | |||
491 | /** |
||
492 | * Get HTML code for chat embedding |
||
493 | * @param $channel |
||
494 | * @param int $width |
||
495 | * @param int $height |
||
496 | * @return string |
||
497 | */ |
||
498 | public function embedChat($channel, $width = 400, $height = 300) |
||
508 | |||
509 | /** |
||
510 | * Get login URL for authentication |
||
511 | * @param string $scope Specify which permissions your app requires (space separated list) |
||
512 | * @return string |
||
513 | * @throws TwitchException |
||
514 | */ |
||
515 | View Code Duplication | public function authLoginURL($scope) |
|
532 | |||
533 | /** |
||
534 | * Get authentication access token |
||
535 | * @param string $code returned after app authorization by user |
||
536 | * @return \stdClass |
||
537 | * @throws TwitchException |
||
538 | */ |
||
539 | View Code Duplication | public function authAccessTokenGet($code) |
|
557 | |||
558 | /** |
||
559 | * Get the authenticated user |
||
560 | * - requires scope 'user_read' |
||
561 | * @param string |
||
562 | * @return \stdClass |
||
563 | * @throws TwitchException |
||
564 | */ |
||
565 | View Code Duplication | public function authUserGet($token) |
|
579 | |||
580 | /** |
||
581 | * Get the authenticated channel |
||
582 | * - requires scope 'channel_read' |
||
583 | * @param string |
||
584 | * @return \stdClass |
||
585 | * @throws TwitchException |
||
586 | */ |
||
587 | View Code Duplication | public function authChannelGet($token) |
|
602 | |||
603 | /** |
||
604 | * Returns an array of users who are editors of specified channel |
||
605 | * - requires scope 'channel_read' |
||
606 | * @param string |
||
607 | * @param string |
||
608 | * @return \stdClass |
||
609 | * @throws TwitchException |
||
610 | */ |
||
611 | View Code Duplication | public function authChannelEditors($token, $channel) |
|
626 | |||
627 | /** |
||
628 | * Returns an array of subscriptions who are subscribed to specified channel |
||
629 | * - requires scope 'channel_subscriptions' |
||
630 | * @param string $token - user's access token |
||
631 | * @param string $channel |
||
632 | * @param integer $limit - can be up to 100 |
||
633 | * @param integer $offset |
||
634 | * @param string $direction can be DESC|ASC, if DESC - lasts will be showed first |
||
635 | * @return \stdClass |
||
636 | * @throws TwitchException |
||
637 | */ |
||
638 | View Code Duplication | public function authChannelSubscriptions($token, $channel, $limit = 25, $offset = 0, $direction = 'DESC') |
|
656 | |||
657 | /** |
||
658 | * List the live streams that the authenticated user is following |
||
659 | * - requires scope 'user_read' |
||
660 | * @param string |
||
661 | * @param integer $limit |
||
662 | * @param integer $offset |
||
663 | * @param bool $hls |
||
664 | * @return \stdClass |
||
665 | * @throws TwitchException |
||
666 | */ |
||
667 | View Code Duplication | public function authStreamsFollowed($token, $limit = 25, $offset = 0, $hls = null) |
|
684 | |||
685 | /** |
||
686 | * Get streams helper |
||
687 | * @param null $game |
||
688 | * @param null $limit |
||
689 | * @param null $offset |
||
690 | * @param null $channels |
||
691 | * @param null $embeddable |
||
692 | * @param null $hls |
||
693 | * @return \stdClass |
||
694 | * @throws TwitchException |
||
695 | */ |
||
696 | public function getStreams($game = null, $limit = null, $offset = null, $channels = null, $embeddable = null, $hls = null) |
||
712 | |||
713 | /** |
||
714 | * Validate parameters for authentication |
||
715 | * @param array |
||
716 | * @return boolean |
||
717 | */ |
||
718 | private function configValidate($config) |
||
733 | |||
734 | /** |
||
735 | * Configuration exception |
||
736 | * @throws TwitchException |
||
737 | */ |
||
738 | private function authConfigException() |
||
742 | } |
||
743 |
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.