Complex classes like GraphNode 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 GraphNode, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 49 | class GraphNode |
||
| 50 | { |
||
| 51 | /** |
||
| 52 | * The id of the node. |
||
| 53 | * |
||
| 54 | * @var int |
||
| 55 | * |
||
| 56 | * @since 1.0 |
||
| 57 | */ |
||
| 58 | private $id = 0; |
||
| 59 | |||
| 60 | /** |
||
| 61 | * The height of the node. |
||
| 62 | * |
||
| 63 | * @var int |
||
| 64 | * |
||
| 65 | * @since 1.0 |
||
| 66 | */ |
||
| 67 | private $height = 0; |
||
| 68 | |||
| 69 | /** |
||
| 70 | * The width of the node. |
||
| 71 | * |
||
| 72 | * @var int |
||
| 73 | * |
||
| 74 | * @since 1.0 |
||
| 75 | */ |
||
| 76 | private $width = 0; |
||
| 77 | |||
| 78 | /** |
||
| 79 | * The x position of the node. |
||
| 80 | * |
||
| 81 | * @var int |
||
| 82 | * |
||
| 83 | * @since 1.0 |
||
| 84 | */ |
||
| 85 | private $x = 0; |
||
| 86 | |||
| 87 | /** |
||
| 88 | * The y position of the node. |
||
| 89 | * |
||
| 90 | * @var int |
||
| 91 | * |
||
| 92 | * @since 1.0 |
||
| 93 | */ |
||
| 94 | private $y = 0; |
||
| 95 | |||
| 96 | /** |
||
| 97 | * The node to the left of this one. |
||
| 98 | * |
||
| 99 | * @var Alpha\Util\Graph\GraphNode |
||
| 100 | * |
||
| 101 | * @since 1.0 |
||
| 102 | */ |
||
| 103 | private $leftNode; |
||
| 104 | |||
| 105 | /** |
||
| 106 | * The node to the right of this one. |
||
| 107 | * |
||
| 108 | * @var Alpha\Util\Graph\GraphNode |
||
| 109 | * |
||
| 110 | * @since 1.0 |
||
| 111 | */ |
||
| 112 | private $rightNode; |
||
| 113 | |||
| 114 | /** |
||
| 115 | * An array of child nodes of this node. |
||
| 116 | * |
||
| 117 | * @var array |
||
| 118 | * |
||
| 119 | * @since 1.0 |
||
| 120 | */ |
||
| 121 | private $children = array(); |
||
| 122 | |||
| 123 | /** |
||
| 124 | * The margin offset of the current node. |
||
| 125 | * |
||
| 126 | * @var int |
||
| 127 | * |
||
| 128 | * @since 1.0 |
||
| 129 | */ |
||
| 130 | private $offset = 0; |
||
| 131 | |||
| 132 | /** |
||
| 133 | * Optional positional modifier. |
||
| 134 | * |
||
| 135 | * @var int |
||
| 136 | * |
||
| 137 | * @since 1.0 |
||
| 138 | */ |
||
| 139 | private $modifier = 0; |
||
| 140 | |||
| 141 | /** |
||
| 142 | * Parent node of this node (if any). |
||
| 143 | * |
||
| 144 | * @var Alpha\Util\Graph\GraphNode |
||
| 145 | * |
||
| 146 | * @since 1.0 |
||
| 147 | */ |
||
| 148 | private $parentNode; |
||
| 149 | |||
| 150 | /** |
||
| 151 | * The text message to display on the node. |
||
| 152 | * |
||
| 153 | * @var string |
||
| 154 | * |
||
| 155 | * @since 1.0 |
||
| 156 | */ |
||
| 157 | private $message; |
||
| 158 | |||
| 159 | /** |
||
| 160 | * A 2D array of the coordinates of the endpoints for connectots on this node. |
||
| 161 | * |
||
| 162 | * @var array |
||
| 163 | * |
||
| 164 | * @since 1.0 |
||
| 165 | */ |
||
| 166 | private $links = array(); |
||
| 167 | |||
| 168 | /** |
||
| 169 | * An array containing the R,G,B values for the colour of this node. |
||
| 170 | * |
||
| 171 | * @var array |
||
| 172 | * |
||
| 173 | * @since 1.0 |
||
| 174 | */ |
||
| 175 | private $nodeColour = array(); |
||
| 176 | |||
| 177 | /** |
||
| 178 | * If the node is clickable in an image map, use this property to hold the target URL. |
||
| 179 | * |
||
| 180 | * @var string |
||
| 181 | * |
||
| 182 | * @since 1.0 |
||
| 183 | */ |
||
| 184 | private $URL; |
||
| 185 | |||
| 186 | /** |
||
| 187 | * Constructor. |
||
| 188 | * |
||
| 189 | * @param int $id |
||
| 190 | * @param int $width |
||
| 191 | * @param int $height |
||
| 192 | * @param string $message |
||
| 193 | * @param array $nodeColour |
||
| 194 | * @param string $URL |
||
| 195 | */ |
||
| 196 | public function __construct($id, $width, $height, $message = '', $nodeColour = null, $URL = null) |
||
| 197 | { |
||
| 198 | $this->id = $id; |
||
| 199 | $this->width = $width; |
||
| 200 | $this->height = $height; |
||
| 201 | $this->message = $message; |
||
| 202 | $this->nodeColour = $nodeColour; |
||
|
|
|||
| 203 | $this->URL = $URL; |
||
| 204 | } |
||
| 205 | |||
| 206 | /** |
||
| 207 | * Get the node colour array. |
||
| 208 | * |
||
| 209 | * @return array |
||
| 210 | * |
||
| 211 | * @since 1.0 |
||
| 212 | */ |
||
| 213 | public function getNodeColour() |
||
| 214 | { |
||
| 215 | return $this->nodeColour; |
||
| 216 | } |
||
| 217 | |||
| 218 | /** |
||
| 219 | * Set the node colour array. |
||
| 220 | * |
||
| 221 | * @param array $nodeColour |
||
| 222 | * |
||
| 223 | * @throws Alpha\Exception\IllegalArguementException |
||
| 224 | * |
||
| 225 | * @since 1.0 |
||
| 226 | */ |
||
| 227 | public function setNodeColour($nodeColour) |
||
| 228 | { |
||
| 229 | if (is_array($nodeColour) && count($nodeColour) == 3) { |
||
| 230 | $this->nodeColour = $nodeColour; |
||
| 231 | } else { |
||
| 232 | throw new IllegalArguementException('The nodeColour value passed ['.$nodeColour.'] is not a valid array!'); |
||
| 233 | } |
||
| 234 | } |
||
| 235 | |||
| 236 | /** |
||
| 237 | * Get the node URL. |
||
| 238 | * |
||
| 239 | * @return string |
||
| 240 | * |
||
| 241 | * @since 1.0 |
||
| 242 | */ |
||
| 243 | public function getURL() |
||
| 247 | |||
| 248 | /** |
||
| 249 | * Set the node URL. |
||
| 250 | * |
||
| 251 | * @param string $URL |
||
| 252 | * |
||
| 253 | * @since 1.0 |
||
| 254 | */ |
||
| 255 | public function setURL($URL) |
||
| 259 | |||
| 260 | /** |
||
| 261 | * Get the node text message. |
||
| 262 | * |
||
| 263 | * @return string |
||
| 264 | * |
||
| 265 | * @since 1.0 |
||
| 266 | */ |
||
| 267 | public function getMessage() |
||
| 271 | |||
| 272 | /** |
||
| 273 | * Set the node text message. |
||
| 274 | * |
||
| 275 | * @param string $message |
||
| 276 | * |
||
| 277 | * @since 1.0 |
||
| 278 | */ |
||
| 279 | public function setMessage($message) |
||
| 283 | |||
| 284 | /** |
||
| 285 | * Get the node offset. |
||
| 286 | * |
||
| 287 | * @return string |
||
| 288 | * |
||
| 289 | * @since 1.0 |
||
| 290 | */ |
||
| 291 | public function getOffset() |
||
| 295 | |||
| 296 | /** |
||
| 297 | * Set the node offset. |
||
| 298 | * |
||
| 299 | * @param int $offset |
||
| 300 | * |
||
| 301 | * @since 1.0 |
||
| 302 | */ |
||
| 303 | public function setOffset($offset) |
||
| 307 | |||
| 308 | /** |
||
| 309 | * Get the node modifier. |
||
| 310 | * |
||
| 311 | * @return int |
||
| 312 | * |
||
| 313 | * @since 1.0 |
||
| 314 | */ |
||
| 315 | public function getModifier() |
||
| 316 | { |
||
| 317 | return $this->modifier; |
||
| 318 | } |
||
| 319 | |||
| 320 | /** |
||
| 321 | * Set the node modifier. |
||
| 322 | * |
||
| 323 | * @param int $modifier |
||
| 324 | * |
||
| 325 | * @since 1.0 |
||
| 326 | */ |
||
| 327 | public function setModifier($modifier) |
||
| 328 | { |
||
| 329 | $this->modifier = $modifier; |
||
| 330 | } |
||
| 331 | |||
| 332 | /** |
||
| 333 | * Get the number of child nodes attached to this node. |
||
| 334 | * |
||
| 335 | * @return int |
||
| 336 | * |
||
| 337 | * @since 1.0 |
||
| 338 | */ |
||
| 339 | public function childCount() |
||
| 340 | { |
||
| 341 | return count($this->children); |
||
| 342 | } |
||
| 343 | |||
| 344 | /** |
||
| 345 | * Get the parent node of this node (if any). |
||
| 346 | * |
||
| 347 | * @return Alpha\Util\Graph\GraphNode |
||
| 348 | * |
||
| 349 | * @since 1.0 |
||
| 350 | */ |
||
| 351 | public function getParentNode() |
||
| 352 | { |
||
| 353 | return $this->parentNode; |
||
| 354 | } |
||
| 355 | |||
| 356 | /** |
||
| 357 | * Set the parent node. |
||
| 358 | * |
||
| 359 | * @param Alpha\Util\Graph\GraphNode $node |
||
| 360 | * |
||
| 361 | * @throws Alpha\Exception\IllegalArguementException |
||
| 362 | * |
||
| 363 | * @since 1.0 |
||
| 364 | */ |
||
| 365 | public function setParentNode($node) |
||
| 366 | { |
||
| 367 | if ($node instanceof self) { |
||
| 368 | $this->parentNode = $node; |
||
| 369 | } else { |
||
| 370 | throw new IllegalArguementException('The node object passed to setParentNode is not a valid GraphNode instance!'); |
||
| 371 | } |
||
| 372 | } |
||
| 373 | |||
| 374 | /** |
||
| 375 | * Get the node to the left of this one (if any). |
||
| 376 | * |
||
| 377 | * @return Alpha\Util\Graph\GraphNode |
||
| 378 | * |
||
| 379 | * @since 1.0 |
||
| 380 | */ |
||
| 381 | public function getLeftSibling() |
||
| 382 | { |
||
| 383 | if ($this->leftNode) { |
||
| 384 | return $this->leftNode; |
||
| 385 | } else { |
||
| 386 | return; |
||
| 387 | } |
||
| 388 | } |
||
| 389 | |||
| 390 | /** |
||
| 391 | * Sets the node to the left of this node. |
||
| 392 | * |
||
| 393 | * @param Alpha\Util\Graph\GraphNode $node |
||
| 394 | * |
||
| 395 | * @throws Alpha\Exception\IllegalArguementException |
||
| 396 | * |
||
| 397 | * @since 1.0 |
||
| 398 | */ |
||
| 399 | public function setLeftSibling($node) |
||
| 400 | { |
||
| 401 | if ($node instanceof self) { |
||
| 402 | $this->leftNode = $node; |
||
| 403 | } else { |
||
| 404 | throw new IllegalArguementException('The node object passed to setLeftSibling is not a valid GraphNode instance!'); |
||
| 405 | } |
||
| 406 | } |
||
| 407 | |||
| 408 | /** |
||
| 409 | * Get the node to the right of this one (if any). |
||
| 410 | * |
||
| 411 | * @return Alpha\Util\Graph\GraphNode |
||
| 412 | * |
||
| 413 | * @since 1.0 |
||
| 414 | */ |
||
| 415 | public function getRightSibling() |
||
| 416 | { |
||
| 417 | if ($this->rightNode) { |
||
| 418 | return $this->rightNode; |
||
| 419 | } else { |
||
| 420 | return; |
||
| 421 | } |
||
| 422 | } |
||
| 423 | |||
| 424 | /** |
||
| 425 | * Sets the node to the right of this node. |
||
| 426 | * |
||
| 427 | * @param Alpha\Util\Graph\GraphNode $node |
||
| 428 | * |
||
| 429 | * @throws Alpha\Exception\IllegalArguementException |
||
| 430 | * |
||
| 431 | * @since 1.0 |
||
| 432 | */ |
||
| 433 | public function setRightSibling($node) |
||
| 434 | { |
||
| 435 | if ($node instanceof self) { |
||
| 436 | $this->rightNode = $node; |
||
| 437 | } else { |
||
| 438 | throw new IllegalArguementException('The node object passed to setRightSibling is not a valid GraphNode instance!'); |
||
| 439 | } |
||
| 440 | } |
||
| 441 | |||
| 442 | /** |
||
| 443 | * Gets the child node at the index provided, or returns false if none is found. |
||
| 444 | * |
||
| 445 | * @param int $i |
||
| 446 | * |
||
| 447 | * @return mixed |
||
| 448 | * |
||
| 449 | * @since 1.0 |
||
| 450 | */ |
||
| 451 | public function getChildAt($i) |
||
| 452 | { |
||
| 453 | if (isset($this->children[$i])) { |
||
| 454 | return $this->children[$i]; |
||
| 455 | } else { |
||
| 456 | return false; |
||
| 457 | } |
||
| 458 | } |
||
| 459 | |||
| 460 | /** |
||
| 461 | * Calculates and returns the midpoint X coordinate of the children of this node. |
||
| 462 | * |
||
| 463 | * @return int |
||
| 464 | * |
||
| 465 | * @since 1.0 |
||
| 466 | */ |
||
| 467 | public function getChildrenCenter() |
||
| 468 | { |
||
| 469 | $node = $this->getChildAt(0); |
||
| 470 | $node1 = $this->getChildAt(count($this->children) - 1); |
||
| 471 | |||
| 472 | return $node->getOffset() + (($node1->getOffset() - $node->getOffset()) + $node1->getWidth()) / 2; |
||
| 473 | } |
||
| 474 | |||
| 475 | /** |
||
| 476 | * Returns the array of child GraphNode objects. |
||
| 477 | * |
||
| 478 | * @return array |
||
| 479 | * |
||
| 480 | * @since 1.0 |
||
| 481 | */ |
||
| 482 | public function getChildren() |
||
| 486 | |||
| 487 | /** |
||
| 488 | * Add a new node to the children array of this node. |
||
| 489 | * |
||
| 490 | * @param Alpha\Util\Graph\GraphNode $node |
||
| 491 | * |
||
| 492 | * @throws ALpha\Exception\IllegalArguementException |
||
| 493 | * |
||
| 494 | * @since 1.0 |
||
| 495 | */ |
||
| 496 | public function addChild($node) |
||
| 497 | { |
||
| 498 | if ($node instanceof self) { |
||
| 499 | array_push($this->children, $node); |
||
| 500 | } else { |
||
| 501 | throw new IllegalArguementException('The node object passed to addChild is not a valid GraphNode instance!'); |
||
| 502 | } |
||
| 503 | } |
||
| 504 | |||
| 505 | /** |
||
| 506 | * Returns the links array. |
||
| 507 | * |
||
| 508 | * @return array |
||
| 509 | * |
||
| 510 | * @since 1.0 |
||
| 511 | */ |
||
| 512 | public function getLinks() |
||
| 516 | |||
| 517 | /** |
||
| 518 | * Sets up the array of connector endpoints. |
||
| 519 | * |
||
| 520 | * @since 1.0 |
||
| 521 | */ |
||
| 522 | public function setUpLinks() |
||
| 523 | { |
||
| 524 | $xa = $this->x + ($this->width / 2); |
||
| 525 | $ya = $this->y + $this->height; |
||
| 526 | |||
| 527 | foreach ($this->children as $child) { |
||
| 528 | $xd = $xc = $child->getX() + ($child->getWidth() / 2); |
||
| 529 | $yd = $child->getY(); |
||
| 530 | $xb = $xa; |
||
| 531 | $yb = $yc = $ya + ($yd - $ya) / 2; |
||
| 542 | |||
| 543 | /** |
||
| 544 | * Returns the node height. |
||
| 545 | * |
||
| 546 | * @return int |
||
| 547 | * |
||
| 548 | * @since 1.0 |
||
| 549 | */ |
||
| 550 | public function getHeight() |
||
| 554 | |||
| 555 | /** |
||
| 556 | * Returns the node width. |
||
| 557 | * |
||
| 558 | * @return int |
||
| 559 | * |
||
| 560 | * @since 1.0 |
||
| 561 | */ |
||
| 562 | public function getWidth() |
||
| 566 | |||
| 567 | /** |
||
| 568 | * Returns the node X-coordinate. |
||
| 569 | * |
||
| 570 | * @return int |
||
| 571 | * |
||
| 572 | * @since 1.0 |
||
| 573 | */ |
||
| 574 | public function getX() |
||
| 578 | |||
| 579 | /** |
||
| 580 | * Returns the node Y-coordinate. |
||
| 581 | * |
||
| 582 | * @return int |
||
| 583 | * |
||
| 584 | * @since 1.0 |
||
| 585 | */ |
||
| 586 | public function getY() |
||
| 590 | |||
| 591 | /** |
||
| 592 | * Sets the node X-coordinate. |
||
| 593 | * |
||
| 594 | * @param int $x |
||
| 595 | * |
||
| 596 | * @since 1.0 |
||
| 597 | */ |
||
| 598 | public function setX($x) |
||
| 602 | |||
| 603 | /** |
||
| 604 | * Sets the node Y-coordinate. |
||
| 605 | * |
||
| 606 | * @param int $y |
||
| 607 | * |
||
| 608 | * @since 1.0 |
||
| 609 | */ |
||
| 610 | public function setY($y) |
||
| 614 | } |
||
| 615 |
Our type inference engine has found an assignment of a scalar value (like a string, an integer or null) to a property which is an array.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.
To type hint that a parameter can be either an array or null, you can set a type hint of array and a default value of null. The PHP interpreter will then accept both an array or null for that parameter.
The function can be called with either null or an array for the parameter
$needlebut will only accept an array as$haystack.