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 EntityProperty 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 EntityProperty, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 19 | class EntityProperty |
||
| 20 | { |
||
| 21 | |||
| 22 | const STRING = 'string'; |
||
| 23 | const INTEGER = 'integer'; |
||
| 24 | const FLOAT = 'float'; |
||
| 25 | const DOUBLE = 'double'; |
||
| 26 | const BOOL = 'bool'; |
||
| 27 | |||
| 28 | const DATE = 'date'; |
||
| 29 | const DATETIME = 'datetime'; |
||
| 30 | |||
| 31 | const VARBINARY = 'varbinary'; |
||
| 32 | |||
| 33 | const UUID = 'uuid'; |
||
| 34 | |||
| 35 | const ENUM = 'enum'; |
||
| 36 | |||
| 37 | /** |
||
| 38 | * @var string Entity property type |
||
| 39 | */ |
||
| 40 | protected $type; |
||
| 41 | |||
| 42 | /** |
||
| 43 | * @var int Entity property max length |
||
| 44 | */ |
||
| 45 | protected $length; |
||
| 46 | |||
| 47 | /** |
||
| 48 | * @var array Allowed values |
||
| 49 | */ |
||
| 50 | protected $values; |
||
| 51 | |||
| 52 | /** |
||
| 53 | * @param string|array $type |
||
| 54 | */ |
||
| 55 | 13 | public function __construct($type) |
|
| 84 | |||
| 85 | /** |
||
| 86 | * Set entity property type |
||
| 87 | * |
||
| 88 | * @param string $type |
||
| 89 | * |
||
| 90 | * @throws EntityPropertyTypeNonexistentException |
||
| 91 | */ |
||
| 92 | 13 | protected function setType(string $type) |
|
| 100 | |||
| 101 | /** |
||
| 102 | * Validate value for entity property |
||
| 103 | * |
||
| 104 | * @param mixed $value Entity property value |
||
| 105 | * |
||
| 106 | * @return bool TRUE if valid, otherwise FALSE |
||
| 107 | * |
||
| 108 | * @throws EntityPropertyTypeNotImplementedException If entity property type is not implemented |
||
| 109 | * @throws EntityPropertyValueExceedingLengthException If value is exceeding allowed length for entity property |
||
| 110 | * @throws InvalidENUMValueForEntityPropertyException If ENUM value is invalid for entity property |
||
| 111 | * @throws InvalidUUIDValueForEntityPropertyException If UUID value is invalid for entity property |
||
| 112 | * @throws InvalidValueTypeForEntityPropertyException If value is invalid for entity property |
||
| 113 | */ |
||
| 114 | public function validateValue($value): bool |
||
| 213 | |||
| 214 | /** |
||
| 215 | * Format value according to entity property type |
||
| 216 | * |
||
| 217 | * @param mixed $value Value |
||
| 218 | * |
||
| 219 | * @return mixed Value |
||
| 220 | * |
||
| 221 | * @throws EntityPropertyTypeNotImplementedException If entity property type is not implemented |
||
| 222 | */ |
||
| 223 | public function formatValueForEntity($value) |
||
| 266 | |||
| 267 | /** |
||
| 268 | * Format value for insertion into the database |
||
| 269 | * |
||
| 270 | * @param mixed $value Value |
||
| 271 | * |
||
| 272 | * @return mixed Value |
||
| 273 | */ |
||
| 274 | public function formatValueForDatabase($value) |
||
| 294 | } |
||
| 295 |
This check looks for accesses to local static members using the fully qualified name instead of
self::.While this is perfectly valid, the fully qualified name of
Certificate::TRIPLEDES_CBCcould just as well be replaced byself::TRIPLEDES_CBC. Referencing local members withself::assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.