Uma maneira simples de manter as configurações de um aplicativo Java é representada por um arquivo de texto com a extensão ".properties", contendo o identificador de cada configuração associada a um valor específico (esse valor pode ser um número, string, data, etc.) . O C # usa uma abordagem semelhante, mas o arquivo de texto deve ter o nome "App.config". Nos dois casos, no código fonte, você deve inicializar uma classe específica para ler as configurações: essa classe possui um método que retorna o valor (como string) associado ao identificador de configuração especificado.
// Java example
Properties config = new Properties();
config.load(...);
String valueStr = config.getProperty("listening-port");
// ...
// C# example
NameValueCollection setting = ConfigurationManager.AppSettings;
string valueStr = setting["listening-port"];
// ...
Nos dois casos, devemos analisar as seqüências carregadas do arquivo de configuração e atribuir os valores convertidos aos objetos digitados relacionados (erros de análise podem ocorrer durante esta fase). Após a etapa de análise, devemos verificar se os valores de configuração pertencem a um domínio específico de validade: por exemplo, o tamanho máximo de uma fila deve ser um valor positivo, alguns valores podem estar relacionados (exemplo: min <max ), e assim por diante.
Suponha que o aplicativo carregue as configurações assim que for iniciado: em outras palavras, a primeira operação executada pelo aplicativo é carregar as configurações. Quaisquer valores inválidos para as configurações devem ser substituídos automaticamente pelos valores padrão: se isso acontecer com um grupo de configurações relacionadas, essas configurações serão todas definidas com valores padrão.
A maneira mais fácil de executar essas operações é criar um método que primeiro analise todas as configurações, verifique os valores carregados e, finalmente, defina quaisquer valores padrão. No entanto, a manutenção é difícil se você usar esta abordagem: à medida que o número de configurações aumenta durante o desenvolvimento do aplicativo, fica cada vez mais difícil atualizar o código.
Para resolver esse problema, pensei em usar o padrão Template Method , da seguinte maneira.
public abstract class Setting
{
protected abstract bool TryParseValues();
protected abstract bool CheckValues();
public abstract void SetDefaultValues();
/// <summary>
/// Template Method
/// </summary>
public bool TrySetValuesOrDefault()
{
if (!TryParseValues() || !CheckValues())
{
// parsing error or domain error
SetDefaultValues();
return false;
}
return true;
}
}
public class RangeSetting : Setting
{
private string minStr, maxStr;
private byte min, max;
public RangeSetting(string minStr, maxStr)
{
this.minStr = minStr;
this.maxStr = maxStr;
}
protected override bool TryParseValues()
{
return (byte.TryParse(minStr, out min)
&& byte.TryParse(maxStr, out max));
}
protected override bool CheckValues()
{
return (0 < min && min < max);
}
public override void SetDefaultValues()
{
min = 5;
max = 10;
}
}
O problema é que, dessa maneira, precisamos criar uma nova classe para cada configuração, mesmo para um único valor. Existem outras soluções para esse tipo de problema?
Em suma:
- Manutenção fácil: por exemplo, a adição de um ou mais parâmetros.
- Extensibilidade: uma primeira versão do aplicativo pode ler um único arquivo de configuração, mas versões posteriores podem dar a possibilidade de uma configuração para vários usuários (o administrador define uma configuração básica, os usuários podem definir apenas determinadas configurações, etc.).
- Projeto orientado a objetos.