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:
1 | <?php |
||
34 | class Client implements ClientInterface |
||
35 | { |
||
36 | const VERSION = 'KarmaBot for Gitter 0.1b'; |
||
37 | |||
38 | /** |
||
39 | * @var string |
||
40 | */ |
||
41 | protected $token; |
||
42 | |||
43 | /** |
||
44 | * @var \React\EventLoop\ExtEventLoop|\React\EventLoop\LibEventLoop|\React\EventLoop\LibEvLoop|\React\EventLoop\StreamSelectLoop |
||
45 | */ |
||
46 | protected $loop; |
||
47 | |||
48 | /** |
||
49 | * @var \React\Dns\Resolver\Resolver |
||
50 | */ |
||
51 | protected $dnsResolver; |
||
52 | |||
53 | /** |
||
54 | * @var UrlStorage |
||
55 | */ |
||
56 | protected $urlStorage; |
||
57 | |||
58 | /** |
||
59 | * @var string |
||
60 | */ |
||
61 | protected $room; |
||
62 | |||
63 | /** |
||
64 | * @var User |
||
65 | */ |
||
66 | protected $user; |
||
67 | |||
68 | /** |
||
69 | * @var TextParserInterface |
||
70 | */ |
||
71 | protected $parser; |
||
72 | |||
73 | /** |
||
74 | * @var \Gitter\Client |
||
75 | */ |
||
76 | protected $gitterClient; |
||
77 | |||
78 | /** |
||
79 | * @var ReactClient |
||
80 | */ |
||
81 | protected $httpClient; |
||
82 | |||
83 | /** |
||
84 | * Client constructor. |
||
85 | * |
||
86 | * @param string $token |
||
87 | */ |
||
88 | public function __construct($token) |
||
100 | |||
101 | /** |
||
102 | * @param null|string $gitterUserId |
||
103 | * @return $this |
||
104 | * @throws InvalidArgumentException |
||
105 | */ |
||
106 | public function authAs($gitterUserId = null) |
||
114 | |||
115 | /** |
||
116 | * @return User |
||
117 | */ |
||
118 | public function getAuthUser() |
||
122 | |||
123 | /** |
||
124 | * @return array |
||
125 | */ |
||
126 | public function getHeaders(): array |
||
134 | |||
135 | /** |
||
136 | * @return ReactClient |
||
137 | */ |
||
138 | public function getHttpClient(): ReactClient |
||
142 | |||
143 | /** |
||
144 | * @return UrlStorage |
||
145 | */ |
||
146 | public function getRouter(): UrlStorage |
||
150 | |||
151 | /** |
||
152 | * @return \React\EventLoop\ExtEventLoop|\React\EventLoop\LibEventLoop|\React\EventLoop\LibEvLoop|\React\EventLoop\StreamSelectLoop |
||
153 | */ |
||
154 | public function getEventLoop() |
||
158 | |||
159 | /** |
||
160 | * @param $route |
||
161 | * @param array $args |
||
162 | * @param string $method |
||
163 | * @return Stream |
||
164 | * @throws \InvalidArgumentException |
||
165 | */ |
||
166 | public function stream($route, array $args = [], $method = 'GET'): Stream |
||
170 | |||
171 | /** |
||
172 | * @param $route |
||
173 | * @param array $args |
||
174 | * @param null $content |
||
175 | * @param string $method |
||
176 | * @return array |
||
177 | * @throws \InvalidArgumentException |
||
178 | */ |
||
179 | public function request($route, array $args = [], $content = null, $method = 'GET') |
||
189 | |||
190 | /** |
||
191 | * @return ClientInterface |
||
192 | */ |
||
193 | public function run(): ClientInterface |
||
199 | |||
200 | /** |
||
201 | * @param RoomInterface $room |
||
202 | */ |
||
203 | public function listen(RoomInterface $room) |
||
221 | |||
222 | /** |
||
223 | * @return string |
||
224 | */ |
||
225 | public function version() |
||
229 | |||
230 | /** |
||
231 | * @param Storage $middleware |
||
232 | * @param Message $message |
||
233 | */ |
||
234 | public function onMessage(Storage $middleware, Message $message) |
||
242 | |||
243 | /** |
||
244 | * @return \Gitter\Client |
||
245 | */ |
||
246 | public function getGitterClient(): \Gitter\Client |
||
250 | |||
251 | /** |
||
252 | * @TODO I do not know if it works |
||
253 | * @param Stream $stream |
||
254 | */ |
||
255 | protected function onClose(Stream $stream) |
||
259 | |||
260 | /** |
||
261 | * @param Stream $stream |
||
262 | * @param \Exception $e |
||
263 | */ |
||
264 | protected function onError(Stream $stream, \Exception $e) |
||
268 | |||
269 | /** |
||
270 | * @param \Exception $e |
||
271 | */ |
||
272 | View Code Duplication | protected function logException(\Exception $e) |
|
280 | |||
281 | /** |
||
282 | * @param RoomInterface $room |
||
283 | * @param string $message |
||
284 | */ |
||
285 | public function sendMessage(RoomInterface $room, $message) |
||
291 | |||
292 | /** |
||
293 | * @param string $id |
||
294 | * |
||
295 | * @return User |
||
296 | */ |
||
297 | public function getUserById($id) |
||
303 | } |
||
304 |
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.