AJUDA COM REFATORA?ÃO
Prezados,
Há um tópico sobre refatoração que me chamou atenção e pensei em aplicar em um pequeno bloco de meus códigos.
Em uma tela tenho 3 caixas de verificação sendo
[ ] Exibe Status FATURADO
[ ] Exibe Status AGUARDANDO
[ ] Exibe Demais Status
a tabela TabItens tem o campo Status Varchar(1) que funciona como flag, sendo [Ô]F[Ô] para Faturado, [Ô]A[Ô] para Aguardando, [Ô]B[Ô] para desistência do item, [Ô]C[Ô] para Em Transporte e alguns outros status possÃveis.
Se marcar [Ô]Exibe Faturado[Ô] e Exibe Aguardando, por exemplo, poderia ser
Where Status in ([ô]F[ô],[ô]A[ô]) por exemplo.
A opção [Ô]Exibe Demais Status[Ô] faz com que sejam listados os status [Ô]C[Ô], [Ô]D[Ô], [Ô]H[Ô], etc. Claro, deverá desconsiderar o [ô]F[ô] e o [ô]A[ô] se não forem marcados. Ou considerar ambos/um deles, conforme o usuário selecione.
Tenho já um Código em VB6 que cria uma string na variável strComandoSQL e monta o sql conforme as opções selecionadas. Mas está feio o código. E complexo.
Algum colega ajuda a criar um código [Ô]limpo[Ô] e eficiente para o caso?
Há um tópico sobre refatoração que me chamou atenção e pensei em aplicar em um pequeno bloco de meus códigos.
Em uma tela tenho 3 caixas de verificação sendo
[ ] Exibe Status FATURADO
[ ] Exibe Status AGUARDANDO
[ ] Exibe Demais Status
a tabela TabItens tem o campo Status Varchar(1) que funciona como flag, sendo [Ô]F[Ô] para Faturado, [Ô]A[Ô] para Aguardando, [Ô]B[Ô] para desistência do item, [Ô]C[Ô] para Em Transporte e alguns outros status possÃveis.
Se marcar [Ô]Exibe Faturado[Ô] e Exibe Aguardando, por exemplo, poderia ser
Where Status in ([ô]F[ô],[ô]A[ô]) por exemplo.
A opção [Ô]Exibe Demais Status[Ô] faz com que sejam listados os status [Ô]C[Ô], [Ô]D[Ô], [Ô]H[Ô], etc. Claro, deverá desconsiderar o [ô]F[ô] e o [ô]A[ô] se não forem marcados. Ou considerar ambos/um deles, conforme o usuário selecione.
Tenho já um Código em VB6 que cria uma string na variável strComandoSQL e monta o sql conforme as opções selecionadas. Mas está feio o código. E complexo.
Algum colega ajuda a criar um código [Ô]limpo[Ô] e eficiente para o caso?
Posta o código para a gente analisar. Ficará bem mais fácil indicar o que está errado (se estiver errado) e o que de ser feito (se precisar ser feito).
Olá, FFCOUTO
Segue o código, conforme pediu.
Usei de outra situação no sistema antigo em VB6, mas o caso é exatamente o mesmo. Tem os campos para exibir ou não proprietário de uma torre, exibir ou não o fornecedor de energia de uma torre, exibir ou não ou demais clientes que tenham vinculo com a torre (excetuando proprietário e fornecedor de energia) e se deve ou não exibir contas que já estejam quitadas (contas ainda não quitadas têm o campo dtquitacao = [ô]01/01/1900[ô])
vw_ficontas é uma View que junta dados da tabela ficontas (contas a receber/pagar) com dados de zxcadgrl (cadastros de clientes e fornecedores) e de pvtorres (cadastro de torres).
é em vw_ficontas que faço o select.
Tudo de bom.
Segue o código, conforme pediu.
Usei de outra situação no sistema antigo em VB6, mas o caso é exatamente o mesmo. Tem os campos para exibir ou não proprietário de uma torre, exibir ou não o fornecedor de energia de uma torre, exibir ou não ou demais clientes que tenham vinculo com a torre (excetuando proprietário e fornecedor de energia) e se deve ou não exibir contas que já estejam quitadas (contas ainda não quitadas têm o campo dtquitacao = [ô]01/01/1900[ô])
vw_ficontas é uma View que junta dados da tabela ficontas (contas a receber/pagar) com dados de zxcadgrl (cadastros de clientes e fornecedores) e de pvtorres (cadastro de torres).
é em vw_ficontas que faço o select.
[ô]------------------------------------------------------------------------------------------------
[ô] !
[ô] !
[ô] FORMAR O COMANDO SQL QUE FAZ A FILTRAGEM DOS DADOS !
[ô] !
[ô] !
[ô]------------------------------------------------------------------------------------------------
[ô]----------------------------------------------------------------
[ô] !
[ô] Filtragem conforme opções marcadas !
[ô] !
[ô]----------------------------------------------------------------
[ô]-------------------------------------------------------------------------------------
[ô] Proprietário e Fornecedor de energia !
[ô]-------------------------------------------------------------------------------------
[ô]Inicialização
str_Operador_IN = [Ô] and (identregclifor in ([Ô]
[ô]Proprietário
str_Operador_IN = str_Operador_IN & IIf(Me.ck_Exibe_Contas_do_Proprietario.Value = 1, [Ô][ô][Ô] & NR_0022.txtIDENTREGPROPRIETARIO.Text & [Ô][ô],[Ô], [Ô][ô][ô][Ô])
[ô]Fornecedor de energia
str_Operador_IN = str_Operador_IN & IIf(Me.ck_Exibe_Contas_do_Proprietario.Value = 1, [Ô][ô][Ô] & NR_0022.txtIDENTREGFORNECEDORENERGIA.Text & [Ô][ô][Ô], [Ô][ô][ô][Ô])
[ô]Remover caracteres separadores de IN que sobrarem no final
str_Operador_IN = RemoveSeparadorDePieceNoInicioOuFinal(str_Operador_IN, [Ô],[Ô], False, True)
[ô]Término
str_Operador_IN = str_Operador_IN & [Ô]))[Ô]
[ô]Formar o comando SQL
str_Comando_SQL_Parte_01 = [Ô]select * from vw_ficontas where (codemp=[Ô] & CodigoEmpresa & [Ô]) and (snexcluido=[ô]N[ô]) and (id_torre_vinculada=[ô][Ô] & NR_0022.txtIDENTREG.Text & [Ô][ô])[Ô] & str_Operador_IN & IIf(Me.ck_Ocultar_Contas_Quitadas.Value = 1, [Ô] and (dtquitacao=[ô]01/01/1900[ô])[Ô], [Ô][Ô])
[ô]-------------------------------------------------------------------------------------
[ô] Exibir contas de demais cadastros que tenham vÃnculo com a torre !
[ô]-------------------------------------------------------------------------------------
If Me.ck_Exibe_Contas_demais_Cadastros.Value = 1 Then
[ô]Para INSERIR todos os demais cadastros
str_Comando_SQL_Parte_02 = [Ô]select * from vw_ficontas where (codemp=[Ô] & CodigoEmpresa & [Ô]) and (snexcluido=[ô]N[ô]) and (id_torre_vinculada=[ô][Ô] & NR_0022.txtIDENTREG.Text & [Ô][ô])[Ô] & [Ô] and (identregclifor<>[ô]AZBXAZBXAZBXAZBX[ô]) and (identregclifor not in ([ô][Ô] & NR_0022.txtIDENTREGPROPRIETARIO.Text & [Ô][ô],[ô][Ô] & NR_0022.txtIDENTREGFORNECEDORENERGIA.Text & [Ô][ô]))[Ô] & IIf(Me.ck_Ocultar_Contas_Quitadas.Value = 1, [Ô] and (dtquitacao=[ô]01/01/1900[ô])[Ô], [Ô][Ô])
Else
[ô]Para SUPRIMIR todos os demais cadastros
str_Comando_SQL_Parte_02 = [Ô]select * from vw_ficontas where (codemp=[Ô] & CodigoEmpresa & [Ô]) and (snexcluido=[ô]N[ô]) and (id_torre_vinculada=[ô][Ô] & NR_0022.txtIDENTREG.Text & [Ô][ô])[Ô] & [Ô] and (identregclifor=[ô]AZBXAZBXAZBXAZBX[ô]) and (identregclifor not in ([ô][Ô] & NR_0022.txtIDENTREGPROPRIETARIO.Text & [Ô][ô],[ô][Ô] & NR_0022.txtIDENTREGFORNECEDORENERGIA.Text & [Ô][ô]))[Ô] & IIf(Me.ck_Ocultar_Contas_Quitadas.Value = 1, [Ô] and (dtquitacao=[ô]01/01/1900[ô])[Ô], [Ô][Ô])
End If
[ô]----------------------------------------------------------------
[ô] !
[ô] Selecionar os dados !
[ô] !
[ô]----------------------------------------------------------------
Set Registros01 = Conect_PG_SQL_Local.Execute([Ô]select [Ô] & vbCrLf & _
[Ô] * [Ô] & vbCrLf & _
[Ô]from [Ô] & vbCrLf & _
[Ô] ([Ô] & vbCrLf & _
[Ô] [Ô] & str_Comando_SQL_Parte_01 & vbCrLf & _
[Ô] union all[Ô] & vbCrLf & _
[Ô] [Ô] & str_Comando_SQL_Parte_02 & vbCrLf & _
[Ô] ) as Query[Ô] & vbCrLf & _
[Ô]order by dtvencto asc, nome_cliente asc[Ô] & vbCrLf _
)
Tudo de bom.
é alguma coisa da pra melhorar vamos tentar
[ô]Inicialização
[ô]Inicialização
With Me.ck_Exibe_Contas_do_Proprietario
str_Operador_IN = [Ô] and (identregclifor in ([Ô] & IIf(.Value = 1, [Ô][ô][Ô] & _
NR_0022.txtIDENTREGPROPRIETARIO.Text & _
[Ô][ô],[ô][Ô] & NR_0022.txtIDENTREGFORNECEDORENERGIA.Text & [Ô][ô][Ô], [Ô][ô][ô],[ô][ô][Ô])
End With
[ô]Remover caracteres separadores de IN que sobrarem no final <---- não sei como está esta função mas acredito que um replace ajudaria
str_Operador_IN = RemoveSeparadorDePieceNoInicioOuFinal(str_Operador_IN, [Ô],[Ô], False, True)
[ô]Término
str_Operador_IN = str_Operador_IN & [Ô]))[Ô]
[ô]Formar o comando SQL
str_Comando_SQL_Parte_01 = [Ô]select * from vw_ficontas where (codemp=[Ô] & CodigoEmpresa & [Ô]) and (snexcluido=[ô]N[ô]) and (id_torre_vinculada=[ô][Ô] & NR_0022.txtIDENTREG.Text & [Ô][ô])[Ô] & str_Operador_IN & IIf(Me.ck_Ocultar_Contas_Quitadas.Value = 1, [Ô] and (dtquitacao=[ô]01/01/1900[ô])[Ô], [Ô][Ô])
[ô]-------------------------------------------------------------------------------------
[ô] Exibir contas de demais cadastros que tenham vÃnculo com a torre !
[ô]-------------------------------------------------------------------------------------
With Me.ck_Exibe_Contas_demais_Cadastros
[ô]Para INSERIR ou SUPRIMIR todos os demais cadastros
str_Comando_SQL_Parte_02 = [Ô]select * from vw_ficontas where (codemp=[Ô] & CodigoEmpresa & [Ô]) and (snexcluido=[ô]N[ô]) and (id_torre_vinculada=[ô][Ô] & NR_0022.txtIDENTREG.Text & [Ô][ô])[Ô] & [Ô] and (identregclifor[Ô] & IIF(.Value = 1,[Ô]<>[Ô],[Ô]=[Ô]) &[Ô][ô]AZBXAZBXAZBXAZBX[ô]) and (identregclifor not in ([ô][Ô] & NR_0022.txtIDENTREGPROPRIETARIO.Text & [Ô][ô],[ô][Ô] & NR_0022.txtIDENTREGFORNECEDORENERGIA.Text & [Ô][ô]))[Ô] & IIf(Me.ck_Ocultar_Contas_Quitadas.Value = 1, [Ô] and (dtquitacao=[ô]01/01/1900[ô])[Ô], [Ô][Ô])
End With
[ô]----------------------------------------------------------------
[ô] !
[ô] Selecionar os dados !
[ô] !
[ô]----------------------------------------------------------------
Set Registros01 = Conect_PG_SQL_Local.Execute([Ô]select * from ([Ô] & _
[Ô] & str_Comando_SQL_Parte_01 & [Ô]union all[Ô] & _
[Ô] & str_Comando_SQL_Parte_02 & _
[Ô] ) as Query order by dtvencto asc, nome_cliente asc[Ô])
)
Colegas,
Obrigado por terem respondido.
Antes de encerrar o tópico, vou fazer mais algumas tentativas de refatoração.
Caso mudanças sejam realmente feitas, postarei como ficou o código.
Tudo de bom.
Obrigado por terem respondido.
Antes de encerrar o tópico, vou fazer mais algumas tentativas de refatoração.
Caso mudanças sejam realmente feitas, postarei como ficou o código.
Tudo de bom.
ZEUZEBIO3,
Neste fim de semana vou olhar seu código mais a fundo.
Pelo que pude ver rapidamente, seu código aplica vários filtros num Select.
Aguarde pela minha resposta, ok.
Abraços
Neste fim de semana vou olhar seu código mais a fundo.
Pelo que pude ver rapidamente, seu código aplica vários filtros num Select.
Aguarde pela minha resposta, ok.
Abraços
Olá, Fabiano...
São 2 selects, sendo um para que insira na cláusula IN o código (chamado identreg) do proprietário do terreno onde fica a torre e/ou do fornecedor de energia para a torre.
O outro select é para incluir na resultset outros cadastros (de outras pessoas) que possam ter financeiro ligado à torre, como o cidadão que vai lá capinar o terreno onde a torre está ou a prefeitura que pode cobrar IPTU.
No cadastro da torre sempre tem o identreg do proprietário do terreno. Nem sempre tem o identreg do fornecedor de energia elétrica. No financeiro pode haver contas para os mesmos e para terceiros (contas lançadas manualmente) que quando do lançamento se escolhe alguma torre que tenha vÃnculo.
Então a filtragem é assim:
Incluir ou não o proprietário no resultset
Incluir ou não o fornecedor de energia no resultset
Incluir ou não outros cadastros no resultset
Eu fiz um select com IN para os identreg de proprietário e fornecedor de energia (no campo identregclifor de vw_ficontas) e outro select para identregclifor se quaisquer outros cadastros (nenhum identreg é igual a [ô]AZBXAZBXAZBX[ô]). Neste segundo select eu coloco o NOT IN para os identreg do proprietário e fornecedor de energia, porque se marcar somente esta opção (a terceira) o identregclifor <> [ô]AZBXAZBXAZBX[ô] pegaria os identregclifor de proprietário e fornecedor (que não deve pegar porque foram desmarcados).
Aguardo sim, colega. E muito obrigado por sua atenção.
Tudo de bom.
São 2 selects, sendo um para que insira na cláusula IN o código (chamado identreg) do proprietário do terreno onde fica a torre e/ou do fornecedor de energia para a torre.
O outro select é para incluir na resultset outros cadastros (de outras pessoas) que possam ter financeiro ligado à torre, como o cidadão que vai lá capinar o terreno onde a torre está ou a prefeitura que pode cobrar IPTU.
No cadastro da torre sempre tem o identreg do proprietário do terreno. Nem sempre tem o identreg do fornecedor de energia elétrica. No financeiro pode haver contas para os mesmos e para terceiros (contas lançadas manualmente) que quando do lançamento se escolhe alguma torre que tenha vÃnculo.
Então a filtragem é assim:
Eu fiz um select com IN para os identreg de proprietário e fornecedor de energia (no campo identregclifor de vw_ficontas) e outro select para identregclifor se quaisquer outros cadastros (nenhum identreg é igual a
Aguardo sim, colega. E muito obrigado por sua atenção.
Tudo de bom.
ZEUZEBIO3,
Como prometido aqui está o seu código refatorado.
Algumas observações devem ser feitas:
1) O ideal seria você colar esse código numa classe e alterar os controles checkbox e textbox para propriedades da classe. A partir daà você apenas instancia a classe, seta as propriedades, executa a consulta e destrói a instacia.
2) Ao usar um campo data e esta possuir a condição de não ser setada, como a data de quitação do seu exemplo, use null para preenche-la e desta forma você poderá usar o operador Is Null.
3) Use parâmetros no lugar de concatenar a string de sql, dessa forma você evita ataques de sql injection.
Qualquer dúvida no novo código é só postar
Espero ter ajudado.
Como prometido aqui está o seu código refatorado.
Algumas observações devem ser feitas:
1) O ideal seria você colar esse código numa classe e alterar os controles checkbox e textbox para propriedades da classe. A partir daà você apenas instancia a classe, seta as propriedades, executa a consulta e destrói a instacia.
2) Ao usar um campo data e esta possuir a condição de não ser setada, como a data de quitação do seu exemplo, use null para preenche-la e desta forma você poderá usar o operador Is Null.
3) Use parâmetros no lugar de concatenar a string de sql, dessa forma você evita ataques de sql injection.
Qualquer dúvida no novo código é só postar
[ô]Essas variáveis devem ser declaradas na sessão Declarations para que fiquem visÃveis a todas as funções abaixo.
Private strSqlComando1 As String
Private strSqlComando2 As String
[ô]----------------------------------------------------------------
[ô] REALIZA A FILTRAGEM DOS DADOS !
[ô]----------------------------------------------------------------
Public Sub Consultar()
[ô]----------------------------------------------------------------
[ô] Filtragem conforme opções marcadas !
[ô]----------------------------------------------------------------
[ô]----------------------------------------------------------------
[ô] Proprietário e Fornecedor de energia !
[ô]----------------------------------------------------------------
PrepararComandoBase strSqlComando1
PrepararFiltroCadastroPrincipal strSqlComando1, False
PrepararFiltroContasQuitadas strSqlComando1
[ô]-------------------------------------------------------------------
[ô] Exibir contas de demais cadastros que tenham vÃnculo com a torre !
[ô]-------------------------------------------------------------------
Dim bolOutrosCadastros As Boolean
[ô]Quando [ô]True[ô] a consulta vai INSERIR todos os demais cadastros
[ô]Quanto [ô]False[ô] a consulta vai SUPRIMIR todos os demais cadastros
bolOutrosCadastros = (ck_Exibe_Contas_demais_Cadastros.Value = 1)
PrepararComandoBase strSqlComando2
PrepararFiltroOutrosCadastros strSqlComando2, IIf(bolOutrosCadastros, [Ô]<>[Ô], [Ô]=[Ô])
PrepararFiltroCadastroPrincipal strSqlComando2, True
PrepararFiltroContasQuitadas strSqlComando2
[ô]----------------------------------------------------------------
[ô] Selecionar os dados !
[ô]----------------------------------------------------------------
Dim strSqlComando As String
strSqlComando = [Ô]SELECT * FROM ([Ô] & _
strSqlComando1 & [Ô] UNION ALL [Ô] & strSqlComando2 & [Ô]) AS Query [Ô] & _
[Ô]ORDER BY dtvencto ASC, nome_cliente ASC;[Ô]
Set Registros01 = Conect_PG_SQL_Local.Execute(strSqlComando)
End Sub
Private Sub PrepararComandoBase(ByRef strSQL As String)
[ô]realiza a montagem do comando 1
strSQL = [Ô]SELECT * FROM vw_ficontas [Ô]
strSQL = strSQL & [Ô]WHERE (codemp = [Ô] & CodigoEmpresa & [Ô]) [Ô]
strSQL = strSQL & [Ô]AND (snexcluido = [ô]N[ô]) [Ô]
strSQL = strSQL & [Ô]AND (id_torre_vinculada = [ô][Ô] & NR_0022.txtIDENTREG.Text & [Ô][ô]) [Ô]
End Sub
Private Sub PrepararFiltroCadastroPrincipal(ByRef strSQL As String, ByVal bExcluir As Boolean)
Dim inOper() As String
Dim intCountFilter As Integer
[ô]nenhum filtro foi especificado
intCountFilter = -1
If (ck_Exibe_Contas_do_Proprietario.Value = 1) Then
intCountFilter = intCountFilter + 1
ReDim Preserve inOper(intCountFilter)
inOper(intCountFilter) = NR_0022.txtIDENTREGPROPRIETARIO.Text
End If
If (ck_Exibe_Contas_do_Proprietario.Value = 1) Then
intCountFilter = intCountFilter + 1
ReDim Preserve inOper(intCountFilter)
inOper(intCountFilter) = NR_0022.txtIDENTREGFORNECEDORENERGIA.Text
End If
If intCountFilter > -1 Then
strSQL = strSQL & [Ô] AND (identregclifor [Ô] & IIf(bExcluir, [Ô]NOT[Ô], [Ô][Ô]) & [Ô] IN ([Ô] & Join(inOper, [Ô], [Ô]) & [Ô])) [Ô]
End If
End Sub
Private Sub PrepararFiltroOutrosCadastros(ByRef strSQL As String, ByVal operComparacao As String)
[ô]O ideal é substituir a sequencia de caracteres por uma sequencia de 5 astericos
[ô]strSQL = strSQL & Replace([Ô]AND (identregclifor %1 [ô]*****[ô]) [Ô], [Ô]%1[Ô], operComparacao)
strSQL = strSQL & Replace([Ô]AND (identregclifor %1 [ô]AZBXAZBXAZBXAZBX[ô]) [Ô], [Ô]%1[Ô], operComparacao)
End Sub
Private Sub PrepararFiltroContasQuitadas(ByRef strSQL As String)
[ô]O correto é utilizar o campo com valor null e não uma data antiga para
[ô]informar o seu não preenchimento
[ô]Com null ficara dessa forma
[ô]If (ck_Ocultar_Contas_Quitadas.Value = 1) Then
[ô] strSQL = strSQL & [Ô] AND (dtquitacao IS NULL) [Ô]
[ô]End If
[ô]Usando um valor antigo
If (ck_Ocultar_Contas_Quitadas.Value = 1) Then
strSQL = strSQL & [Ô] AND (dtquitacao = [ô]01/01/1900[ô]) [Ô]
End If
End Sub
Espero ter ajudado.
Colega FFCOUTO.
Maravilha.
Código Entendido e Refatorado.
Vou colocar na parte de adições da versão no novo sistema.
Grato e Tudo de bom!
Maravilha.
Código Entendido e Refatorado.
Vou colocar na parte de adições da versão no novo sistema.
Grato e Tudo de bom!
Tópico encerrado , respostas não são mais permitidas