Delphi - Parametrizando o comportamento de um software - André Celestino
[Delphi] Parametrizando o comportamento de um software
09/03/2015 por André Celestino·6 Comentários
Alô, pessoal! Na 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!
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. Temos a oportunidade de gerar um único executável e personalizar o comportamento do software para cada um deles.
Por meio de parâmetros, ou, talvez, você pode chamá-los de "opçõ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.
Exemplo tela para configuração de parâmetros do sistema
Embora essa questão de parâmetros pareça comum, muitos desenvolvedores ainda insistem na definição de valores fixos no código-fonte. Essa prática pode oferecer uma solução pontual no software mas, cedo ou tarde, por conta do crescimento do número de usuários ou por questões arquiteturais, estes valores fixos deverão ser convertidos em parâmetros.
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:
ArquivoINI := TIniFile.Create('C:\MeuAplicativo\Configuracoes.ini');
ArquivoINI.WriteString('Parametros', 'FormatoExportacao', ComboBoxFormatacao.Text);
ArquivoINI.WriteInteger('Parametros', 'NumMaximoParcelas', StrToIntDef(EditNumParcelas.Text, 1));
Após a execução dos comandos acima, o arquivo será criado na seguinte estrutura:
FormatoExportacao=PDF
NumMaximoParcelas=8
Para ler estes valores, os comandos são bem parecidos:
ArquivoINI := TIniFle.Create('C:\MeuAplicativo\Configuracoes.ini');
sFormatoExportacao := ArquivoINI.ReadString('Parametros', 'FormatoExportacao', EmptyStr);
nNumMaximoParcelas := ArquivoINI.ReadInteger('Parametros', 'NumMaximoParcelas', 1);
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:
if ClientDataSet.RecordCount = 0 then
ClientDataSet.Append // Inclui os valores
ClientDataSet.Edit; // Altera os valores
ClientDataSet.FieldByName('FormatoExportacao').AsString := ComboBoxFormatacao.Text;
ClientDataSet.FieldByName('NumMaximoParcelas').AsInteger := StrToIntDef(EditNumParcelas.Text, 1);
ClientDataSet.SaveToFile('C:\MeuAplicativo\Configuracoes.xml');
Quando for necessário ler os valores salvos, basta apenas carregar o arquivo:
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:
Registro.RootKey := HKEY_CURRENT_USER; // raiz
Registro.OpenKey('Software\MeuAplicativo', True); // chave
Registro.WriteString('FormatoExportacao', ComboBoxFormatacao.Text);
Registro.WriteInteger('NumMaximoParcelas', StrToIntDef(EditNumParcelas.Text, 1));
Por sua vez, assim como acontece com os arquivos INI, a leitura é bem semelhante com a gravação:
if Registro.ValueExists('FormatoExportacao') then
sFormatoExportacao := Registro.ReadString('FormatoExportacao');
if Registro.ValueExists('NumMaximoParcelas') then
nNumMaximoParcelas := Registro.ReadInteger('NumMaximoParcelas');
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", "CONFIGURACOES" ou "OPCOES". A tabela poderá ser criada 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:
Query.SQL.Add('Update PARAMETROS set Valor = :Valor where NomeParametro = :NomeParametro');
Query.ParamByName('NomeParametro').AsString := 'FormatoExportacao';
Query.ParamByName('Valor').AsString := ComboBoxFormato.Text;
Query.ParamByName('NomeParametro').AsString := 'NumMaximoParcelas';
Query.ParamByName('Valor').AsInteger := StrToIntDef(EditNumParcelas.Text, 1);
Para ler os valores, portanto, é necessário usar o SELECT em uma instrução SQL:
Query.SQL.Add('Select Valor from PARAMETROS where NomeParametro = :NomeParametro');
sFormatoExportacao := Query.FieldByName('Valor').AsString;
nNumMaximoParcelas := Query.FieldByName('Valor').AsInteger;
E qual é a melhor forma?
Fica a seu critério, caro amigo!
[Delphi] Parametrizando o comportamento de um software foi atualizado em: março 9th, 2015 por André Celestino
Anterior Post anterior: O limite entre o desenvolvedor e o usuário
Seguinte Próximo post: Acoplamento temporário explícito
12/03/2015 às 19:09
O_O Como tem coisas para eu aprender , até hoje só tinha feito arquivo ini nem imaginava que existia outros .
Muito bom mesmo. (^_^)
12/03/2015 às 19:51
Às vezes a programação nos surpreende, não é? 🙂
Assim como você, eu também tenho muita coisa para aprender.
13/03/2015 às 16:41
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.
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.
Ronaldo Macena disse:
15/08/2018 às 14:17
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.