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 DateTimeProperty 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 DateTimeProperty, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
17 | class DateTimeProperty extends AbstractProperty |
||
18 | { |
||
19 | const DEFAULT_MIN = null; |
||
20 | const DEFAULT_MAX = null; |
||
21 | const DEFAULT_FORMAT = 'Y-m-d H:i:s'; |
||
22 | |||
23 | /** |
||
24 | * @var DateTimeInterface|null |
||
25 | */ |
||
26 | private $min = self::DEFAULT_MIN; |
||
27 | |||
28 | /** |
||
29 | * @var DateTimeInterface|null |
||
30 | */ |
||
31 | private $max = self::DEFAULT_MAX; |
||
32 | |||
33 | /** |
||
34 | * @var string |
||
35 | */ |
||
36 | private $format = self::DEFAULT_FORMAT; |
||
37 | |||
38 | /** |
||
39 | * @return string |
||
40 | */ |
||
41 | public function type() |
||
45 | |||
46 | /** |
||
47 | * Ensure multiple can not be true for DateTime property. |
||
48 | * |
||
49 | * @see AbstractProperty::setMultiple() |
||
50 | * |
||
51 | * @param boolean $multiple Multiple flag. |
||
52 | * @throws InvalidArgumentException If the multiple argument is true (must be false). |
||
53 | * @return self |
||
54 | */ |
||
55 | View Code Duplication | public function setMultiple($multiple) |
|
65 | |||
66 | /** |
||
67 | * Multiple is always false for DateTime property. |
||
68 | * |
||
69 | * @see AbstractProperty::getMultiple() |
||
70 | * |
||
71 | * @return boolean |
||
72 | */ |
||
73 | public function getMultiple() |
||
77 | |||
78 | /** |
||
79 | * Ensure `DateTime` object in val. |
||
80 | * |
||
81 | * @see AbstractProperty::parseOne() |
||
82 | * @see AbstractProperty::parseVal() |
||
83 | * |
||
84 | * @param string|DateTimeInterface $val The value to set. |
||
85 | * @return DateTimeInterface|null |
||
86 | */ |
||
87 | public function parseOne($val) |
||
91 | |||
92 | /** |
||
93 | * Convert `DateTime` to input-friendly string. |
||
94 | * |
||
95 | * @see AbstractProperty::inputVal() |
||
96 | * |
||
97 | * @param mixed $val The value to to convert for input. |
||
98 | * @param array $options Unused, optional options. |
||
99 | * @throws Exception If the date/time is invalid. |
||
100 | * @return string|null |
||
101 | */ |
||
102 | public function inputVal($val, array $options = []) |
||
113 | |||
114 | /** |
||
115 | * Convert `DateTime` to SQL-friendly string. |
||
116 | * |
||
117 | * @see StorablePropertyTrait::storageVal() |
||
118 | * |
||
119 | * @param string|DateTime $val Optional. Value to convert to storage format. |
||
120 | * @throws Exception If the date/time is invalid. |
||
121 | * @return string|null |
||
122 | */ |
||
123 | public function storageVal($val) |
||
139 | |||
140 | /** |
||
141 | * Format a date/time object to string. |
||
142 | * |
||
143 | * @see AbstractProperty::displayVal() |
||
144 | * |
||
145 | * @param mixed $val The value to to convert for display. |
||
146 | * @param array $options Optional display options. |
||
147 | * @return string |
||
148 | */ |
||
149 | public function displayVal($val, array $options = []) |
||
164 | |||
165 | /** |
||
166 | * @param string|DateTime|null $min The minimum allowed value. |
||
167 | * @throws InvalidArgumentException If the date/time is invalid. |
||
168 | * @return self |
||
169 | */ |
||
170 | View Code Duplication | public function setMin($min) |
|
196 | |||
197 | /** |
||
198 | * @return DateTimeInterface|null |
||
199 | */ |
||
200 | public function getMin() |
||
204 | |||
205 | /** |
||
206 | * @param string|DateTime|null $max The maximum allowed value. |
||
207 | * @throws InvalidArgumentException If the date/time is invalid. |
||
208 | * @return self |
||
209 | */ |
||
210 | View Code Duplication | public function setMax($max) |
|
236 | |||
237 | /** |
||
238 | * @return DateTimeInterface|null |
||
239 | */ |
||
240 | public function getMax() |
||
244 | |||
245 | /** |
||
246 | * @param string|null $format The date format. |
||
247 | * @throws InvalidArgumentException If the format is not a string. |
||
248 | * @return DateTimeProperty Chainable |
||
249 | */ |
||
250 | View Code Duplication | public function setFormat($format) |
|
263 | |||
264 | /** |
||
265 | * @return string |
||
266 | */ |
||
267 | public function getFormat() |
||
271 | |||
272 | /** |
||
273 | * @return array |
||
274 | */ |
||
275 | public function validationMethods() |
||
284 | |||
285 | /** |
||
286 | * @return boolean |
||
287 | */ |
||
288 | View Code Duplication | public function validateMin() |
|
300 | |||
301 | /** |
||
302 | * @return boolean |
||
303 | */ |
||
304 | View Code Duplication | public function validateMax() |
|
316 | |||
317 | /** |
||
318 | * @see StorablePropertyTrait::sqlType() |
||
319 | * @return string |
||
320 | */ |
||
321 | public function sqlType() |
||
325 | |||
326 | /** |
||
327 | * @see StorablePropertyTrait::sqlPdoType() |
||
328 | * @return integer |
||
329 | */ |
||
330 | public function sqlPdoType() |
||
334 | |||
335 | /** |
||
336 | * @param mixed $val Value to convert to DateTime. |
||
337 | * @throws InvalidArgumentException If the value is not a valid datetime. |
||
338 | * @return DateTimeInterface|null |
||
339 | */ |
||
340 | private function dateTimeVal($val) |
||
366 | |||
367 | /** |
||
368 | * @param integer|string $timestamp Timestamp. |
||
369 | * @return boolean |
||
370 | */ |
||
371 | private function isValidTimeStamp($timestamp) |
||
377 | } |
||
378 |
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.