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 Socket 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 Socket, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 12 | class Socket |
||
| 13 | { |
||
| 14 | protected $resource = null; |
||
| 15 | protected $domain = null; |
||
| 16 | protected $type = null; |
||
| 17 | protected $protocol = null; |
||
| 18 | protected static $map = []; |
||
| 19 | |||
| 20 | /** |
||
| 21 | * Sets up the Socket Resource. |
||
| 22 | * |
||
| 23 | * @param resource $resource |
||
| 24 | */ |
||
| 25 | 3 | protected function __construct($resource) |
|
| 30 | |||
| 31 | /** |
||
| 32 | * Cleans up the Socket. |
||
| 33 | */ |
||
| 34 | public function __destruct() |
||
| 39 | |||
| 40 | /** |
||
| 41 | * Return the resource name. |
||
| 42 | * |
||
| 43 | * @return string |
||
| 44 | */ |
||
| 45 | public function __toString() |
||
| 49 | |||
| 50 | /** |
||
| 51 | * Accept a connection. |
||
| 52 | * |
||
| 53 | * @throws Exception\SocketException |
||
| 54 | * |
||
| 55 | * @return Socket |
||
| 56 | */ |
||
| 57 | public function accept() |
||
| 67 | |||
| 68 | /** |
||
| 69 | * @param string $address |
||
| 70 | * @param int $port |
||
| 71 | * |
||
| 72 | * @throws Exception\SocketException |
||
| 73 | * |
||
| 74 | * @return bool |
||
| 75 | */ |
||
| 76 | 1 | public function bind($address, $port = 0) |
|
| 86 | |||
| 87 | /** |
||
| 88 | * Close the socket. |
||
| 89 | * |
||
| 90 | * @return void |
||
| 91 | */ |
||
| 92 | public function close() |
||
| 97 | |||
| 98 | /** |
||
| 99 | * Connect to a socket. |
||
| 100 | * |
||
| 101 | * @param $address |
||
| 102 | * @param int $port |
||
| 103 | * |
||
| 104 | * @throws Exception\SocketException |
||
| 105 | * |
||
| 106 | * @return bool |
||
| 107 | */ |
||
| 108 | public function connect($address, $port = 0) |
||
| 118 | |||
| 119 | /** |
||
| 120 | * @param array $resources |
||
| 121 | * |
||
| 122 | * @return Socket[] |
||
| 123 | */ |
||
| 124 | protected static function constructFromResources(array $resources) |
||
| 134 | |||
| 135 | /** |
||
| 136 | * Create a socket. |
||
| 137 | * |
||
| 138 | * @param int $domain |
||
| 139 | * @param int $type |
||
| 140 | * @param int $protocol |
||
| 141 | * |
||
| 142 | * @throws Exception\SocketException |
||
| 143 | * |
||
| 144 | * @return Socket |
||
| 145 | */ |
||
| 146 | 4 | public static function create($domain, $type, $protocol) |
|
| 161 | |||
| 162 | /** |
||
| 163 | * @param $port |
||
| 164 | * @param int $backlog |
||
| 165 | * |
||
| 166 | * @throws Exception\SocketException |
||
| 167 | * |
||
| 168 | * @return Socket |
||
| 169 | */ |
||
| 170 | public static function createListen($port, $backlog = 128) |
||
| 183 | |||
| 184 | /** |
||
| 185 | * @param $domain |
||
| 186 | * @param $type |
||
| 187 | * @param $protocol |
||
| 188 | * |
||
| 189 | * @throws Exception\SocketException |
||
| 190 | * |
||
| 191 | * @return Socket[] |
||
| 192 | */ |
||
| 193 | public static function createPair($domain, $type, $protocol) |
||
| 212 | |||
| 213 | /** |
||
| 214 | * @param $level |
||
| 215 | * @param $optname |
||
| 216 | * |
||
| 217 | * @throws Exception\SocketException |
||
| 218 | * |
||
| 219 | * @return mixed |
||
| 220 | */ |
||
| 221 | public function getOption($level, $optname) |
||
| 231 | |||
| 232 | /** |
||
| 233 | * @param $address |
||
| 234 | * @param $port |
||
| 235 | * |
||
| 236 | * @throws Exception\SocketException |
||
| 237 | * |
||
| 238 | * @return bool |
||
| 239 | */ |
||
| 240 | public function getPeerName(&$address, &$port) |
||
| 250 | |||
| 251 | /** |
||
| 252 | * @param string $address |
||
| 253 | * @param int $port |
||
| 254 | * |
||
| 255 | * @throws Exception\SocketException |
||
| 256 | * |
||
| 257 | * @return bool |
||
| 258 | */ |
||
| 259 | 1 | public function getSockName(&$address, &$port) |
|
| 273 | |||
| 274 | /** |
||
| 275 | * @param $stream |
||
| 276 | * |
||
| 277 | * @throws Exception\SocketException |
||
| 278 | * |
||
| 279 | * @return Socket |
||
| 280 | */ |
||
| 281 | public static function importStream($stream) |
||
| 291 | |||
| 292 | /** |
||
| 293 | * @param int $backlog |
||
| 294 | * |
||
| 295 | * @throws Exception\SocketException |
||
| 296 | * |
||
| 297 | * @return bool |
||
| 298 | */ |
||
| 299 | 1 | public function listen($backlog = 0) |
|
| 309 | |||
| 310 | /** |
||
| 311 | * @param int $length |
||
| 312 | * @param int $type |
||
| 313 | * |
||
| 314 | * @throws Exception\SocketException |
||
| 315 | * |
||
| 316 | * @return string |
||
| 317 | */ |
||
| 318 | public function read($length, $type = PHP_BINARY_READ) |
||
| 328 | |||
| 329 | /** |
||
| 330 | * @param $buffer |
||
| 331 | * @param int $length |
||
| 332 | * @param int $flags |
||
| 333 | * |
||
| 334 | * @throws Exception\SocketException |
||
| 335 | * |
||
| 336 | * @return int |
||
| 337 | */ |
||
| 338 | public function receive(&$buffer, $length, $flags) |
||
| 348 | |||
| 349 | /** |
||
| 350 | * @param Socket[] &$read |
||
| 351 | * @param Socket[] &$write |
||
| 352 | * @param Socket[] &$except |
||
| 353 | * @param int $timeoutSeconds |
||
| 354 | * @param int $timeoutMilliseconds |
||
| 355 | * @param Socket[] $read |
||
| 356 | * |
||
| 357 | * @throws SocketException |
||
| 358 | * |
||
| 359 | * @return int |
||
| 360 | */ |
||
| 361 | public static function select( |
||
| 410 | |||
| 411 | /** |
||
| 412 | * Maps an array of {@see Socket}s to an array of socket resources. |
||
| 413 | * |
||
| 414 | * @param Socket[] $sockets |
||
| 415 | * |
||
| 416 | * @return resource[] |
||
| 417 | */ |
||
| 418 | protected static function mapClassToRawSocket($sockets) |
||
| 424 | |||
| 425 | /** |
||
| 426 | * Maps an array of socket resources to an array of {@see Socket}s. |
||
| 427 | * |
||
| 428 | * @param resource[] $sockets |
||
| 429 | * |
||
| 430 | * @return Socket[] |
||
| 431 | */ |
||
| 432 | protected static function mapRawSocketToClass($sockets) |
||
| 438 | |||
| 439 | /** |
||
| 440 | * @param $buffer |
||
| 441 | * @param int $length |
||
| 442 | * |
||
| 443 | * @throws Exception\SocketException |
||
| 444 | * |
||
| 445 | * @return int |
||
| 446 | */ |
||
| 447 | 1 | View Code Duplication | public function write($buffer, $length = null) |
| 471 | |||
| 472 | /** |
||
| 473 | * Sends data to a connected socket. |
||
| 474 | * |
||
| 475 | * @param $buffer |
||
| 476 | * @param int $flags |
||
| 477 | * @param int $length |
||
| 478 | * |
||
| 479 | * @throws Exception\SocketException |
||
| 480 | * |
||
| 481 | * @return int |
||
| 482 | */ |
||
| 483 | View Code Duplication | public function send($buffer, $flags = 0, $length = null) |
|
| 507 | |||
| 508 | /** |
||
| 509 | * Set the socket to blocking / non blocking. |
||
| 510 | * |
||
| 511 | * @param bool |
||
| 512 | * |
||
| 513 | * @return void |
||
| 514 | */ |
||
| 515 | public function setBlocking($bool) |
||
| 523 | } |
||
| 524 |
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.