Complex classes like FactoryTrait 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 FactoryTrait, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
31 | trait FactoryTrait |
||
32 | { |
||
33 | use ScopeTrait; |
||
34 | |||
35 | /** |
||
36 | * for loop detection |
||
37 | * |
||
38 | * @var array |
||
39 | * @access protected |
||
40 | */ |
||
41 | protected $loop = []; |
||
42 | |||
43 | /** |
||
44 | * Full scope info |
||
45 | * |
||
46 | * @param sting $id |
||
47 | * @return array |
||
48 | * @access protected |
||
49 | */ |
||
50 | protected function fullScopeInfo(/*# string */ $id)/*# : array */ |
||
61 | |||
62 | /** |
||
63 | * Create the instance with loop detection |
||
64 | * |
||
65 | * @param string $rawId |
||
66 | * @param array $args arguments for the constructor if any |
||
67 | * @return object |
||
68 | * @throws LogicException if instantiation goes wrong or loop detected |
||
69 | * @access protected |
||
70 | */ |
||
71 | protected function createInstance(/*# string */ $rawId, array $args) |
||
97 | |||
98 | /** |
||
99 | * Create object base on the raw id |
||
100 | * |
||
101 | * @param string $rawId |
||
102 | * @param array $arguments |
||
103 | * @return object |
||
104 | * @throws LogicException if instantiation goes wrong |
||
105 | * @access protected |
||
106 | */ |
||
107 | protected function createFromId(/*# string */ $rawId, array $arguments) |
||
126 | |||
127 | /** |
||
128 | * Get service definition |
||
129 | * |
||
130 | * @param string $rawId |
||
131 | * @param array $args |
||
132 | * @return array |
||
133 | * @access protected |
||
134 | */ |
||
135 | protected function getDefinition( |
||
157 | |||
158 | /** |
||
159 | * Instantiate service object from classname |
||
160 | * |
||
161 | * @param string $class |
||
162 | * @param array $args |
||
163 | * @return object |
||
164 | * @throws LogicException if something goes wrong |
||
165 | * @access protected |
||
166 | */ |
||
167 | protected function constructObject(/*# string */ $class, array $args) |
||
187 | |||
188 | /** |
||
189 | * Execute a (pseudo) callable with arguments |
||
190 | * |
||
191 | * @param callable|array|object $callable callable or pseudo callable |
||
192 | * @param array $arguments |
||
193 | * @return mixed |
||
194 | * @throws LogicException if something goes wrong |
||
195 | * @access protected |
||
196 | */ |
||
197 | protected function executeCallable($callable, array $arguments = []) |
||
211 | |||
212 | /** |
||
213 | * Rebuild callable base methodName and object |
||
214 | * |
||
215 | * method: |
||
216 | * - ['function', [ arguments...]] |
||
217 | * |
||
218 | * - [ callable, [ arguments ...]] |
||
219 | * |
||
220 | * - ['method', [ arguments ...]] |
||
221 | * convert to [[$object, 'method'], [ ... ]] |
||
222 | * |
||
223 | * @param mixed method |
||
224 | * @param object|null $object to construct callable |
||
225 | * @throws LogicException if something goes wrong |
||
226 | * @access protected |
||
227 | */ |
||
228 | protected function executeMethod($method, $object = null) |
||
240 | |||
241 | /** |
||
242 | * Matching callable arguments |
||
243 | * |
||
244 | * @param callable $callable |
||
245 | * @param array $arguments |
||
246 | * @return array the matched arguments |
||
247 | * @throws LogicException if something goes wrong |
||
248 | * @access protected |
||
249 | */ |
||
250 | protected function matchCallableArguments( |
||
273 | |||
274 | /** |
||
275 | * Match provided arguments with a method/function's reflection parameters |
||
276 | * |
||
277 | * @param \ReflectionParameter[] $reflectionParameters |
||
278 | * @param array $providedArguments |
||
279 | * @return array the resolved arguments |
||
280 | * @throws LogicException |
||
281 | * @throws NotFoundException |
||
282 | * @access protected |
||
283 | */ |
||
284 | protected function matchArguments( |
||
325 | |||
326 | /** |
||
327 | * Is $parameter same type as the $argument ? |
||
328 | * |
||
329 | * @param \ReflectionParameter $parameter |
||
330 | * @param mixed $argument |
||
331 | * @param null|string $class |
||
332 | * @return bool |
||
333 | * @throws LogicException if type missmatch |
||
334 | * @access protected |
||
335 | */ |
||
336 | protected function isTypeMatched( |
||
349 | |||
350 | /** |
||
351 | * Get an object base on provided classname or interface name |
||
352 | * |
||
353 | * @param string $classname class or interface name |
||
354 | * @return object |
||
355 | * @throws \Exception if something goes wrong |
||
356 | * @access protected |
||
357 | */ |
||
358 | protected function getObjectByClass(/*# string */ $classname) |
||
369 | |||
370 | /** |
||
371 | * Is $var an object with '__invoke()' defined |
||
372 | * |
||
373 | * @param mixed $var |
||
374 | * @return bool |
||
375 | * @access protected |
||
376 | */ |
||
377 | protected function isInvocable($var)/*# : bool */ |
||
381 | |||
382 | /** |
||
383 | * Things to do after object created. |
||
384 | * |
||
385 | * @param object $object |
||
386 | * @param array $definition service definition for $object |
||
387 | * @access protected |
||
388 | */ |
||
389 | protected function afterCreation($object, array $definition) |
||
404 | |||
405 | /** |
||
406 | * Execute [tester, todo] pairs, both use $object as argument |
||
407 | * |
||
408 | * signatures |
||
409 | * |
||
410 | * - tester: function($object) { return $object instance of XXXX; } |
||
411 | * - todoer: function($object, $container) { } |
||
412 | * |
||
413 | * @param object $object |
||
414 | * @param array $methods |
||
415 | * @access protected |
||
416 | */ |
||
417 | protected function executeTester($object, array $methods) |
||
427 | |||
428 | /** |
||
429 | * Merge data in the node, normally merge methods |
||
430 | * |
||
431 | * @param array $nodeData |
||
432 | * @return array |
||
433 | * @access protected |
||
434 | */ |
||
435 | protected function mergeNodeInfo(array $nodeData)/*# : array */ |
||
449 | |||
450 | /** |
||
451 | * Append '#' to rawId, representing a service object id |
||
452 | * |
||
453 | * @param string $rawId |
||
454 | * @return string |
||
455 | * @access protected |
||
456 | */ |
||
457 | protected function getServiceId(/*# string */ $rawId)/*# : string */ |
||
461 | } |
||
462 |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.