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 ExperimentMetricResults 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 ExperimentMetricResults, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
15 | class ExperimentMetricResults |
||
16 | { |
||
17 | /** |
||
18 | * The aggregation function for the numerator of the metric. 'unique' measures |
||
19 | * the number of unique visitors/sessions that include the specified Event. |
||
20 | * 'count' measures the total number of occurrences of Event for the scope |
||
21 | * (visitor/session). 'sum' is the sum of the 'field' value. 'exit' measures |
||
22 | * the ratio of sessions with last activation occurring on the target page to |
||
23 | * the sessions that activated the target page at least once during the session. |
||
24 | * 'bounce' measures the ratio of sessions that with first and last activation |
||
25 | * occurring on the target page to the sessions with first activation on the |
||
26 | * target page. For both 'exit' and 'bounce', the eventId must be the ID of a Page. |
||
27 | * |
||
28 | * @var string |
||
29 | */ |
||
30 | private $aggregator; |
||
31 | |||
32 | /** |
||
33 | * |
||
34 | * @var string |
||
35 | */ |
||
36 | private $eventId; |
||
37 | |||
38 | /** |
||
39 | * |
||
40 | * @var string |
||
41 | */ |
||
42 | private $eventName; |
||
43 | |||
44 | /** |
||
45 | * |
||
46 | * @var type |
||
47 | */ |
||
48 | private $field; |
||
49 | |||
50 | /** |
||
51 | * Conversions indicate the total number of visitors or sessions where the |
||
52 | * event happened. Impressions indicate the total number of times the event |
||
53 | * happened (possibly multiple per visitor or session). Revenue indicates |
||
54 | * the sum of all revenue sent from all events in the Experiment. |
||
55 | * Can be 'conversions', 'impressions' or 'revenue'. |
||
56 | * @var string |
||
57 | */ |
||
58 | private $measure; |
||
59 | |||
60 | /** |
||
61 | * |
||
62 | * @var string |
||
63 | */ |
||
64 | private $metricId; |
||
65 | |||
66 | /** |
||
67 | * |
||
68 | * @var integer |
||
69 | */ |
||
70 | private $priority; |
||
71 | |||
72 | /** |
||
73 | * Can be 'session', 'visitor' or 'event' |
||
74 | * @var string |
||
75 | */ |
||
76 | private $unit; |
||
77 | |||
78 | /** |
||
79 | * |
||
80 | * @var string |
||
81 | */ |
||
82 | private $name; |
||
83 | |||
84 | /** |
||
85 | * A map of results for each variation in the Experiment keyed by variation ID. |
||
86 | * For Personalization Campaigns, the special variant 'baseline' represents |
||
87 | * visitors that have been held back from any change in experience for the Experiment |
||
88 | * |
||
89 | * @var object[VariantResults] |
||
90 | */ |
||
91 | private $results; |
||
92 | |||
93 | /** |
||
94 | * |
||
95 | * @var string |
||
96 | */ |
||
97 | private $scope; |
||
98 | |||
99 | /** |
||
100 | * |
||
101 | * @var type |
||
102 | */ |
||
103 | private $winningDirection; |
||
104 | |||
105 | /** |
||
106 | * Constructor. |
||
107 | */ |
||
108 | 3 | public function __construct($options = array()) |
|
135 | |||
136 | /** |
||
137 | * Returns this object as array. |
||
138 | */ |
||
139 | 1 | public function toArray() |
|
169 | |||
170 | 1 | public function getAggregator() |
|
174 | |||
175 | public function setAggregator($aggregator) |
||
179 | |||
180 | 1 | public function getEventId() |
|
184 | |||
185 | 3 | public function setEventId($eventId) |
|
189 | |||
190 | 1 | public function getEventName() |
|
194 | |||
195 | 3 | public function setEventName($eventName) |
|
199 | |||
200 | 1 | public function getField() |
|
204 | |||
205 | public function setField($field) |
||
209 | |||
210 | 1 | public function getMeasure() |
|
214 | |||
215 | 3 | public function setMeasure($measure) |
|
219 | |||
220 | 1 | public function getMetricId() |
|
224 | |||
225 | 3 | public function setMetricId($metricId) |
|
229 | |||
230 | 1 | public function getPriority() |
|
234 | |||
235 | 3 | public function setPriority($priority) |
|
239 | |||
240 | 1 | public function getUnit() |
|
244 | |||
245 | 3 | public function setUnit($unit) |
|
249 | |||
250 | 1 | public function getResults() |
|
254 | |||
255 | 3 | public function setResults($results) |
|
259 | |||
260 | 1 | public function getName() |
|
264 | |||
265 | public function setName($name) |
||
269 | |||
270 | 1 | public function getScope() |
|
274 | |||
275 | public function setScope($scope) |
||
279 | |||
280 | 1 | public function getWinningDirection() |
|
284 | |||
285 | public function setWinningDirection($winningDirection) |
||
289 | } |
||
290 | |||
300 |
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.