Complex classes like Produto 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 Produto, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
38 | class Produto implements Node |
||
39 | { |
||
40 | |||
41 | /** |
||
42 | * Unidade do produto, Não informar a grandeza |
||
43 | */ |
||
44 | const UNIDADE_UNIDADE = 'unidade'; |
||
45 | const UNIDADE_PECA = 'peca'; |
||
46 | const UNIDADE_METRO = 'metro'; |
||
47 | const UNIDADE_GRAMA = 'grama'; |
||
48 | const UNIDADE_LITRO = 'litro'; |
||
49 | |||
50 | private $item; |
||
51 | private $pedido; |
||
52 | private $codigo; |
||
53 | private $codigo_tributario; |
||
54 | private $codigo_barras; |
||
55 | private $descricao; |
||
56 | private $unidade; |
||
57 | private $multiplicador; |
||
58 | private $preco; |
||
59 | private $quantidade; |
||
60 | private $tributada; |
||
61 | private $peso; |
||
62 | private $desconto; |
||
63 | private $seguro; |
||
64 | private $frete; |
||
65 | private $despesas; |
||
66 | private $excecao; |
||
67 | private $cfop; |
||
68 | private $ncm; |
||
69 | private $cest; |
||
70 | private $impostos; |
||
71 | |||
72 | 8 | public function __construct($produto = array()) |
|
76 | |||
77 | /** |
||
78 | * Número do Item do Pedido de Compra - Identificação do número do item do |
||
79 | * pedido de Compra |
||
80 | */ |
||
81 | 7 | public function getItem($normalize = false) |
|
88 | |||
89 | 8 | public function setItem($item) |
|
90 | { |
||
91 | 8 | if (trim($item) != '') { |
|
92 | 7 | $item = intval($item); |
|
93 | 7 | } |
|
94 | 8 | $this->item = $item; |
|
95 | 8 | return $this; |
|
96 | } |
||
97 | |||
98 | /** |
||
99 | * informar o número do pedido de compra, o campo é de livre uso do emissor |
||
100 | */ |
||
101 | 7 | public function getPedido($normalize = false) |
|
108 | |||
109 | 8 | public function setPedido($pedido) |
|
114 | |||
115 | /** |
||
116 | * Código do produto ou serviço. Preencher com CFOP caso se trate de itens |
||
117 | * não relacionados com mercadorias/produto e que o contribuinte não possua |
||
118 | * codificação própria |
||
119 | * Formato ”CFOP9999”. |
||
120 | */ |
||
121 | 7 | public function getCodigo($normalize = false) |
|
128 | |||
129 | 8 | public function setCodigo($codigo) |
|
134 | |||
135 | /** |
||
136 | * Código do produto ou serviço. Preencher com CFOP caso se trate de itens |
||
137 | * não relacionados com mercadorias/produto e que o contribuinte não possua |
||
138 | * codificação própria |
||
139 | * Formato ”CFOP9999”. |
||
140 | */ |
||
141 | 7 | public function getCodigoTributario($normalize = false) |
|
148 | |||
149 | 8 | public function setCodigoTributario($codigo_tributario) |
|
154 | |||
155 | /** |
||
156 | * GTIN (Global Trade Item Number) do produto, antigo código EAN ou código |
||
157 | * de barras |
||
158 | */ |
||
159 | 7 | public function getCodigoBarras($normalize = false) |
|
166 | |||
167 | 8 | public function setCodigoBarras($codigo_barras) |
|
172 | |||
173 | /** |
||
174 | * Descrição do produto ou serviço |
||
175 | */ |
||
176 | 7 | public function getDescricao($normalize = false) |
|
183 | |||
184 | 8 | public function setDescricao($descricao) |
|
189 | |||
190 | /** |
||
191 | * Unidade do produto, Não informar a grandeza |
||
192 | */ |
||
193 | 7 | public function getUnidade($normalize = false) |
|
194 | { |
||
195 | 7 | if (!$normalize) { |
|
196 | 3 | return $this->unidade; |
|
197 | } |
||
198 | 7 | switch ($this->unidade) { |
|
199 | 7 | case self::UNIDADE_UNIDADE: |
|
200 | 7 | return 'UN'; |
|
201 | case self::UNIDADE_PECA: |
||
202 | return 'PC'; |
||
203 | case self::UNIDADE_METRO: |
||
204 | return 'm'; |
||
205 | case self::UNIDADE_GRAMA: |
||
206 | return 'g'; |
||
207 | case self::UNIDADE_LITRO: |
||
208 | return 'L'; |
||
209 | } |
||
210 | return $this->unidade; |
||
211 | } |
||
212 | |||
213 | 8 | public function setUnidade($unidade) |
|
235 | |||
236 | 7 | public function getMultiplicador($normalize = false) |
|
243 | |||
244 | 8 | public function setMultiplicador($multiplicador) |
|
245 | { |
||
246 | 8 | if (trim($multiplicador) != '') { |
|
247 | 8 | $multiplicador = intval($multiplicador); |
|
248 | 8 | } |
|
249 | 8 | $this->multiplicador = $multiplicador; |
|
250 | 8 | return $this; |
|
251 | } |
||
252 | |||
253 | /** |
||
254 | * Valor unitário de comercialização - alterado para aceitar 0 a 10 casas |
||
255 | * decimais e 11 inteiros |
||
256 | */ |
||
257 | 7 | public function getPreco($normalize = false) |
|
264 | |||
265 | 8 | public function setPreco($preco) |
|
266 | { |
||
267 | 8 | if (trim($preco) != '') { |
|
268 | 7 | $preco = floatval($preco); |
|
269 | 7 | } |
|
270 | 8 | $this->preco = $preco; |
|
271 | 8 | return $this; |
|
272 | } |
||
273 | |||
274 | /** |
||
275 | * Quantidade Comercial do produto, alterado para aceitar de 0 a 4 casas |
||
276 | * decimais e 11 inteiros. |
||
277 | */ |
||
278 | 7 | public function getQuantidade($normalize = false) |
|
285 | |||
286 | 8 | public function setQuantidade($quantidade) |
|
287 | { |
||
288 | 8 | if (trim($quantidade) != '') { |
|
289 | 7 | $quantidade = floatval($quantidade); |
|
290 | 7 | } |
|
291 | 8 | $this->quantidade = $quantidade; |
|
292 | 8 | return $this; |
|
293 | } |
||
294 | |||
295 | /** |
||
296 | * Informa a quantidade tributada |
||
297 | */ |
||
298 | 7 | public function getTributada($normalize = false) |
|
305 | |||
306 | 8 | public function setTributada($tributada) |
|
307 | { |
||
308 | 8 | if (trim($tributada) != '') { |
|
309 | 7 | $tributada = floatval($tributada); |
|
310 | 7 | } |
|
311 | 8 | $this->tributada = $tributada; |
|
312 | 8 | return $this; |
|
313 | } |
||
314 | |||
315 | 3 | public function getPeso() |
|
319 | |||
320 | 8 | public function setPeso($peso) |
|
325 | |||
326 | /** |
||
327 | * Valor do Desconto |
||
328 | */ |
||
329 | 7 | public function getDesconto($normalize = false) |
|
336 | |||
337 | 8 | public function setDesconto($desconto) |
|
338 | { |
||
339 | 8 | if (trim($desconto) != '') { |
|
340 | 7 | $desconto = floatval($desconto); |
|
341 | 7 | } |
|
342 | 8 | $this->desconto = $desconto; |
|
343 | 8 | return $this; |
|
344 | } |
||
345 | |||
346 | /** |
||
347 | * informar o valor do Seguro, o Seguro deve ser rateado entre os itens de |
||
348 | * produto |
||
349 | */ |
||
350 | 7 | public function getSeguro($normalize = false) |
|
357 | |||
358 | 8 | public function setSeguro($seguro) |
|
359 | { |
||
360 | 8 | if (trim($seguro) != '') { |
|
361 | 2 | $seguro = floatval($seguro); |
|
362 | 2 | } |
|
363 | 8 | $this->seguro = $seguro; |
|
364 | 8 | return $this; |
|
365 | } |
||
366 | |||
367 | /** |
||
368 | * informar o valor do Frete, o Frete deve ser rateado entre os itens de |
||
369 | * produto. |
||
370 | */ |
||
371 | 7 | public function getFrete($normalize = false) |
|
378 | |||
379 | 8 | public function setFrete($frete) |
|
380 | { |
||
381 | 8 | if (trim($frete) != '') { |
|
382 | 2 | $frete = floatval($frete); |
|
383 | 2 | } |
|
384 | 8 | $this->frete = $frete; |
|
385 | 8 | return $this; |
|
386 | } |
||
387 | |||
388 | /** |
||
389 | * informar o valor de outras despesas acessórias do item de produto ou |
||
390 | * serviço |
||
391 | */ |
||
392 | 7 | public function getDespesas($normalize = false) |
|
399 | |||
400 | 8 | public function setDespesas($despesas) |
|
401 | { |
||
402 | 8 | if (trim($despesas) != '') { |
|
403 | 2 | $despesas = floatval($despesas); |
|
404 | 2 | } |
|
405 | 8 | $this->despesas = $despesas; |
|
406 | 8 | return $this; |
|
407 | } |
||
408 | |||
409 | /** |
||
410 | * Código EX TIPI |
||
411 | */ |
||
412 | 7 | public function getExcecao($normalize = false) |
|
419 | |||
420 | 8 | public function setExcecao($excecao) |
|
425 | |||
426 | 7 | public function getCFOP($normalize = false) |
|
433 | |||
434 | 8 | public function setCFOP($cfop) |
|
435 | { |
||
436 | 8 | if (trim($cfop) != '') { |
|
437 | 7 | $cfop = intval($cfop); |
|
438 | 7 | } |
|
439 | 8 | $this->cfop = $cfop; |
|
440 | 8 | return $this; |
|
441 | } |
||
442 | |||
443 | /** |
||
444 | * Código NCM (8 posições), será permitida a informação do gênero (posição |
||
445 | * do capítulo do NCM) quando a operação não for de comércio exterior |
||
446 | * (importação/exportação) ou o produto não seja tributado pelo IPI. Em |
||
447 | * caso de item de serviço ou item que não tenham produto (Ex. |
||
448 | * transferência de crédito, crédito do ativo imobilizado, etc.), informar |
||
449 | * o código 00 (zeros) (v2.0) |
||
450 | */ |
||
451 | 7 | public function getNCM($normalize = false) |
|
458 | |||
459 | 8 | public function setNCM($ncm) |
|
464 | |||
465 | 7 | public function getCEST($normalize = false) |
|
472 | |||
473 | 8 | public function setCEST($cest) |
|
478 | |||
479 | 7 | public function getImpostos() |
|
483 | |||
484 | 8 | public function setImpostos($impostos) |
|
489 | |||
490 | 3 | public function addImposto($imposto) |
|
495 | |||
496 | /** |
||
497 | * Valor unitário |
||
498 | */ |
||
499 | 7 | public function getPrecoUnitario($normalize = false) |
|
506 | |||
507 | /** |
||
508 | * Valor tributável |
||
509 | */ |
||
510 | 7 | public function getPrecoTributavel($normalize = false) |
|
517 | |||
518 | 7 | public function getBase($normalize = false) |
|
525 | |||
526 | 5 | public function getContabilizado($normalize = false) |
|
533 | |||
534 | 7 | public function getImpostoInfo() |
|
535 | { |
||
536 | 7 | $config = SEFAZ::getInstance()->getConfiguracao(); |
|
537 | 7 | $db = $config->getBanco(); |
|
538 | 7 | $endereco = $config->getEmitente()->getEndereco(); |
|
539 | 7 | $info = array('total' => 0.00); |
|
540 | $tipos = array( |
||
541 | // Imposto::TIPO_IMPORTADO, // TODO: determinar quando usar |
||
542 | 7 | Imposto::TIPO_NACIONAL, |
|
543 | 7 | Imposto::TIPO_ESTADUAL, |
|
544 | Imposto::TIPO_MUNICIPAL |
||
545 | 7 | ); |
|
546 | 7 | $imposto = new \NFe\Entity\Imposto\Total(); |
|
547 | 7 | $imposto->setBase($this->getBase()); |
|
548 | 7 | $aliquota = $db->getImpostoAliquota( |
|
549 | 7 | $this->getNCM(), |
|
550 | 7 | $endereco->getMunicipio()->getEstado()->getUF(), |
|
551 | 7 | $this->getExcecao(), |
|
552 | 7 | $config->getEmitente()->getCNPJ(), |
|
553 | 7 | $config->getTokenIBPT() |
|
554 | 7 | ); |
|
555 | 7 | if ($aliquota === false) { |
|
556 | throw new \Exception('Não foi possível obter o tributo aproximado do produto "'. |
||
557 | $this->getDescricao().'" e item '.$this->getItem(), 404); |
||
558 | } |
||
559 | 7 | foreach ($tipos as $tipo) { |
|
560 | 7 | $imposto->setAliquota($aliquota[$tipo]); |
|
561 | 7 | $tributo = round($imposto->getTotal(), 2); |
|
562 | 7 | $info[$tipo] = $tributo; |
|
563 | 7 | $info['total'] += $tributo; |
|
564 | 7 | } |
|
565 | 7 | $info['info'] = $aliquota['info']; |
|
566 | 7 | return $info; |
|
567 | } |
||
568 | |||
569 | 3 | public function toArray() |
|
595 | |||
596 | 8 | public function fromArray($produto = array()) |
|
597 | { |
||
598 | 8 | if ($produto instanceof Produto) { |
|
599 | 3 | $produto = $produto->toArray(); |
|
600 | 8 | } elseif (!is_array($produto)) { |
|
601 | 3 | return $this; |
|
602 | } |
||
603 | 8 | if (isset($produto['item'])) { |
|
604 | 1 | $this->setItem($produto['item']); |
|
605 | 1 | } else { |
|
606 | 8 | $this->setItem(null); |
|
607 | } |
||
710 | |||
711 | 7 | public static function addNodeInformacoes($tributos, $element, $name = null) |
|
742 | |||
743 | 7 | public function getNode($name = null) |
|
820 | |||
821 | 4 | public function loadNode($element, $name = null) |
|
949 | } |
||
950 |
The number of this metric differs depending on the chosen design (inheritance vs. composition). For inheritance, the number should generally be a bit lower.
A high number indicates a reusable class. It might also make the class harder to change without breaking other classes though.