Complex classes like GenericRoute 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 GenericRoute, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
41 | class GenericRoute extends TemplateRoute |
||
42 | { |
||
43 | /** |
||
44 | * The URI path. |
||
45 | * |
||
46 | * @var string |
||
47 | */ |
||
48 | private $path; |
||
49 | |||
50 | /** |
||
51 | * The object route. |
||
52 | * |
||
53 | * @var ObjectRouteInterface |
||
54 | */ |
||
55 | private $objectRoute; |
||
56 | |||
57 | /** |
||
58 | * The target object of the {@see GenericRoute Chainable::$objectRoute}. |
||
59 | * |
||
60 | * @var ModelInterface|RoutableInterface |
||
61 | */ |
||
62 | private $contextObject; |
||
63 | |||
64 | /** |
||
65 | * Store the factory instance for the current class. |
||
66 | * |
||
67 | * @var FactoryInterface |
||
68 | */ |
||
69 | private $modelFactory; |
||
70 | |||
71 | /** |
||
72 | * Store the collection loader for the current class. |
||
73 | * |
||
74 | * @var CollectionLoader |
||
75 | */ |
||
76 | private $collectionLoader; |
||
77 | |||
78 | /** |
||
79 | * The class name of the object route model. |
||
80 | * |
||
81 | * Must be a fully-qualified PHP namespace and an implementation of |
||
82 | * {@see \Charcoal\Object\ObjectRouteInterface}. Used by the model factory. |
||
83 | * |
||
84 | * @var string |
||
85 | */ |
||
86 | protected $objectRouteClass = ObjectRoute::class; |
||
87 | |||
88 | /** |
||
89 | * @var array $availableTemplates |
||
90 | */ |
||
91 | protected $availableTemplates = []; |
||
92 | |||
93 | /** |
||
94 | * Setting Language on TranslatorConfig allows to seT local properly. |
||
95 | * |
||
96 | * @var TranslatorConfig $translatorConfig |
||
97 | */ |
||
98 | protected $translatorConfig; |
||
99 | |||
100 | /** |
||
101 | * Returns new template route object. |
||
102 | * |
||
103 | * @param array|\ArrayAccess $data Class depdendencies. |
||
104 | */ |
||
105 | public function __construct($data) |
||
111 | |||
112 | /** |
||
113 | * Inject dependencies from a DI Container. |
||
114 | * |
||
115 | * @param Container $container A dependencies container instance. |
||
116 | * @return void |
||
117 | */ |
||
118 | public function setDependencies(Container $container) |
||
127 | |||
128 | /** |
||
129 | * Determine if the URI path resolves to an object. |
||
130 | * |
||
131 | * @param Container $container A DI (Pimple) container. |
||
132 | * @return boolean |
||
133 | */ |
||
134 | public function pathResolvable(Container $container) |
||
151 | |||
152 | /** |
||
153 | * Resolve the dynamic route. |
||
154 | * |
||
155 | * @param Container $container A DI (Pimple) container. |
||
156 | * @param RequestInterface $request A PSR-7 compatible Request instance. |
||
157 | * @param ResponseInterface $response A PSR-7 compatible Response instance. |
||
158 | * @return ResponseInterface |
||
159 | */ |
||
160 | public function __invoke( |
||
177 | |||
178 | /** |
||
179 | * @param RequestInterface $request A PSR-7 compatible Request instance. |
||
180 | * @param ResponseInterface $response A PSR-7 compatible Response instance. |
||
181 | * @return ResponseInterface |
||
182 | */ |
||
183 | protected function resolveLatestObjectRoute( |
||
201 | |||
202 | /** |
||
203 | * @return GenericRoute Chainable |
||
204 | */ |
||
205 | protected function resolveTemplateContextObject() |
||
289 | |||
290 | /** |
||
291 | * @param Container $container A DI (Pimple) container. |
||
292 | * @param RequestInterface $request The request to intialize the template with. |
||
293 | * @return string |
||
294 | */ |
||
295 | protected function createTemplate(Container $container, RequestInterface $request) |
||
304 | |||
305 | /** |
||
306 | * Create a route object. |
||
307 | * |
||
308 | * @return ObjectRouteInterface |
||
309 | */ |
||
310 | public function createRouteObject() |
||
316 | |||
317 | /** |
||
318 | * Set the class name of the object route model. |
||
319 | * |
||
320 | * @param string $className The class name of the object route model. |
||
321 | * @throws InvalidArgumentException If the class name is not a string. |
||
322 | * @return GenericRoute Chainable |
||
323 | */ |
||
324 | protected function setObjectRouteClass($className) |
||
336 | |||
337 | /** |
||
338 | * Retrieve the class name of the object route model. |
||
339 | * |
||
340 | * @return string |
||
341 | */ |
||
342 | public function objectRouteClass() |
||
346 | |||
347 | /** |
||
348 | * Load the object associated with the matching object route. |
||
349 | * |
||
350 | * Validating if the object ID exists is delegated to the |
||
351 | * {@see GenericRoute Chainable::pathResolvable()} method. |
||
352 | * |
||
353 | * @return RoutableInterface |
||
354 | */ |
||
355 | protected function loadContextObject() |
||
370 | |||
371 | /** |
||
372 | * Load the object route matching the URI path. |
||
373 | * |
||
374 | * @return \Charcoal\Object\ObjectRouteInterface |
||
375 | */ |
||
376 | protected function loadObjectRouteFromPath() |
||
397 | |||
398 | /** |
||
399 | * Retrieve the latest object route from the given object route's |
||
400 | * associated object. |
||
401 | * |
||
402 | * The object routes are ordered by descending creation date (latest first). |
||
403 | * Should never MISS, the given object route should exist. |
||
404 | * |
||
405 | * @param ObjectRouteInterface $route Routable Object. |
||
406 | * @return ObjectRouteInterface |
||
407 | */ |
||
408 | public function getLatestObjectPathHistory(ObjectRouteInterface $route) |
||
428 | |||
429 | /** |
||
430 | * SETTERS |
||
431 | */ |
||
432 | |||
433 | /** |
||
434 | * Set the specified URI path. |
||
435 | * |
||
436 | * @param string $path The path to use for route resolution. |
||
437 | * @return GenericRoute Chainable |
||
438 | */ |
||
439 | protected function setPath($path) |
||
445 | |||
446 | /** |
||
447 | * Set an object model factory. |
||
448 | * |
||
449 | * @param FactoryInterface $factory The model factory, to create objects. |
||
450 | * @return GenericRoute Chainable |
||
451 | */ |
||
452 | protected function setModelFactory(FactoryInterface $factory) |
||
458 | |||
459 | /** |
||
460 | * Set a model collection loader. |
||
461 | * |
||
462 | * @param CollectionLoader $loader The collection loader. |
||
463 | * @return GenericRoute Chainable |
||
464 | */ |
||
465 | public function setCollectionLoader(CollectionLoader $loader) |
||
471 | |||
472 | /** |
||
473 | * GETTERS |
||
474 | */ |
||
475 | |||
476 | /** |
||
477 | * Retrieve the URI path. |
||
478 | * |
||
479 | * @return string |
||
480 | */ |
||
481 | protected function path() |
||
485 | |||
486 | /** |
||
487 | * Retrieve the object model factory. |
||
488 | * |
||
489 | * @throws RuntimeException If the model factory was not previously set. |
||
490 | * @return FactoryInterface |
||
491 | */ |
||
492 | public function modelFactory() |
||
502 | |||
503 | /** |
||
504 | * Retrieve the model collection loader. |
||
505 | * |
||
506 | * @throws RuntimeException If the collection loader was not previously set. |
||
507 | * @return CollectionLoader |
||
508 | */ |
||
509 | protected function collectionLoader() |
||
519 | |||
520 | /** |
||
521 | * @return boolean |
||
522 | */ |
||
523 | protected function cacheEnabled() |
||
528 | |||
529 | /** |
||
530 | * @return integer |
||
531 | */ |
||
532 | protected function cacheTtl() |
||
537 | |||
538 | /** |
||
539 | * @return string |
||
540 | */ |
||
541 | protected function cacheIdent() |
||
546 | } |
||
547 |
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.