Alô, pessoal! Semana passada, comentei sobre a parametrização para personalizar o comportamento de um software conforme o perfil do cliente, lembram-se? Esse tipo de funcionalidade traz flexibilidade para o software, além de várias vantagens para os próprios desenvolvedores. Mas, afinal, o que é essa parametrização, como funciona e como podemos implementá-la? “Bora” pro artigo!
Introdução
Precisamos definir os parâmetros do nosso investimento, como o valor e o prazo.
Consegue identificar o sentido do emprego da palavra “parâmetros” na frase acima? Tenho certeza que sim. Significa que o valor e o prazo serão dados variáveis, e não fixos. O investimento pode ser de 40 mil para este ano e de 50 mil para o ano que vem. Em outras palavras, a definição destes parâmetros depende da situação atual.
Da mesma forma, o comportamento de um software também depende de quem está o utilizando. Por exemplo, um dos usuários precisa exportar os dados de um histórico de compras no formato XLS para que possa editá-los. Outro usuário do mesmo software solicita essa exportação em formato PDF, de modo que o arquivo possa ser enviado por e-mail para vários destinatários.
Simples! Basta gerar um executável diferente para cada um dos usuários, não é?
No artigo sobre parâmetros na Query, levantei uma questão bem semelhante. A diferença é que, naquele artigo, expliquei a parametrização em consultas SQL e, neste artigo, explico a parametrização do comportamento do software.
Pois bem, já reparou que alguns desenvolvedores gostam de programar com fundo branco, enquanto outros preferem o fundo preto? Essa é uma opção da ferramenta de desenvolvimento, que permite a personalização conforme a preferência do desenvolvedor. Observe que não há uma versão exclusiva para cada cor de fundo. Quem define essa aparência é o usuário que utiliza a ferramenta. Então, respondendo a pergunta: não, não devemos gerar um executável diferente para cada usuário. O correto é gerar um único executável e personalizar o comportamento do software para cada um deles.
Parâmetrização do software
Podemos alcançar essa customização do comportamento por meio de parâmetros, ou você também pode chamá-los de “configurações”.
Estes parâmetros consistem em uma tela no software que permite a definição de alguns valores para o seu funcionamento, nos quais podem ser diferentes para cada usuário do sistema. A imagem abaixo é um exemplo de uma tela de opções. Basta configurá-los para que o sistema se comporte da forma esperada.
Como posso implementá-los no meu software?
Existem várias formas de codificar a gravação e a leitura de parâmetros. Neste artigo, apresentarei quatro delas. Para que o artigo não fique extenso demais, utilizarei apenas dois parâmetros nos exemplos abaixo, referente ao formato de exportação de um relatório (texto) e o número máximo de parcelas que o valor total de uma venda pode ser desdobrada (número inteiro).
1) Arquivos INI
Os arquivos INI são largamente utilizados para essa finalidade. Através de seções, chaves e valores, é possÃvel gravar e ler parâmetros facilmente, já que o Delphi traz uma biblioteca exclusiva para a manipulação destes arquivos. Para gravar os valores, faça uso dos comandos a seguir:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
uses IniFiles; var ArquivoINI: TIniFile; begin ArquivoINI := TIniFile.Create('C:\MeuAplicativo\Configuracoes.ini'); try ArquivoINI.WriteString('Parametros', 'FormatoExportacao', ComboBoxFormatacao.Text); ArquivoINI.WriteInteger('Parametros', 'NumMaximoParcelas', StrToIntDef(EditNumParcelas.Text, 1)); finally ArquivoINI.Free; end; end; |
Após a execução dos comandos acima, o arquivo será criado na seguinte estrutura:
1 2 3 |
[Parametros] FormatoExportacao=PDF NumMaximoParcelas=8 |
Para ler estes valores, os comandos são bem parecidos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
uses IniFiles; var ArquivoINI: TIniFile; begin ArquivoINI := TIniFle.Create('C:\MeuAplicativo\Configuracoes.ini'); try sFormatoExportacao := ArquivoINI.ReadString('Parametros', 'FormatoExportacao', EmptyStr); nNumMaximoParcelas := ArquivoINI.ReadInteger('Parametros', 'NumMaximoParcelas', 1); finally ArquivoINI.Free; end; end; |
2) Arquivos XML
A segunda alternativa é gravar as configurações em formato XML. Para isso, é necessário utilizar o componente TClientDataSet
, que traz o comando SaveToFile
 para exportar os dados. A minha sugestão é criar uma tabela temporária com os campos referentes aos parâmetros e preenchê-la em tempo de execução.
