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 AuthToken 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 AuthToken, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 16 | class AuthToken extends AbstractModel |
||
| 17 | { |
||
| 18 | |||
| 19 | /** |
||
| 20 | * @var string $ident |
||
| 21 | */ |
||
| 22 | private $ident; |
||
| 23 | |||
| 24 | /** |
||
| 25 | * @var string $token |
||
| 26 | */ |
||
| 27 | private $token; |
||
| 28 | |||
| 29 | /** |
||
| 30 | * The username should be unique and mandatory. |
||
| 31 | * @var string $username |
||
| 32 | */ |
||
| 33 | private $username; |
||
| 34 | |||
| 35 | /** |
||
| 36 | * @var Datetime $expiry |
||
| 37 | */ |
||
| 38 | private $expiry; |
||
| 39 | |||
| 40 | /** |
||
| 41 | * Token creation date (set automatically on save) |
||
| 42 | * @var DateTime $Created |
||
| 43 | */ |
||
| 44 | private $created; |
||
| 45 | |||
| 46 | /** |
||
| 47 | * Token last modified date (set automatically on save and update) |
||
| 48 | * @var DateTime $LastModified |
||
| 49 | */ |
||
| 50 | private $lastModified; |
||
| 51 | |||
| 52 | /** |
||
| 53 | * @return string |
||
| 54 | */ |
||
| 55 | public function key() |
||
| 59 | |||
| 60 | /** |
||
| 61 | * @param string $ident The token ident. |
||
| 62 | * @return AuthToken Chainable |
||
| 63 | */ |
||
| 64 | public function setIdent($ident) |
||
| 69 | |||
| 70 | /** |
||
| 71 | * @return string |
||
| 72 | */ |
||
| 73 | public function ident() |
||
| 77 | |||
| 78 | /** |
||
| 79 | * @param string $token The token. |
||
| 80 | * @return AuthToken Chainable |
||
| 81 | */ |
||
| 82 | public function setToken($token) |
||
| 87 | |||
| 88 | /** |
||
| 89 | * @return string |
||
| 90 | */ |
||
| 91 | public function token() |
||
| 95 | |||
| 96 | |||
| 97 | /** |
||
| 98 | * Force a lowercase username |
||
| 99 | * |
||
| 100 | * @param string $username The username (also the login name). |
||
| 101 | * @throws InvalidArgumentException If the username is not a string. |
||
| 102 | * @return User Chainable |
||
| 103 | */ |
||
| 104 | View Code Duplication | public function setUsername($username) |
|
| 114 | |||
| 115 | /** |
||
| 116 | * @return string |
||
| 117 | */ |
||
| 118 | public function username() |
||
| 122 | |||
| 123 | /** |
||
| 124 | * @param DateTime|string|null $expiry The date/time at object's creation. |
||
| 125 | * @throws InvalidArgumentException If the date/time is invalid. |
||
| 126 | * @return Content Chainable |
||
| 127 | */ |
||
| 128 | public function setExpiry($expiry) |
||
| 145 | |||
| 146 | /** |
||
| 147 | * @return DateTimeInterface|null |
||
| 148 | */ |
||
| 149 | public function expiry() |
||
| 153 | |||
| 154 | /** |
||
| 155 | * @param DateTime|string|null $created The date/time at object's creation. |
||
| 156 | * @throws InvalidArgumentException If the date/time is invalid. |
||
| 157 | * @return Content Chainable |
||
| 158 | */ |
||
| 159 | public function setCreated($created) |
||
| 176 | |||
| 177 | /** |
||
| 178 | * @return DateTime|null |
||
| 179 | */ |
||
| 180 | public function created() |
||
| 184 | |||
| 185 | /** |
||
| 186 | * @param DateTime|string|null $lastModified The last modified date/time. |
||
| 187 | * @throws InvalidArgumentException If the date/time is invalid. |
||
| 188 | * @return Content Chainable |
||
| 189 | */ |
||
| 190 | public function setLastModified($lastModified) |
||
| 207 | |||
| 208 | /** |
||
| 209 | * @return DateTime |
||
| 210 | */ |
||
| 211 | public function lastModified() |
||
| 215 | |||
| 216 | /** |
||
| 217 | * Note: the `random_bytes()` function is new to PHP-7. Available in PHP 5 with `compat-random`. |
||
| 218 | * |
||
| 219 | * @param string $username The username to generate the auth token from. |
||
| 220 | * @return AuthToken Chainable |
||
| 221 | */ |
||
| 222 | public function generate($username) |
||
| 231 | |||
| 232 | /** |
||
| 233 | * @return AuthToken Chainable |
||
| 234 | */ |
||
| 235 | public function sendCookie() |
||
| 246 | |||
| 247 | /** |
||
| 248 | * StorableTrait > preSave(): Called automatically before saving the object to source. |
||
| 249 | * @return boolean |
||
| 250 | */ |
||
| 251 | public function preSave() |
||
| 263 | |||
| 264 | /** |
||
| 265 | * StorableTrait > preUpdate(): Called automatically before updating the object to source. |
||
| 266 | * @param array $properties The properties (ident) set for update. |
||
| 267 | * @return boolean |
||
| 268 | */ |
||
| 269 | public function preUpdate(array $properties = null) |
||
| 277 | |||
| 278 | /** |
||
| 279 | * @return array `['ident'=>'', 'token'=>''] |
||
| 280 | */ |
||
| 281 | public function getTokenDataFromCookie() |
||
| 300 | |||
| 301 | /** |
||
| 302 | * @param mixed $ident The auth-token identifier. |
||
| 303 | * @param string $token The token key to validate against. |
||
| 304 | * @return mixed The user id. |
||
| 305 | */ |
||
| 306 | public function getUserId($ident, $token) |
||
| 310 | |||
| 311 | /** |
||
| 312 | * @param mixed $ident The auth-token identifier (username). |
||
| 313 | * @param string $token The token to validate against. |
||
| 314 | * @return mixed The user id. An empty string if no token match. |
||
| 315 | */ |
||
| 316 | public function getUsernameFromToken($ident, $token) |
||
| 342 | |||
| 343 | /** |
||
| 344 | * Something is seriously wrong: a cookie ident was in the database but with a tampered token. |
||
| 345 | * |
||
| 346 | * @return void |
||
| 347 | */ |
||
| 348 | protected function panic() |
||
| 369 | |||
| 370 | /** |
||
| 371 | * DescribableTrait > create_metadata(). |
||
| 372 | * |
||
| 373 | * @param array $data Optional data to intialize the Metadata object with. |
||
| 374 | * @return MetadataInterface |
||
| 375 | */ |
||
| 376 | protected function createMetadata(array $data = null) |
||
| 384 | } |
||
| 385 |
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.