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 ConfigHelper 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 ConfigHelper, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
8 | class ConfigHelper |
||
9 | { |
||
10 | /** @var ServiceHelper */ |
||
11 | private $serviceHelper; |
||
12 | |||
13 | /** @var string */ |
||
14 | private $token = false; |
||
15 | |||
16 | /** @var string */ |
||
17 | private $propertyId = false; |
||
18 | |||
19 | /** @var string */ |
||
20 | private $accountId = false; |
||
21 | |||
22 | /** @var string */ |
||
23 | private $profileId = false; |
||
24 | |||
25 | /** @var EntityManager */ |
||
26 | private $em; |
||
27 | |||
28 | /** |
||
29 | * constructor |
||
30 | * |
||
31 | * @param ServiceHelper $serviceHelper |
||
32 | * @param EntityManager $em |
||
33 | */ |
||
34 | public function __construct(ServiceHelper $serviceHelper, EntityManager $em) |
||
40 | |||
41 | /** |
||
42 | * Tries to initialise the Client object |
||
43 | * |
||
44 | * @param int $configId |
||
45 | */ |
||
46 | public function init($configId = false) |
||
63 | |||
64 | /* =============================== TOKEN =============================== */ |
||
65 | |||
66 | /** |
||
67 | * Get the token from the database |
||
68 | * |
||
69 | * @return string $token |
||
70 | */ |
||
71 | View Code Duplication | private function getToken($configId = false) |
|
85 | |||
86 | /** |
||
87 | * Save the token to the database |
||
88 | */ |
||
89 | public function saveToken($token, $configId = false) |
||
94 | |||
95 | /** |
||
96 | * Check if token is set |
||
97 | * |
||
98 | * @return bool $result |
||
99 | */ |
||
100 | public function tokenIsSet() |
||
104 | |||
105 | /* =============================== ACCOUNT =============================== */ |
||
106 | |||
107 | /** |
||
108 | * Get a list of all available accounts |
||
109 | * |
||
110 | * @return array $data A list of all properties |
||
111 | */ |
||
112 | public function getAccounts() |
||
127 | |||
128 | /** |
||
129 | * Get the accountId from the database |
||
130 | * |
||
131 | * @return string $accountId |
||
132 | */ |
||
133 | View Code Duplication | public function getAccountId($configId = false) |
|
147 | |||
148 | /** |
||
149 | * Save the accountId to the database |
||
150 | */ |
||
151 | public function saveAccountId($accountId, $configId = false) |
||
156 | |||
157 | /** |
||
158 | * Check if token is set |
||
159 | * |
||
160 | * @return bool $result |
||
161 | */ |
||
162 | public function accountIsSet() |
||
166 | |||
167 | /* =============================== PROPERTY =============================== */ |
||
168 | |||
169 | /** |
||
170 | * Get a list of all available properties |
||
171 | * |
||
172 | * @return array $data A list of all properties |
||
173 | */ |
||
174 | public function getProperties($accountId = false) |
||
200 | |||
201 | /** |
||
202 | * Get the propertyId from the database |
||
203 | * |
||
204 | * @return string $propertyId |
||
205 | */ |
||
206 | View Code Duplication | public function getPropertyId($configId = false) |
|
220 | |||
221 | /** |
||
222 | * Save the propertyId to the database |
||
223 | */ |
||
224 | public function savePropertyId($propertyId, $configId = false) |
||
229 | |||
230 | /** |
||
231 | * Check if propertyId is set |
||
232 | * |
||
233 | * @return bool $result |
||
234 | */ |
||
235 | public function propertyIsSet() |
||
239 | |||
240 | /* =============================== PROFILE =============================== */ |
||
241 | |||
242 | /** |
||
243 | * Get a list of all available profiles |
||
244 | * |
||
245 | * @return array $data A list of all properties |
||
246 | */ |
||
247 | public function getProfiles($accountId = false, $propertyId = false) |
||
280 | |||
281 | /** |
||
282 | * Get the propertyId from the database |
||
283 | * |
||
284 | * @return string $propertyId |
||
285 | */ |
||
286 | View Code Duplication | public function getProfileId($configId = false) |
|
300 | |||
301 | /** |
||
302 | * Save the profileId to the database |
||
303 | */ |
||
304 | public function saveProfileId($profileId, $configId = false) |
||
309 | |||
310 | /** |
||
311 | * Check if token is set |
||
312 | * |
||
313 | * @return bool $result |
||
314 | */ |
||
315 | public function profileIsSet() |
||
319 | |||
320 | /** |
||
321 | * Get the active profile |
||
322 | * |
||
323 | * @return the profile |
||
324 | */ |
||
325 | public function getActiveProfile() |
||
340 | |||
341 | /* =============================== PROFILE SEGMENTS =============================== */ |
||
342 | |||
343 | /** |
||
344 | * get all segments for the saved profile |
||
345 | * |
||
346 | * @return array |
||
347 | */ |
||
348 | public function getProfileSegments() |
||
375 | |||
376 | /* =============================== CONFIG =============================== */ |
||
377 | |||
378 | /** |
||
379 | * Save the config to the database |
||
380 | */ |
||
381 | public function saveConfigName($configName, $configId = false) |
||
385 | |||
386 | /* =============================== AUTH URL =============================== */ |
||
387 | |||
388 | /** |
||
389 | * get the authUrl |
||
390 | * |
||
391 | * @return string $authUrl |
||
392 | */ |
||
393 | public function getAuthUrl() |
||
401 | } |
||
402 |
The
EntityManager
might become unusable for example if a transaction is rolled back and it gets closed. Let’s assume that somewhere in your application, or in a third-party library, there is code such as the following:If that code throws an exception and the
EntityManager
is closed. Any other code which depends on the same instance of theEntityManager
during this request will fail.On the other hand, if you instead inject the
ManagerRegistry
, thegetManager()
method guarantees that you will always get a usable manager instance.