Ideia chave: Cada função deve fazer apenas uma tarefa.
As funções devem ser curtas para evitar bugs, facilitar o entendimento, a manutenção, etc.
Deve-se extrair subtarefas em funções separadas, sempre de maneira a tornar o código o mais legível possível. Para isso, cada função deve conter apenas um nível de abstração.
Funções com blocos longos de declarações If, else, while, for, case ou muitos aninhamentos normalmente contém várias subtarefas que poderiam ser quebradas em funções distintas. As declarações If/Else, While, Case, etc deveriam conter poucas linhas, normalmente apenas as chamadas às funções que realizam cada tarefa específica.
Exemplo:
#INCLUDE "TOTVS.CH"
Function EnvEmail()
Local cSMTP := ''
Local cConta := ''
Local cPass := ''
Local cDestinatario := ''
Local cAssunto := "Assunto"
Local cHtml := ''
Local lRet := .F.
U_CfgMailIni(@cSMTP, @cConta, @cDestinatario) // Busca configuracoes do ini
cHtml := U_MontaHTML() // Monta corpo do email
lRet := U_EnviaEmail(cSMTP, cConta, cPass, cDestinatario, cAssunto, cHtml) // Envia Email
Return lRet
Neste exemplo, a função faz apenas as chamadas necessárias para que o procedimento que ela se encarrega seja executado. A forma e os detalhes necessários para que o processo macro seja executado está subdividido em outras funções. Cada uma com apenas uma tarefa no seu nível de abstração.
Uma função ficará encarregada apenas de buscar as configurações do arquivo ini:
#INCLUDE "TOTVS.CH"
Function CfgMailIni(cSmtp, cConta, cDestinatario)
Local cSecao := 'EMAIL'
Local cPath := "C:\EmailCFG.ini"
// Le configuracoes de arquivo .ini
cSmtp := GetPvProfString(cSecao, "SMTP", '', cPath)
cConta := GetPvProfString(cSecao, "CONTA", '', cPath)
cDestinatario := GetPvProfString(cSecao, "DESTINATARIO", '', cPath)
Return
Outra função irá apenas montar o corpo do email:
#INCLUDE "TOTVS.CH"
Function MontaHtml()
Local cHtml :=''
cHtml += '<html>'
cHtml += '<head>'
cHtml += '<META http-equiv="Content-Type" content="text/html;charset=ISO-8859-1">'
cHtml += '<style type="text/css">'
cHtml += '#Cab{font-family:Verdana;}'
cHtml += '</style>'
cHtml += '<title>Email de testes</title>'
cHtml += '</head>'
cHtml += '<body>'
cHtml += '<h3 id="Cab">Corpo do Email</h3>'
cHtml += '</body>'
cHtml += '</html>'
Return cHtml
E uma última irá apenas receber tudo e enviar o email definitivamente:
#INCLUDE "TOTVS.CH"
Function EnviaEmail(cSMTP, cConta, cPass, cDestinatario, cAssunto, cMensagem)
Local lConSMTP := .F.
Local lEnvEmail := .F.
Local cError := ''
Connect SMTP Server cSMTP Account cConta Password cPass Result lConSMTP
// Se a conexao com o SMPT funcionou
If lConSMTP
Send Mail From cConta;
To cDestinatario;
Subject cAssunto;
Body cMensagem;
Result lEnvEmail
If !lEnvEmail // Erro no envio do email
Get Mail Error cError
ConOut("Erro no envio do email. " + cError)
Endif
Disconnect SMTP Server
Else // Erro na conexao com o SMTP Server
Get Mail Error cError
ConOut("Erro na conexão SMTP. " + cError)
Endif
Return lEnvEmail