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 TranslationManager 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 TranslationManager, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
45 | class TranslationManager |
||
46 | { |
||
47 | const MESSAGE = 'msg'; |
||
48 | const NUMBER = 'num'; |
||
49 | const CURRENCY = 'cur'; |
||
50 | const DATETIME = 'date'; |
||
51 | |||
52 | /** |
||
53 | * @var Context A Context instance. |
||
54 | */ |
||
55 | protected $context = null; |
||
56 | |||
57 | /** |
||
58 | * @var array An array of the translator instances for the domains. |
||
59 | */ |
||
60 | protected $translators = array(); |
||
61 | |||
62 | /** |
||
63 | * @var Locale The current locale. |
||
64 | */ |
||
65 | protected $currentLocale = null; |
||
66 | |||
67 | /** |
||
68 | * @var string The original locale identifier given to this instance. |
||
69 | */ |
||
70 | protected $givenLocaleIdentifier = null; |
||
71 | |||
72 | /** |
||
73 | * @var string The identifier of the current locale. |
||
74 | */ |
||
75 | protected $currentLocaleIdentifier = null; |
||
76 | |||
77 | /** |
||
78 | * @var string The default locale identifier. |
||
79 | */ |
||
80 | protected $defaultLocaleIdentifier = null; |
||
81 | |||
82 | /** |
||
83 | * @var string The default domain which shall be used for translation. |
||
84 | */ |
||
85 | protected $defaultDomain = null; |
||
86 | |||
87 | /** |
||
88 | * @var array The available locales which have been defined in the |
||
89 | * translation.xml config file. |
||
90 | */ |
||
91 | protected $availableConfigLocales = array(); |
||
92 | |||
93 | /** |
||
94 | * @var array All available locales. Just stores the info for lazyload. |
||
95 | */ |
||
96 | protected $availableLocales = array(); |
||
97 | |||
98 | /** |
||
99 | * @var array A cache for locale instances. |
||
100 | */ |
||
101 | protected $localeCache = array(); |
||
102 | |||
103 | /** |
||
104 | * @var array A cache for locale identifiers resolved from a string. |
||
105 | */ |
||
106 | protected $localeIdentifierCache = array(); |
||
107 | |||
108 | /** |
||
109 | * @var array A cache for the data of the available locales. |
||
110 | */ |
||
111 | protected $localeDataCache = array(); |
||
112 | |||
113 | /** |
||
114 | * @var array The supplemental data from the cldr |
||
115 | */ |
||
116 | protected $supplementalData = array(); |
||
117 | |||
118 | /** |
||
119 | * @var array The list of available time zones. |
||
120 | */ |
||
121 | protected $timeZoneList = array(); |
||
122 | |||
123 | /** |
||
124 | * @var array A cache for the time zone instances. |
||
125 | */ |
||
126 | protected $timeZoneCache = array(); |
||
127 | |||
128 | /** |
||
129 | * @var string The default time zone. If not set the timezone php |
||
130 | * will be used as default. |
||
131 | */ |
||
132 | protected $defaultTimeZone = null; |
||
133 | |||
134 | /** |
||
135 | * Initialize this TranslationManager. |
||
136 | * |
||
137 | * @param Context $context The current application context. |
||
138 | * @param array $parameters An associative array of initialization parameters. |
||
139 | * |
||
140 | * @author Dominik del Bondio <[email protected]> |
||
141 | * @since 0.11.0 |
||
142 | */ |
||
143 | public function initialize(Context $context, array $parameters = array()) |
||
165 | |||
166 | /** |
||
167 | * Do any necessary startup work after initialization. |
||
168 | * |
||
169 | * This method is not called directly after initialize(). |
||
170 | * |
||
171 | * @author David Zülke <[email protected]> |
||
172 | * @since 0.11.0 |
||
173 | */ |
||
174 | public function startup() |
||
177 | |||
178 | /** |
||
179 | * Execute the shutdown procedure. |
||
180 | * |
||
181 | * @author David Zülke <[email protected]> |
||
182 | * @since 0.11.0 |
||
183 | */ |
||
184 | public function shutdown() |
||
187 | |||
188 | /** |
||
189 | * Retrieve the current application context. |
||
190 | * |
||
191 | * @return Context The current Context instance. |
||
192 | * |
||
193 | * @author Dominik del Bondio <[email protected]> |
||
194 | * @since 0.11.0 |
||
195 | */ |
||
196 | final public function getContext() |
||
200 | |||
201 | /** |
||
202 | * Returns the list of available locales. |
||
203 | * |
||
204 | * @author David Zülke <[email protected]> |
||
205 | * @since 0.11.0 |
||
206 | */ |
||
207 | public function getAvailableLocales() |
||
211 | |||
212 | /** |
||
213 | * Sets the current locale. |
||
214 | * |
||
215 | * @param string $identifier The locale identifier. |
||
216 | * |
||
217 | * @author Dominik del Bondio <[email protected]> |
||
218 | * @since 0.11.0 |
||
219 | */ |
||
220 | public function setLocale($identifier) |
||
228 | |||
229 | /** |
||
230 | * Retrieve the current locale. |
||
231 | * |
||
232 | * @return Locale The current locale. |
||
233 | * |
||
234 | * @author Dominik del Bondio <[email protected]> |
||
235 | * @since 0.11.0 |
||
236 | */ |
||
237 | public function getCurrentLocale() |
||
242 | |||
243 | /** |
||
244 | * Retrieve the current locale identifier. This may not necessarily match |
||
245 | * what has be given to setLocale() but instead the identifier of the closest |
||
246 | * match from the available locales. |
||
247 | * |
||
248 | * @return string The locale identifier. |
||
249 | * |
||
250 | * @author Dominik del Bondio <[email protected]> |
||
251 | * @since 0.11.0 |
||
252 | */ |
||
253 | public function getCurrentLocaleIdentifier() |
||
257 | |||
258 | /** |
||
259 | * Retrieve the default locale. |
||
260 | * |
||
261 | * @return Locale The current default. |
||
262 | * |
||
263 | * @author David Zülke <[email protected]> |
||
264 | * @since 0.11.0 |
||
265 | */ |
||
266 | public function getDefaultLocale() |
||
270 | |||
271 | /** |
||
272 | * Retrieve the default locale identifier. |
||
273 | * |
||
274 | * @return string The default locale identifier. |
||
275 | * |
||
276 | * @author David Zülke <[email protected]> |
||
277 | * @since 0.11.0 |
||
278 | */ |
||
279 | public function getDefaultLocaleIdentifier() |
||
283 | |||
284 | /** |
||
285 | * Sets the default domain. |
||
286 | * |
||
287 | * @param string $domain The new default domain. |
||
288 | * |
||
289 | * @author Dominik del Bondio <[email protected]> |
||
290 | * @since 0.11.0 |
||
291 | */ |
||
292 | public function setDefaultDomain($domain) |
||
296 | |||
297 | /** |
||
298 | * Retrieve the default domain. |
||
299 | * |
||
300 | * @return string The default domain. |
||
301 | * |
||
302 | * @author Dominik del Bondio <[email protected]> |
||
303 | * @since 0.11.0 |
||
304 | */ |
||
305 | public function getDefaultDomain() |
||
309 | |||
310 | /** |
||
311 | * Formats a date in the current locale. |
||
312 | * |
||
313 | * @param mixed $date The date to be formatted. |
||
314 | * @param string $domain The domain in which the date should be formatted. |
||
315 | * @param Locale $locale The locale which should be used for formatting. |
||
316 | * Defaults to the currently active locale. |
||
317 | * |
||
318 | * @return string The formatted date. |
||
319 | * |
||
320 | * @author Dominik del Bondio <[email protected]> |
||
321 | * @since 0.11.0 |
||
322 | */ |
||
323 | View Code Duplication | public function _d($date, $domain = null, $locale = null) |
|
344 | |||
345 | /** |
||
346 | * Formats a currency amount in the current locale. |
||
347 | * |
||
348 | * @param mixed $number The number to be formatted. |
||
349 | * @param string $domain The domain in which the amount should be formatted. |
||
350 | * @param Locale $locale The locale which should be used for formatting. |
||
351 | * Defaults to the currently active locale. |
||
352 | * |
||
353 | * @return string The formatted number. |
||
354 | * |
||
355 | * @author Dominik del Bondio <[email protected]> |
||
356 | * @since 0.11.0 |
||
357 | */ |
||
358 | View Code Duplication | public function _c($number, $domain = null, $locale = null) |
|
379 | |||
380 | /** |
||
381 | * Formats a number in the current locale. |
||
382 | * |
||
383 | * @param mixed $number The number to be formatted. |
||
384 | * @param string $domain The domain in which the number should be formatted. |
||
385 | * @param Locale $locale The locale which should be used for formatting. |
||
386 | * Defaults to the currently active locale. |
||
387 | * |
||
388 | * @return string The formatted number. |
||
389 | * |
||
390 | * @author Dominik del Bondio <[email protected]> |
||
391 | * @since 0.11.0 |
||
392 | */ |
||
393 | View Code Duplication | public function _n($number, $domain = null, $locale = null) |
|
414 | |||
415 | /** |
||
416 | * Translate a message into the current locale. |
||
417 | * |
||
418 | * @param mixed $message The message. |
||
419 | * @param string $domain The domain in which the translation should be done. |
||
420 | * @param Locale $locale The locale which should be used for formatting. |
||
421 | * Defaults to the currently active locale. |
||
422 | * @param array $parameters The parameters which should be used for sprintf on |
||
423 | * the translated string. |
||
424 | * |
||
425 | * @return string The translated message. |
||
426 | * |
||
427 | * @author Dominik del Bondio <[email protected]> |
||
428 | * @since 0.11.0 |
||
429 | */ |
||
430 | public function _($message, $domain = null, $locale = null, array $parameters = null) |
||
454 | |||
455 | /** |
||
456 | * Translate a singular/plural message into the current locale. |
||
457 | * |
||
458 | * @param string $singularMessage The message for the singular form. |
||
459 | * @param string $pluralMessage The message for the plural form. |
||
460 | * @param int $amount The amount for which the translation should happen. |
||
461 | * @param string $domain The domain in which the translation should be done. |
||
462 | * @param Locale $locale The locale which should be used for formatting. |
||
463 | * Defaults to the currently active locale. |
||
464 | * @param array $parameters The parameters which should be used for sprintf on |
||
465 | * the translated string. |
||
466 | * |
||
467 | * @return string The translated message. |
||
468 | * |
||
469 | * @author David Zülke <[email protected]> |
||
470 | * @since 0.11.0 |
||
471 | */ |
||
472 | public function __($singularMessage, $pluralMessage, $amount, $domain = null, $locale = null, array $parameters = null) |
||
476 | |||
477 | /** |
||
478 | * Returns the translators for a given domain. |
||
479 | * |
||
480 | * @param string $domain The domain. |
||
481 | * @param string $domainExtra The remaining part in the domain which didn't match |
||
482 | * @param string $type The type of the translator |
||
483 | * |
||
484 | * @return TranslatorInterface An array of translators for the given domain |
||
485 | * |
||
486 | * @author Dominik del Bondio <[email protected]> |
||
487 | * @since 0.11.0 |
||
488 | */ |
||
489 | protected function getTranslators(&$domain, &$domainExtra, $type = null) |
||
509 | |||
510 | /** |
||
511 | * Returns the translators for a given domain and type. The domain can contain |
||
512 | * any extra parts which will be ignored. Will return null when no translator |
||
513 | * is defined. |
||
514 | * |
||
515 | * @param string $domain The domain. |
||
516 | * @param string $type The type of the translator. |
||
517 | * |
||
518 | * @return TranslatorInterface The translator instance. |
||
519 | * |
||
520 | * @author Dominik del Bondio <[email protected]> |
||
521 | * @since 0.11.0 |
||
522 | */ |
||
523 | public function getDomainTranslator($domain, $type) |
||
532 | |||
533 | /** |
||
534 | * Returns the translator filters for a given domain. |
||
535 | * |
||
536 | * @param string $message The message. |
||
537 | * @param string $domain The domain (w/o extra parts). |
||
538 | * @param string $type The type. |
||
539 | * |
||
540 | * @return string The new message. |
||
541 | * |
||
542 | * @author David Zülke <[email protected]> |
||
543 | * @since 0.11.0 |
||
544 | */ |
||
545 | protected function applyFilters($message, $domain, $type = self::MESSAGE) |
||
555 | |||
556 | /** |
||
557 | * Loads the available locales into the instance variable |
||
558 | * |
||
559 | * @author Dominik del Bondio <[email protected]> |
||
560 | * @since 0.11.0 |
||
561 | */ |
||
562 | protected function loadAvailableLocales() |
||
566 | |||
567 | /** |
||
568 | * Lazy loads the current locale if necessary. |
||
569 | * |
||
570 | * @author Dominik del Bondio <[email protected]> |
||
571 | * @since 0.11.0 |
||
572 | */ |
||
573 | protected function loadCurrentLocale() |
||
598 | |||
599 | /** |
||
600 | * Loads the supplemental data into the instance variable |
||
601 | * |
||
602 | * @author Dominik del Bondio <[email protected]> |
||
603 | * @since 0.11.0 |
||
604 | */ |
||
605 | protected function loadSupplementalData() |
||
609 | |||
610 | /** |
||
611 | * Loads the time zone data. |
||
612 | * |
||
613 | * @author Dominik del Bondio <[email protected]> |
||
614 | * @since 0.11.0 |
||
615 | */ |
||
616 | protected function loadTimeZoneData() |
||
620 | |||
621 | /** |
||
622 | * Returns all the identifiers of the available locales which match the given |
||
623 | * locale identifier. |
||
624 | * |
||
625 | * @param string $identifier A locale identifier |
||
626 | * |
||
627 | * @return array The actual locale identifiers of the available locales. |
||
628 | * |
||
629 | * @author Dominik del Bondio <[email protected]> |
||
630 | * @author David Zülke <[email protected]> |
||
631 | * @author Thomas Bachem <[email protected]> |
||
632 | */ |
||
633 | public function getMatchingLocaleIdentifiers($identifier) |
||
668 | |||
669 | /** |
||
670 | * Returns the identifier of the available locale which matches the given |
||
671 | * locale identifier most. |
||
672 | * |
||
673 | * @param string $identifier A locale identifier |
||
674 | * |
||
675 | * @return string The actual locale identifier of the available locale. |
||
676 | * |
||
677 | * @author Dominik del Bondio <[email protected]> |
||
678 | * @author David Zülke <[email protected]> |
||
679 | * @since 0.11.0 |
||
680 | */ |
||
681 | public function getLocaleIdentifier($identifier) |
||
701 | |||
702 | /** |
||
703 | * Returns a new AgaviLocale object from the given identifier. |
||
704 | * |
||
705 | * @param string $identifier The locale identifier |
||
706 | * @param bool $forceNew Force a new instance even if an identical one exists. |
||
707 | * |
||
708 | * @return Locale The locale instance which matches the available |
||
709 | * locales most. |
||
710 | * |
||
711 | * @author Dominik del Bondio <[email protected]> |
||
712 | * @author David Zülke <[email protected]> |
||
713 | * @since 0.11.0 |
||
714 | */ |
||
715 | public function getLocale($identifier, $forceNew = false) |
||
798 | |||
799 | /** |
||
800 | * Sets the default time zone. |
||
801 | * |
||
802 | * @param string $id The timezone identifier |
||
803 | * |
||
804 | * @author Dominik del Bondio <[email protected]> |
||
805 | * @since 0.11.0 |
||
806 | */ |
||
807 | public function setDefaultTimeZone($id) |
||
811 | |||
812 | /** |
||
813 | * Gets the instance of the current timezone. |
||
814 | * |
||
815 | * @return TimeZone The current timezone instance. |
||
816 | * |
||
817 | * @author Dominik del Bondio <[email protected]> |
||
818 | * @since 0.11.0 |
||
819 | * |
||
820 | * @deprecated Superseded by TranslationManager::getDefaultTimeZone() |
||
821 | */ |
||
822 | public function getCurrentTimeZone() |
||
826 | |||
827 | /** |
||
828 | * Get the default timezone instance. |
||
829 | * |
||
830 | * @return TimeZone The default timezone instance. |
||
831 | * |
||
832 | * @author David Zülke <[email protected]> |
||
833 | * @since 1.0.0 |
||
834 | */ |
||
835 | public function getDefaultTimeZone() |
||
839 | |||
840 | /** |
||
841 | * Gets the territory id a (resolved) timezone id belongs to. |
||
842 | * |
||
843 | * @param string $id The resolved timezone id. |
||
844 | * @param bool $hasMultipleZones Will receive whether the territory has multiple |
||
845 | * time zones |
||
846 | * |
||
847 | * @return string The territory identifier or null. |
||
848 | * |
||
849 | * @author Dominik del Bondio <[email protected]> |
||
850 | * @since 0.11.0 |
||
851 | */ |
||
852 | public function getTimeZoneTerritory($id, &$hasMultipleZones = false) |
||
862 | |||
863 | /** |
||
864 | * Resolved the given timezone identifier to its 'real' timezone id. |
||
865 | * |
||
866 | * This provides the same functionality like |
||
867 | * $tm->createTimeZone(id)->getResolvedId() with the difference, that using |
||
868 | * this method will not create a new timezone instance and look up the |
||
869 | * resolved id there, but instead directly returns the resolved id by using |
||
870 | * a simple lookup. |
||
871 | * |
||
872 | * @param int $id The timezone id to be resolved |
||
873 | * @return int The resolved timezone id |
||
874 | * |
||
875 | * @author Dominik del Bondio <[email protected]> |
||
876 | * @since 1.0.0 |
||
877 | */ |
||
878 | public function resolveTimeZoneId($id) |
||
888 | |||
889 | |||
890 | /** |
||
891 | * Creates a new timezone instance for the given identifier. |
||
892 | * |
||
893 | * Please note that this method caches the results for each identifier, so |
||
894 | * if you plan to modify the timezones returned by this method you need to |
||
895 | * clone them first. Alternatively you can set the cache parameter to false, |
||
896 | * but this will mean the data for this timezone will be loaded from the |
||
897 | * hdd again. |
||
898 | * |
||
899 | * @return TimeZone The timezone instance for the given id. |
||
900 | * |
||
901 | * @author Dominik del Bondio <[email protected]> |
||
902 | * @since 0.11.0 |
||
903 | */ |
||
904 | public function createTimeZone($id, $cache = true) |
||
935 | |||
936 | /** |
||
937 | * Creates a new calendar instance with the current time set. |
||
938 | * |
||
939 | * @param mixed $type This can be either a Locale, a TimeZone or |
||
940 | * a string specifying the calendar type. |
||
941 | * |
||
942 | * @return Calendar The current timezone instance. |
||
943 | * |
||
944 | * @author Dominik del Bondio <[email protected]> |
||
945 | * @since 0.11.0 |
||
946 | */ |
||
947 | public function createCalendar($type = null) |
||
1020 | |||
1021 | /** |
||
1022 | * Creates a new date format instance with the given format. |
||
1023 | * |
||
1024 | * @param string $format The date format. |
||
1025 | * |
||
1026 | * @return DateFormat The dateformat instance. |
||
1027 | * |
||
1028 | * @author Dominik del Bondio <[email protected]> |
||
1029 | * @since 0.11.0 |
||
1030 | */ |
||
1031 | public function createDateFormat($format) |
||
1037 | |||
1038 | |||
1039 | /** |
||
1040 | * Returns the stored information from the ldml supplemental data about a |
||
1041 | * territory. |
||
1042 | * |
||
1043 | * @param string $country The uppercase 2 letter country iso code. |
||
1044 | * |
||
1045 | * @return array The data. |
||
1046 | * |
||
1047 | * @author Dominik del Bondio <[email protected]> |
||
1048 | * @since 0.11.0 |
||
1049 | */ |
||
1050 | public function getTerritoryData($country) |
||
1057 | |||
1058 | /** |
||
1059 | * Returns an array containing digits and rounding information for a currency. |
||
1060 | * |
||
1061 | * @param string $currency The uppercase 3 letter currency iso code. |
||
1062 | * |
||
1063 | * @return array The data. |
||
1064 | * |
||
1065 | * @author Dominik del Bondio <[email protected]> |
||
1066 | * @since 0.11.0 |
||
1067 | */ |
||
1068 | public function getCurrencyFraction($currency) |
||
1075 | } |
||
1076 |
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.