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 HttplugExtension 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 HttplugExtension, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
28 | class HttplugExtension extends Extension |
||
29 | { |
||
30 | /** |
||
31 | * {@inheritdoc} |
||
32 | */ |
||
33 | 8 | public function load(array $configs, ContainerBuilder $container) |
|
77 | |||
78 | /** |
||
79 | * Configure client services. |
||
80 | * |
||
81 | * @param ContainerBuilder $container |
||
82 | * @param array $config |
||
83 | */ |
||
84 | 8 | private function configureClients(ContainerBuilder $container, array $config) |
|
106 | |||
107 | /** |
||
108 | * @param ContainerBuilder $container |
||
109 | * @param array $config |
||
110 | */ |
||
111 | 8 | private function configurePlugins(ContainerBuilder $container, array $config) |
|
129 | |||
130 | /** |
||
131 | * @param string $name |
||
132 | * @param Definition $definition |
||
133 | * @param array $config |
||
134 | */ |
||
135 | 8 | private function configurePluginByName($name, Definition $definition, array $config) |
|
172 | |||
173 | /** |
||
174 | * @param ContainerBuilder $container |
||
175 | * @param array $config |
||
176 | */ |
||
177 | private function configureAuthentication(ContainerBuilder $container, array $config) |
||
207 | |||
208 | /** |
||
209 | * @param ContainerBuilder $container |
||
210 | * @param string $name |
||
211 | * @param array $arguments |
||
212 | * @param bool $profiling |
||
213 | */ |
||
214 | private function configureClient(ContainerBuilder $container, $name, array $arguments, $profiling) |
||
215 | { |
||
216 | $serviceId = 'httplug.client.'.$name; |
||
217 | |||
218 | $pluginClientOptions = []; |
||
219 | |||
220 | if ($profiling) { |
||
221 | if (!in_array('httplug.plugin.stopwatch', $arguments['plugins'])) { |
||
222 | // Add the stopwatch plugin |
||
223 | array_unshift($arguments['plugins'], 'httplug.plugin.stopwatch'); |
||
224 | } |
||
225 | |||
226 | // Tell the plugin journal what plugins we used |
||
227 | $container |
||
228 | ->getDefinition('httplug.collector.plugin_journal') |
||
229 | ->addMethodCall('setPlugins', [$name, $arguments['plugins']]) |
||
230 | ; |
||
231 | |||
232 | $debugPluginServiceId = $this->registerDebugPlugin($container, $serviceId); |
||
233 | |||
234 | $pluginClientOptions['debug_plugins'] = [new Reference($debugPluginServiceId)]; |
||
235 | } |
||
236 | |||
237 | $container |
||
238 | ->register($serviceId, DummyClient::class) |
||
239 | ->setFactory([PluginClientFactory::class, 'createPluginClient']) |
||
240 | ->addArgument( |
||
241 | array_map( |
||
242 | function ($id) { |
||
243 | return new Reference($id); |
||
244 | }, |
||
245 | $arguments['plugins'] |
||
246 | ) |
||
247 | ) |
||
248 | ->addArgument(new Reference($arguments['factory'])) |
||
249 | ->addArgument($arguments['config']) |
||
250 | ->addArgument($pluginClientOptions) |
||
251 | ; |
||
252 | |||
253 | |||
254 | /* |
||
255 | * Decorate the client with clients from client-common |
||
256 | */ |
||
257 | View Code Duplication | if ($arguments['flexible_client']) { |
|
258 | $container |
||
259 | ->register($serviceId.'.flexible', FlexibleHttpClient::class) |
||
260 | ->addArgument(new Reference($serviceId.'.flexible.inner')) |
||
261 | ->setPublic(false) |
||
262 | ->setDecoratedService($serviceId) |
||
263 | ; |
||
264 | } |
||
265 | |||
266 | View Code Duplication | if ($arguments['http_methods_client']) { |
|
267 | $container |
||
268 | ->register($serviceId.'.http_methods', HttpMethodsClient::class) |
||
269 | ->setArguments([new Reference($serviceId.'.http_methods.inner'), new Reference('httplug.message_factory')]) |
||
270 | ->setPublic(false) |
||
271 | ->setDecoratedService($serviceId) |
||
272 | ; |
||
273 | } |
||
274 | |||
275 | View Code Duplication | if ($arguments['batch_client']) { |
|
276 | $container |
||
277 | ->register($serviceId.'.batch_client', BatchClient::class) |
||
278 | ->setArguments([new Reference($serviceId.'.batch_client.inner')]) |
||
279 | ->setPublic(false) |
||
280 | ->setDecoratedService($serviceId) |
||
281 | ; |
||
282 | } |
||
283 | } |
||
284 | |||
285 | /** |
||
286 | * Make the user can select what client is used for auto discovery. If none is provided, a service will be created |
||
287 | * by finding a client using auto discovery. |
||
288 | * |
||
289 | * @param ContainerBuilder $container |
||
290 | * @param array $config |
||
291 | */ |
||
292 | private function configureAutoDiscoveryClients(ContainerBuilder $container, array $config) |
||
330 | |||
331 | /** |
||
332 | * Find a client with auto discovery and return a service Reference to it. |
||
333 | * |
||
334 | * @param ContainerBuilder $container |
||
335 | * @param string $name |
||
336 | * @param callable $factory |
||
337 | * @param bool $profiling |
||
338 | * |
||
339 | * @return string service id |
||
340 | */ |
||
341 | private function registerAutoDiscoverableClient(ContainerBuilder $container, $name, $factory, $profiling) |
||
367 | |||
368 | /** |
||
369 | * Create a new plugin service for this client. |
||
370 | * |
||
371 | * @param ContainerBuilder $container |
||
372 | * @param string $serviceId |
||
373 | * |
||
374 | * @return string |
||
375 | */ |
||
376 | private function registerDebugPlugin(ContainerBuilder $container, $serviceId) |
||
389 | |||
390 | /** |
||
391 | * {@inheritdoc} |
||
392 | */ |
||
393 | public function getConfiguration(array $config, ContainerBuilder $container) |
||
397 | } |
||
398 |
Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code: