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 Date 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 Date, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
33 | class Date implements DateTimeInterface |
||
34 | { |
||
35 | /** |
||
36 | * @var DateTime object warnings and errors |
||
37 | */ |
||
38 | protected static $lastErrors = array(); |
||
39 | |||
40 | /** |
||
41 | * @var DateTimeZone default timezone |
||
42 | */ |
||
43 | protected static $defaultTimezone; |
||
44 | |||
45 | /** |
||
46 | * @var string encoding to use for strftime() |
||
47 | */ |
||
48 | protected static $encoding = null; |
||
49 | |||
50 | /** |
||
51 | * @var int any GMT offset for ill configured servers (application timezone !== server timezone) |
||
52 | */ |
||
53 | protected static $gmtOffset = 0; |
||
54 | |||
55 | /** |
||
56 | * @var array custom defined datetime formats |
||
57 | */ |
||
58 | protected static $patterns = array( |
||
59 | ); |
||
60 | |||
61 | /** |
||
62 | * Returns the warnings and errors from the last parsing operation |
||
63 | * |
||
64 | * @return array array of warnings and errors found while parsing a date/time string. |
||
65 | */ |
||
66 | public static function getLastErrors() |
||
70 | |||
71 | /** |
||
72 | * Sets the default timezone, the current display timezone of the application |
||
73 | * |
||
74 | * @throws Exception if the timezone passed is not valid |
||
75 | * @return DateTimeZone |
||
76 | */ |
||
77 | public static function defaultTimezone($timezone = null) |
||
91 | |||
92 | /** |
||
93 | * Magic method that handles running code generated by var_export() |
||
94 | * |
||
95 | */ |
||
96 | public static function __set_state(Array $array) |
||
106 | |||
107 | /** |
||
108 | * @var DateTime object used internally to store the datetime |
||
109 | */ |
||
110 | protected $datetime; |
||
111 | |||
112 | /** |
||
113 | * Constructor, create a new Date object using the information passed |
||
114 | * |
||
115 | * @param string|int $time date/time as a UNIX timestamp or a string |
||
116 | * @param string|DateTimeZone $timezone timezone $time is in |
||
117 | * @param array $config any custom configuration for this object |
||
118 | * |
||
119 | * @throws Exception if the time passed is not valid |
||
120 | */ |
||
121 | public function __construct($time = "now", $timezone = null, Array $config = array()) |
||
190 | |||
191 | /** |
||
192 | */ |
||
193 | public function __wakeup() |
||
197 | |||
198 | /** |
||
199 | * Allows you to just put the object in a string and get it inserted in the default pattern |
||
200 | * |
||
201 | * @return bool|string the formatted date string on success or false on failure. |
||
202 | */ |
||
203 | public function __toString() |
||
207 | |||
208 | /** |
||
209 | * Returns new Date object formatted according to the specified format. The |
||
210 | * method supports both strptime() formats and DateTime formats |
||
211 | * |
||
212 | * @param string $format any format supported by DateTime, or a format name configured |
||
213 | * @param string $time string representing the time. |
||
214 | * @param string|DateTimeZone $time timezone, if null the default timezone will be used |
||
215 | * |
||
216 | * @throws Exception if the timezone passed is not valid |
||
217 | * @throws OutOfBoundsException if the input time passed is not valid |
||
218 | * |
||
219 | * @return bool|Date new Date instance, or false on failure |
||
220 | */ |
||
221 | public function createFromFormat($format = 'local', $time, $timezone = null) |
||
292 | |||
293 | /** |
||
294 | * Adds an amount of days, months, years, hours, minutes and seconds to the object |
||
295 | * |
||
296 | * @param int|DateInterval $interval either a number of seconds, or a DateInterval object |
||
297 | * |
||
298 | * @return bool|Date this object for chaining, or false on failure |
||
299 | */ |
||
300 | View Code Duplication | public function add($interval = null) |
|
322 | |||
323 | /** |
||
324 | * Subtracts an amount of days, months, years, hours, minutes and seconds to the object |
||
325 | * |
||
326 | * @param int|DateInterval $interval either a number of seconds, or a DateInterval object |
||
327 | * |
||
328 | * @return bool|Date this object for chaining, or false on failure |
||
329 | */ |
||
330 | View Code Duplication | public function sub($interval = null) |
|
352 | |||
353 | /** |
||
354 | * Alter the timestamp of a Date object by incrementing or decrementing |
||
355 | * |
||
356 | * @param string $modify any format accepted by strtotime(). |
||
357 | * |
||
358 | * @return bool|Date this object, or false on failure |
||
359 | */ |
||
360 | public function modify($modify) |
||
369 | |||
370 | /** |
||
371 | * (re)sets the date |
||
372 | * |
||
373 | * @param int $year Year |
||
374 | * @param int $month Month |
||
375 | * @param int $day Day |
||
376 | * |
||
377 | * @return bool|Date this object, or false on failure |
||
378 | */ |
||
379 | public function setDate($year, $month, $day) |
||
388 | |||
389 | /** |
||
390 | * (re)sets the ISO date |
||
391 | * |
||
392 | * @param int $year Year |
||
393 | * @param int $week Week |
||
394 | * @param int $day Offset of the first day of the week, base 1 |
||
395 | * |
||
396 | * @return bool|Date this object, or false on failure |
||
397 | */ |
||
398 | public function setISODate($year, $week, $day = 1) |
||
407 | |||
408 | /** |
||
409 | * (re)sets the time |
||
410 | * |
||
411 | * @param int $hour Hour |
||
412 | * @param int $minute Minute |
||
413 | * @param int $second Second |
||
414 | * |
||
415 | * @return bool|Date this object, or false on failure |
||
416 | */ |
||
417 | public function setTime($hour, $minute, $second = 0) |
||
426 | |||
427 | /** |
||
428 | * (re)sets the date and time based on an Unix timestamp |
||
429 | * |
||
430 | * @param int unixTimestamp unix timestamp |
||
431 | * |
||
432 | * @return bool|Date this object, or false on failure |
||
433 | */ |
||
434 | public function setTimestamp($unixTimestamp) |
||
443 | |||
444 | /** |
||
445 | * (re)sets the time zone for the DateTime object |
||
446 | * |
||
447 | * @param string|DateTimeZone $timezone New timezone, or null for default timezone |
||
448 | * |
||
449 | * @throws Exception if the timezone string passed is not valid |
||
450 | * @return Date this object |
||
451 | */ |
||
452 | public function setTimezone($timezone) |
||
470 | |||
471 | /** |
||
472 | * Returns the difference between this objects time and anothers |
||
473 | * |
||
474 | * @param DateTimeInterface $datetime2 Other DateTimeInterface object to compare against |
||
475 | * @param bool $absolute true if the interval must be forced to be positive |
||
476 | * |
||
477 | * @return bool|DateInterval object defining the difference between the two, or false on failure |
||
478 | */ |
||
479 | public function diff($datetime2, $absolute = false) |
||
490 | |||
491 | /** |
||
492 | * Returns date formatted according to given format |
||
493 | * |
||
494 | * @param string $format any format supported by DateTime, or a format name configured |
||
495 | * |
||
496 | * @return bool|string the formatted date string on success or false on failure. |
||
497 | */ |
||
498 | public function format($format = 'local', $timezone = null) |
||
567 | |||
568 | /** |
||
569 | * Returns the internal DateTime object |
||
570 | * |
||
571 | * @return DateTime the internal DateTime object |
||
572 | */ |
||
573 | public function getDateTime() |
||
577 | |||
578 | /** |
||
579 | * Returns the timezone offset in seconds from UTC |
||
580 | * |
||
581 | * @return bool|int the timezone offset in seconds from UTC on success or false on failure. |
||
582 | */ |
||
583 | public function getOffset() |
||
587 | |||
588 | /** |
||
589 | * Returns the Unix timestamp |
||
590 | * |
||
591 | * @return int the Unix timestamp representing the date. |
||
592 | */ |
||
593 | public function getTimestamp() |
||
597 | |||
598 | /** |
||
599 | * Return the time zone of this object |
||
600 | * |
||
601 | * @return DateTimeZone the defined timezone |
||
602 | */ |
||
603 | public function getTimezone() |
||
607 | } |
||
608 |
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.