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 PhpSerial 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 PhpSerial, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
25 | class PhpSerial |
||
26 | { |
||
27 | const OS_UNKNOWN = 0; |
||
28 | const OS_WIN = 1; //WINS32 WINNT Windows |
||
29 | const OS_LINUX = 2; |
||
30 | const OS_CYGWIN = 3; //Cygwin Windows Linux like commands |
||
31 | const OS_UNIX = 4; |
||
32 | const OS_BSD = 5; //FreeBSD or NetBSD or OpenBSD /dev/ttyu1 |
||
33 | const OS_OSX = 6; //Darwin MacOS |
||
34 | const OS_HPUX = 7; //tty1p0 |
||
35 | |||
36 | const SERIAL_DEVICE_NOTSET = 0; |
||
37 | const SERIAL_DEVICE_SET = 1; |
||
38 | const SERIAL_DEVICE_OPENED = 2; |
||
39 | |||
40 | const PARITY_NONE = 0; |
||
41 | const PARITY_ODD = 1; |
||
42 | const PARITY_EVEN = 2; |
||
43 | |||
44 | const FLOW_NONE = 0; //no flow control |
||
45 | const FLOW_RTSCTS = 1; // use RTS/CTS handshaking |
||
46 | const FLOW_XONXOFF = 2; //use XON/XOFF protocol |
||
47 | |||
48 | /** |
||
49 | * Pointer for device |
||
50 | * |
||
51 | * @var resource |
||
52 | */ |
||
53 | protected $handle = null; |
||
54 | /** |
||
55 | * Data buffer |
||
56 | * |
||
57 | * @var string |
||
58 | */ |
||
59 | protected $buffer = ""; |
||
60 | /** |
||
61 | * This var says if buffer should be flushed by write (true) or |
||
62 | * manually (false) |
||
63 | * |
||
64 | * @var bool |
||
65 | */ |
||
66 | protected $autoflush = false; |
||
67 | /** |
||
68 | * Wait time after send data to serial |
||
69 | * |
||
70 | * @var float |
||
71 | */ |
||
72 | protected $waittime = 0.1; |
||
73 | /** |
||
74 | * OS type where php is running |
||
75 | * linux is default |
||
76 | * |
||
77 | * @var int |
||
78 | */ |
||
79 | protected $ostype = 2; |
||
80 | /** |
||
81 | * Mode command to set up serial port |
||
82 | * formated device mode for especific OS use |
||
83 | * |
||
84 | * @var string |
||
85 | */ |
||
86 | protected $mode = ''; |
||
87 | /** |
||
88 | * Status of port |
||
89 | * NoSet, Set or Open |
||
90 | * |
||
91 | * @var int |
||
92 | */ |
||
93 | protected $state = self::SERIAL_DEVICE_NOTSET; |
||
94 | /** |
||
95 | * Port name |
||
96 | * |
||
97 | * @var string |
||
98 | */ |
||
99 | protected $port = '/dev/ttyS0'; |
||
100 | /** |
||
101 | * Data bits |
||
102 | * |
||
103 | * @var int |
||
104 | */ |
||
105 | protected $databits = 8; |
||
106 | /** |
||
107 | * Baud Rate |
||
108 | * |
||
109 | * @var int |
||
110 | */ |
||
111 | protected $baudrate = 9600; |
||
112 | /** |
||
113 | * Parity |
||
114 | * |
||
115 | * @var int |
||
116 | */ |
||
117 | protected $parity = self::PARITY_NONE; |
||
118 | /** |
||
119 | * Stop Bits |
||
120 | * |
||
121 | * @var float |
||
122 | */ |
||
123 | protected $stopbits = 1; |
||
124 | /** |
||
125 | * Flow Control |
||
126 | * |
||
127 | * @var int |
||
128 | */ |
||
129 | protected $flowcontrol = self::FLOW_NONE; |
||
130 | /** |
||
131 | * Formated device name command |
||
132 | * |
||
133 | * @var string |
||
134 | */ |
||
135 | protected $device = '/dev/ttyS0'; |
||
136 | /** |
||
137 | * Formated Data Bits command |
||
138 | * |
||
139 | * @var string |
||
140 | */ |
||
141 | protected $formatedDataBits = 'cs8'; |
||
142 | /** |
||
143 | * Formated Baud Rate command |
||
144 | * |
||
145 | * @var string |
||
146 | */ |
||
147 | protected $formatedBaudRate = '9600'; |
||
148 | /** |
||
149 | * Formated parity command |
||
150 | * |
||
151 | * @var string |
||
152 | */ |
||
153 | protected $formatedParity = '-parenb'; |
||
154 | /** |
||
155 | * Formated stop bits command |
||
156 | * |
||
157 | * @var string |
||
158 | */ |
||
159 | protected $formatedStopBits = '-cstopb'; |
||
160 | /** |
||
161 | * Formated flow control command |
||
162 | * |
||
163 | * @var string |
||
164 | */ |
||
165 | protected $formatedFlowControl = 'clocal -crtscts -ixon -ixoff'; |
||
166 | |||
167 | /** |
||
168 | * Parity data |
||
169 | * |
||
170 | * @var array |
||
171 | */ |
||
172 | private $parityargs = [ |
||
173 | "none" => [0, "-parenb"], |
||
174 | "odd" => [1, "parenb parodd"], |
||
175 | "even" => [2, "parenb -parodd"] |
||
176 | ]; |
||
177 | |||
178 | /** |
||
179 | * Basud Rate data |
||
180 | * |
||
181 | * @var array |
||
182 | */ |
||
183 | private $baudsargs = array ( |
||
184 | 110 => 11, |
||
185 | 150 => 15, |
||
186 | 300 => 30, |
||
187 | 600 => 60, |
||
188 | 1200 => 12, |
||
189 | 2400 => 24, |
||
190 | 4800 => 48, |
||
191 | 9600 => 96, |
||
192 | 19200 => 19, |
||
193 | 38400 => 38400, |
||
194 | 57600 => 57600, |
||
195 | 115200 => 115200 |
||
196 | ); |
||
197 | |||
198 | /** |
||
199 | * Constructor |
||
200 | * Set ostype parameter |
||
201 | * |
||
202 | 14 | * @param int $forceOS |
|
203 | */ |
||
204 | 14 | public function __construct($forceOS = null) |
|
216 | |||
217 | /** |
||
218 | * Clear class params |
||
219 | * Used for testing proporses |
||
220 | */ |
||
221 | protected function clearParams() |
||
238 | |||
239 | /** |
||
240 | 14 | * Close port |
|
241 | */ |
||
242 | 14 | public function __destruct() |
|
246 | |||
247 | /** |
||
248 | * Open set port |
||
249 | * |
||
250 | 2 | * @return boolean |
|
251 | */ |
||
252 | 2 | public function open() |
|
274 | 14 | ||
275 | /** |
||
276 | 14 | * Close serial port |
|
277 | 13 | * |
|
278 | * @return boolean |
||
279 | 1 | */ |
|
280 | 1 | public function close() |
|
292 | 2 | ||
293 | /** |
||
294 | * Returns the setup configuration for serial port |
||
295 | 2 | * this command will be exectuted in terminal |
|
296 | * |
||
297 | * @return string |
||
298 | */ |
||
299 | 2 | public function getSetUp() |
|
303 | 2 | ||
304 | 2 | /** |
|
305 | * Use class parameters to configure the serial port |
||
306 | 2 | * before the serial port is opened it must be configured, |
|
307 | * and in windows environment, all sets at a single time |
||
308 | 2 | * |
|
309 | * @return bool |
||
310 | 2 | */ |
|
311 | 2 | public function setUp() |
|
345 | |||
346 | /** |
||
347 | * Set automatic send massage to serial |
||
348 | * |
||
349 | * @param bool $auto |
||
350 | * @param float $waittime |
||
351 | */ |
||
352 | public function setAuto($auto, $waittime) |
||
363 | |||
364 | /** |
||
365 | * Returns automatic mode |
||
366 | * |
||
367 | * @return bool |
||
368 | */ |
||
369 | public function getAuto() |
||
373 | |||
374 | /** |
||
375 | * Read serial port |
||
376 | * |
||
377 | * @param int $count Number of characters to be read (will stop before |
||
378 | * if less characters are in the buffer) |
||
379 | * @return string |
||
380 | */ |
||
381 | public function read($count = 0) |
||
406 | 1 | ||
407 | 1 | /** |
|
408 | 1 | * Write data to buffer or serial port |
|
409 | * depends of getAuto() |
||
410 | * if getAuto() == true this command writes directly to port |
||
411 | * if getAuto() == false this command writes to buffer (default) |
||
412 | * |
||
413 | * @param string $data |
||
414 | * @return boolean |
||
415 | 1 | */ |
|
416 | 1 | public function write($data) |
|
425 | |||
426 | 1 | /** |
|
427 | * Flushs imediatly data to serial port |
||
428 | * |
||
429 | * @return boolean |
||
430 | */ |
||
431 | public function flush() |
||
439 | |||
440 | /** |
||
441 | * Set port name |
||
442 | * |
||
443 | * @param string $port |
||
444 | */ |
||
445 | public function setPort($port) |
||
467 | |||
468 | /** |
||
469 | * Returns port name |
||
470 | * |
||
471 | * @return string |
||
472 | 1 | */ |
|
473 | public function getPort() |
||
477 | |||
478 | /** |
||
479 | 1 | * Returns device formated name |
|
480 | * |
||
481 | * @return string |
||
482 | */ |
||
483 | public function getDevice() |
||
487 | |||
488 | 1 | /** |
|
489 | * Sets the length of a character. |
||
490 | 1 | * length of a character (5 <= length <= 8) |
|
491 | * |
||
492 | * @param int $length |
||
493 | 1 | * @return boolean |
|
494 | 1 | */ |
|
495 | 1 | public function setDataBits($length) |
|
504 | |||
505 | 2 | /** |
|
506 | * Returns char length |
||
507 | * |
||
508 | * @return int |
||
509 | */ |
||
510 | public function getDataBits() |
||
514 | 1 | ||
515 | /** |
||
516 | 1 | * Format data bits commands |
|
517 | 1 | * |
|
518 | * @param int $length |
||
519 | * @return string |
||
520 | */ |
||
521 | 1 | protected function zDataBits($length) |
|
530 | |||
531 | 1 | /** |
|
532 | * Set serial baud rate |
||
533 | 1 | * |
|
534 | * @param int $rate |
||
535 | * @return boolean |
||
536 | 1 | */ |
|
537 | 1 | public function setBaudRate($rate) |
|
546 | 2 | ||
547 | /** |
||
548 | 2 | * Return baud rate |
|
549 | 2 | * |
|
550 | 1 | * @return int |
|
551 | 1 | */ |
|
552 | 1 | public function getBaudRate() |
|
556 | |||
557 | /** |
||
558 | * Format baud rate command |
||
559 | * |
||
560 | * @param int $rate |
||
561 | * @return string |
||
562 | */ |
||
563 | protected function zBaudRate($rate) |
||
572 | |||
573 | |||
574 | /** |
||
575 | * Sets parity mode |
||
576 | * |
||
577 | * @param string $parity odd, even, none |
||
578 | * @return boolean |
||
579 | */ |
||
580 | public function setParity($parity) |
||
589 | 1 | ||
590 | 1 | /** |
|
591 | 1 | * Get parity mode set |
|
592 | * |
||
593 | * @return string |
||
594 | */ |
||
595 | public function getParity() |
||
606 | |||
607 | /** |
||
608 | * Format parity command |
||
609 | * |
||
610 | 1 | * @param string $parity |
|
611 | * @return string |
||
612 | 1 | */ |
|
613 | 1 | protected function zParity($parity) |
|
622 | |||
623 | |||
624 | /** |
||
625 | * Set length of stop bits |
||
626 | * the length of a stop bit. |
||
627 | * It must be either 1, 1.5 or 2. |
||
628 | * 1.5 is not supported under linux and on some computers. |
||
629 | 1 | * |
|
630 | * @param float $length |
||
631 | * @return boolean |
||
632 | 1 | */ |
|
633 | public function setStopBits($length) |
||
642 | 1 | ||
643 | /** |
||
644 | * Return stop bits set |
||
645 | * |
||
646 | * @return float |
||
647 | */ |
||
648 | public function getStopBits() |
||
652 | 2 | ||
653 | 2 | /** |
|
654 | 1 | * Format stop bit command |
|
655 | 1 | * |
|
656 | * @param float $length |
||
657 | 1 | * @return string |
|
658 | 1 | */ |
|
659 | public function zStopBits($length) |
||
667 | |||
668 | 1 | /** |
|
669 | * Set the flow control mode. |
||
670 | * Availible modes : |
||
671 | * "none" : no flow control |
||
672 | 1 | * "rts/cts" : use RTS/CTS handshaking |
|
673 | * "xon/xoff" : use XON/XOFF protocol |
||
674 | 1 | * |
|
675 | * @param string $flow |
||
676 | 1 | * @return boolean |
|
677 | */ |
||
678 | 1 | public function setFlowControl($flow) |
|
693 | |||
694 | 14 | /** |
|
695 | * Returns flow control set |
||
696 | 14 | * |
|
697 | * @return string |
||
698 | 14 | */ |
|
699 | public function getFlowControl() |
||
710 | |||
711 | /** |
||
712 | * Return flow control command formated for OP type |
||
713 | * |
||
714 | * @param int $flow |
||
715 | * @return string |
||
716 | */ |
||
717 | protected function zFlowControl($flow) |
||
765 | |||
766 | /** |
||
767 | * Find OS type |
||
768 | * |
||
769 | * @return int |
||
770 | */ |
||
771 | protected function getOs() |
||
793 | |||
794 | /** |
||
795 | * Exec command line in OS console |
||
796 | * |
||
797 | * @param string $cmd comand line to execute |
||
798 | * @param array $out retorn of this command in terminal |
||
799 | * @return int |
||
800 | */ |
||
801 | public function execCommand($cmd, &$out = null) |
||
818 | } |
||
819 |
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.