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 AppConfiguration 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 AppConfiguration, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
26 | final class AppConfiguration |
||
27 | { |
||
28 | const DIRECTION_LEFT_TO_RIGHT = "ltr"; |
||
29 | const DIRECTION_RIGHT_TO_LEFT = "rtl"; |
||
30 | const DIRECTION_AUTO = "auto"; |
||
31 | |||
32 | const DISPLAY_FULLSCREEN = "fullscreen"; |
||
33 | const DISPLAY_STANDALONE = "standalone"; |
||
34 | const DISPLAY_MINIMAL_UI = "minimal-ui"; |
||
35 | const DISPLAY_BROWSER = "browser"; |
||
36 | |||
37 | const ORIENTATION_ANY = "any"; |
||
38 | const ORIENTATION_NATURAL = "natural"; |
||
39 | const ORIENTATION_LANDSCAPE = "landscape"; |
||
40 | const ORIENTATION_LANDSCAPE_PRIMARY = "landscape-primary"; |
||
41 | const ORIENTATION_LANDSCAPE_SECONDARY = "landscape-secondary"; |
||
42 | const ORIENTATION_PORTRAIT = "portrait"; |
||
43 | const ORIENTATION_PORTRAIT_PRIMARY = "portrait-primary"; |
||
44 | const ORIENTATION_PORTRAIT_SECONDARY = "portrait-secondary"; |
||
45 | |||
46 | const PLATFORM_ANDROID = "android"; |
||
47 | const PLATFORM_IOS = "ios"; |
||
48 | const PLATFORM_WEB = "web"; |
||
49 | |||
50 | private $backgroundColor; |
||
51 | private $description; |
||
52 | private $direction; |
||
53 | private $display; |
||
54 | private $icons = [ ]; |
||
55 | private $language; |
||
56 | private $name; |
||
57 | private $orientation; |
||
58 | private $scope; |
||
59 | private $screenshots = [ ]; |
||
60 | private $shortName; |
||
61 | private $startUrl; |
||
62 | private $themeColor; |
||
63 | |||
64 | private $manifestUrl; |
||
65 | |||
66 | /** |
||
67 | * Returns the manifest URL. |
||
68 | * |
||
69 | * @return string |
||
70 | */ |
||
71 | public function getManifestUrl() |
||
79 | |||
80 | /** |
||
81 | * Sets the manifest URL. You MUST set one for proper deployment. |
||
82 | * |
||
83 | * @param string $url |
||
84 | * |
||
85 | * @return AppConfiguration |
||
86 | */ |
||
87 | public function setManifestUrl($url) |
||
92 | |||
93 | /** |
||
94 | * Returns the expected background color for the web application. |
||
95 | * |
||
96 | * @return string|null |
||
97 | */ |
||
98 | 2 | public function getBackgroundColor() |
|
102 | |||
103 | /** |
||
104 | * Sets the expected background color for the web application. Will also be used by Chrome 47 and later to |
||
105 | * auto-generate a splash screen. |
||
106 | * |
||
107 | * <p> |
||
108 | * This value repeats what is already available in the application stylesheet, but can be used by browsers to draw |
||
109 | * the background color of a web application when the manifest is available before the style sheet has loaded. |
||
110 | * |
||
111 | * <p> |
||
112 | * This creates a smooth transition between launching the web application and loading the application's content. |
||
113 | * |
||
114 | * @param string $backgroundColor |
||
115 | * |
||
116 | * @return AppConfiguration |
||
117 | * |
||
118 | * @see https://www.w3.org/TR/appmanifest/#background_color-member |
||
119 | */ |
||
120 | 2 | public function setBackgroundColor($backgroundColor) |
|
125 | |||
126 | /** |
||
127 | * Returns the general description of what the web application does. |
||
128 | * |
||
129 | * @return string|null |
||
130 | */ |
||
131 | 2 | public function getDescription() |
|
135 | |||
136 | /** |
||
137 | * Sets a general description of what the web application does. |
||
138 | * |
||
139 | * @param string $description |
||
140 | * |
||
141 | * @return AppConfiguration |
||
142 | * |
||
143 | * @see https://www.w3.org/TR/appmanifest/#description-member |
||
144 | */ |
||
145 | 2 | public function setDescription($description) |
|
150 | |||
151 | /** |
||
152 | * Returns the primary text direction for the {@link $name}, {@link $shortName}, and {@link $description} members. |
||
153 | * |
||
154 | * @return string|null |
||
155 | */ |
||
156 | 1 | public function getDirection() |
|
160 | |||
161 | /** |
||
162 | * Sets the primary text direction for the {@link $name}, {@link $shortName}, and {@link $description} members. |
||
163 | * |
||
164 | * @param string $direction One of AppConfiguration::DIRECTION_* constants. |
||
165 | * |
||
166 | * @return AppConfiguration |
||
167 | * |
||
168 | * @see https://www.w3.org/TR/appmanifest/#dir-member |
||
169 | */ |
||
170 | 2 | View Code Duplication | public function setDirection($direction) |
186 | |||
187 | /** |
||
188 | * Returns the preferred display mode. |
||
189 | * |
||
190 | * @return string|null |
||
191 | */ |
||
192 | 2 | public function getDisplay() |
|
196 | |||
197 | /** |
||
198 | * Sets the preferred display mode. |
||
199 | * |
||
200 | * @param string $display One of AppConfiguration::DISPLAY_* constants. |
||
201 | * |
||
202 | * @return AppConfiguration |
||
203 | * |
||
204 | * @see https://www.w3.org/TR/appmanifest/#display-member |
||
205 | */ |
||
206 | 2 | View Code Duplication | public function setDisplay($display) |
223 | |||
224 | /** |
||
225 | * Returns an array of all application icons. |
||
226 | * |
||
227 | * @return Image[] |
||
228 | */ |
||
229 | 2 | public function getIcons() |
|
233 | |||
234 | /** |
||
235 | * Adds an application icon. |
||
236 | * |
||
237 | * @param Image $icon |
||
238 | * |
||
239 | * @return AppConfiguration |
||
240 | * |
||
241 | * @see https://www.w3.org/TR/appmanifest/#icons-member |
||
242 | */ |
||
243 | 2 | public function addIcon(Image $icon) |
|
248 | |||
249 | /** |
||
250 | * Returns the application's language. |
||
251 | * |
||
252 | * @return string|null |
||
253 | */ |
||
254 | 2 | public function getLanguage() |
|
258 | |||
259 | /** |
||
260 | * Sets the application's language. Must be a RFC5646 compliant string. |
||
261 | * |
||
262 | * @param string $language |
||
263 | * |
||
264 | * @return AppConfiguration |
||
265 | * |
||
266 | * @see https://www.w3.org/TR/appmanifest/#lang-member |
||
267 | */ |
||
268 | 2 | public function setLanguage($language) |
|
273 | |||
274 | /** |
||
275 | * Returns the application's name. |
||
276 | * |
||
277 | * @return string|null |
||
278 | */ |
||
279 | 2 | public function getName() |
|
283 | |||
284 | /** |
||
285 | * Sets the application's name. |
||
286 | * |
||
287 | * @param string $name |
||
288 | * |
||
289 | * @return AppConfiguration |
||
290 | * |
||
291 | * @see https://www.w3.org/TR/appmanifest/#name-member |
||
292 | */ |
||
293 | 2 | public function setName($name) |
|
298 | |||
299 | /** |
||
300 | * Returns the default device orientation. |
||
301 | * |
||
302 | * @return string|null |
||
303 | */ |
||
304 | 2 | public function getOrientation() |
|
308 | |||
309 | /** |
||
310 | * Sets the default device orientation.. |
||
311 | * |
||
312 | * @param string $orientation One of AppConfiguration::ORIENTATION_* constants. |
||
313 | * |
||
314 | * @return AppConfiguration |
||
315 | * |
||
316 | * @see https://www.w3.org/TR/appmanifest/#orientation-member |
||
317 | */ |
||
318 | 2 | public function setOrientation($orientation) |
|
339 | |||
340 | /** |
||
341 | * Returns the application's navigation scope. |
||
342 | * |
||
343 | * @return string|null |
||
344 | */ |
||
345 | 2 | public function getScope() |
|
349 | |||
350 | /** |
||
351 | * Sets the application's navigation scope. |
||
352 | * |
||
353 | * <p> |
||
354 | * This basically restricts what web pages can be viewed while the manifest is applied. If the user navigates the |
||
355 | * application outside the scope, it returns to being a normal web page. |
||
356 | * |
||
357 | * @param string $scope |
||
358 | * |
||
359 | * @return AppConfiguration |
||
360 | * |
||
361 | * @see https://www.w3.org/TR/appmanifest/#scope-member |
||
362 | */ |
||
363 | 2 | public function setScope($scope) |
|
368 | |||
369 | /** |
||
370 | * Returns an array of all application screenshots. |
||
371 | * |
||
372 | * @return Image[] |
||
373 | */ |
||
374 | 2 | public function getScreenshots() |
|
378 | |||
379 | /** |
||
380 | * Adds an application screenshot. |
||
381 | * |
||
382 | * @param Image $screenshot |
||
383 | * |
||
384 | * @return AppConfiguration |
||
385 | * |
||
386 | * @see https://www.w3.org/TR/appmanifest/#screenshots-member |
||
387 | */ |
||
388 | 2 | public function addScreenshot(Image $screenshot) |
|
393 | |||
394 | /** |
||
395 | * Returns the application's short name. |
||
396 | * |
||
397 | * @return string|null |
||
398 | */ |
||
399 | 2 | public function getShortName() |
|
403 | |||
404 | /** |
||
405 | * Sets the application's short name. |
||
406 | * |
||
407 | * @param string $shortName |
||
408 | * |
||
409 | * @return AppConfiguration |
||
410 | * |
||
411 | * @see https://www.w3.org/TR/appmanifest/#short_name-member |
||
412 | */ |
||
413 | 2 | public function setShortName($shortName) |
|
418 | |||
419 | /** |
||
420 | * Returns the application's start URL. |
||
421 | * |
||
422 | * @return string|null |
||
423 | */ |
||
424 | 2 | public function getStartUrl() |
|
428 | |||
429 | /** |
||
430 | * Sets the application's start URL. |
||
431 | * |
||
432 | * @param string $startUrl |
||
433 | * |
||
434 | * @return AppConfiguration |
||
435 | * |
||
436 | * @see https://www.w3.org/TR/appmanifest/#start_url-member |
||
437 | */ |
||
438 | 2 | public function setStartUrl($startUrl) |
|
443 | |||
444 | /** |
||
445 | * Returns the theme color. |
||
446 | * |
||
447 | * @return string|null |
||
448 | */ |
||
449 | 2 | public function getThemeColor() |
|
453 | |||
454 | /** |
||
455 | * Sets the theme color. Will be used by Android's task switcher, for example. |
||
456 | * |
||
457 | * @param string $color |
||
458 | * |
||
459 | * @return AppConfiguration |
||
460 | * |
||
461 | * @see https://www.w3.org/TR/appmanifest/#theme_color-member |
||
462 | */ |
||
463 | 2 | public function setThemeColor($color) |
|
468 | |||
469 | /** |
||
470 | * Creates an instance of the {@link AppConfiguration} class based on the values in the provided manifest file. Use |
||
471 | * the {@link fromManifest} method to use a JSON string as source. |
||
472 | * |
||
473 | * @param string $path Path to a file containing an application manifest compatible |
||
474 | * with the Web App Manifest specification. |
||
475 | * |
||
476 | * @return AppConfiguration |
||
477 | * |
||
478 | * @see https://www.w3.org/TR/appmanifest/ |
||
479 | */ |
||
480 | 1 | public static function fromManifestFile($path) |
|
484 | |||
485 | /** |
||
486 | * Creates an instance of the {@link AppConfiguration} class based on the values in the provided JSON string. Use |
||
487 | * the {@link fromManifestFile} method to use a file as source. |
||
488 | * |
||
489 | * @param string $json A JSON string that is compatible with the Web App Manifest |
||
490 | * specification. |
||
491 | * |
||
492 | * @return AppConfiguration |
||
493 | * |
||
494 | * @see https://www.w3.org/TR/appmanifest/ |
||
495 | */ |
||
496 | 2 | public static function fromManifest($json) |
|
559 | |||
560 | 2 | private static function imageFromData(array $data) |
|
583 | } |
||
584 |
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.