Complex classes like Organization 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 Organization, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
35 | class Organization extends ElementQuery |
||
36 | { |
||
37 | |||
38 | /** |
||
39 | * @var int|int[]|null The user ID(s) that the resulting organizations’ owners must have. |
||
40 | */ |
||
41 | public $ownerId; |
||
42 | |||
43 | /** |
||
44 | * @var int|int[]|null The user group ID(s) that the resulting organizations’ owners must be in. |
||
45 | */ |
||
46 | public $ownerGroupId; |
||
47 | |||
48 | /** |
||
49 | * @var int|int[]|null The organization type ID(s) that the resulting organizations must have. |
||
50 | */ |
||
51 | public $typeId; |
||
52 | |||
53 | /** |
||
54 | * @var int|int[]|null The organization type ID(s) that the resulting organizations must have. |
||
55 | */ |
||
56 | public $userId; |
||
57 | |||
58 | /** |
||
59 | * @var int|int[]|null The organization type ID(s) that the resulting organizations must have. |
||
60 | */ |
||
61 | public $memberId; |
||
62 | |||
63 | /** |
||
64 | * @var mixed The Join Date that the resulting organization must have. |
||
65 | */ |
||
66 | public $dateJoined; |
||
67 | |||
68 | /** |
||
69 | * @inheritdoc |
||
70 | */ |
||
71 | public function __set($name, $value) |
||
98 | |||
99 | |||
100 | /** |
||
101 | * Sets the [[typeId]] property based on a given element owner. |
||
102 | * |
||
103 | * @param string|string[]|integer|integer[]|Type|Type[] $value The property value |
||
104 | * |
||
105 | * @return self The query object itself |
||
106 | */ |
||
107 | public function setType($value) |
||
114 | |||
115 | /** |
||
116 | * Sets the [[typeId]] property. |
||
117 | * |
||
118 | * @param string|string[]|integer|integer[]|Type|Type[] $type The property value |
||
119 | * |
||
120 | * @return self The query object itself |
||
121 | */ |
||
122 | public function type($type) |
||
129 | |||
130 | /** |
||
131 | * @param $typeId |
||
132 | * @return $this |
||
133 | */ |
||
134 | public function setTypeId($typeId) |
||
141 | |||
142 | /** |
||
143 | * Sets the [[typeId]] property. |
||
144 | * |
||
145 | * @param integer|integer[] $type The property value |
||
146 | * |
||
147 | * @return self The query object itself |
||
148 | */ |
||
149 | public function typeId($type) |
||
156 | |||
157 | /** |
||
158 | * Sets the [[ownerId]] property based on a given element owner. |
||
159 | * |
||
160 | * @param string|string[]|integer|integer[]|UserElement|UserElement[] $value The property value |
||
161 | * |
||
162 | * @return self The query object itself |
||
163 | */ |
||
164 | public function setOwner($value) |
||
172 | |||
173 | /** |
||
174 | * Sets the [[ownerId]] property. |
||
175 | * |
||
176 | * @param string|string[]|integer|integer[]|UserElement|UserElement[] $owner The property value |
||
177 | * |
||
178 | * @return self The query object itself |
||
179 | */ |
||
180 | public function owner($owner) |
||
187 | |||
188 | /** |
||
189 | * @param $ownerId |
||
190 | * @return $this |
||
191 | */ |
||
192 | public function setOwnerId($ownerId) |
||
199 | |||
200 | /** |
||
201 | * Sets the [[ownerId]] property. |
||
202 | * |
||
203 | * @param integer|integer[] $owner The property value |
||
204 | * |
||
205 | * @return self The query object itself |
||
206 | */ |
||
207 | public function ownerId($owner) |
||
214 | |||
215 | |||
216 | /** |
||
217 | * Sets the [[ownerGroupId]] property based on a given user group(s)’s handle(s). |
||
218 | * |
||
219 | * @param string|string[]|null $value The property value |
||
220 | * |
||
221 | * @return static self reference |
||
222 | */ |
||
223 | public function ownerGroup($value) |
||
239 | |||
240 | /** |
||
241 | * Sets the [[authorGroupId]] property. |
||
242 | * |
||
243 | * @param int|int[]|null $value The property value |
||
244 | * |
||
245 | * @return static self reference |
||
246 | */ |
||
247 | public function ownerGroupId($value) |
||
253 | |||
254 | |||
255 | /** |
||
256 | * Sets the [[userId]] property based on a given element owner. |
||
257 | * |
||
258 | * @param string|string[]|integer|integer[]|UserElement|UserElement[] $value The property value |
||
259 | * |
||
260 | * @return self The query object itself |
||
261 | */ |
||
262 | public function setUser($value) |
||
269 | |||
270 | /** |
||
271 | * Sets the [[userId]] property. |
||
272 | * |
||
273 | * @param string|string[]|integer|integer[]|UserElement|UserElement[] $users The property value |
||
274 | * |
||
275 | * @return self The query object itself |
||
276 | */ |
||
277 | public function user($users) |
||
284 | |||
285 | /** |
||
286 | * @param $userIds |
||
287 | * @return $this |
||
288 | */ |
||
289 | public function setUserId($userIds) |
||
296 | |||
297 | /** |
||
298 | * Sets the [[userId]] property. |
||
299 | * |
||
300 | * @param integer|integer[] $user The property value |
||
301 | * |
||
302 | * @return self The query object itself |
||
303 | */ |
||
304 | public function userId($user) |
||
311 | |||
312 | /** |
||
313 | * Sets the [[userId]] property based on a given element owner. |
||
314 | * |
||
315 | * @param string|string[]|integer|integer[]|UserElement|UserElement[] $value The property value |
||
316 | * |
||
317 | * @return self The query object itself |
||
318 | */ |
||
319 | public function setMember($value) |
||
326 | |||
327 | /** |
||
328 | * Sets the [[userId]] property. |
||
329 | * |
||
330 | * @param string|string[]|integer|integer[]|UserElement|UserElement[] $members The property value |
||
331 | * |
||
332 | * @return self The query object itself |
||
333 | */ |
||
334 | public function member($members) |
||
341 | |||
342 | /** |
||
343 | * @param $memberIds |
||
344 | * @return $this |
||
345 | */ |
||
346 | public function setMemberId($memberIds) |
||
353 | |||
354 | /** |
||
355 | * Sets the [[userId]] property. |
||
356 | * |
||
357 | * @param integer|integer[] $member The property value |
||
358 | * |
||
359 | * @return self The query object itself |
||
360 | */ |
||
361 | public function memberId($member) |
||
368 | |||
369 | /** |
||
370 | * Sets the [[dateJoined]] property. |
||
371 | * |
||
372 | * @param mixed $value The property value |
||
373 | * |
||
374 | * @return static self reference |
||
375 | */ |
||
376 | public function dateJoined($value) |
||
382 | |||
383 | /** |
||
384 | * @inheritdoc |
||
385 | */ |
||
386 | protected function statusCondition(string $status) |
||
397 | |||
398 | /** |
||
399 | * @inheritdoc |
||
400 | */ |
||
401 | protected function beforePrepare(): bool |
||
477 | |||
478 | /** |
||
479 | * @return string |
||
480 | */ |
||
481 | private function organizationDbTableReference(): string |
||
485 | |||
486 | /** |
||
487 | * @param $value |
||
488 | * @return array |
||
489 | */ |
||
490 | private function parseTypeValue($value) |
||
523 | |||
524 | /** |
||
525 | * @param $value |
||
526 | * @return array |
||
527 | */ |
||
528 | private function parseUserValue($value) |
||
561 | } |
||
562 |
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.