4.3 Implementação
6.5.4 Refatoração de um Brain Repository Method
A Listagem6.7exibe parte do código da camada de modelo onde houve a ocorrência do problema de design Brain Repository Method. Na linha 4 é exibido o trecho de um método com complexidade ciclomática e estrutural do SQL altas.
Listagem 6.7 – Ocorrência de Brain Repository Method
1 # models.py
2 class Variavel(models.ModelPlus): 3
4 def get_qs_despesas_custeios_nes(self, list=None, uo=None, for_diff=False): 5 ...
6 sql = """with recursive empenhos (empenho_id, emit_ug, ref_id, ptres, item_id, sb_nat, valor) as
7 (select n.id as empenho_id, n.emitente_ug_id as emit_ug, n.referencia_empenho_id as ref_id, pt.codigo as ptres, it.id as item_id,
8 nd.codigo as sbnat_codigo, nd.nome as sbnat_nome, it.valor_total as valor, e.tipo as evento
9 from [...]
10 where rf.id = n.referencia_empenho_id
11 and pt.id = rf.ptres_id
12 and e.id = n.evento_id
13 and n.id = li.nota_empenho_id
14 and li.id = it.lista_itens_id
15 and nd.id = it.subitem_id
16 and n.referencia_empenho_id in (select distinct ne.id
17 from [...]
18 where ne.referencia_empenho_id is null
19 and ne.referencia_empenho_original = ’’
20 and nd.id = ne.natureza_despesa_id
21 and pt.id = ne.ptres_id
22 and ci.id = pt.classificacao_institucional_id
23 and pt.codigo != ’031727’
24 and ci.codigo = ’{}’
25 and nd.codigo like ’33%%’
26 and extract(YEAR FROM ne.data_emissao) = {})
27 UNION ALL
28 select distinct n.id as empenho_id, n.emitente_ug_id as emit_ug, n.referencia_empenho_id as ref_id, empenhos.ptres, it.id as item_id,
29 nd.codigo as sbnat_codigo, nd.nome as sbnat_nome, it.valor_total as valor, e.tipo as evento
30 from [...]
31 where e.id = n.evento_id
32 and n.id = li.nota_empenho_id
33 and li.id = it.lista_itens_id
Capítulo 6. Estudo de Caso 70
35 and extract(YEAR FROM n.data_emissao) = {}
36 )
37 select * from (
38 select codigo, nome, sum(valor)-sum(desconto) as valor , emit_ug
39 from (select sbnat_codigo as codigo, emit_ug,
40 sbnat_nome as nome,
41 case when evento in ({})
42 then sum(valor)
43 else 0
44 end as valor,
45 case when evento not in ({})
46 then sum(valor)
47 else 0
48 end as desconto
49 from (select ne.id as empenho_id, ne.emitente_ug_id as emit_ug,
ne.referencia_empenho_id as ref_id, pt.codigo as ptres, it.id as item_id,
50 nd.codigo as sbnat_codigo, nd.nome as sbnat_nome, it.valor_total as valor, ev.tipo as evento
51 from [...]
52 where ne.referencia_empenho_id is null
53 and ne.id = li.nota_empenho_id
54 and li.id = it.lista_itens_id
55 and nd.id = it.subitem_id
56 and ev.id = ne.evento_id
57 and pt.id = ne.ptres_id
58 and ci.id = pt.classificacao_institucional_id
59 and pt.codigo != ’031727’
60 and ci.codigo = ’{}’
61 and nd.codigo like ’33%%’
62 and extract(YEAR FROM ne.data_emissao) = {}
63 UNION ALL
64 select * from empenhos) despesas
65 group by sbnat_codigo, sbnat_nome, evento, emit_ug) desp
66 group by codigo, nome, emit_ug
67 ) list where valor != 0.00 {}""".format( 68 ...
A sugestão do catálogo para remoção do problema Brain Repository Method é quebrar o método em métodos menores separando a parte do código responsável pela construção ou execução do SQL do restante da lógica. Para isso identificamos a parte do método onde a consulta SQL é construída. Em seguida, movemos esta consulta para um novo método na mesma classe. Após isso, corrigimos o método refatorado para acessar o SQL gerado novo método. A Listagem 6.8 exibe as alterações realizadas no código.
Listagem 6.8 – Ocorrência de Brain Repository Method Refatorada
1 # models.py
2 class Variavel(models.ModelPlus): 3
4 def get_qs_despesas_custeios_nes(self, list=None, uo=None, for_diff=False): 5 ...
6 sql = self.get_sql_despesas_custeios_nes.format(
7 gestao, ano_referencia, ano_referencia, eventos_emp, eventos_emp, gestao, ano_referencia, 8 self.get_filtro_emit_ug(uo))
9 ... 10
Capítulo 6. Estudo de Caso 71
12 return """with recursive empenhos (empenho_id, emit_ug, ref_id, ptres, item_id, sb_nat, valor) as
13 (select n.id as empenho_id, n.emitente_ug_id as emit_ug, n.referencia_empenho_id as ref_id, pt.codigo as ptres, it.id as item_id,
14 nd.codigo as sbnat_codigo, nd.nome as sbnat_nome, it.valor_total as valor, e.tipo as evento
15 from [...]
16 where rf.id = n.referencia_empenho_id
17 and pt.id = rf.ptres_id
18 and e.id = n.evento_id
19 and n.id = li.nota_empenho_id
20 and li.id = it.lista_itens_id
21 and nd.id = it.subitem_id
22 and n.referencia_empenho_id in (select distinct ne.id
23 from [...]
24 where ne.referencia_empenho_id is null
25 and ne.referencia_empenho_original = ’’
26 and nd.id = ne.natureza_despesa_id
27 and pt.id = ne.ptres_id
28 and ci.id = pt.classificacao_institucional_id
29 and pt.codigo != ’031727’
30 and ci.codigo = ’{}’
31 and nd.codigo like ’33%%’
32 and extract(YEAR FROM ne.data_emissao) = {})
33 UNION ALL
34 select distinct n.id as empenho_id, n.emitente_ug_id as emit_ug, n.referencia_empenho_id as ref_id, empenhos.ptres, it.id as item_id,
35 nd.codigo as sbnat_codigo, nd.nome as sbnat_nome, it.valor_total as valor, e.tipo as evento
36 from [...]
37 where e.id = n.evento_id
38 and n.id = li.nota_empenho_id
39 and li.id = it.lista_itens_id
40 and nd.id = it.subitem_id
41 and extract(YEAR FROM n.data_emissao) = {}
42 )
43 select * from (
44 select codigo, nome, sum(valor)-sum(desconto) as valor , emit_ug
45 from (select sbnat_codigo as codigo, emit_ug,
46 sbnat_nome as nome,
47 case when evento in ({})
48 then sum(valor)
49 else 0
50 end as valor,
51 case when evento not in ({})
52 then sum(valor)
53 else 0
54 end as desconto
55 from (select ne.id as empenho_id, ne.emitente_ug_id as emit_ug,
ne.referencia_empenho_id as ref_id, pt.codigo as ptres, it.id as item_id,
56 nd.codigo as sbnat_codigo, nd.nome as sbnat_nome, it.valor_total as valor, ev.tipo as evento
57 from [...]
58 where ne.referencia_empenho_id is null
59 and ne.id = li.nota_empenho_id
60 and li.id = it.lista_itens_id
61 and nd.id = it.subitem_id
62 and ev.id = ne.evento_id
63 and pt.id = ne.ptres_id
64 and ci.id = pt.classificacao_institucional_id
Capítulo 6. Estudo de Caso 72
66 and ci.codigo = ’{}’
67 and nd.codigo like ’33%%’
68 and extract(YEAR FROM ne.data_emissao) = {}
69 UNION ALL
70 select * from empenhos) despesas
71 group by sbnat_codigo, sbnat_nome, evento, emit_ug) desp
72 group by codigo, nome, emit_ug
73 ) list where valor != 0.00 {}"""
Para resolver este problema, na linha 11 da Listagem6.8, o SQL é extraído para um novo método, assim, a complexidade estrutural do SQL é isolada da complexidade ciclomática do método original.