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 RouteHandler 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 RouteHandler, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
13 | class RouteHandler |
||
14 | { |
||
15 | /** |
||
16 | * @var ContainerInterface $di the dependency/service container. |
||
17 | */ |
||
18 | protected $di; |
||
19 | |||
20 | |||
21 | |||
22 | /** |
||
23 | * Handle the action for a route and return the results. |
||
24 | * |
||
25 | * @param string $method the request method. |
||
26 | * @param string $path that was matched. |
||
27 | * @param string|array $action base for the callable. |
||
28 | * @param array $arguments optional arguments. |
||
29 | * @param ContainerInjectableInterface $di container with services. |
||
30 | * |
||
31 | * @return mixed as the result from the route handler. |
||
32 | */ |
||
33 | 147 | public function handle( |
|
76 | |||
77 | |||
78 | |||
79 | /** |
||
80 | * Get an informative string representing the handler type. |
||
81 | * |
||
82 | * @param string|array $action base for the callable. |
||
83 | * @param ContainerInjectableInterface $di container with services. |
||
84 | * |
||
85 | * @return string as the type of handler. |
||
86 | */ |
||
87 | 2 | public function getHandlerType( |
|
119 | |||
120 | |||
121 | |||
122 | /** |
||
123 | * Check if items can be used to call a controller action, verify |
||
124 | * that the controller exists, the action has a class-method to call. |
||
125 | * |
||
126 | * @param string $method the request method. |
||
127 | * @param string $path the matched path, base for the controller action |
||
128 | * and the arguments. |
||
129 | * @param string $class the controller class |
||
130 | * |
||
131 | * @return array with callable details. |
||
132 | */ |
||
133 | 25 | protected function isControllerAction( |
|
177 | |||
178 | |||
179 | |||
180 | /** |
||
181 | * Call the controller action with optional arguments and call |
||
182 | * initialisation methods if available. |
||
183 | * |
||
184 | * @param string $callable with details on what controller action to call. |
||
185 | * |
||
186 | * @return mixed result from the handler. |
||
187 | */ |
||
188 | 22 | protected function handleAsControllerAction(array $callable) |
|
249 | |||
250 | |||
251 | |||
252 | /** |
||
253 | * Handle as callable support callables where the method is not static. |
||
254 | * |
||
255 | * @param string|array $action base for the callable |
||
256 | * @param array $arguments optional arguments |
||
257 | * @param ContainerInjectableInterface $di container with services |
||
258 | * |
||
259 | * @return mixed as the result from the route handler. |
||
260 | */ |
||
261 | 116 | protected function handleAsCallable( |
|
291 | |||
292 | |||
293 | |||
294 | /** |
||
295 | * Load callable as a service from the $di container. |
||
296 | * |
||
297 | * @param string|array $action base for the callable |
||
298 | * @param array $arguments optional arguments |
||
299 | * @param ContainerInjectableInterface $di container with services |
||
300 | * |
||
301 | * @return mixed as the result from the route handler. |
||
302 | */ |
||
303 | 3 | protected function handleUsingDi( |
|
324 | } |
||
325 |
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.