Complex classes like Entity 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 Entity, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
14 | class Entity { |
||
15 | |||
16 | private $parent = null, $name = '', $path = '', $path_full = '', $type = ''; |
||
17 | |||
18 | /** |
||
19 | * Get entity prototype data |
||
20 | * |
||
21 | * @return array|false : the data array or false if the name is invalid |
||
22 | */ |
||
23 | |||
24 | private function getPrototype(string $name) { |
||
38 | |||
39 | /** |
||
40 | * Constructor |
||
41 | */ |
||
42 | |||
43 | public function __construct(Container $parent, string $name = '') { |
||
47 | |||
48 | /** |
||
49 | * Initialize the entity by a directory/file name |
||
50 | * |
||
51 | * @return bool : true on success or false if a corresponding directory/file does not exist |
||
52 | */ |
||
53 | |||
54 | public function init(string $name) : bool { |
||
74 | |||
75 | /** |
||
76 | * Check whether another entity with a given name exists in the same parent directory. |
||
77 | * This method is useful to find out is it possible to create or rename the entity |
||
78 | * |
||
79 | * @return bool : true if the check has been successful and no other items with the given name found, otherwise false |
||
80 | */ |
||
81 | |||
82 | public function check(string $name) : bool { |
||
92 | |||
93 | /** |
||
94 | * Create the entity |
||
95 | * |
||
96 | * @return bool : true on success or false on failure |
||
97 | */ |
||
98 | |||
99 | public function create(string $name, string $type) : bool { |
||
121 | |||
122 | /** |
||
123 | * Rename the entity |
||
124 | * |
||
125 | * @return bool : true on success or false on failure |
||
126 | */ |
||
127 | |||
128 | public function rename(string $name) : bool { |
||
144 | |||
145 | /** |
||
146 | * Remove the entity |
||
147 | * |
||
148 | * @return bool : true on success or false on failure |
||
149 | */ |
||
150 | |||
151 | public function remove() : bool { |
||
169 | |||
170 | /** |
||
171 | * Get the entity extension in lower case |
||
172 | * |
||
173 | * @return string|false : the extension or false on failure |
||
174 | */ |
||
175 | |||
176 | public function getExtension() { |
||
182 | |||
183 | /** |
||
184 | * Get the entity creation time |
||
185 | * |
||
186 | * @return int|false : the time or false on failure |
||
187 | */ |
||
188 | |||
189 | public function getCreated() { |
||
195 | |||
196 | /** |
||
197 | * Get the entity access time |
||
198 | * |
||
199 | * @return int|false : the time or false on failure |
||
200 | */ |
||
201 | |||
202 | public function getAccessed() { |
||
208 | |||
209 | /** |
||
210 | * Get the entity modification time |
||
211 | * |
||
212 | * @return int|false : the time or false on failure |
||
213 | */ |
||
214 | |||
215 | public function getModified() { |
||
221 | |||
222 | /** |
||
223 | * Get the entity permissions |
||
224 | * |
||
225 | * @return int|false : the permissions or false on failure |
||
226 | */ |
||
227 | |||
228 | public function getPermissions() { |
||
234 | |||
235 | /** |
||
236 | * Get the entity size |
||
237 | * |
||
238 | * @return int|false : the size or false on failure |
||
239 | */ |
||
240 | |||
241 | public function getSize() { |
||
247 | |||
248 | /** |
||
249 | * Get the file contents |
||
250 | * |
||
251 | * @return string|false : the read data or false on failure |
||
252 | */ |
||
253 | |||
254 | public function getContents() { |
||
260 | |||
261 | /** |
||
262 | * Save data into the file |
||
263 | * |
||
264 | * @return int|false : the number of bytes that were written to the file or false on failure |
||
265 | */ |
||
266 | |||
267 | public function putContents(string $contents) { |
||
273 | |||
274 | /** |
||
275 | * Check if the entity has been successfully initialized |
||
276 | */ |
||
277 | |||
278 | public function isInited() : bool { |
||
282 | |||
283 | /** |
||
284 | * Check if the entity is a directory |
||
285 | */ |
||
286 | |||
287 | public function isDir() : bool { |
||
291 | |||
292 | /** |
||
293 | * Check if the entity is a file |
||
294 | */ |
||
295 | |||
296 | public function isFile() : bool { |
||
300 | |||
301 | /** |
||
302 | * Get the entity parent |
||
303 | */ |
||
304 | |||
305 | public function getParent() : Container { |
||
309 | |||
310 | /** |
||
311 | * Get the entity name |
||
312 | */ |
||
313 | |||
314 | public function getName() : string { |
||
318 | |||
319 | /** |
||
320 | * Get the entity relative path |
||
321 | */ |
||
322 | |||
323 | public function getPath() : string { |
||
327 | |||
328 | /** |
||
329 | * Get the entity full path |
||
330 | */ |
||
331 | |||
332 | public function getPathFull() : string { |
||
336 | |||
337 | /** |
||
338 | * Get the entity type |
||
339 | */ |
||
340 | |||
341 | public function getType() : string { |
||
345 | } |
||
346 | } |
||
347 |
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.