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 BinaryDataReader 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 BinaryDataReader, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
11 | class BinaryDataReader |
||
12 | { |
||
13 | const NULL_COLUMN = 251; |
||
14 | const UNSIGNED_CHAR_COLUMN = 251; |
||
15 | const UNSIGNED_SHORT_COLUMN = 252; |
||
16 | const UNSIGNED_INT24_COLUMN = 253; |
||
17 | const UNSIGNED_INT64_COLUMN = 254; |
||
18 | const UNSIGNED_CHAR_LENGTH = 1; |
||
19 | const UNSIGNED_SHORT_LENGTH = 2; |
||
20 | const UNSIGNED_INT24_LENGTH = 3; |
||
21 | const UNSIGNED_INT32_LENGTH = 4; |
||
22 | const UNSIGNED_FLOAT_LENGTH = 4; |
||
23 | const UNSIGNED_DOUBLE_LENGTH = 8; |
||
24 | const UNSIGNED_INT40_LENGTH = 5; |
||
25 | const UNSIGNED_INT48_LENGTH = 6; |
||
26 | const UNSIGNED_INT56_LENGTH = 7; |
||
27 | const UNSIGNED_INT64_LENGTH = 8; |
||
28 | |||
29 | /** |
||
30 | * @var int |
||
31 | */ |
||
32 | private $readBytes = 0; |
||
33 | /** |
||
34 | * @var string |
||
35 | */ |
||
36 | private $binaryData = ''; |
||
37 | |||
38 | /** |
||
39 | * Package constructor. |
||
40 | * @param string $binaryData |
||
41 | */ |
||
42 | public function __construct($binaryData) |
||
46 | |||
47 | /** |
||
48 | * @param int $length |
||
49 | */ |
||
50 | public function advance($length) |
||
56 | |||
57 | /** |
||
58 | * @param int $length |
||
59 | * @return string |
||
60 | * @throws BinaryDataReaderException |
||
61 | */ |
||
62 | public function read($length) |
||
71 | |||
72 | /** |
||
73 | * @return int |
||
74 | */ |
||
75 | public function readInt16() |
||
79 | |||
80 | /** |
||
81 | * Push again data in data buffer. It's use when you want |
||
82 | * to extract a bit from a value a let the rest of the code normally |
||
83 | * read the data |
||
84 | * |
||
85 | * @param string $data |
||
86 | */ |
||
87 | public function unread($data) |
||
92 | |||
93 | /** |
||
94 | * Read a 'Length Coded Binary' number from the data buffer. |
||
95 | * Length coded numbers can be anywhere from 1 to 9 bytes depending |
||
96 | * on the value of the first byte. |
||
97 | * From PyMYSQL source code |
||
98 | * |
||
99 | * @return int|string |
||
100 | * @throws BinaryDataReaderException |
||
101 | */ |
||
102 | public function readCodedBinary() |
||
129 | |||
130 | /** |
||
131 | * @return int |
||
132 | */ |
||
133 | public function readUInt16() |
||
137 | |||
138 | /** |
||
139 | * @return int |
||
140 | */ |
||
141 | public function readUInt24() |
||
146 | |||
147 | /** |
||
148 | * @return int |
||
149 | */ |
||
150 | public function readUInt64() |
||
154 | |||
155 | /** |
||
156 | * @param string $data |
||
157 | * @return string |
||
158 | */ |
||
159 | public function unpackUInt64($data) |
||
164 | |||
165 | /** |
||
166 | * @return int |
||
167 | */ |
||
168 | View Code Duplication | public function readInt24() |
|
179 | |||
180 | /** |
||
181 | * @return string |
||
182 | */ |
||
183 | public function readInt64() |
||
188 | |||
189 | /** |
||
190 | * @param int $size |
||
191 | * @return string |
||
192 | * @throws BinaryDataReaderException |
||
193 | */ |
||
194 | public function readLengthCodedPascalString($size) |
||
198 | |||
199 | /** |
||
200 | * Read a little endian integer values based on byte number |
||
201 | * |
||
202 | * @param $size |
||
203 | * @return mixed |
||
204 | * @throws BinaryDataReaderException |
||
205 | */ |
||
206 | public function readUIntBySize($size) |
||
243 | |||
244 | /** |
||
245 | * @return int |
||
246 | */ |
||
247 | public function readUInt8() |
||
251 | |||
252 | /** |
||
253 | * @return int |
||
254 | */ |
||
255 | public function readUInt32() |
||
259 | |||
260 | /** |
||
261 | * @return mixed |
||
262 | */ |
||
263 | View Code Duplication | public function readUInt40() |
|
270 | |||
271 | /** |
||
272 | * @return mixed |
||
273 | */ |
||
274 | public function readUInt48() |
||
280 | |||
281 | /** |
||
282 | * @return mixed |
||
283 | */ |
||
284 | public function readUInt56() |
||
292 | |||
293 | /** |
||
294 | * Read a big endian integer values based on byte number |
||
295 | * |
||
296 | * @param int $size |
||
297 | * @return int |
||
298 | * @throws BinaryDataReaderException |
||
299 | */ |
||
300 | public function readIntBeBySize($size) |
||
325 | |||
326 | /** |
||
327 | * @return int |
||
328 | */ |
||
329 | public function readInt8() |
||
333 | |||
334 | /** |
||
335 | * @return mixed |
||
336 | */ |
||
337 | public function readInt16Be() |
||
341 | |||
342 | /** |
||
343 | * @return int |
||
344 | */ |
||
345 | View Code Duplication | public function readInt24Be() |
|
356 | |||
357 | /** |
||
358 | * @return int |
||
359 | */ |
||
360 | public function readInt32Be() |
||
364 | |||
365 | /** |
||
366 | * @return int |
||
367 | */ |
||
368 | View Code Duplication | public function readInt40Be() |
|
375 | |||
376 | /** |
||
377 | * @return int |
||
378 | */ |
||
379 | public function readInt32() |
||
383 | |||
384 | /** |
||
385 | * @return float |
||
386 | */ |
||
387 | public function readFloat() |
||
391 | |||
392 | /** |
||
393 | * @return double |
||
394 | */ |
||
395 | public function readDouble() |
||
399 | |||
400 | /** |
||
401 | * @return string |
||
402 | */ |
||
403 | public function readTableId() |
||
407 | |||
408 | /** |
||
409 | * @param int $size |
||
410 | * @return bool |
||
411 | */ |
||
412 | public function isComplete($size) |
||
420 | |||
421 | /** |
||
422 | * @param int $value |
||
423 | * @return string |
||
424 | */ |
||
425 | public static function pack64bit($value) |
||
429 | |||
430 | /** |
||
431 | * @return int |
||
432 | */ |
||
433 | public function getBinaryDataLength() |
||
437 | |||
438 | /** |
||
439 | * @return string |
||
440 | */ |
||
441 | public function getBinaryData() |
||
445 | } |
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.