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 AutomatedBehaviorTrait 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 AutomatedBehaviorTrait, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
16 | trait AutomatedBehaviorTrait |
||
17 | { |
||
18 | /** |
||
19 | * The list of access rights on each property of the object. |
||
20 | * |
||
21 | * @var array |
||
22 | */ |
||
23 | private $_accessProperties; |
||
24 | |||
25 | /** |
||
26 | * The list of collection properties and their item names. |
||
27 | * Ex: [ |
||
28 | * "byItemName" => "user" => ["property" => "users", "behavior" => "list", "methods" => ["add", "remove"]], |
||
29 | * "byProperty" => "users" => ["itemName" => "user", "behavior" => "list", "methods" => ["add", "remove"]] |
||
30 | * ] |
||
31 | * |
||
32 | * @var array |
||
33 | */ |
||
34 | private $_collectionsItemNames; |
||
35 | |||
36 | /** |
||
37 | * The list of associations for each property |
||
38 | * Ex: ["products" => ["property" => "cart", "association" => "inverted"]] |
||
39 | * |
||
40 | * @var array |
||
41 | */ |
||
42 | private $_associationsList; |
||
43 | |||
44 | /** |
||
45 | * Indicates wether the constraints validation should be enabled or not. |
||
46 | * |
||
47 | * @var boolean |
||
48 | */ |
||
49 | private $_constraintsValidationEnabled; |
||
50 | |||
51 | /** |
||
52 | * Indicates wether getPropertiesInfo() has been called or not. |
||
53 | * |
||
54 | * @var boolean |
||
55 | */ |
||
56 | private $_automatedBehaviorInitialized = false; |
||
57 | |||
58 | /** |
||
59 | * Directly calls the initialization method. |
||
60 | */ |
||
61 | 28 | public function __construct() |
|
65 | |||
66 | /** |
||
67 | * Indicates if the properties constraints validation is enabled. |
||
68 | * |
||
69 | * @return boolean |
||
70 | */ |
||
71 | public function isPropertiesConstraintsValidationEnabled() |
||
75 | |||
76 | /** |
||
77 | * Enable (or disable) the properties constraints validation. |
||
78 | * |
||
79 | * @param boolean $enabled |
||
80 | */ |
||
81 | 1 | public function setPropertiesConstraintsValidationEnabled($enabled = true) |
|
85 | |||
86 | /** |
||
87 | * Disable (or enable) the properties constraints validation. |
||
88 | * |
||
89 | * @param boolean $disabled |
||
90 | */ |
||
91 | 1 | public function setPropertiesConstraintsValidationDisabled($disabled = true) |
|
95 | |||
96 | /** |
||
97 | * This function will be called each time a getter or a setter that is not |
||
98 | * already defined in the class is called. |
||
99 | * |
||
100 | * @param string $name The name of the called function. |
||
101 | * It must be a getter or a setter. |
||
102 | * @param array $args The array of arguments for the called function. |
||
103 | * It should be empty for a getter call, |
||
104 | * and should have one item for a setter call. |
||
105 | * |
||
106 | * @return mixed The value that should be returned by the function called if it is a getter, |
||
107 | * the object itself if the function called is a setter. |
||
108 | * |
||
109 | * @throws \BadMethodCallException When the method called is neither a getter nor a setter, |
||
110 | * or if the access right has not be given for this method, |
||
111 | * or if the method is a setter called without argument. |
||
112 | * @throws \InvalidArgumentException When the argument given to the method called (as a setter) |
||
113 | * does not satisfy the constraints attached to the property |
||
114 | * to modify. |
||
115 | */ |
||
116 | 26 | public function __call($name, array $args) |
|
194 | |||
195 | /** |
||
196 | * Validates the given value compared to given property constraints. |
||
197 | * If the value is not valid, an InvalidArgumentException will be thrown. |
||
198 | * |
||
199 | * @param string $property The name of the reference property. |
||
200 | * @param mixed $value The value to check. |
||
201 | * |
||
202 | * @throws \InvalidArgumentException If the value is not valid. |
||
203 | */ |
||
204 | 29 | protected function assertPropertyValue($property, $value) |
|
222 | |||
223 | /** |
||
224 | * Update the property associated to the given property. |
||
225 | * You can pass the old or the new value given to the property. |
||
226 | * |
||
227 | * @param string $property The property of the current class to update |
||
228 | * @param object $values An array of old a new value under the following form: |
||
229 | * ['oldValue' => $oldvalue, 'newValue' => $newValue] |
||
230 | * If one of theses values is not given, it will simply not be updated. |
||
231 | */ |
||
232 | 29 | protected function updatePropertyAssociation($property, array $values) |
|
274 | |||
275 | /** |
||
276 | * Initializes the object according to its class specification and given arguments. |
||
277 | * |
||
278 | * @param array $properties The values to give to the properties. |
||
279 | */ |
||
280 | 29 | protected function initializeProperties($properties = null) |
|
331 | |||
332 | /** |
||
333 | * Get every information needed from this class. |
||
334 | */ |
||
335 | 29 | private function getPropertiesInfo() |
|
346 | |||
347 | /** |
||
348 | * Extract the info about the method called. |
||
349 | * |
||
350 | * @param string $name |
||
351 | * |
||
352 | * @return array |
||
353 | */ |
||
354 | 26 | private function getMethodCallInfo($name) |
|
385 | } |
||
386 |
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.