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 |
||
22 | abstract class Entity |
||
23 | { |
||
24 | /** |
||
25 | * @var string |
||
26 | */ |
||
27 | protected $bot_name; |
||
28 | |||
29 | /** |
||
30 | * Get bot name |
||
31 | * |
||
32 | * @return string |
||
33 | */ |
||
34 | public function getBotName() |
||
38 | |||
39 | /** |
||
40 | * Entity constructor. |
||
41 | * |
||
42 | * @todo Get rid of the $bot_name, it shouldn't be here! |
||
43 | * |
||
44 | * @param $data |
||
45 | * @param string $bot_name |
||
46 | * |
||
47 | * @throws \Longman\TelegramBot\Exception\TelegramException |
||
48 | */ |
||
49 | 58 | public function __construct($data, $bot_name = '') |
|
55 | |||
56 | /** |
||
57 | * Perform to json |
||
58 | * |
||
59 | * @return string |
||
60 | */ |
||
61 | 1 | public function toJson() |
|
65 | |||
66 | /** |
||
67 | * Reflect |
||
68 | * |
||
69 | * @param null $object |
||
70 | * |
||
71 | * @return array |
||
72 | */ |
||
73 | 1 | public function reflect($object = null) |
|
142 | |||
143 | /** |
||
144 | * Perform to string |
||
145 | * |
||
146 | * @return string |
||
147 | */ |
||
148 | public function __toString() |
||
152 | |||
153 | /** |
||
154 | * Helper to set member variables |
||
155 | * |
||
156 | * @param array $data |
||
157 | */ |
||
158 | 58 | protected function assignMemberVariables(array $data) |
|
164 | |||
165 | /** |
||
166 | * Get the list of the properties that are themselves Entities |
||
167 | * |
||
168 | * @return array |
||
169 | */ |
||
170 | 36 | protected function subEntities() |
|
174 | |||
175 | /** |
||
176 | * Perform any special entity validation |
||
177 | * |
||
178 | * @throws \Longman\TelegramBot\Exception\TelegramException |
||
179 | */ |
||
180 | 31 | protected function validate() |
|
183 | |||
184 | /** |
||
185 | * Get a property from the current Entity |
||
186 | * |
||
187 | * @param mixed $property |
||
188 | * @param mixed $default |
||
189 | * |
||
190 | * @return mixed |
||
191 | */ |
||
192 | 53 | public function getProperty($property, $default = null) |
|
200 | |||
201 | /** |
||
202 | * Return the variable for the called getter or magically set properties dynamically. |
||
203 | * |
||
204 | * @param $method |
||
205 | * @param $args |
||
206 | * |
||
207 | * @return mixed|null |
||
208 | */ |
||
209 | 39 | public function __call($method, $args) |
|
210 | { |
||
211 | //Convert method to snake_case (which is the name of the property) |
||
212 | 39 | $property_name = ltrim(strtolower(preg_replace('/[A-Z]/', '_$0', substr($method, 3))), '_'); |
|
213 | |||
214 | 39 | $action = substr($method, 0, 3); |
|
215 | 39 | if ($action === 'get') { |
|
216 | 39 | $property = $this->getProperty($property_name); |
|
217 | |||
218 | 39 | if ($property !== null) { |
|
219 | //Get all sub-Entities of the current Entity |
||
220 | 39 | $sub_entities = $this->subEntities(); |
|
221 | |||
222 | 39 | if (isset($sub_entities[$property_name])) { |
|
223 | 15 | return new $sub_entities[$property_name]($property); |
|
224 | } |
||
225 | |||
226 | 38 | return $property; |
|
227 | } |
||
228 | 3 | } elseif ($action === 'set') { |
|
229 | // Limit setters to specific classes. |
||
230 | 3 | if ($this instanceof InlineEntity || $this instanceof Keyboard || $this instanceof KeyboardButton) { |
|
231 | 3 | $this->$property_name = $args[0]; |
|
232 | |||
233 | 3 | return $this; |
|
234 | } |
||
235 | } |
||
236 | |||
237 | 23 | return null; |
|
238 | } |
||
239 | |||
240 | /** |
||
241 | * Return an array of nice objects from an array of object arrays |
||
242 | * |
||
243 | * This method is used to generate pretty object arrays |
||
244 | * mainly for PhotoSize and Entities object arrays. |
||
245 | * |
||
246 | * @param string $class |
||
247 | * @param string $property |
||
248 | * |
||
249 | * @return array |
||
250 | */ |
||
251 | 6 | protected function makePrettyObjectArray($class, $property) |
|
269 | |||
270 | /** |
||
271 | * Escape markdown special characters |
||
272 | * |
||
273 | * @param string $string |
||
274 | * |
||
275 | * @return string |
||
276 | */ |
||
277 | 1 | public function escapeMarkdown($string) |
|
285 | |||
286 | /** |
||
287 | * Try to mention the user |
||
288 | * |
||
289 | * Mention the user with the username otherwise print first and last name |
||
290 | * if the $escape_markdown argument is true special characters are escaped from the output |
||
291 | * |
||
292 | * @param bool $escape_markdown |
||
293 | * |
||
294 | * @return string|null |
||
295 | */ |
||
296 | 3 | public function tryMention($escape_markdown = false) |
|
326 | } |
||
327 |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.