Para exportar os valores, é simples. Em primeiro lugar, é preciso verificar se os valores estão sendo adicionados ou alterados através da contagem de registros. Em seguida, preenchemos os campos, mesclamos as alterações e salvamos o arquivo:
1 2 3 4 5 6 7 8 9 10 11 |
if ClientDataSet.RecordCount = 0 then ClientDataSet.Append // Inclui os valores else ClientDataSet.Edit; // Altera os valores ClientDataSet.FieldByName('FormatoExportacao').AsString := ComboBoxFormatacao.Text; ClientDataSet.FieldByName('NumMaximoParcelas').AsInteger := StrToIntDef(EditNumParcelas.Text, 1); ClientDataSet.Post; ClientDataSet.MergeChangeLog; ClientDataSet.SaveToFile('C:\MeuAplicativo\Configuracoes.xml'); |
Quando for necessário ler os valores salvos, basta apenas carregar o arquivo:
1 |
ClientDataSet.LoadFromFile('C:\MeuAplicativo\Configuracoes.xml); |
3) Registro do Windows
As duas alternativas acima apresentam um problema: ambas criam um arquivo fÃsico, passÃvel de ser alterado por um editor de texto (como o bloco de notas) ou, no pior dos casos, excluÃdo do computador. Neste caso, como o software depende da leitura destes parâmetros, o seu funcionamento pode ficar comprometido. Como solução, pode-se gravar essas configurações no registro do Windows, que consiste em uma área do sistema operacional exclusiva para o armazenamento de configurações dos aplicativos instalados.
A gravação dos valores pode ser feita da seguinte forma:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
uses Registry; var Registro: TRegistry; begin Registro := TRegistry.Create; try Registro.RootKey := HKEY_CURRENT_USER; // raiz Registro.OpenKey('Software\MeuAplicativo', True); // chave Registro.WriteString('FormatoExportacao', ComboBoxFormatacao.Text); Registro.WriteInteger('NumMaximoParcelas', StrToIntDef(EditNumParcelas.Text, 1)); Registro.CloseKey; finally Registro.Free; end; end; |
Por sua vez, assim como acontece com os arquivos INI, a leitura é bem semelhante com a gravação:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
var Registro: TRegistry; begin Registro := TRegistry.Create; try Registro.RootKey := HKEY_CURRENT_USER; // raiz Registro.OpenKey('Software\MeuAplicativo', True); // chave if Registro.ValueExists('FormatoExportacao') then sFormatoExportacao := Registro.ReadString('FormatoExportacao'); if Registro.ValueExists('NumMaximoParcelas') then nNumMaximoParcelas := Registro.ReadInteger('NumMaximoParcelas'); Registro.CloseKey; finally Registro.Free; end; end; |
4) Banco de dados
Por fim, nada impede que os parâmetros do sistema sejam gravados em uma tabela no banco de dados com um nome condizente, como PARAMETROS
ou CONFIGURACOES
. A tabela poderá ser criada basicamente com apenas três colunas: Codigo
(para fins de indexação), NomeParametro
e Valor
. Para cada parâmetro existente no sistema, um registro é adicionado nessa tabela.
Considerando que os registros já existam (por meio de uma instrução INSERT
), os valores podem ser alterados através de uma Query preenchida com um comando UPDATE
:
1 2 3 4 5 6 7 8 9 10 |
Query.SQL.Clear; Query.SQL.Add('Update PARAMETROS set Valor = :Valor where NomeParametro = :NomeParametro'); Query.ParamByName('NomeParametro').AsString := 'FormatoExportacao'; Query.ParamByName('Valor').AsString := ComboBoxFormato.Text; Query.ExecSQL; Query.ParamByName('NomeParametro').AsString := 'NumMaximoParcelas'; Query.ParamByName('Valor').AsInteger := StrToIntDef(EditNumParcelas.Text, 1); Query.ExecSQL; |
Para ler os valores, portanto, é necessário usar o SELECT
em uma instrução SQL:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Query.Close; Query.SQL.Clear; Query.SQL.Add('Select Valor from PARAMETROS where NomeParametro = :NomeParametro'); Query.ParamByName('NomeParametro').AsString := 'FormatoExportacao'; Query.Open; sFormatoExportacao := Query.FieldByName('Valor').AsString; Query.Close; Query.ParamByName('NomeParametro').AsString := 'NumMaximoParcelas'; Query.Open; nNumMaximoParcelas := Query.FieldByName('Valor').AsInteger; Query.Close; |
E qual é a melhor forma?
Fica a seu critério, caro amigo!
Até a próxima! Abraço!
O_O Como tem coisas para eu aprender , até hoje só tinha feito arquivo ini nem imaginava que existia outros .
Muito bom mesmo. (^_^)
Fala, André!
Às vezes a programação nos surpreende, não é? 🙂
Assim como você, eu também tenho muita coisa para aprender.
Obrigado pelo comentário!
No caso da opção 4 (banco de dados) deve-se tomar cuidado caso a tabela seja compartilhada por outros usuários do sistema pois todos utilizarão os mesmos parâmetros . Diferente dos outros exemplos que serão validos para o computador em que sistema esteja instalado.
Espero ter colaborado
Olá, Alexandre!
Isso mesmo. Em um sistema multiusuário, se os parâmetros estiverem armazenados no banco de dados, eles serão compartilhados para todos os usuários da aplicação, ao menos que a tabela possua uma coluna para diferenciar os parâmetros de cada usuário. Por exemplo, além dos campos que mencionei do artigo, terÃamos a coluna “CodigoUsuario”, de forma que fosse possÃvel gravar valores do mesmo parâmetro para usuários diferentes. Ao iniciar a aplicação, carregarÃamos apenas as configurações do usuário conectado.
Obrigado pela colaboração!
Abraço!
Boa tarde,
André, preciso aprender como fazer meu sistema filtrar a data de aniversariante do mês e do dia.
Eu uso Firedac e o componente FDQuery. Poderia por favor me passar um exemplo para eu estudar aqui.
Já pesquisei em vários sites e não tenho conseguido fazer a programação.
Tive uma dúvida em outra ocasião, relativo a configurar um arquivo INI para meu sistema acessar a base de dados do meu sistema, e consegui solucionar usando as dicas aqui do seu site.
André, muito obrigado.
Olá, Ronaldo.
Notei que você enviou um e-mail também. Vamos nos falar por lá!
Abraço!