Complex classes like Imposto 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 Imposto, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
36 | abstract class Imposto implements Node |
||
37 | { |
||
38 | |||
39 | /** |
||
40 | * Tipo de imposto |
||
41 | */ |
||
42 | const TIPO_IMPORTADO = 'importado'; |
||
43 | const TIPO_NACIONAL = 'nacional'; |
||
44 | const TIPO_ESTADUAL = 'estadual'; |
||
45 | const TIPO_MUNICIPAL = 'municipal'; |
||
46 | |||
47 | /** |
||
48 | * Grupo do imposto |
||
49 | */ |
||
50 | const GRUPO_ICMS = 'icms'; |
||
51 | const GRUPO_PIS = 'pis'; |
||
52 | const GRUPO_COFINS = 'cofins'; |
||
53 | const GRUPO_IPI = 'ipi'; |
||
54 | const GRUPO_II = 'ii'; |
||
55 | const GRUPO_PISST = 'pisst'; |
||
56 | const GRUPO_COFINSST = 'cofinsst'; |
||
57 | const GRUPO_ISSQN = 'issqn'; |
||
58 | const GRUPO_ICMSUFDEST = 'icmsufdest'; |
||
59 | |||
60 | private $tipo; |
||
61 | private $grupo; |
||
62 | private $tributacao; |
||
63 | private $aliquota; |
||
64 | private $base; |
||
65 | |||
66 | 141 | public function __construct($imposto = []) |
|
70 | |||
71 | /** |
||
72 | * Tipo de imposto |
||
73 | */ |
||
74 | 57 | public function getTipo($normalize = false) |
|
81 | |||
82 | 141 | public function setTipo($tipo) |
|
87 | |||
88 | /** |
||
89 | * Grupo do imposto |
||
90 | */ |
||
91 | 84 | public function getGrupo($normalize = false) |
|
118 | |||
119 | 141 | public function setGrupo($grupo) |
|
120 | { |
||
121 | 141 | switch ($grupo) { |
|
122 | 141 | case 'ICMS': |
|
123 | 29 | $grupo = self::GRUPO_ICMS; |
|
124 | 29 | break; |
|
125 | 141 | case 'PIS': |
|
126 | 27 | $grupo = self::GRUPO_PIS; |
|
127 | 27 | break; |
|
128 | 141 | case 'COFINS': |
|
129 | 27 | $grupo = self::GRUPO_COFINS; |
|
130 | 27 | break; |
|
131 | 141 | case 'IPI': |
|
132 | $grupo = self::GRUPO_IPI; |
||
133 | break; |
||
134 | 141 | case 'II': |
|
135 | $grupo = self::GRUPO_II; |
||
136 | break; |
||
137 | 141 | case 'PISST': |
|
138 | $grupo = self::GRUPO_PISST; |
||
139 | break; |
||
140 | 141 | case 'COFINSST': |
|
141 | $grupo = self::GRUPO_COFINSST; |
||
142 | break; |
||
143 | 141 | case 'ISSQN': |
|
144 | $grupo = self::GRUPO_ISSQN; |
||
145 | break; |
||
146 | 141 | case 'ICMSUFDest': |
|
147 | $grupo = self::GRUPO_ICMSUFDEST; |
||
148 | break; |
||
149 | } |
||
150 | 141 | $this->grupo = $grupo; |
|
151 | 141 | return $this; |
|
152 | } |
||
153 | |||
154 | /** |
||
155 | * Código da situação tributária |
||
156 | */ |
||
157 | 126 | public function getTributacao($normalize = false) |
|
164 | |||
165 | 141 | public function setTributacao($tributacao) |
|
170 | |||
171 | /** |
||
172 | * Porcentagem do imposto |
||
173 | */ |
||
174 | 117 | public function getAliquota($normalize = false) |
|
181 | |||
182 | 141 | public function setAliquota($aliquota) |
|
187 | |||
188 | /** |
||
189 | * Valor base para cálculo do imposto |
||
190 | */ |
||
191 | 119 | public function getBase($normalize = false) |
|
198 | |||
199 | /** |
||
200 | * Altera o valor do Base para o informado no parâmetro |
||
201 | * @param mixed $base novo valor para Base |
||
202 | * @return Imposto A própria instância da classe |
||
203 | */ |
||
204 | 141 | public function setBase($base) |
|
209 | |||
210 | /** |
||
211 | * Calcula o valor do imposto com base na aliquota e valor base |
||
212 | */ |
||
213 | 97 | public function getValor($normalize = false) |
|
220 | |||
221 | /** |
||
222 | * Obtém o valor total do imposto |
||
223 | */ |
||
224 | 36 | public function getTotal($normalize = false) |
|
228 | |||
229 | 57 | public function toArray($recursive = false) |
|
240 | |||
241 | 141 | public function fromArray($imposto = []) |
|
275 | |||
276 | 59 | public static function criaPeloNome($nome, $quantitativo = false) |
|
277 | { |
||
278 | 59 | switch ($nome) { |
|
279 | /* Grupo COFINS */ |
||
280 | 59 | case 'COFINSAliq': |
|
281 | 27 | $imposto = new Imposto\COFINS\Aliquota(); |
|
282 | 27 | break; |
|
283 | 59 | case 'COFINSOutr': |
|
284 | 1 | $imposto = new Imposto\COFINS\Generico(); |
|
285 | 1 | break; |
|
286 | 58 | case 'COFINSNT': |
|
287 | 1 | $imposto = new Imposto\COFINS\Isento(); |
|
288 | 1 | break; |
|
289 | 57 | case 'COFINSQtde': |
|
290 | 1 | $imposto = new Imposto\COFINS\Quantidade(); |
|
291 | 1 | break; |
|
292 | /* Grupo COFINSST */ |
||
293 | 56 | case 'COFINSST': |
|
294 | 2 | if ($quantitativo) { |
|
295 | 1 | $imposto = new Imposto\COFINS\ST\Quantidade(); |
|
296 | } else { |
||
297 | 1 | $imposto = new Imposto\COFINS\ST\Aliquota(); |
|
298 | } |
||
299 | 2 | break; |
|
300 | /* Grupo ICMS */ |
||
301 | 54 | case 'ICMS60': |
|
302 | 27 | $imposto = new Imposto\ICMS\Cobrado(); |
|
303 | 27 | break; |
|
304 | 54 | case 'ICMS10': |
|
305 | 1 | $imposto = new Imposto\ICMS\Cobranca(); |
|
306 | 1 | break; |
|
307 | 53 | case 'ICMS51': |
|
308 | 1 | $imposto = new Imposto\ICMS\Diferido(); |
|
309 | 1 | break; |
|
310 | 52 | case 'ICMS90': |
|
311 | 1 | $imposto = new Imposto\ICMS\Generico(); |
|
312 | 1 | break; |
|
313 | 51 | case 'ICMS00': |
|
314 | 1 | $imposto = new Imposto\ICMS\Integral(); |
|
315 | 1 | break; |
|
316 | 50 | case 'ICMS40': |
|
317 | 1 | $imposto = new Imposto\ICMS\Isento(); |
|
318 | 1 | break; |
|
319 | 49 | case 'ICMS70': |
|
320 | 1 | $imposto = new Imposto\ICMS\Mista(); |
|
321 | 1 | break; |
|
322 | 48 | case 'ICMS30': |
|
323 | 1 | $imposto = new Imposto\ICMS\Parcial(); |
|
324 | 1 | break; |
|
325 | 47 | case 'ICMSPart': |
|
326 | 1 | $imposto = new Imposto\ICMS\Partilha(); |
|
327 | 1 | break; |
|
328 | 46 | case 'ICMS20': |
|
329 | 1 | $imposto = new Imposto\ICMS\Reducao(); |
|
330 | 1 | break; |
|
331 | 45 | case 'ICMSST': |
|
332 | 1 | $imposto = new Imposto\ICMS\Substituto(); |
|
333 | 1 | break; |
|
334 | /* Grupo ICMS Simples */ |
||
335 | 44 | case 'ICMSSN500': |
|
336 | 2 | $imposto = new Imposto\ICMS\Simples\Cobrado(); |
|
337 | 2 | break; |
|
338 | 42 | case 'ICMSSN201': |
|
339 | 1 | $imposto = new Imposto\ICMS\Simples\Cobranca(); |
|
340 | 1 | break; |
|
341 | 41 | case 'ICMSSN900': |
|
342 | 1 | $imposto = new Imposto\ICMS\Simples\Generico(); |
|
343 | 1 | break; |
|
344 | 40 | case 'ICMSSN102': |
|
345 | 1 | $imposto = new Imposto\ICMS\Simples\Isento(); |
|
346 | 1 | break; |
|
347 | 39 | case 'ICMSSN101': |
|
348 | 1 | $imposto = new Imposto\ICMS\Simples\Normal(); |
|
349 | 1 | break; |
|
350 | 38 | case 'ICMSSN202': |
|
351 | 1 | $imposto = new Imposto\ICMS\Simples\Parcial(); |
|
352 | 1 | break; |
|
353 | /* Grupo IPI */ |
||
354 | 37 | case 'IPITrib': |
|
355 | 2 | if ($quantitativo) { |
|
356 | 1 | $imposto = new Imposto\IPI\Quantidade(); |
|
357 | } else { |
||
358 | 1 | $imposto = new Imposto\IPI\Aliquota(); |
|
359 | } |
||
360 | 2 | break; |
|
361 | 36 | case 'IPINT': |
|
362 | 1 | $imposto = new Imposto\IPI\Isento(); |
|
363 | 1 | break; |
|
364 | /* Grupo PIS */ |
||
365 | 35 | case 'PISAliq': |
|
366 | 27 | $imposto = new Imposto\PIS\Aliquota(); |
|
367 | 27 | break; |
|
368 | 8 | case 'PISOutr': |
|
369 | 1 | $imposto = new Imposto\PIS\Generico(); |
|
370 | 1 | break; |
|
371 | 7 | case 'PISNT': |
|
372 | 1 | $imposto = new Imposto\PIS\Isento(); |
|
373 | 1 | break; |
|
374 | 6 | case 'PISQtde': |
|
375 | 1 | $imposto = new Imposto\PIS\Quantidade(); |
|
376 | 1 | break; |
|
377 | /* Grupo PISST */ |
||
378 | 5 | case 'PISST': |
|
379 | 2 | if ($quantitativo) { |
|
380 | 1 | $imposto = new Imposto\PIS\ST\Quantidade(); |
|
381 | } else { |
||
382 | 1 | $imposto = new Imposto\PIS\ST\Aliquota(); |
|
383 | } |
||
384 | 2 | break; |
|
385 | /* Grupo II básico */ |
||
386 | 3 | case 'II': |
|
387 | 1 | $imposto = new Imposto\II(); |
|
388 | 1 | break; |
|
389 | /* Grupo IPI básico */ |
||
390 | 2 | case 'IPI': |
|
391 | 1 | $imposto = new Imposto\IPI(); |
|
392 | 1 | break; |
|
393 | default: |
||
394 | 1 | return false; |
|
395 | } |
||
396 | 58 | return $imposto; |
|
397 | } |
||
398 | |||
399 | 59 | public static function loadImposto($element) |
|
426 | } |
||
427 |
The class complexity is the sum of the complexity of all methods. A very high value is usually an indication that your class does not follow the single reponsibility principle and does more than one job.
Some resources for further reading:
You can also find more detailed suggestions for refactoring in the “Code” section of your repository.