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 Subscription 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 Subscription, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
8 | final class Subscription extends BaseResource implements Emptiable |
||
9 | { |
||
10 | use EmptiableTrait; |
||
11 | |||
12 | /** |
||
13 | * @var string |
||
14 | */ |
||
15 | private $profileId; |
||
16 | |||
17 | /** |
||
18 | * @var int |
||
19 | */ |
||
20 | private $frequency; |
||
21 | |||
22 | /** |
||
23 | * @var int |
||
24 | */ |
||
25 | private $interval; |
||
26 | |||
27 | /** |
||
28 | * @var string |
||
29 | */ |
||
30 | private $start; |
||
31 | |||
32 | /** |
||
33 | * @var int |
||
34 | */ |
||
35 | private $cycle; |
||
36 | |||
37 | /** |
||
38 | * @var float |
||
39 | */ |
||
40 | private $amount; |
||
41 | |||
42 | /** |
||
43 | * @var bool |
||
44 | */ |
||
45 | private $trial; |
||
46 | |||
47 | /** |
||
48 | * @var int |
||
49 | */ |
||
50 | private $trialCycle; |
||
51 | |||
52 | /** |
||
53 | * @var int |
||
54 | */ |
||
55 | private $trialFrequency; |
||
56 | |||
57 | /** |
||
58 | * @var float |
||
59 | */ |
||
60 | private $trialAmount; |
||
61 | |||
62 | /** |
||
63 | * @return int |
||
64 | */ |
||
65 | public function getFrequency() |
||
69 | |||
70 | /** |
||
71 | * @return int |
||
72 | */ |
||
73 | public function getInterval() |
||
77 | |||
78 | /** |
||
79 | * @return string |
||
80 | */ |
||
81 | public function getStart() |
||
85 | |||
86 | /** |
||
87 | * @return int |
||
88 | */ |
||
89 | public function getCycle() |
||
93 | |||
94 | /** |
||
95 | * @return float |
||
96 | */ |
||
97 | public function getAmount() |
||
101 | |||
102 | /** |
||
103 | * @return bool |
||
104 | */ |
||
105 | public function isTrial() |
||
109 | |||
110 | /** |
||
111 | * @return int |
||
112 | */ |
||
113 | public function getTrialCycle() |
||
117 | |||
118 | /** |
||
119 | * @return int |
||
120 | */ |
||
121 | public function getTrialFrequency() |
||
125 | |||
126 | /** |
||
127 | * @return float |
||
128 | */ |
||
129 | public function getTrialAmount() |
||
133 | |||
134 | /** |
||
135 | * @param int $frequency the frequency |
||
136 | */ |
||
137 | public function setFrequency($frequency) |
||
148 | |||
149 | /** |
||
150 | * Sets the value of interval. |
||
151 | */ |
||
152 | public function setInterval($interval) |
||
164 | |||
165 | /** |
||
166 | * @param string $start the start |
||
167 | */ |
||
168 | public function setStart($start) |
||
180 | |||
181 | /** |
||
182 | * @param int $cycle |
||
183 | */ |
||
184 | public function setCycle($cycle) |
||
195 | |||
196 | /** |
||
197 | * @param float $amount |
||
198 | */ |
||
199 | public function setAmount($amount) |
||
205 | |||
206 | /** |
||
207 | * @param bool $trial |
||
208 | */ |
||
209 | public function setTrial($trial) |
||
215 | |||
216 | /** |
||
217 | * @param int $trialCycle |
||
218 | */ |
||
219 | public function setTrialCycle($trialCycle) |
||
230 | |||
231 | /** |
||
232 | * @param int $trialFrequency |
||
233 | */ |
||
234 | public function setTrialFrequency($trialFrequency) |
||
245 | |||
246 | /** |
||
247 | * @param float $trialAmount |
||
248 | */ |
||
249 | public function setTrialAmount($trialAmount) |
||
255 | |||
256 | /** |
||
257 | * @return string |
||
258 | */ |
||
259 | public function getProfileId() |
||
263 | |||
264 | /** |
||
265 | * @param string $profileId |
||
266 | */ |
||
267 | public function setProfileId($profileId) |
||
278 | |||
279 | private function isValidFrequency($frequency) |
||
283 | |||
284 | private function isValidInterval($interval) |
||
297 | |||
298 | View Code Duplication | private function isValidStartFormatDate($date) |
|
309 | |||
310 | private function isValidCycle($cycle) |
||
314 | |||
315 | private function isValidProfileId($profileId) |
||
319 | } |
||
320 |
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.
Unreachable code is most often the result of
return
,die
orexit
statements that have been added for debug purposes.In the above example, the last
return false
will never be executed, because a return statement has already been met in every possible execution path.