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 BaseController 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 BaseController, and based on these observations, apply Extract Interface, too.
| 1 | <?php namespace Limoncello\Flute\Http; |
||
| 50 | abstract class BaseController implements ControllerInterface |
||
| 51 | { |
||
| 52 | use CreateResponsesTrait; |
||
| 53 | |||
| 54 | /** API class name */ |
||
| 55 | const API_CLASS = null; |
||
| 56 | |||
| 57 | /** JSON API Schema class name */ |
||
| 58 | const SCHEMA_CLASS = null; |
||
| 59 | |||
| 60 | /** JSON API validation rules set class */ |
||
| 61 | const ON_CREATE_VALIDATION_RULES_SET_CLASS = null; |
||
| 62 | |||
| 63 | /** JSON API validation rules set class */ |
||
| 64 | const ON_UPDATE_VALIDATION_RULES_SET_CLASS = null; |
||
| 65 | |||
| 66 | /** |
||
| 67 | * @inheritdoc |
||
| 68 | */ |
||
| 69 | 12 | public static function index( |
|
| 89 | |||
| 90 | /** |
||
| 91 | * @inheritdoc |
||
| 92 | */ |
||
| 93 | 1 | public static function create( |
|
| 107 | |||
| 108 | /** |
||
| 109 | * @inheritdoc |
||
| 110 | */ |
||
| 111 | 1 | public static function read( |
|
| 132 | |||
| 133 | /** |
||
| 134 | * @inheritdoc |
||
| 135 | */ |
||
| 136 | 5 | View Code Duplication | public static function update( |
| 153 | |||
| 154 | /** |
||
| 155 | * @inheritdoc |
||
| 156 | */ |
||
| 157 | 1 | public static function delete( |
|
| 168 | |||
| 169 | /** @deprecated Use `readRelationshipWithClosure` instead |
||
| 170 | * @param string $index |
||
| 171 | * @param string $relationshipName |
||
| 172 | * @param ContainerInterface $container |
||
| 173 | * @param ServerRequestInterface $request |
||
| 174 | * |
||
| 175 | * @return ResponseInterface |
||
| 176 | * |
||
| 177 | * @throws ContainerExceptionInterface |
||
| 178 | * @throws NotFoundExceptionInterface |
||
| 179 | */ |
||
| 180 | View Code Duplication | protected static function readRelationship( |
|
| 192 | |||
| 193 | /** @deprecated Use `readRelationshipIdentifiersWithClosure` instead |
||
| 194 | * @param string $index |
||
| 195 | * @param string $relationshipName |
||
| 196 | * @param ContainerInterface $container |
||
| 197 | * @param ServerRequestInterface $request |
||
| 198 | * |
||
| 199 | * @return ResponseInterface |
||
| 200 | * |
||
| 201 | * @throws ContainerExceptionInterface |
||
| 202 | * @throws NotFoundExceptionInterface |
||
| 203 | */ |
||
| 204 | View Code Duplication | protected static function readRelationshipIdentifiers( |
|
| 216 | |||
| 217 | /** |
||
| 218 | * @param Closure $apiHandler |
||
| 219 | * @param string $relationshipName |
||
| 220 | * @param ContainerInterface $container |
||
| 221 | * @param ServerRequestInterface $request |
||
| 222 | * |
||
| 223 | * @return ResponseInterface |
||
| 224 | * |
||
| 225 | * @throws ContainerExceptionInterface |
||
| 226 | * @throws NotFoundExceptionInterface |
||
| 227 | */ |
||
| 228 | 2 | View Code Duplication | protected static function readRelationshipWithClosure( |
| 250 | |||
| 251 | /** |
||
| 252 | * @param Closure $apiHandler |
||
| 253 | * @param string $relationshipName |
||
| 254 | * @param ContainerInterface $container |
||
| 255 | * @param ServerRequestInterface $request |
||
| 256 | * |
||
| 257 | * @return ResponseInterface |
||
| 258 | * |
||
| 259 | * @throws ContainerExceptionInterface |
||
| 260 | * @throws NotFoundExceptionInterface |
||
| 261 | */ |
||
| 262 | 1 | View Code Duplication | protected static function readRelationshipIdentifiersWithClosure( |
| 284 | |||
| 285 | /** |
||
| 286 | * @param ContainerInterface $container |
||
| 287 | * @param string|null $class |
||
| 288 | * |
||
| 289 | * @return CrudInterface |
||
| 290 | * |
||
| 291 | * @throws ContainerExceptionInterface |
||
| 292 | * @throws NotFoundExceptionInterface |
||
| 293 | */ |
||
| 294 | 22 | protected static function createApi(ContainerInterface $container, string $class = null): CrudInterface |
|
| 302 | |||
| 303 | /** |
||
| 304 | * @param ContainerInterface $container |
||
| 305 | * @param ServerRequestInterface $request |
||
| 306 | * |
||
| 307 | * @return array |
||
| 308 | * |
||
| 309 | * @throws ContainerExceptionInterface |
||
| 310 | * @throws NotFoundExceptionInterface |
||
| 311 | */ |
||
| 312 | 8 | protected static function readJsonFromRequest(ContainerInterface $container, ServerRequestInterface $request): array |
|
| 328 | |||
| 329 | /** |
||
| 330 | * @param array $routeParams |
||
| 331 | * @param ContainerInterface $container |
||
| 332 | * @param array $jsonData |
||
| 333 | * |
||
| 334 | * @return array |
||
| 335 | * @SuppressWarnings(PHPMD.ElseExpression) |
||
| 336 | * |
||
| 337 | * @throws ContainerExceptionInterface |
||
| 338 | * @throws NotFoundExceptionInterface |
||
| 339 | */ |
||
| 340 | 4 | protected static function normalizeIndexValueOnUpdate( |
|
| 370 | |||
| 371 | /** |
||
| 372 | * @param int|string $parentIndex |
||
| 373 | * @param string $relationshipName |
||
| 374 | * @param int|string $childIndex |
||
| 375 | * @param string $childApiClass |
||
| 376 | * @param ContainerInterface $container |
||
| 377 | * @param ServerRequestInterface $request |
||
| 378 | * |
||
| 379 | * @return ResponseInterface |
||
| 380 | * |
||
| 381 | * @throws ContainerExceptionInterface |
||
| 382 | * @throws NotFoundExceptionInterface |
||
| 383 | */ |
||
| 384 | 1 | protected static function deleteInRelationship( |
|
| 407 | |||
| 408 | /** @noinspection PhpTooManyParametersInspection |
||
| 409 | * @param int|string $parentIndex |
||
| 410 | * @param string $relationshipName |
||
| 411 | * @param int|string $childIndex |
||
| 412 | * @param array $attributes |
||
| 413 | * @param array $toMany |
||
| 414 | * @param string $childApiClass |
||
| 415 | * @param ContainerInterface $container |
||
| 416 | * @param ServerRequestInterface $request |
||
| 417 | * |
||
| 418 | * @return ResponseInterface |
||
| 419 | * |
||
| 420 | * @throws ContainerExceptionInterface |
||
| 421 | * @throws NotFoundExceptionInterface |
||
| 422 | */ |
||
| 423 | 2 | View Code Duplication | protected static function updateInRelationship( |
| 454 | |||
| 455 | /** |
||
| 456 | * @param ContainerInterface $container |
||
| 457 | * |
||
| 458 | * @return JsonApiValidatorInterface |
||
| 459 | * |
||
| 460 | * @throws ContainerExceptionInterface |
||
| 461 | * @throws NotFoundExceptionInterface |
||
| 462 | */ |
||
| 463 | 1 | View Code Duplication | protected static function createOnCreateValidator(ContainerInterface $container): JsonApiValidatorInterface |
| 472 | |||
| 473 | /** |
||
| 474 | * @param ContainerInterface $container |
||
| 475 | * |
||
| 476 | * @return JsonApiValidatorInterface |
||
| 477 | * |
||
| 478 | * @throws ContainerExceptionInterface |
||
| 479 | * @throws NotFoundExceptionInterface |
||
| 480 | */ |
||
| 481 | 3 | View Code Duplication | protected static function createOnUpdateValidator(ContainerInterface $container): JsonApiValidatorInterface |
| 490 | |||
| 491 | /** |
||
| 492 | * @param ContainerInterface $container |
||
| 493 | * @param string $rulesSetClass |
||
| 494 | * |
||
| 495 | * @return JsonApiValidatorInterface |
||
| 496 | * |
||
| 497 | * @throws ContainerExceptionInterface |
||
| 498 | * @throws NotFoundExceptionInterface |
||
| 499 | */ |
||
| 500 | 6 | protected static function createJsonApiValidator( |
|
| 510 | |||
| 511 | /** |
||
| 512 | * @param ContainerInterface $container |
||
| 513 | * |
||
| 514 | * @return QueryParserInterface |
||
| 515 | * |
||
| 516 | * @throws ContainerExceptionInterface |
||
| 517 | * @throws NotFoundExceptionInterface |
||
| 518 | */ |
||
| 519 | 16 | protected static function createQueryParser(ContainerInterface $container): QueryParserInterface |
|
| 523 | |||
| 524 | /** |
||
| 525 | * @param QueryParserInterface $parser |
||
| 526 | * |
||
| 527 | * @return QueryParserInterface |
||
| 528 | */ |
||
| 529 | 12 | protected static function configureOnIndexParser(QueryParserInterface $parser): QueryParserInterface |
|
| 533 | |||
| 534 | /** |
||
| 535 | * @param QueryParserInterface $parser |
||
| 536 | * |
||
| 537 | * @return QueryParserInterface |
||
| 538 | */ |
||
| 539 | 1 | protected static function configureOnReadParser(QueryParserInterface $parser): QueryParserInterface |
|
| 543 | |||
| 544 | /** |
||
| 545 | * @param string $name |
||
| 546 | * @param QueryParserInterface $parser |
||
| 547 | * |
||
| 548 | * @return QueryParserInterface |
||
| 549 | * |
||
| 550 | * @SuppressWarnings(PHPMD.UnusedFormalParameter) |
||
| 551 | */ |
||
| 552 | 2 | protected static function configureOnReadRelationshipParser( |
|
| 558 | |||
| 559 | /** |
||
| 560 | * @param string $name |
||
| 561 | * @param QueryParserInterface $parser |
||
| 562 | * |
||
| 563 | * @return QueryParserInterface |
||
| 564 | * |
||
| 565 | * @SuppressWarnings(PHPMD.UnusedFormalParameter) |
||
| 566 | */ |
||
| 567 | 1 | protected static function configureOnReadRelationshipIdentifiersParser( |
|
| 573 | |||
| 574 | /** |
||
| 575 | * @param ContainerInterface $container |
||
| 576 | * |
||
| 577 | * @return ParametersMapperInterface |
||
| 578 | * |
||
| 579 | * @throws ContainerExceptionInterface |
||
| 580 | * @throws NotFoundExceptionInterface |
||
| 581 | */ |
||
| 582 | 15 | protected static function createParameterMapper(ContainerInterface $container): ParametersMapperInterface |
|
| 593 | |||
| 594 | /** |
||
| 595 | * @param ContainerInterface $container |
||
| 596 | * @param array $captures |
||
| 597 | * @param string $schemeClass |
||
| 598 | * |
||
| 599 | * @return array |
||
| 600 | * |
||
| 601 | * @throws ContainerExceptionInterface |
||
| 602 | * @throws NotFoundExceptionInterface |
||
| 603 | */ |
||
| 604 | 5 | protected static function mapSchemeDataToModelData( |
|
| 644 | |||
| 645 | /** |
||
| 646 | * @param ContainerInterface $container |
||
| 647 | * @param ServerRequestInterface $request |
||
| 648 | * |
||
| 649 | * @return array |
||
| 650 | * |
||
| 651 | * @throws ContainerExceptionInterface |
||
| 652 | * @throws NotFoundExceptionInterface |
||
| 653 | */ |
||
| 654 | 1 | protected static function createImpl( |
|
| 670 | |||
| 671 | /** |
||
| 672 | * @param array $routeParams |
||
| 673 | * @param ContainerInterface $container |
||
| 674 | * @param ServerRequestInterface $request |
||
| 675 | * |
||
| 676 | * @return array [int $updated, string $index, CrudInterface $api] |
||
| 677 | * |
||
| 678 | * @throws ContainerExceptionInterface |
||
| 679 | * @throws NotFoundExceptionInterface |
||
| 680 | */ |
||
| 681 | 5 | protected static function updateImpl( |
|
| 702 | |||
| 703 | /** |
||
| 704 | * @param $parentIndex |
||
| 705 | * @param string $relationshipName |
||
| 706 | * @param $childIndex |
||
| 707 | * @param array $attributes |
||
| 708 | * @param array $toMany |
||
| 709 | * @param string $childApiClass |
||
| 710 | * @param ContainerInterface $container |
||
| 711 | * |
||
| 712 | * @return array |
||
| 713 | * |
||
| 714 | * @throws ContainerExceptionInterface |
||
| 715 | * @throws NotFoundExceptionInterface |
||
| 716 | */ |
||
| 717 | 2 | private static function updateInRelationshipImpl( |
|
| 740 | |||
| 741 | /** |
||
| 742 | * @param ContainerInterface $container |
||
| 743 | * @param string $namespace |
||
| 744 | * |
||
| 745 | * @return FormatterInterface |
||
| 746 | * |
||
| 747 | * @throws ContainerExceptionInterface |
||
| 748 | * @throws NotFoundExceptionInterface |
||
| 749 | */ |
||
| 750 | 2 | protected static function createMessageFormatter( |
|
| 760 | } |
||
| 761 |
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.