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 ImageWithStyle 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 ImageWithStyle, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
5 | class ImageWithStyle extends DataObject |
||
|
|||
6 | { |
||
7 | |||
8 | ####################### |
||
9 | ### Names Section |
||
10 | ####################### |
||
11 | |||
12 | private static $singular_name = 'Image With Style'; |
||
13 | |||
14 | public function i18n_singular_name() |
||
18 | |||
19 | private static $plural_name = 'Images With Style'; |
||
20 | |||
21 | public function i18n_plural_name() |
||
25 | |||
26 | |||
27 | ####################### |
||
28 | ### Model Section |
||
29 | ####################### |
||
30 | |||
31 | private static $db = [ |
||
32 | 'Title' => 'Varchar', |
||
33 | 'Description' => 'Text', |
||
34 | 'Var1' => 'Varchar', |
||
35 | 'Var2' => 'Varchar', |
||
36 | 'Var3' => 'Varchar', |
||
37 | 'Var4' => 'Varchar', |
||
38 | 'Var5' => 'Varchar' |
||
39 | ]; |
||
40 | |||
41 | private static $has_one = [ |
||
42 | 'Image' => 'Image', |
||
43 | 'Style' => 'ImageStyle' |
||
44 | ]; |
||
45 | |||
46 | private static $belongs_many_many = [ |
||
47 | 'Selections' => 'ImagesWithStyleSelection' |
||
48 | ]; |
||
49 | |||
50 | |||
51 | ####################### |
||
52 | ### Further DB Field Details |
||
53 | ####################### |
||
54 | |||
55 | private static $indexes = [ |
||
56 | 'Created' => true |
||
57 | ]; |
||
58 | |||
59 | private static $default_sort = [ |
||
60 | 'Created' => 'DESC' |
||
61 | ]; |
||
62 | |||
63 | private static $required_fields = [ |
||
64 | 'Title', |
||
65 | 'StyleID' |
||
66 | ]; |
||
67 | |||
68 | private static $searchable_fields = [ |
||
69 | 'Title' => 'PartialMatchFilter' |
||
70 | ]; |
||
71 | |||
72 | |||
73 | ####################### |
||
74 | ### Field Names and Presentation Section |
||
75 | ####################### |
||
76 | |||
77 | private static $field_labels = [ |
||
78 | 'Style' => 'Display Style', |
||
79 | 'Title' => 'Image Title', |
||
80 | 'Selections' => 'Lists' |
||
81 | ]; |
||
82 | |||
83 | private static $field_labels_right = [ |
||
84 | 'Pages' => 'On what pages is this image visible' |
||
85 | ]; |
||
86 | |||
87 | private static $summary_fields = [ |
||
88 | 'Title' => 'Title', |
||
89 | 'Style.Title' => 'Style', |
||
90 | 'Image.CMSThumbnail' => 'Image' |
||
91 | ]; |
||
92 | |||
93 | |||
94 | private static $casting = [ |
||
95 | 'ImageElement' => 'HTMLText' |
||
96 | ]; |
||
97 | |||
98 | private static $unique_vars = ['Var1', 'Var2', 'Var3', 'Var4', 'Var5']; |
||
99 | |||
100 | |||
101 | ####################### |
||
102 | ### Casting Section |
||
103 | ####################### |
||
104 | |||
105 | |||
106 | ####################### |
||
107 | ### can Section |
||
108 | ####################### |
||
109 | |||
110 | public function canDelete($member = null) |
||
114 | |||
115 | |||
116 | |||
117 | ####################### |
||
118 | ### write Section |
||
119 | ####################### |
||
120 | |||
121 | |||
122 | |||
123 | |||
124 | public function validate() |
||
172 | |||
173 | public function onBeforeWrite() |
||
181 | |||
182 | public function onAfterWrite() |
||
192 | |||
193 | public function requireDefaultRecords() |
||
198 | |||
199 | |||
200 | ####################### |
||
201 | ### Import / Export Section |
||
202 | ####################### |
||
203 | |||
204 | public function getExportFields() |
||
209 | |||
210 | |||
211 | |||
212 | ####################### |
||
213 | ### CMS Edit Section |
||
214 | ####################### |
||
215 | |||
216 | |||
217 | public function CMSEditLink() |
||
223 | |||
224 | public function CMSAddLink() |
||
230 | |||
231 | |||
232 | public function getCMSFields() |
||
305 | |||
306 | /** |
||
307 | * @return string (HTML) |
||
308 | */ |
||
309 | public function ImageElement() |
||
313 | |||
314 | |||
315 | /** |
||
316 | * @return string (HTML) |
||
317 | */ |
||
318 | public function getImageElement() |
||
337 | |||
338 | /** |
||
339 | * @return string (HTML) |
||
340 | */ |
||
341 | public function buildStyles() |
||
364 | |||
365 | protected function hasRealStyle() |
||
374 | |||
375 | /** |
||
376 | * @param string |
||
377 | * @return string |
||
378 | */ |
||
379 | protected function convertVarTypeToCSS($type) |
||
394 | |||
395 | public function BestFolder() |
||
410 | } |
||
411 |
You can fix this by adding a namespace to your class:
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.