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 |
||
36 | class User extends UserAggregateRoot |
||
37 | { |
||
38 | /** |
||
39 | * The id. |
||
40 | * |
||
41 | * @var UserId |
||
42 | */ |
||
43 | protected $id; |
||
44 | |||
45 | /** |
||
46 | * The confirmation token. |
||
47 | * |
||
48 | * @var UserToken |
||
49 | */ |
||
50 | protected $confirmationToken; |
||
51 | |||
52 | /** |
||
53 | * Created on. |
||
54 | * |
||
55 | * @var \DateTimeInterface |
||
56 | */ |
||
57 | protected $createdOn; |
||
58 | |||
59 | /** |
||
60 | * The email. |
||
61 | * |
||
62 | * @var UserEmail |
||
63 | */ |
||
64 | protected $email; |
||
65 | |||
66 | /** |
||
67 | * The invitation token. |
||
68 | * |
||
69 | * @var UserToken |
||
70 | */ |
||
71 | protected $invitationToken; |
||
72 | |||
73 | /** |
||
74 | * The last login. |
||
75 | * |
||
76 | * @var \DateTimeInterface|null |
||
77 | */ |
||
78 | protected $lastLogin; |
||
79 | |||
80 | /** |
||
81 | * The password. |
||
82 | * |
||
83 | * @var UserPassword |
||
84 | */ |
||
85 | protected $password; |
||
86 | |||
87 | /** |
||
88 | * The remember password token. |
||
89 | * |
||
90 | * @var UserToken |
||
91 | */ |
||
92 | protected $rememberPasswordToken; |
||
93 | |||
94 | /** |
||
95 | * Array which contains roles. |
||
96 | * |
||
97 | * @var UserRole[] |
||
98 | */ |
||
99 | protected $roles; |
||
100 | |||
101 | /** |
||
102 | * Updated on. |
||
103 | * |
||
104 | * @var \DateTimeInterface |
||
105 | */ |
||
106 | protected $updatedOn; |
||
107 | |||
108 | /** |
||
109 | * Constructor. |
||
110 | * |
||
111 | * @param UserId $anId The id |
||
112 | * @param UserEmail $anEmail The email |
||
113 | * @param array $userRoles Array which contains the roles |
||
114 | * @param UserPassword|null $aPassword The encoded password |
||
115 | */ |
||
116 | protected function __construct( |
||
117 | UserId $anId, |
||
118 | UserEmail $anEmail, |
||
119 | array $userRoles, |
||
120 | UserPassword $aPassword = null |
||
121 | ) { |
||
122 | $this->id = $anId; |
||
123 | $this->email = $anEmail; |
||
124 | $this->password = $aPassword; |
||
125 | $this->confirmationToken = new UserToken(); |
||
126 | $this->createdOn = new \DateTimeImmutable(); |
||
127 | $this->updatedOn = new \DateTimeImmutable(); |
||
128 | |||
129 | $this->roles = []; |
||
130 | foreach ($userRoles as $userRole) { |
||
131 | $this->grant($userRole); |
||
132 | } |
||
133 | } |
||
134 | |||
135 | /** |
||
136 | * Sign up user. |
||
137 | * |
||
138 | * @param UserId $anId The id |
||
139 | * @param UserEmail $anEmail The email |
||
140 | * @param UserPassword $aPassword The encoded password |
||
141 | * @param array $userRoles Array which contains the roles |
||
142 | * |
||
143 | * @return static |
||
144 | */ |
||
145 | View Code Duplication | public static function signUp(UserId $anId, UserEmail $anEmail, UserPassword $aPassword, array $userRoles) |
|
158 | |||
159 | /** |
||
160 | * Invites user. |
||
161 | * |
||
162 | * @param UserId $anId The id |
||
163 | * @param UserEmail $anEmail The email |
||
164 | * @param array $userRoles Array which contains the roles |
||
165 | * |
||
166 | * @return static |
||
167 | */ |
||
168 | View Code Duplication | public static function invite(UserId $anId, UserEmail $anEmail, array $userRoles) |
|
182 | |||
183 | /** |
||
184 | * Gets the id. |
||
185 | * |
||
186 | * @return UserId |
||
187 | */ |
||
188 | public function id() |
||
192 | |||
193 | /** |
||
194 | * Accepts the invitation request. |
||
195 | */ |
||
196 | public function acceptInvitation() |
||
207 | |||
208 | /** |
||
209 | * Updates the user password. |
||
210 | * |
||
211 | * @param UserPassword $aPassword The old password |
||
212 | */ |
||
213 | public function changePassword(UserPassword $aPassword) |
||
219 | |||
220 | /** |
||
221 | * Gets the confirmation token. |
||
222 | * |
||
223 | * @return UserToken |
||
224 | */ |
||
225 | public function confirmationToken() |
||
229 | |||
230 | /** |
||
231 | * Gets the created on. |
||
232 | * |
||
233 | * @return \DateTimeInterface |
||
234 | */ |
||
235 | public function createdOn() |
||
239 | |||
240 | /** |
||
241 | * Gets the email. |
||
242 | * |
||
243 | * @return UserEmail |
||
244 | */ |
||
245 | public function email() |
||
249 | |||
250 | /** |
||
251 | * Enables the user account. |
||
252 | */ |
||
253 | public function enableAccount() |
||
265 | |||
266 | /** |
||
267 | * Adds the given role. |
||
268 | * |
||
269 | * @param UserRole $aRole The user role |
||
270 | */ |
||
271 | public function grant(UserRole $aRole) |
||
290 | |||
291 | /** |
||
292 | * Gets the invitation token. |
||
293 | * |
||
294 | * @return UserToken |
||
295 | */ |
||
296 | public function invitationToken() |
||
300 | |||
301 | /** |
||
302 | * Checks if the user is enabled or not. |
||
303 | * |
||
304 | * @return bool |
||
305 | */ |
||
306 | public function isEnabled() |
||
310 | |||
311 | /** |
||
312 | * Checks if the user has the given role. |
||
313 | * |
||
314 | * @param UserRole $aRole The user role |
||
315 | * |
||
316 | * @return bool |
||
317 | */ |
||
318 | public function isGranted(UserRole $aRole) |
||
328 | |||
329 | /** |
||
330 | * Checks if the role given appears between allowed roles. |
||
331 | * |
||
332 | * @param UserRole $aRole The user role |
||
333 | * |
||
334 | * @return bool |
||
335 | */ |
||
336 | public function isRoleAllowed(UserRole $aRole) |
||
340 | |||
341 | /** |
||
342 | * Gets the last login. |
||
343 | * |
||
344 | * @return \DateTimeInterface |
||
345 | */ |
||
346 | public function lastLogin() |
||
350 | |||
351 | /** |
||
352 | * Validates user login for the given password. |
||
353 | * |
||
354 | * @param string $aPlainPassword Plain password used to log in |
||
355 | * @param UserPasswordEncoder $anEncoder The encoder used to encode the password |
||
356 | * |
||
357 | * @throws UserInactiveException when the user is not enabled |
||
358 | * @throws UserPasswordInvalidException when the user password is invalid |
||
359 | */ |
||
360 | public function login($aPlainPassword, UserPasswordEncoder $anEncoder) |
||
377 | |||
378 | /** |
||
379 | * Updated the user state after logout. |
||
380 | * |
||
381 | * @throws UserInactiveException when the user is not enabled |
||
382 | */ |
||
383 | public function logout() |
||
396 | |||
397 | /** |
||
398 | * Gets the password. |
||
399 | * |
||
400 | * @return UserPassword |
||
401 | */ |
||
402 | public function password() |
||
406 | |||
407 | /** |
||
408 | * Updates the invitation token in case a user has |
||
409 | * been already invited and has lost the token. |
||
410 | * |
||
411 | * @throws UserInvitationAlreadyAcceptedException in case user has already accepted the invitation |
||
412 | */ |
||
413 | public function regenerateInvitationToken() |
||
420 | |||
421 | /** |
||
422 | * Gets the remember password token. |
||
423 | * |
||
424 | * @return UserToken |
||
425 | */ |
||
426 | public function rememberPasswordToken() |
||
430 | |||
431 | /** |
||
432 | * Remembers the password. |
||
433 | */ |
||
434 | public function rememberPassword() |
||
446 | |||
447 | /** |
||
448 | * Removes the given role. |
||
449 | * |
||
450 | * @param UserRole $aRole The user role |
||
451 | */ |
||
452 | public function revoke(UserRole $aRole) |
||
473 | |||
474 | /** |
||
475 | * Gets the roles. |
||
476 | * |
||
477 | * @return UserRole[] |
||
478 | */ |
||
479 | public function roles() |
||
483 | |||
484 | /** |
||
485 | * Gets the updated on. |
||
486 | * |
||
487 | * @return \DateTimeInterface |
||
488 | */ |
||
489 | public function updatedOn() |
||
493 | |||
494 | /** |
||
495 | * Gets the available roles in scalar type. |
||
496 | * |
||
497 | * This method is an extension point that it allows |
||
498 | * to add more roles easily in the domain. |
||
499 | * |
||
500 | * @return array |
||
501 | */ |
||
502 | public static function availableRoles() |
||
506 | } |
||
507 |
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.