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 XMLContext 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 XMLContext, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
33 | class XMLContext implements |
||
34 | \PEIP\INF\Context\Context, |
||
35 | \PEIP\INF\Channel\ChannelResolver |
||
36 | { |
||
37 | protected $services = [], |
||
38 | $configs = [], |
||
39 | $gateways = [], |
||
40 | $nodeBuilders = [], |
||
41 | $channelRegistry, |
||
42 | $serviceProvider; |
||
43 | |||
44 | /** |
||
45 | * constructor. |
||
46 | * |
||
47 | * @param string $string the configuration string |
||
48 | * |
||
49 | * @return |
||
50 | */ |
||
51 | public function __construct($string) |
||
62 | |||
63 | public function addConfig($config) |
||
67 | |||
68 | public function handleReadConfig(\PEIP\INF\Event\Event $event) |
||
72 | |||
73 | /** |
||
74 | * Creates and returns a XMLContext instance from a given config-string. |
||
75 | * |
||
76 | * @param string $string the configuration string |
||
77 | * |
||
78 | * @throws RuntimeException |
||
79 | * |
||
80 | * @return XMLContext the context instance |
||
81 | */ |
||
82 | public static function createFromString($string) |
||
86 | |||
87 | /** |
||
88 | * Creates and returns a XMLContext instance from a given config-file. |
||
89 | * |
||
90 | * @param string $file the path to the configuration file |
||
91 | * |
||
92 | * @throws RuntimeException |
||
93 | * |
||
94 | * @return XMLContext the context instance |
||
95 | */ |
||
96 | public static function createFromFile($file) |
||
104 | |||
105 | /** |
||
106 | * Initializes the context. |
||
107 | * |
||
108 | * @return void |
||
109 | */ |
||
110 | protected function init() |
||
123 | |||
124 | /** |
||
125 | * Registers a callable as builder for given node-name. |
||
126 | * |
||
127 | * @implements \PEIP\INF\Context\Context |
||
128 | * |
||
129 | * @param string $nodeName the name of the node |
||
130 | * @param callable $callable a callable which creates instances for node-name |
||
131 | */ |
||
132 | public function registerNodeBuilder($nodeName, $callable) |
||
136 | |||
137 | /** |
||
138 | * Registers a context-plugin instance. |
||
139 | * |
||
140 | * @implements \PEIP\INF\Context\Context |
||
141 | * |
||
142 | * @param \PEIP\INF\Context\ContextPlugin $plugin a plugin instance |
||
143 | */ |
||
144 | public function addPlugin(\PEIP\INF\Context\ContextPlugin $plugin) |
||
148 | |||
149 | /** |
||
150 | * Creates a registers a context-plugin instance from a config object. |
||
151 | * |
||
152 | * @param object $config configuration object for the plugin |
||
153 | * |
||
154 | * @return |
||
155 | */ |
||
156 | public function createPlugin($config) |
||
161 | |||
162 | /** |
||
163 | * Adds a context instance to the services stack. |
||
164 | * Note: Object instances registered with the included context will |
||
165 | * overwrite any instance with the same id on the including context. |
||
166 | * If you need a different behavior, please, make use |
||
167 | * of an include-tag in your configuration before your main |
||
168 | * configuration part. |
||
169 | * eg.: |
||
170 | * <config> |
||
171 | * <include file="path/to/include/context/config.xml"/> |
||
172 | * <!-- main configuration --> |
||
173 | * </config>. |
||
174 | */ |
||
175 | public function includeContext(XMLContext $context) |
||
179 | |||
180 | /** |
||
181 | * Creates and adds a context from file. |
||
182 | * |
||
183 | * @see XMLContext::includeContext |
||
184 | * |
||
185 | * @param string $filePath |
||
186 | */ |
||
187 | public function includeContextFromFile($filePath) |
||
193 | |||
194 | /** |
||
195 | * Creates and adds a context from string. |
||
196 | * |
||
197 | * @see XMLContext::includeContext |
||
198 | * |
||
199 | * @param string $configString the config to include |
||
200 | */ |
||
201 | public function includeContextFromString($configString) |
||
206 | |||
207 | /** |
||
208 | * Creates a context instance from a config object and includes it. |
||
209 | * |
||
210 | * @see XMLContext::includeContext |
||
211 | * |
||
212 | * @param object $config the configuration for the context |
||
213 | */ |
||
214 | protected function createContext($config) |
||
220 | |||
221 | public function getServiceProvider() |
||
227 | |||
228 | /** |
||
229 | * Registers the build-methods for the main-components with this context. |
||
230 | * Note: This method and subsequent registered methods of this class are |
||
231 | * candidates for refactoring. Because this class has grown much to large |
||
232 | * and for better design and flexibility the core builder-methods should be |
||
233 | * put into a core context-plugin. |
||
234 | * |
||
235 | * @see XMLContext::includeContext |
||
236 | */ |
||
237 | protected function initNodeBuilders() |
||
260 | |||
261 | /** |
||
262 | * Builds a specific configuration-node. Calls the build-method which |
||
263 | * is registered with the node-name. If none is registered does nothing. |
||
264 | * |
||
265 | * @see XMLContext::doCreateChannel |
||
266 | * |
||
267 | * @param object $node configuration-node |
||
268 | * |
||
269 | * @return void |
||
270 | */ |
||
271 | protected function buildNode($node) |
||
279 | |||
280 | /** |
||
281 | * Resolves a channel-name and returns channel-instace if found. |
||
282 | * Main purpose is to allow the context to act as a channel-resolver for |
||
283 | * mainly routers, hence implement the \PEIP\INF\Channel\ChannelResolver pattern. |
||
284 | * Note: Channels are registerd globally in a registry per thread/process. |
||
285 | * This allows to connect many context instances through channels without |
||
286 | * coupling them by in a include in configuration. |
||
287 | * |
||
288 | * @see \PEIP\INF\Channel\ChannelResolver |
||
289 | * @implements \PEIP\INF\Channel\ChannelResolver |
||
290 | * |
||
291 | * @param string $channelName the name/id of the channel to return |
||
292 | * |
||
293 | * @return \PEIP\INF\Channel\Channel |
||
294 | */ |
||
295 | public function resolveChannelName($channelName) |
||
299 | |||
300 | /** |
||
301 | * returns a service for a given id. |
||
302 | * |
||
303 | * @implements \PEIP\INF\Context\Context |
||
304 | * |
||
305 | * @param mixed $id the id for the service |
||
306 | * |
||
307 | * @return object the service instance if found |
||
308 | */ |
||
309 | public function getService($id) |
||
313 | |||
314 | /** |
||
315 | * returns all registered services. |
||
316 | * |
||
317 | * @return array registered services |
||
318 | */ |
||
319 | public function getServices() |
||
323 | |||
324 | /** |
||
325 | * Checks wether a service with a given id is registered. |
||
326 | * |
||
327 | * @param mixed $id the id for the service |
||
328 | * |
||
329 | * @return bool wether service is registered |
||
330 | */ |
||
331 | public function hasService($id) |
||
335 | |||
336 | /** |
||
337 | * Tries to receive a service for a given id. |
||
338 | * Throws RuntimeException if no service is found. |
||
339 | * |
||
340 | * @param mixed $id the id for the service |
||
341 | * |
||
342 | * @throws RuntimeException |
||
343 | * |
||
344 | * @return object the service instance if found |
||
345 | */ |
||
346 | protected function requestService($id) |
||
355 | |||
356 | /** |
||
357 | * Creates and initializes service instance from a given configuration. |
||
358 | * Registers instance if id is set in config. |
||
359 | * |
||
360 | * @param object $config |
||
361 | * |
||
362 | * @return \PEIP\INF\Context\ContextPlugin|null the initialized service instance |
||
363 | */ |
||
364 | protected function initService($config) |
||
371 | |||
372 | /** |
||
373 | * Creates and initializes service instance from a given configuration. |
||
374 | * |
||
375 | * @param $config |
||
376 | * |
||
377 | * @return \PEIP\INF\Context\ContextPlugin the initialized service instance |
||
378 | */ |
||
379 | public function createService($config) |
||
383 | |||
384 | /** |
||
385 | * Modifies a service instance from configuration. |
||
386 | * - Sets properties on the instance. |
||
387 | * -- Calls a public setter method if exists. |
||
388 | * -- Else sets a public property if exists. |
||
389 | * - Calls methods on the instance. |
||
390 | * - Registers listeners to events on the instance. |
||
391 | * |
||
392 | * @param object $service the service instance to modify |
||
393 | * @param object $config configuration to get the modification instructions from. |
||
394 | * |
||
395 | * @return object the modificated service |
||
396 | */ |
||
397 | protected function modifyService($service, $config) |
||
439 | |||
440 | /** |
||
441 | * returns gateway instance forgiven id. |
||
442 | * the use of this method is deprecated. Use getService instead. |
||
443 | * |
||
444 | * @deprecated |
||
445 | * |
||
446 | * @param mixed $id the id ofthe gateway |
||
447 | * |
||
448 | * @return object the gateway instance |
||
449 | */ |
||
450 | public function getGateway($id) |
||
454 | |||
455 | /** |
||
456 | * Creates a pollable channel from a configuration object. |
||
457 | * |
||
458 | * @see XMLContext::doCreateChannel |
||
459 | * |
||
460 | * @param object $config configuration object for the pollable channel. |
||
461 | * |
||
462 | * @return \PEIP\INF\Channel\Channel the created pollable channel instance |
||
463 | */ |
||
464 | public function createChannel($config) |
||
468 | |||
469 | /** |
||
470 | * Creates a subscribable channel from a configuration object. |
||
471 | * |
||
472 | * @see XMLContext::doCreateChannel |
||
473 | * |
||
474 | * @param object $config configuration object for the subscribable channel. |
||
475 | * |
||
476 | * @return \PEIP\INF\Channel\Channel the created subscribable channel instance |
||
477 | */ |
||
478 | public function createSubscribableChannel($config) |
||
482 | |||
483 | /** |
||
484 | * Creates and registers arbitrary channel from a configuration object and additional information. |
||
485 | * |
||
486 | * @param object $config configuration object for the channel. |
||
487 | * @param string $defaultChannelClass the channel class to use if none is set in config |
||
488 | * @param $additionalArguments additional arguments for the channel constructor (without first arg = id) |
||
489 | * |
||
490 | * @return \PEIP\INF\Channel\Channel the created channel instance |
||
491 | */ |
||
492 | View Code Duplication | public function doCreateChannel($config, $defaultChannelClass, array $additionalArguments = []) |
|
503 | |||
504 | /** |
||
505 | * Creates and registers gateway from a configuration object. |
||
506 | * |
||
507 | * @see XMLContext::initNodeBuilders |
||
508 | * |
||
509 | * @param object $config configuration object for the gateway. |
||
510 | * @param string $defaultClass the class to use if none is set in config. |
||
511 | * |
||
512 | * @return object the gateway instance |
||
513 | */ |
||
514 | View Code Duplication | public function createGateway($config, $defaultClass = false) |
|
527 | |||
528 | /** |
||
529 | * Creates and registers router from a configuration object. |
||
530 | * Adds this context instance as channel-resolver to the router if |
||
531 | * none is set in config. |
||
532 | * |
||
533 | * @see XMLContext::resolveChannelName |
||
534 | * @see XMLContext::initNodeBuilders |
||
535 | * |
||
536 | * @param object $config configuration object for the gateway. |
||
537 | * @param string $defaultClass the class to use if none is set in config. |
||
538 | * |
||
539 | * @return object the router instance |
||
540 | */ |
||
541 | View Code Duplication | public function createRouter($config, $defaultClass = false) |
|
550 | |||
551 | /** |
||
552 | * Creates and registers splitter from a configuration object. |
||
553 | * |
||
554 | * @see XMLContext::initNodeBuilders |
||
555 | * @see XMLContext::createReplyMessageHandler |
||
556 | * |
||
557 | * @param object $config configuration object for the splitter. |
||
558 | * |
||
559 | * @return object the splitter instance |
||
560 | */ |
||
561 | public function createSplitter($config) |
||
565 | |||
566 | /** |
||
567 | * Creates and registers transformer from a configuration object. |
||
568 | * |
||
569 | * @see XMLContext::initNodeBuilders |
||
570 | * @see XMLContext::createReplyMessageHandler |
||
571 | * |
||
572 | * @param object $config configuration object for the transformer. |
||
573 | * |
||
574 | * @return object the transformer instance |
||
575 | */ |
||
576 | public function createTransformer($config) |
||
580 | |||
581 | /** |
||
582 | * Creates aggregator from a configuration object. |
||
583 | * |
||
584 | * @see XMLContext::initNodeBuilders |
||
585 | * @see XMLContext::createReplyMessageHandler |
||
586 | * |
||
587 | * @param object $config configuration object for the aggregator. |
||
588 | * |
||
589 | * @return object the aggregator instance |
||
590 | */ |
||
591 | public function createAggregator($config) |
||
595 | |||
596 | /** |
||
597 | * Creates wiretap from a configuration object. |
||
598 | * |
||
599 | * @see XMLContext::initNodeBuilders |
||
600 | * @see XMLContext::createReplyMessageHandler |
||
601 | * |
||
602 | * @param object $config configuration object for the wiretap. |
||
603 | * |
||
604 | * @return object the wiretap instance |
||
605 | */ |
||
606 | public function createWiretap($config) |
||
610 | |||
611 | /** |
||
612 | * Creates a reply-message-handler from a configuration object. |
||
613 | * |
||
614 | * @see XMLContext::initNodeBuilders |
||
615 | * |
||
616 | * @param object $config configuration object for the reply-message-handler. |
||
617 | * @param string $defaultClass the class to use if none is set in config. |
||
618 | * |
||
619 | * @return object the reply-message-handler instance |
||
620 | */ |
||
621 | public function createReplyMessageHandler($config, $defaultClass = false) |
||
625 | |||
626 | /** |
||
627 | * Creates and registers service-activator from a configuration object. |
||
628 | * |
||
629 | * @see XMLContext::initNodeBuilders |
||
630 | * |
||
631 | * @param object $config configuration object for the service-activator. |
||
632 | * @param string $defaultClass the class to use if none is set in config. |
||
633 | * |
||
634 | * @return object the service-activator instance |
||
635 | */ |
||
636 | View Code Duplication | public function createServiceActivator($config, $defaultClass = false) |
|
651 | |||
652 | /** |
||
653 | * Provides a service for a configuration object. |
||
654 | * Returns reference to a service if configured, otherwise |
||
655 | * creates new service instance. |
||
656 | * |
||
657 | * @see XMLContext::getService |
||
658 | * @see XMLContext::createService |
||
659 | * |
||
660 | * @param object $config configuration object for the service. |
||
661 | * |
||
662 | * @return |
||
663 | */ |
||
664 | protected function provideService($config) |
||
675 | |||
676 | /** |
||
677 | * Utility method to return a (camel-cased) setter method-name for a property of a config-obect. |
||
678 | * Returns setter-name if set in configuration, otherwise if name of property is set, returns |
||
679 | * camel-cased setter-name build from property-name. |
||
680 | * |
||
681 | * @see XMLContext::getService |
||
682 | * @see XMLContext::createService |
||
683 | * |
||
684 | * @param object $config configuration object for the setter-method. |
||
685 | * |
||
686 | * @return string camel-cased |
||
687 | */ |
||
688 | protected static function getSetter($config) |
||
698 | |||
699 | /** |
||
700 | * Builds single argument (to call a method with later) from a config-obect. |
||
701 | * |
||
702 | * @param object $config configuration object to create argument from. |
||
703 | * |
||
704 | * @return mixed build argument |
||
705 | */ |
||
706 | protected function buildArg($config) |
||
735 | |||
736 | /** |
||
737 | * Utility method to create arguments for a reply-handler constructor from a config-obect. |
||
738 | * |
||
739 | * @param object $config configuration object to create arguments from. |
||
740 | * |
||
741 | * @return \PEIP\INF\Channel\Channel[] build arguments |
||
742 | */ |
||
743 | View Code Duplication | protected function getReplyHandlerArguments($config) |
|
755 | |||
756 | /** |
||
757 | * Utility method to return a request-channel from a config-obect. |
||
758 | * |
||
759 | * @see XMLContext::doGetChannel |
||
760 | * |
||
761 | * @param object $config configuration object to return request-channel from. |
||
762 | * |
||
763 | * @return \PEIP\INF\Channel\Channel request-channel |
||
764 | */ |
||
765 | protected function getRequestChannel($config) |
||
769 | |||
770 | /** |
||
771 | * Utility method to return a reply-channel from a config-obect. |
||
772 | * |
||
773 | * @see XMLContext::doGetChannel |
||
774 | * |
||
775 | * @param object $config configuration object to return reply-channel from. |
||
776 | * |
||
777 | * @return \PEIP\INF\Channel\Channel reply-channel |
||
778 | */ |
||
779 | protected function getReplyChannel($config) |
||
783 | |||
784 | /** |
||
785 | * Utility method to return a certainn channel from a config-obect. |
||
786 | * |
||
787 | * @param string the configuration type ofthe channel (e.g.: 'reply', 'request') |
||
788 | * @param object $config configuration object to return channel from. |
||
789 | * @param string $type |
||
790 | * |
||
791 | * @return \PEIP\INF\Channel\Channel reply-channel |
||
792 | */ |
||
793 | public function doGetChannel($type, $config) |
||
801 | |||
802 | /** |
||
803 | * Builds and modifies an arbitrary service/object instance from a config-obect. |
||
804 | * |
||
805 | * @see XMLContext::doBuild |
||
806 | * @see XMLContext::modifyService |
||
807 | * @implements \PEIP\INF\Context\Context |
||
808 | * |
||
809 | * @param object $config configuration object to build a service instance from. |
||
810 | * @param array $arguments arguments for the service constructor |
||
811 | * @param string $defaultClass class to create instance for if none is set in config |
||
812 | * |
||
813 | * @return object build and modified srvice instance |
||
814 | */ |
||
815 | public function buildAndModify($config, $arguments, $defaultClass = false) |
||
819 | |||
820 | /** |
||
821 | * Builds an arbitrary service/object instance from a config-obect. |
||
822 | * |
||
823 | * @static |
||
824 | * |
||
825 | * @param object $config configuration object to build a service instance from. |
||
826 | * @param array $arguments arguments for the service constructor |
||
827 | * @param string $defaultClass class to create instance for if none is set in config |
||
828 | * |
||
829 | * @return object build and modified srvice instance |
||
830 | */ |
||
831 | protected static function doBuild($config, $arguments, $defaultClass = false) |
||
851 | |||
852 | /** |
||
853 | * Utility function to build an object instance for given class with given constructor-arguments. |
||
854 | * |
||
855 | * @see GenericBuilder |
||
856 | * @static |
||
857 | * |
||
858 | * @param string $className name of class to build instance for. |
||
859 | * @param array $arguments arguments for the constructor |
||
860 | * |
||
861 | * @return object build and modified srvice instance |
||
862 | */ |
||
863 | protected static function build($className, $arguments) |
||
867 | |||
868 | /** |
||
869 | * @param string $type |
||
870 | * @param string $name |
||
871 | */ |
||
872 | protected static function hasPublicProperty($service, $type, $name) |
||
881 | } |
||
882 |
It seems like the type of the argument is not accepted by the function/method which you are calling.
In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.
We suggest to add an explicit type cast like in the following example: