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 CallableRepository 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 CallableRepository, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
19 | class CallableRepository |
||
20 | { |
||
21 | use \Jaxon\Utils\Traits\Config; |
||
22 | use \Jaxon\Utils\Traits\Template; |
||
23 | |||
24 | /** |
||
25 | * The registered namespaces |
||
26 | * |
||
27 | * These are the namespaces specified when registering directories. |
||
28 | * |
||
29 | * @var array |
||
30 | */ |
||
31 | protected $aNamespaceOptions = []; |
||
32 | |||
33 | /** |
||
34 | * The registered classes |
||
35 | * |
||
36 | * These are registered classes, and classes in directories registered without a namespace. |
||
37 | * |
||
38 | * @var array |
||
39 | */ |
||
40 | protected $aClassOptions = []; |
||
41 | |||
42 | /** |
||
43 | * The namespaces |
||
44 | * |
||
45 | * These are all the namespaces found in registered directories |
||
46 | * |
||
47 | * @var array |
||
48 | */ |
||
49 | protected $aNamespaces = []; |
||
50 | |||
51 | /** |
||
52 | * The created callable objects |
||
53 | * |
||
54 | * @var array |
||
55 | */ |
||
56 | protected $aCallableObjects = []; |
||
57 | |||
58 | /** |
||
59 | * The options to be applied to callable objects |
||
60 | * |
||
61 | * @var array |
||
62 | */ |
||
63 | protected $aCallableOptions = []; |
||
64 | |||
65 | /** |
||
66 | * |
||
67 | * @param string $sClassName The name of the class being registered |
||
68 | * @param array|string $aOptions The associated options |
||
69 | * |
||
70 | * @return void |
||
71 | */ |
||
72 | public function addClass($sClassName, $aOptions) |
||
78 | |||
79 | /** |
||
80 | * Get a given class options from specified directory options |
||
81 | * |
||
82 | * @param string $sClassName The name of the class |
||
83 | * @param array $aDirectoryOptions The directory options |
||
84 | * @param array $aDefaultOptions The default options |
||
85 | * |
||
86 | * @return array |
||
87 | */ |
||
88 | private function getClassOptions($sClassName, array $aDirectoryOptions, array $aDefaultOptions = []) |
||
110 | |||
111 | /** |
||
112 | * |
||
113 | * @param string $sDirectory The directory being registered |
||
114 | * @param array $aOptions The associated options |
||
115 | * |
||
116 | * @return void |
||
117 | */ |
||
118 | public function addDirectory($sDirectory, $aOptions) |
||
143 | |||
144 | /** |
||
145 | * |
||
146 | * @param string $sNamespace The namespace of the directory being registered |
||
147 | * @param array $aOptions The associated options |
||
148 | * |
||
149 | * @return void |
||
150 | */ |
||
151 | public function addNamespace($sNamespace, $aOptions) |
||
155 | |||
156 | /** |
||
157 | * Find a class name is register with Jaxon::CALLABLE_CLASS type |
||
158 | * |
||
159 | * @param string $sClassName The class name of the callable object |
||
160 | * |
||
161 | * @return array|null |
||
162 | */ |
||
163 | private function getOptionsFromClass($sClassName) |
||
171 | |||
172 | /** |
||
173 | * Find a class name is register with Jaxon::CALLABLE_DIR type |
||
174 | * |
||
175 | * @param string $sClassName The class name of the callable object |
||
176 | * |
||
177 | * @return array|null |
||
178 | */ |
||
179 | private function getOptionsFromNamespace($sClassName) |
||
199 | |||
200 | /** |
||
201 | * Find a callable object by class name |
||
202 | * |
||
203 | * @param string $sClassName The class name of the callable object |
||
204 | * |
||
205 | * @return object |
||
206 | */ |
||
207 | public function getCallableObject($sClassName) |
||
268 | |||
269 | /** |
||
270 | * Create callable objects for all registered namespaces |
||
271 | * |
||
272 | * @return void |
||
273 | */ |
||
274 | private function createCallableObjects() |
||
320 | |||
321 | /** |
||
322 | * Find a user registered callable object by class name |
||
323 | * |
||
324 | * @param string $sClassName The class name of the callable object |
||
325 | * |
||
326 | * @return object |
||
327 | */ |
||
328 | protected function getRegisteredObject($sClassName) |
||
334 | |||
335 | /** |
||
336 | * Generate a hash for the registered callable objects |
||
337 | * |
||
338 | * @return string |
||
339 | */ |
||
340 | public function generateHash() |
||
356 | |||
357 | /** |
||
358 | * Generate client side javascript code for the registered callable objects |
||
359 | * |
||
360 | * @return string |
||
361 | */ |
||
362 | public function getScript() |
||
414 | } |
||
415 |
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.