Complex classes like Communicator 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 Communicator, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
44 | class Communicator |
||
45 | { |
||
46 | /** |
||
47 | * Used when getting/setting all (default) charsets. |
||
48 | */ |
||
49 | const CHARSET_ALL = -1; |
||
50 | |||
51 | /** |
||
52 | * Used when getting/setting the (default) remote charset. |
||
53 | * |
||
54 | * The remote charset is the charset in which RouterOS stores its data. |
||
55 | * If you want to keep compatibility with your Winbox, this charset should |
||
56 | * match the default charset from your Windows' regional settings. |
||
57 | */ |
||
58 | const CHARSET_REMOTE = 0; |
||
59 | |||
60 | /** |
||
61 | * Used when getting/setting the (default) local charset. |
||
62 | * |
||
63 | * The local charset is the charset in which the data from RouterOS will be |
||
64 | * returned as. This charset should match the charset of the place the data |
||
65 | * will eventually be written to. |
||
66 | */ |
||
67 | const CHARSET_LOCAL = 1; |
||
68 | |||
69 | /** |
||
70 | * An array with the default charset. |
||
71 | * |
||
72 | * Charset types as keys, and the default charsets as values. |
||
73 | * |
||
74 | * @var array<string,string|null> |
||
75 | */ |
||
76 | protected static $defaultCharsets = array( |
||
77 | self::CHARSET_REMOTE => null, |
||
78 | self::CHARSET_LOCAL => null |
||
79 | ); |
||
80 | |||
81 | /** |
||
82 | * An array with the current charset. |
||
83 | * |
||
84 | * Charset types as keys, and the current charsets as values. |
||
85 | * |
||
86 | * @var array<string,string|null> |
||
87 | */ |
||
88 | protected $charsets = array(); |
||
89 | |||
90 | /** |
||
91 | * The transmitter for the connection. |
||
92 | * |
||
93 | * @var T\TcpClient |
||
94 | */ |
||
95 | protected $trans; |
||
96 | |||
97 | /** |
||
98 | * Creates a new connection with the specified options. |
||
99 | * |
||
100 | * @param string $host Hostname (IP or domain) of RouterOS. |
||
101 | * @param int|null $port The port on which the RouterOS host |
||
102 | * provides the API service. You can also specify NULL, in which case |
||
103 | * the port will automatically be chosen between 8728 and 8729, |
||
104 | * depending on the value of $crypto. |
||
105 | * @param bool $persist Whether or not the connection should be a |
||
106 | * persistent one. |
||
107 | * @param double|null $timeout The timeout for the connection. |
||
108 | * @param string $key A string that uniquely identifies the |
||
109 | * connection. |
||
110 | * @param string $crypto The encryption for this connection. |
||
111 | * Must be one of the PEAR2\Net\Transmitter\NetworkStream::CRYPTO_* |
||
112 | * constants. Off by default. RouterOS currently supports only TLS, but |
||
113 | * the setting is provided in this fashion for forward compatibility's |
||
114 | * sake. And for the sake of simplicity, if you specify an encryption, |
||
115 | * don't specify a context and your default context uses the value |
||
116 | * "DEFAULT" for ciphers, "ADH" will be automatically added to the list |
||
117 | * of ciphers. |
||
118 | * @param resource|null $context A context for the socket. |
||
119 | * |
||
120 | * @see sendWord() |
||
121 | */ |
||
122 | public function __construct( |
||
179 | |||
180 | /** |
||
181 | * A shorthand gateway. |
||
182 | * |
||
183 | * This is a magic PHP method that allows you to call the object as a |
||
184 | * function. Depending on the argument given, one of the other functions in |
||
185 | * the class is invoked and its returned value is returned by this function. |
||
186 | * |
||
187 | * @param string|null $string A string of the word to send, or NULL to get |
||
188 | * the next word as a string. |
||
189 | * |
||
190 | * @return int|string If a string is provided, returns the number of bytes |
||
191 | * sent, otherwise returns the next word as a string. |
||
192 | */ |
||
193 | public function __invoke($string = null) |
||
198 | |||
199 | /** |
||
200 | * Checks whether a variable is a seekable stream resource. |
||
201 | * |
||
202 | * @param mixed $var The value to check. |
||
203 | * |
||
204 | * @return bool TRUE if $var is a seekable stream, FALSE otherwise. |
||
205 | */ |
||
206 | public static function isSeekableStream($var) |
||
214 | |||
215 | /** |
||
216 | * Uses iconv to convert a stream from one charset to another. |
||
217 | * |
||
218 | * @param string $inCharset The charset of the stream. |
||
219 | * @param string $outCharset The desired resulting charset. |
||
220 | * @param resource $stream The stream to convert. The stream is assumed |
||
221 | * to be seekable, and is read from its current position to its end, |
||
222 | * after which, it is seeked back to its starting position. |
||
223 | * |
||
224 | * @return resource A new stream that uses the $out_charset. The stream is a |
||
225 | * subset from the original stream, from its current position to its |
||
226 | * end, seeked at its start. |
||
227 | */ |
||
228 | public static function iconvStream($inCharset, $outCharset, $stream) |
||
252 | |||
253 | /** |
||
254 | * Sets the default charset(s) for new connections. |
||
255 | * |
||
256 | * @param mixed $charset The charset to set. If $charsetType is |
||
257 | * {@link self::CHARSET_ALL}, you can supply either a string to use for |
||
258 | * all charsets, or an array with the charset types as keys, and the |
||
259 | * charsets as values. |
||
260 | * @param int $charsetType Which charset to set. Valid values are the |
||
261 | * CHARSET_* constants. Any other value is treated as |
||
262 | * {@link self::CHARSET_ALL}. |
||
263 | * |
||
264 | * @return string|array The old charset. If $charsetType is |
||
265 | * {@link self::CHARSET_ALL}, the old values will be returned as an |
||
266 | * array with the types as keys, and charsets as values. |
||
267 | * |
||
268 | * @see setCharset() |
||
269 | */ |
||
270 | public static function setDefaultCharset( |
||
288 | |||
289 | /** |
||
290 | * Gets the default charset(s). |
||
291 | * |
||
292 | * @param int $charsetType Which charset to get. Valid values are the |
||
293 | * CHARSET_* constants. Any other value is treated as |
||
294 | * {@link self::CHARSET_ALL}. |
||
295 | * |
||
296 | * @return string|array The current charset. If $charsetType is |
||
297 | * {@link self::CHARSET_ALL}, the current values will be returned as an |
||
298 | * array with the types as keys, and charsets as values. |
||
299 | * |
||
300 | * @see setDefaultCharset() |
||
301 | */ |
||
302 | public static function getDefaultCharset($charsetType) |
||
307 | |||
308 | /** |
||
309 | * Gets the length of a seekable stream. |
||
310 | * |
||
311 | * Gets the length of a seekable stream. |
||
312 | * |
||
313 | * @param resource $stream The stream to check. The stream is assumed to be |
||
314 | * seekable. |
||
315 | * |
||
316 | * @return double The number of bytes in the stream between its current |
||
317 | * position and its end. |
||
318 | */ |
||
319 | public static function seekableStreamLength($stream) |
||
328 | |||
329 | /** |
||
330 | * Sets the charset(s) for this connection. |
||
331 | * |
||
332 | * Sets the charset(s) for this connection. The specified charset(s) will be |
||
333 | * used for all future words. When sending, {@link self::CHARSET_LOCAL} is |
||
334 | * converted to {@link self::CHARSET_REMOTE}, and when receiving, |
||
335 | * {@link self::CHARSET_REMOTE} is converted to {@link self::CHARSET_LOCAL}. |
||
336 | * Setting NULL to either charset will disable charset conversion, and data |
||
337 | * will be both sent and received "as is". |
||
338 | * |
||
339 | * @param mixed $charset The charset to set. If $charsetType is |
||
340 | * {@link self::CHARSET_ALL}, you can supply either a string to use for |
||
341 | * all charsets, or an array with the charset types as keys, and the |
||
342 | * charsets as values. |
||
343 | * @param int $charsetType Which charset to set. Valid values are the |
||
344 | * CHARSET_* constants. Any other value is treated as |
||
345 | * {@link self::CHARSET_ALL}. |
||
346 | * |
||
347 | * @return string|array The old charset. If $charsetType is |
||
348 | * {@link self::CHARSET_ALL}, the old values will be returned as an |
||
349 | * array with the types as keys, and charsets as values. |
||
350 | * |
||
351 | * @see setDefaultCharset() |
||
352 | */ |
||
353 | public function setCharset($charset, $charsetType = self::CHARSET_ALL) |
||
369 | |||
370 | /** |
||
371 | * Gets the charset(s) for this connection. |
||
372 | * |
||
373 | * @param int $charsetType Which charset to get. Valid values are the |
||
374 | * CHARSET_* constants. Any other value is treated as |
||
375 | * {@link self::CHARSET_ALL}. |
||
376 | * |
||
377 | * @return string|array The current charset. If $charsetType is |
||
378 | * {@link self::CHARSET_ALL}, the current values will be returned as an |
||
379 | * array with the types as keys, and charsets as values. |
||
380 | * |
||
381 | * @see getDefaultCharset() |
||
382 | * @see setCharset() |
||
383 | */ |
||
384 | public function getCharset($charsetType) |
||
389 | |||
390 | /** |
||
391 | * Gets the transmitter for this connection. |
||
392 | * |
||
393 | * @return T\TcpClient The transmitter for this connection. |
||
394 | */ |
||
395 | public function getTransmitter() |
||
399 | |||
400 | /** |
||
401 | * Sends a word. |
||
402 | * |
||
403 | * Sends a word and automatically encodes its length when doing so. |
||
404 | * |
||
405 | * @param string $word The word to send. |
||
406 | * |
||
407 | * @return int The number of bytes sent. |
||
408 | * |
||
409 | * @see sendWordFromStream() |
||
410 | * @see getNextWord() |
||
411 | */ |
||
412 | public function sendWord($word) |
||
433 | |||
434 | /** |
||
435 | * Sends a word based on a stream. |
||
436 | * |
||
437 | * Sends a word based on a stream and automatically encodes its length when |
||
438 | * doing so. The stream is read from its current position to its end, and |
||
439 | * then returned to its current position. Because of those operations, the |
||
440 | * supplied stream must be seekable. |
||
441 | * |
||
442 | * @param string $prefix A string to prepend before the stream contents. |
||
443 | * @param resource $stream The seekable stream to send. |
||
444 | * |
||
445 | * @return int The number of bytes sent. |
||
446 | * |
||
447 | * @see sendWord() |
||
448 | */ |
||
449 | public function sendWordFromStream($prefix, $stream) |
||
482 | |||
483 | /** |
||
484 | * Verifies that the length is supported. |
||
485 | * |
||
486 | * Verifies if the specified length is supported by the API. Throws a |
||
487 | * {@link LengthException} if that's not the case. Currently, RouterOS |
||
488 | * supports words up to 0xFFFFFFFF in length, so that's the only check |
||
489 | * performed. |
||
490 | * |
||
491 | * @param int $length The length to verify. |
||
492 | * |
||
493 | * @return void |
||
494 | */ |
||
495 | public static function verifyLengthSupport($length) |
||
506 | |||
507 | /** |
||
508 | * Encodes the length as required by the RouterOS API. |
||
509 | * |
||
510 | * @param int $length The length to encode. |
||
511 | * |
||
512 | * @return string The encoded length. |
||
513 | */ |
||
514 | public static function encodeLength($length) |
||
546 | |||
547 | /** |
||
548 | * Get the next word in queue as a string. |
||
549 | * |
||
550 | * Get the next word in queue as a string, after automatically decoding its |
||
551 | * length. |
||
552 | * |
||
553 | * @return string The word. |
||
554 | * |
||
555 | * @see close() |
||
556 | */ |
||
557 | public function getNextWord() |
||
585 | |||
586 | /** |
||
587 | * Get the next word in queue as a stream. |
||
588 | * |
||
589 | * Get the next word in queue as a stream, after automatically decoding its |
||
590 | * length. |
||
591 | * |
||
592 | * @return resource The word, as a stream. |
||
593 | * |
||
594 | * @see close() |
||
595 | */ |
||
596 | public function getNextWordAsStream() |
||
626 | |||
627 | /** |
||
628 | * Decodes the length of the incoming message. |
||
629 | * |
||
630 | * Decodes the length of the incoming message, as specified by the RouterOS |
||
631 | * API. |
||
632 | * |
||
633 | * @param T\Stream $trans The transmitter from which to decode the length of |
||
634 | * the incoming message. |
||
635 | * |
||
636 | * @return int|double The decoded length. |
||
637 | * Is of type "double" only for values above "2 << 31". |
||
638 | */ |
||
639 | public static function decodeLength(T\Stream $trans) |
||
649 | |||
650 | /** |
||
651 | * Decodes the length of the incoming message. |
||
652 | * |
||
653 | * Decodes the length of the incoming message, as specified by the RouterOS |
||
654 | * API. |
||
655 | * |
||
656 | * Difference with the non private function is that this one doesn't perform |
||
657 | * locking if the connection is a persistent one. |
||
658 | * |
||
659 | * @param T\Stream $trans The transmitter from which to decode the length of |
||
660 | * the incoming message. |
||
661 | * |
||
662 | * @return int|double The decoded length. |
||
663 | * Is of type "double" only for values above "2 << 31". |
||
664 | */ |
||
665 | private static function _decodeLength(T\Stream $trans) |
||
692 | |||
693 | /** |
||
694 | * Closes the opened connection, even if it is a persistent one. |
||
695 | * |
||
696 | * @return bool TRUE on success, FALSE on failure. |
||
697 | */ |
||
698 | public function close() |
||
702 | } |
||
703 |
This check looks for type mismatches where the missing type is
false
. This is usually indicative of an error condtion.Consider the follow example
This function either returns a new
DateTime
object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returnedfalse
before passing on the value to another function or method that may not be able to handle afalse
.