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:
1 | <?php |
||
13 | trait Properties { |
||
14 | /** |
||
15 | * Do not call this method directly as it is a PHP magic method that |
||
16 | * will be implicitly called when executing `$value = $object->property;`. |
||
17 | * |
||
18 | * @param string $name the property name |
||
19 | * |
||
20 | * @return mixed the property value |
||
21 | * @throws UndefinedPropertyException if the property is not defined |
||
22 | * @throws InvalidAccessException if the property is write-only |
||
23 | * @see getProperty() |
||
24 | * @see __set() |
||
25 | */ |
||
26 | public function __get($name) { |
||
29 | |||
30 | /** |
||
31 | * Returns the value of an object property. |
||
32 | * |
||
33 | * @param string $property the property name |
||
34 | * |
||
35 | * @return mixed the property value |
||
36 | * @throws UndefinedPropertyException if the property is not defined |
||
37 | * @throws InvalidAccessException if the property is write-only |
||
38 | * @see setProperty() |
||
39 | */ |
||
40 | protected function getProperty(string $property) { |
||
52 | |||
53 | /** |
||
54 | * Do not call this method directly as it is a PHP magic method that |
||
55 | * will be implicitly called when executing `$object->property = $value;`. |
||
56 | * |
||
57 | * @param string $name the property name |
||
58 | * @param mixed $value the property value |
||
59 | * |
||
60 | * @throws UndefinedPropertyException if the property is not defined |
||
61 | * @throws InvalidAccessException if the property is read-only |
||
62 | * @see setProperty() |
||
63 | * @see __get() |
||
64 | */ |
||
65 | public function __set($name, $value) { |
||
68 | |||
69 | /** |
||
70 | * Sets value of an object property. |
||
71 | * |
||
72 | * @param string $name the property name |
||
73 | * @param mixed $value the property value |
||
74 | * |
||
75 | * @throws UndefinedPropertyException if the property is not defined |
||
76 | * @throws InvalidAccessException if the property is read-only |
||
77 | * @see getProperty() |
||
78 | */ |
||
79 | protected function setProperty(string $name, $value): void { |
||
89 | |||
90 | /** |
||
91 | * Do not call this method directly as it is a PHP magic method that |
||
92 | * will be implicitly called when executing `isset($object->property)`. |
||
93 | * |
||
94 | * @param string $name the property name |
||
95 | * |
||
96 | * @return bool whether the named property is set (not null). |
||
97 | * @see isPropertySet |
||
98 | * @see http://php.net/manual/en/function.isset.php |
||
99 | */ |
||
100 | public function __isset($name) { |
||
103 | |||
104 | /** |
||
105 | * Checks if a property is set, i.e. defined and not null. |
||
106 | * |
||
107 | * Note that if the property is not defined, false will be returned. |
||
108 | * |
||
109 | * @param string $name the property name |
||
110 | * |
||
111 | * @return bool whether the named property is set (not null). |
||
112 | */ |
||
113 | public function isPropertySet(string $name): bool { |
||
121 | |||
122 | /** |
||
123 | * Do not call this method directly as it is a PHP magic method that |
||
124 | * will be implicitly called when executing `unset($object->property)`. |
||
125 | * |
||
126 | * @param string $name the property name |
||
127 | * |
||
128 | * @throws InvalidAccessException if the property is read only. |
||
129 | * @see unSetProperty |
||
130 | * @see http://php.net/manual/en/function.unset.php |
||
131 | */ |
||
132 | public function __unset($name) { |
||
135 | |||
136 | /** |
||
137 | * Sets an object property to null. |
||
138 | * |
||
139 | * Note that if the property is not defined, this method will do nothing. |
||
140 | * If the property is read-only, it will throw an exception. |
||
141 | * |
||
142 | * @param string $name the property name |
||
143 | * |
||
144 | * @throws InvalidAccessException if the property is read only. |
||
145 | */ |
||
146 | public function unSetProperty(string $name): void { |
||
154 | |||
155 | /** |
||
156 | * Returns a value indicating whether a property is defined. |
||
157 | * |
||
158 | * A property is defined if: |
||
159 | * |
||
160 | * - the class has a getter or setter method associated with the specified name |
||
161 | * (in this case, property name is case-insensitive); |
||
162 | * - the class has a member variable with the specified name; |
||
163 | * |
||
164 | * @param string $name the property name |
||
165 | * |
||
166 | * @return bool whether the property is defined |
||
167 | * @see canGetProperty() |
||
168 | * @see canSetProperty() |
||
169 | */ |
||
170 | public function hasProperty($name): bool { |
||
173 | |||
174 | /** |
||
175 | * Returns a value indicating whether a condition property is defined. |
||
176 | * |
||
177 | * A condition property is defined if: |
||
178 | * - the class has a "is" method associated with the specified name; |
||
179 | * - the class has a "has" method associated with the specified name; |
||
180 | * |
||
181 | * Note: property name is case-insensitive |
||
182 | * |
||
183 | * @param string $name the property name |
||
184 | * |
||
185 | * @return bool whether the condition property is defined |
||
186 | */ |
||
187 | public function hasCondition($name): bool { |
||
190 | |||
191 | /** |
||
192 | * Returns a value indicating whether a property can be read. |
||
193 | * |
||
194 | * A property is readable if: |
||
195 | * |
||
196 | * - the class has a getter method associated with the specified name |
||
197 | * (in this case, property name is case-insensitive); |
||
198 | * - the class has a member variable with the specified name; |
||
199 | * |
||
200 | * @param string $property the property name |
||
201 | * |
||
202 | * @return bool whether the property can be read |
||
203 | * @see canSetProperty() |
||
204 | */ |
||
205 | public function canGetProperty(string $property): bool { |
||
208 | |||
209 | /** |
||
210 | * Returns a value indicating whether a property can be set. |
||
211 | * |
||
212 | * A property is writable if: |
||
213 | * - the class has a setter method associated with the specified name |
||
214 | * (in this case, property name is case-insensitive); |
||
215 | * - the class has a member variable with the specified name; |
||
216 | * |
||
217 | * @param string $property the property name |
||
218 | * |
||
219 | * @return bool whether the property can be written |
||
220 | * @see canGetProperty() |
||
221 | */ |
||
222 | public function canSetProperty(string $property): bool { |
||
225 | |||
226 | /** |
||
227 | * Returns a value indicating whether a class field is defined. |
||
228 | * |
||
229 | * @param string $name the field name |
||
230 | * |
||
231 | * @return bool whether the field is defined |
||
232 | */ |
||
233 | public function hasField(string $name): bool { |
||
236 | |||
237 | /** |
||
238 | * Returns a value indicating whether a getter is defined for property. |
||
239 | * |
||
240 | * @param string $property the property name |
||
241 | * |
||
242 | * @return bool whether the getter is defined |
||
243 | */ |
||
244 | public function hasGetterFor(string $property): bool { |
||
247 | |||
248 | /** |
||
249 | * Returns a value indicating whether a setter is defined for property. |
||
250 | * |
||
251 | * @param string $property the property name |
||
252 | * |
||
253 | * @return bool whether the getter is defined |
||
254 | */ |
||
255 | public function hasSetterFor(string $property): bool { |
||
258 | |||
259 | /** |
||
260 | * Returns a value indicating whether a method is defined. |
||
261 | * |
||
262 | * The default implementation is a call to php function `method_exists()`. |
||
263 | * You may override this method when you implemented the php magic method `__call()`. |
||
264 | * |
||
265 | * @param string $name the method name |
||
266 | * |
||
267 | * @return bool whether the method is defined |
||
268 | */ |
||
269 | public function hasMethod(string $name): bool { |
||
272 | } |
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.