Complex classes like PropertyService 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 PropertyService, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
16 | class PropertyService |
||
17 | { |
||
18 | /** |
||
19 | * definedElements |
||
20 | * |
||
21 | * @var array |
||
22 | */ |
||
23 | private $definedElements; |
||
24 | |||
25 | /** |
||
26 | * FileName |
||
27 | * |
||
28 | * @var string|null |
||
29 | */ |
||
30 | private $fileName; |
||
31 | |||
32 | /** |
||
33 | * Multiple properties for element allowed |
||
34 | * |
||
35 | * @var array |
||
36 | */ |
||
37 | private static $multiplePropertiesForElementAllowed = [ |
||
38 | 'email', |
||
39 | 'address', |
||
40 | 'phoneNumber', |
||
41 | 'url', |
||
42 | ]; |
||
43 | |||
44 | /** |
||
45 | * Properties |
||
46 | * |
||
47 | * @var array |
||
48 | */ |
||
49 | private $properties = []; |
||
50 | |||
51 | /** |
||
52 | * Default Charset |
||
53 | * |
||
54 | * @var string |
||
55 | */ |
||
56 | private $charset; |
||
57 | |||
58 | /** |
||
59 | * @var VCard[] |
||
60 | */ |
||
61 | private $vCards; |
||
62 | |||
63 | /** |
||
64 | * PropertyService constructor. |
||
65 | * |
||
66 | * @param VCard|VCard[] $vCard |
||
67 | * @param string $charset |
||
68 | * |
||
69 | * @throws ElementAlreadyExistsException |
||
70 | */ |
||
71 | public function __construct($vCard, $charset = 'utf-8') |
||
82 | |||
83 | /** |
||
84 | * Get filename |
||
85 | * |
||
86 | * @return string|null |
||
87 | */ |
||
88 | public function getFileName(): ?string |
||
92 | |||
93 | /** |
||
94 | * Get properties |
||
95 | * |
||
96 | * @return array |
||
97 | */ |
||
98 | public function getProperties(): array |
||
102 | |||
103 | /** |
||
104 | * Get charset string |
||
105 | * |
||
106 | * @return string |
||
107 | */ |
||
108 | private function getCharsetString(): string |
||
118 | |||
119 | /** |
||
120 | * Set filename |
||
121 | * |
||
122 | * @param string|array $value |
||
123 | * @param bool $overwrite [optional] Default overwrite is true |
||
124 | * @param string $separator [optional] Default separator is an underscore '_' |
||
125 | * @return void |
||
126 | */ |
||
127 | private function setFileName($value, $overwrite = true, $separator = '_'): void |
||
158 | |||
159 | /** |
||
160 | * Has property |
||
161 | * |
||
162 | * @param string $key |
||
163 | * @return bool |
||
164 | */ |
||
165 | private function hasProperty(string $key): bool |
||
177 | |||
178 | /** |
||
179 | * @throws ElementAlreadyExistsException |
||
180 | */ |
||
181 | private function parseVCarts(): void |
||
187 | |||
188 | /** |
||
189 | * @param VCard $vCard |
||
190 | * |
||
191 | * @throws ElementAlreadyExistsException |
||
192 | */ |
||
193 | private function parseVCart(VCard $vCard): void |
||
209 | |||
210 | /** |
||
211 | * @param VCardAddress[][]|null $addresses |
||
212 | * |
||
213 | * @throws ElementAlreadyExistsException |
||
214 | */ |
||
215 | private function addAddress($addresses): void |
||
229 | |||
230 | /** |
||
231 | * Add birthday |
||
232 | * |
||
233 | * @param \DateTime|null $date Format is YYYY-MM-DD |
||
234 | * |
||
235 | * @throws ElementAlreadyExistsException |
||
236 | */ |
||
237 | private function addBirthday(?\DateTime $date): void |
||
247 | |||
248 | /** |
||
249 | * Add company |
||
250 | * |
||
251 | * @param null|string $company |
||
252 | * @param string $department |
||
253 | * |
||
254 | * @throws ElementAlreadyExistsException |
||
255 | */ |
||
256 | private function addOrganization(?string $company, string $department = ''): void |
||
271 | |||
272 | /** |
||
273 | * Add name |
||
274 | * |
||
275 | * @param string $lastName [optional] |
||
276 | * @param string $firstName [optional] |
||
277 | * @param string $additional [optional] |
||
278 | * @param string $prefix [optional] |
||
279 | * @param string $suffix [optional] |
||
280 | * |
||
281 | * @throws ElementAlreadyExistsException |
||
282 | */ |
||
283 | private function addName( |
||
324 | |||
325 | /** |
||
326 | * Add categories |
||
327 | * |
||
328 | * @param null|array $categories |
||
329 | * |
||
330 | * @throws ElementAlreadyExistsException |
||
331 | */ |
||
332 | private function addCategories(?array $categories): void |
||
342 | |||
343 | /** |
||
344 | * Add Array |
||
345 | * |
||
346 | * @param string $element |
||
347 | * @param string $property |
||
348 | * @param null|string[][] $values |
||
349 | * |
||
350 | * @throws ElementAlreadyExistsException |
||
351 | */ |
||
352 | private function setArrayProperty(string $element, string $property, $values): void |
||
366 | |||
367 | /** |
||
368 | * Set string property |
||
369 | * |
||
370 | * @param string $element |
||
371 | * @param string $property |
||
372 | * @param null|string $value |
||
373 | * |
||
374 | * @throws ElementAlreadyExistsException |
||
375 | */ |
||
376 | private function setStringProperty(string $element, string $property, ?string $value): void |
||
386 | |||
387 | /** |
||
388 | * Set Media |
||
389 | * |
||
390 | * @param string $element |
||
391 | * @param string $property |
||
392 | * @param VCardMedia|null $media |
||
393 | * |
||
394 | * @throws ElementAlreadyExistsException |
||
395 | */ |
||
396 | private function setMedia(string $element, string $property, ?VCardMedia $media): void |
||
418 | |||
419 | /** |
||
420 | * Set property |
||
421 | * |
||
422 | * @param string $element The element name you want to set, f.e.: name, email, phoneNumber, ... |
||
423 | * @param string $key |
||
424 | * @param string $value |
||
425 | * |
||
426 | * @throws ElementAlreadyExistsException |
||
427 | */ |
||
428 | private function setProperty(string $element, string $key, string $value): void |
||
444 | } |
||
445 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.