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 AddonProvider 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 AddonProvider, and based on these observations, apply Extract Interface, too.
1 | <?php namespace Anomaly\Streams\Platform\Addon; |
||
24 | class AddonProvider |
||
25 | { |
||
26 | |||
27 | /** |
||
28 | * The cached services. |
||
29 | * |
||
30 | * @var array |
||
31 | */ |
||
32 | protected $cached = []; |
||
33 | |||
34 | /** |
||
35 | * The registered providers. |
||
36 | * |
||
37 | * @var array |
||
38 | */ |
||
39 | protected $providers = []; |
||
40 | |||
41 | /** |
||
42 | * The router instance. |
||
43 | * |
||
44 | * @var Router |
||
45 | */ |
||
46 | protected $router; |
||
47 | |||
48 | /** |
||
49 | * The event dispatcher. |
||
50 | * |
||
51 | * @var Dispatcher |
||
52 | */ |
||
53 | protected $events; |
||
54 | |||
55 | /** |
||
56 | * The factory manager. |
||
57 | * |
||
58 | * @var Factory |
||
59 | */ |
||
60 | protected $factory; |
||
61 | |||
62 | /** |
||
63 | * The scheduler instance. |
||
64 | * |
||
65 | * @var Schedule |
||
66 | */ |
||
67 | protected $schedule; |
||
68 | |||
69 | /** |
||
70 | * The application container. |
||
71 | * |
||
72 | * @var Application |
||
73 | */ |
||
74 | protected $application; |
||
75 | |||
76 | /** |
||
77 | * The middleware collection. |
||
78 | * |
||
79 | * @var MiddlewareCollection |
||
80 | */ |
||
81 | protected $middlewares; |
||
82 | |||
83 | /** |
||
84 | * The view overrides. |
||
85 | * |
||
86 | * @var ViewOverrides |
||
87 | */ |
||
88 | protected $viewOverrides; |
||
89 | |||
90 | /** |
||
91 | * The mobile view overrides. |
||
92 | * |
||
93 | * @var ViewMobileOverrides |
||
94 | */ |
||
95 | protected $viewMobileOverrides; |
||
96 | |||
97 | /** |
||
98 | * Create a new AddonProvider instance. |
||
99 | * |
||
100 | * @param Router $router |
||
101 | * @param Dispatcher $events |
||
102 | * @param Schedule $schedule |
||
103 | * @param Application $application |
||
104 | * @param ViewOverrides $viewOverrides |
||
105 | * @param MiddlewareCollection $middlewares |
||
106 | * @param ViewMobileOverrides $viewMobileOverrides |
||
107 | */ |
||
108 | public function __construct( |
||
109 | Router $router, |
||
110 | Dispatcher $events, |
||
111 | Schedule $schedule, |
||
112 | Application $application, |
||
113 | ViewOverrides $viewOverrides, |
||
114 | MiddlewareCollection $middlewares, |
||
115 | ViewMobileOverrides $viewMobileOverrides |
||
116 | ) { |
||
117 | $this->router = $router; |
||
118 | $this->events = $events; |
||
119 | $this->schedule = $schedule; |
||
120 | $this->application = $application; |
||
121 | $this->middlewares = $middlewares; |
||
122 | $this->viewOverrides = $viewOverrides; |
||
123 | $this->viewMobileOverrides = $viewMobileOverrides; |
||
124 | } |
||
125 | |||
126 | /** |
||
127 | * Register the service provider for an addon. |
||
128 | * |
||
129 | * @param Addon $addon |
||
130 | */ |
||
131 | public function register(Addon $addon) |
||
173 | |||
174 | /** |
||
175 | * Boot the service providers. |
||
176 | */ |
||
177 | public function boot() |
||
187 | |||
188 | /** |
||
189 | * Register the addon providers. |
||
190 | * |
||
191 | * @param AddonServiceProvider $provider |
||
192 | */ |
||
193 | protected function registerProviders(AddonServiceProvider $provider) |
||
199 | |||
200 | /** |
||
201 | * Register the addon commands. |
||
202 | * |
||
203 | * @param AddonServiceProvider $provider |
||
204 | */ |
||
205 | protected function registerCommands(AddonServiceProvider $provider) |
||
220 | |||
221 | /** |
||
222 | * Register the addon commands. |
||
223 | * |
||
224 | * @param Addon $addon |
||
225 | */ |
||
226 | protected function registerFactories(Addon $addon) |
||
227 | { |
||
228 | /** |
||
229 | * @todo Move this back into a |
||
230 | * dependency for 3.4 |
||
231 | * causes issues with |
||
232 | * 3.2 conversions. |
||
233 | */ |
||
234 | if (is_dir($factories = $addon->getPath('factories'))) { |
||
235 | app(Factory::class)->load($factories); |
||
236 | } |
||
237 | } |
||
238 | |||
239 | /** |
||
240 | * Bind class aliases. |
||
241 | * |
||
242 | * @param AddonServiceProvider $provider |
||
243 | */ |
||
244 | protected function bindAliases(AddonServiceProvider $provider) |
||
245 | { |
||
246 | if ($aliases = $provider->getAliases()) { |
||
247 | AliasLoader::getInstance($aliases)->register(); |
||
248 | } |
||
249 | } |
||
250 | |||
251 | /** |
||
252 | * Bind addon classes. |
||
253 | * |
||
254 | * @param AddonServiceProvider $provider |
||
255 | */ |
||
256 | protected function bindClasses(AddonServiceProvider $provider) |
||
262 | |||
263 | /** |
||
264 | * Bind addon singletons. |
||
265 | * |
||
266 | * @param AddonServiceProvider $provider |
||
267 | */ |
||
268 | protected function bindSingletons(AddonServiceProvider $provider) |
||
274 | |||
275 | /** |
||
276 | * Register the addon events. |
||
277 | * |
||
278 | * @param AddonServiceProvider $provider |
||
279 | */ |
||
280 | protected function registerEvents(AddonServiceProvider $provider) |
||
299 | |||
300 | /** |
||
301 | * Register the addon routes. |
||
302 | * |
||
303 | * @param AddonServiceProvider $provider |
||
304 | * @param Addon $addon |
||
305 | */ |
||
306 | protected function registerRoutes(AddonServiceProvider $provider, Addon $addon) |
||
349 | |||
350 | /** |
||
351 | * Register the addon routes. |
||
352 | * |
||
353 | * @param AddonServiceProvider $provider |
||
354 | * @param Addon $addon |
||
355 | */ |
||
356 | protected function registerApi(AddonServiceProvider $provider, Addon $addon) |
||
357 | { |
||
358 | if ($this->routesAreCached()) { |
||
359 | return; |
||
360 | } |
||
361 | |||
362 | if (!$routes = $provider->getApi()) { |
||
363 | return; |
||
364 | } |
||
365 | |||
366 | $this->router->group( |
||
367 | [ |
||
368 | 'middleware' => 'auth:api', |
||
369 | ], |
||
370 | function (Router $router) use ($routes, $addon) { |
||
371 | |||
372 | foreach ($routes as $uri => $route) { |
||
373 | |||
374 | /* |
||
375 | * If the route definition is an |
||
376 | * not an array then let's make it one. |
||
377 | * Array type routes give us more control |
||
378 | * and allow us to pass information in the |
||
379 | * request's route action array. |
||
380 | */ |
||
381 | if (!is_array($route)) { |
||
382 | $route = [ |
||
383 | 'uses' => $route, |
||
384 | ]; |
||
385 | } |
||
386 | |||
387 | $verb = array_pull($route, 'verb', 'any'); |
||
388 | $middleware = array_pull($route, 'middleware', []); |
||
389 | $constraints = array_pull($route, 'constraints', []); |
||
390 | |||
391 | array_set($route, 'streams::addon', $addon->getNamespace()); |
||
392 | |||
393 | if (is_string($route['uses']) && !str_contains($route['uses'], '@')) { |
||
394 | $router->resource($uri, $route['uses']); |
||
395 | } else { |
||
396 | |||
397 | $route = $router->{$verb}($uri, $route)->where($constraints); |
||
398 | |||
399 | if ($middleware) { |
||
400 | call_user_func_array([$route, 'middleware'], (array)$middleware); |
||
401 | } |
||
402 | } |
||
403 | } |
||
404 | } |
||
405 | ); |
||
406 | } |
||
407 | |||
408 | /** |
||
409 | * Register field routes. |
||
410 | * |
||
411 | * @param Addon $addon |
||
412 | * @param $controller |
||
413 | * @param null $segment |
||
414 | */ |
||
415 | public function registerFieldsRoutes(Addon $addon, $controller, $segment = null) |
||
477 | |||
478 | /** |
||
479 | * Register the addon plugins. |
||
480 | * |
||
481 | * @param AddonServiceProvider $provider |
||
482 | */ |
||
483 | protected function registerPlugins(AddonServiceProvider $provider) |
||
500 | |||
501 | /** |
||
502 | * Register the addon schedules. |
||
503 | * |
||
504 | * @param AddonServiceProvider $provider |
||
505 | */ |
||
506 | protected function registerSchedules(AddonServiceProvider $provider) |
||
528 | |||
529 | /** |
||
530 | * Register view overrides. |
||
531 | * |
||
532 | * @param AddonServiceProvider $provider |
||
533 | * @param Addon $addon |
||
534 | */ |
||
535 | protected function registerOverrides(AddonServiceProvider $provider, Addon $addon) |
||
547 | |||
548 | /** |
||
549 | * Register middleware. |
||
550 | * |
||
551 | * @param AddonServiceProvider $provider |
||
552 | */ |
||
553 | protected function registerMiddleware(AddonServiceProvider $provider) |
||
559 | |||
560 | /** |
||
561 | * Register route middleware. |
||
562 | * |
||
563 | * @param AddonServiceProvider $provider |
||
564 | */ |
||
565 | protected function registerRouteMiddleware(AddonServiceProvider $provider) |
||
571 | |||
572 | /** |
||
573 | * Register additional routes. |
||
574 | * |
||
575 | * @param AddonServiceProvider $provider |
||
576 | */ |
||
577 | protected function registerAdditionalRoutes(AddonServiceProvider $provider) |
||
595 | |||
596 | /** |
||
597 | * Check if routes are cached. |
||
598 | */ |
||
599 | protected function routesAreCached() |
||
611 | } |
||
612 |
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.