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 absences_EntryElem 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 absences_EntryElem, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
36 | class absences_EntryElem extends absences_Record |
||
37 | { |
||
38 | /** |
||
39 | * @var absences_Right |
||
40 | */ |
||
41 | private $right; |
||
42 | |||
43 | |||
44 | /** |
||
45 | * |
||
46 | * @var absences_Entry |
||
47 | */ |
||
48 | private $entry; |
||
49 | |||
50 | |||
51 | |||
52 | /** |
||
53 | * @return absences_EntryElem |
||
54 | */ |
||
55 | public static function getById($id_elem) |
||
62 | |||
63 | |||
64 | |||
65 | |||
66 | /** |
||
67 | * (non-PHPdoc) |
||
68 | * @see absences_Record::getRow() |
||
69 | */ |
||
70 | 41 | public function getRow() |
|
86 | |||
87 | |||
88 | |||
89 | /** |
||
90 | * |
||
91 | * @param absences_Right $right |
||
92 | * @return absences_EntryElem |
||
93 | */ |
||
94 | 32 | public function setRight(absences_Right $right) |
|
99 | |||
100 | |||
101 | /** |
||
102 | * @return absences_Right |
||
103 | */ |
||
104 | 28 | public function getRight() |
|
116 | |||
117 | |||
118 | /** |
||
119 | * |
||
120 | * @param absences_Entry $entry |
||
121 | * @return absences_EntryElem |
||
122 | */ |
||
123 | 32 | public function setEntry(absences_Entry $entry) |
|
128 | |||
129 | |||
130 | /** |
||
131 | * @return absences_Entry |
||
132 | */ |
||
133 | View Code Duplication | public function getEntry() |
|
143 | |||
144 | |||
145 | /** |
||
146 | * @return absences_AgentRight |
||
147 | */ |
||
148 | public function getAgentRight() |
||
163 | |||
164 | |||
165 | |||
166 | /** |
||
167 | * Check validity before saving an element |
||
168 | * @throws UnexpectedValueException |
||
169 | * |
||
170 | * @return bool |
||
171 | */ |
||
172 | public function checkValidity() |
||
173 | { |
||
174 | if (!isset($this->id_right) || $this->id_right <= 0) |
||
175 | { |
||
176 | throw new UnexpectedValueException('Missing id_right'); |
||
177 | } |
||
178 | |||
179 | $quantity = (int) round(100 * $this->quantity); |
||
180 | |||
181 | if (!$quantity && !isset($this->id)) |
||
182 | { |
||
183 | |||
184 | require_once $GLOBALS['babInstallPath'].'utilit/devtools.php'; |
||
185 | bab_debug_print_backtrace(); |
||
186 | |||
187 | $message = sprintf( |
||
188 | absences_translate('An absence cannot be created because of a missing quantity in right "%s"'), |
||
189 | $this->getRight()->description |
||
190 | ); |
||
191 | throw new UnexpectedValueException($message); |
||
192 | } |
||
193 | |||
194 | return true; |
||
195 | } |
||
196 | |||
197 | |||
198 | /** |
||
199 | * For previsional requests, check if requested quantity is available |
||
200 | * @return bool |
||
201 | */ |
||
202 | public function isQuantityAvailable() |
||
213 | |||
214 | |||
215 | |||
216 | /** |
||
217 | * |
||
218 | * @param string $message Generated message |
||
219 | * @param string $comment Author comment |
||
220 | */ |
||
221 | public function addMovement($message, $comment = '') |
||
233 | |||
234 | |||
235 | |||
236 | /** |
||
237 | * Save element (insert or update or delete) |
||
238 | */ |
||
239 | 7 | public function save() |
|
295 | |||
296 | |||
297 | |||
298 | public function delete() |
||
308 | |||
309 | |||
310 | |||
311 | |||
312 | /** |
||
313 | * Trouver la quantitee totale de la demande disponible sur la periode |
||
314 | * la quantitee est dans l'unite du droit |
||
315 | * si les dates de l'element sont comprises dans l'interval, la quantite |
||
316 | * de l'element est utilises |
||
317 | * si les dates de l'element sont a cheval sur la periode demandee |
||
318 | * on utlise les heures travailles de l'utilisateur |
||
319 | * |
||
320 | * @param string $begin Datetime |
||
321 | * @param string $end Datetime |
||
322 | * |
||
323 | * @return float (days or hours) |
||
324 | */ |
||
325 | public function getQuantityBetween($begin, $end) |
||
356 | |||
357 | |||
358 | /** |
||
359 | * Trouver la quantitee totale de la demande disponible sur la periode |
||
360 | * la quantitee est dans l'unite du droit |
||
361 | * si les dates de l'element sont comprises dans l'interval, la quantite |
||
362 | * de l'element est utilises |
||
363 | * si les dates de l'element sont a cheval sur la periode demandee |
||
364 | * on utlise les heures travailles qui etait en vigeur au moment de la creation |
||
365 | * de la demande |
||
366 | * |
||
367 | * @param string $begin Datetime |
||
368 | * @param string $end Datetime |
||
369 | * |
||
370 | * @return float (days or hours) |
||
371 | */ |
||
372 | 1 | public function getPlannedQuantityBetween($begin, $end) |
|
392 | |||
393 | |||
394 | /** |
||
395 | * @return float |
||
396 | */ |
||
397 | public function getDays() |
||
406 | |||
407 | /** |
||
408 | * @return float |
||
409 | */ |
||
410 | public function getHours() |
||
419 | } |
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.