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 |
||
14 | abstract class Entity |
||
15 | { |
||
16 | |||
17 | /** |
||
18 | * @var array Columns |
||
19 | */ |
||
20 | protected static $columns = []; |
||
21 | |||
22 | /** |
||
23 | * @var array Internal entity properties |
||
24 | */ |
||
25 | protected $properties = []; |
||
26 | |||
27 | /** |
||
28 | * @var array Internal altered columns |
||
29 | */ |
||
30 | protected $alteredColumns = []; |
||
31 | |||
32 | /** |
||
33 | * @param int|null $id Entity ID |
||
34 | * @param \DateTime $modified Datetime of last modification |
||
35 | * @param \DateTime $created Datetime of creation |
||
36 | */ |
||
37 | public function __construct($id, \DateTime $modified, \DateTime $created) |
||
43 | |||
44 | /** |
||
45 | * Get entity columns |
||
46 | * |
||
47 | * @return array Entity columns |
||
48 | */ |
||
49 | public static function getColumns(): array |
||
62 | |||
63 | /** |
||
64 | * Set entity property |
||
65 | * |
||
66 | * @param string $key Entity property name |
||
67 | * @param object|int|double|string|array|boolean|null $value Entity property value |
||
68 | * |
||
69 | * @throws InvalidEntityPropertyException If entity does not have that property |
||
70 | * @throws InvalidValueTypeForEntityPropertyException If value is of the wrong type |
||
71 | */ |
||
72 | public function set(string $key, $value) |
||
92 | |||
93 | /** |
||
94 | * Get entity property |
||
95 | * |
||
96 | * @param string $key Entity property |
||
97 | * |
||
98 | * @return object|int|double|string|array|boolean|null Entity property value for given key |
||
99 | * |
||
100 | * @throws InvalidEntityPropertyException If entity does not have that property |
||
101 | */ |
||
102 | public function get(string $key) |
||
110 | |||
111 | /** |
||
112 | * Validate type for given property value |
||
113 | * |
||
114 | * @param string $key Entity property name |
||
115 | * @param mixed $value Entity property value |
||
116 | * |
||
117 | * @return object|int|double|string|array|boolean|null Value |
||
118 | * |
||
119 | * @throws InvalidEntityPropertyException If entity does not have that property |
||
120 | * @throws InvalidValueTypeForEntityPropertyException If value is of the wrong type |
||
121 | */ |
||
122 | public function validatePropertyValueType(string $key, $value) |
||
171 | |||
172 | /** |
||
173 | * Check if entity has been altered |
||
174 | * |
||
175 | * @return bool True if altered, otherwise false |
||
176 | */ |
||
177 | public function isAltered(): bool |
||
181 | |||
182 | /** |
||
183 | * Marks the entity as unaltered |
||
184 | */ |
||
185 | public function setUnaltered() |
||
189 | |||
190 | /** |
||
191 | * Get altered columns |
||
192 | * |
||
193 | * @return array |
||
194 | */ |
||
195 | public function getAlteredColumns(): array |
||
199 | |||
200 | /** |
||
201 | * Return table structure for saving |
||
202 | * Example: `[':{table_field_name}' => $this->fieldName]` |
||
203 | * |
||
204 | * @param bool $includeId Should the ID column be included |
||
205 | * |
||
206 | * @return array |
||
207 | */ |
||
208 | public function toArray(bool $includeId): array |
||
218 | |||
219 | /** |
||
220 | * Return table structure for saving just altered columns |
||
221 | * |
||
222 | * @param bool $includeId Should the ID column be included |
||
223 | * |
||
224 | * @return array |
||
225 | */ |
||
226 | public function alteredToArray(bool $includeId): array |
||
236 | |||
237 | /** |
||
238 | * Return columns in structure for saving |
||
239 | * |
||
240 | * @param array $columns Columns to include |
||
241 | * |
||
242 | * @return array |
||
243 | */ |
||
244 | protected function toArrayFromColumns(array $columns): array |
||
259 | } |
||
260 |
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.