Classe / estrutura de configuração: padrão ou antipadrão? Alternativas?

10

Se você adicionar novas opções de configuração a um programa, ele poderá ter muitos efeitos colaterais em termos de levar as opções para onde elas precisam ser executadas. Existem três maneiras básicas de lidar com isso que eu conheço:

  1. Passe todas as definições de configuração para as partes do seu programa que precisam delas explicitamente como primitivas. Essa é a maneira mais explícita e a que mais desacopla as coisas. A desvantagem é que isso é detalhado e quebradiço.

  2. Torne as definições de configuração usadas com mais freqüência global / estáticas. Essa é a maneira mais simples, mas introduz ação à distância, dificulta a testabilidade e assume que a configuração é realmente global (que você deseja apenas uma configuração a qualquer momento).

  3. Faça uma classe / estrutura de configuração que contenha todas as opções de configuração para todo o programa ou para cada preocupação principal do programa e repasse-a explicitamente. Isso é menos explícito que (1), mas mais explícito que (2). Se você deseja alterar uma configuração apenas para uma chamada de função, pode clonar o objeto de configuração e alterar esse valor. Isso é útil nos testes e na prática. No entanto, você ainda acaba potencialmente passando toneladas de informações para uma função que não precisa, e alterar um valor na classe / estrutura de configuração ainda pode causar ações à distância.

Você consideraria (3) um padrão ou um antipadrão? Se é um anti-padrão, o que você faz?

dsimcha
fonte
Que tal uma variação em 3 - tendo várias classes de configuração, passando a apropriada para onde é necessária?
Oded
@ Oded: eu quis enfatizar isso como uma possibilidade. Editado.
dsimcha

Respostas:

4

A melhor solução seria criar várias interfaces de configuração e implementá-las como desejar. Isso limita a acessibilidade e mantém as coisas localizadas. No entanto, é muito esforço valer a pena simplesmente jogar toda a configuração em uma única classe e passar para um problema com muito mais gravidade. Essa é a configuração, não a UtterlyCrucialAlwaysChangingClass - ela permanecerá praticamente a mesma. Contanto que você não faça tudo global e a implementação seja consistente, eu não me preocuparia.

DeadMG
fonte
4
+1 por dizer que algo não é um projeto teoricamente ideal, mas ainda pode ser bom na prática quando se considera a simplicidade e a probabilidade de mudança (ou a falta dela).
dsimcha
Acabei de lançar quatro argumentos e substituí-lo por uma classe Configurações. Parecia a coisa certa.
Martin Ueding
Não entendo qual das três opções você está defendendo. Você poderia especificar?
precisa saber é o seguinte
1

Prefiro a sua opção 1 porque a dissociação permite testes mais fáceis, e as definições de configuração das quais o objeto depende são explicitadas. Se um objeto exigir uma configuração, forneça explicitamente ao objeto por um argumento construtor ou método setter. Reduza a verbosidade usando uma estrutura de injeção de dependência para injetar essas definições de configuração no objeto.

Jim Huang
fonte
Você se contradiz: diz usar a opção 1, mas diz "Reduza a verbosidade usando uma estrutura de injeção de dependência para injetar essas definições de configuração no objeto". que é a opção 3: injeção de construtor.
precisa saber é o seguinte
0

Imagine se o seu arquivo de configuração foi gravado em XML. Você pode simplesmente passar fragmentos desse XML para cada um dos seus componentes, para que eles obtenham seus dados de configuração.

Se você estiver usando o .NET, é possível criar classes com DataContracts que você pode usar o XmlSerialiser para criar uma hierarquia de objetos a partir do seu Xml de configuração e passar esses objetos como configuração.

Isso então apresenta o próximo problema. Seus dados de configuração possuem três partes diferentes. A configuração estrutural do aplicativo que organiza suas bibliotecas de códigos para se comportar como esse produto específico. As definições de configuração do site que contêm as configurações específicas da instalação e os dados de preferência / configurações do usuário que variam com cada usuário no seu sistema.

Saber qual parte é qual e manter essas configurações de dados separadas tornará a instalação das atualizações muito mais simples (sem perder as configurações dos clientes)

Michael Shaw
fonte
0

Eu tornaria a classe na opção 3 estática. Então, ao invés de

//create SomeCl
Foo f = new Foo();
f.setConfigInst(cfg);
...
...
//Inside Foo
public void setConfig(MyAppConfig c) { localCfg = c; }
...
//somewhere else:
x = localCfg.getConfigForX();

Você pode apenas ter:

//Inside Foo
x = MyAppConfig.getConfigForX();

Deixe os detalhes de carregamento / salvamento dos dados de configuração acontecerem dentro da MyAppConfigclasse. E é claro que você pode ter variações mais complexas, como classes diferentes para diferentes propósitos.

O único caso em que essa abordagem seria um problema seria se você, por algum motivo, precisasse trabalhar em várias instâncias de configurações diferentes ao mesmo tempo , embora eu ainda precise encontrar uma situação dessas.

FrustratedWithFormsDesigner
fonte
11
É o que praticamente acontece ao executar testes de unidade em algumas estruturas de teste ... Mas, mesmo sem testes de unidade explicitamente paralelos, será difícil para os objetos de teste de unidade que dependem do estado global.
Péter Török
0

Estou trabalhando em um projeto em que estamos usando a abordagem "3 camadas (interface, lógica de negócios, acesso a dados)". O aplicativo pode ser um servidor web multiusuário ou servidor cliente.

Trabalhamos com 3 configurações diferentes, a primeira específica para o PC, independentemente de o usuário estar trabalhando. O segundo específico para o usuário atual e uma terceira configuração global para todos os usuários e aplicativos clientes.

Cada configuração é representada em cada instância do aplicativo por um objeto.

Essa abordagem pode ajudar seu projeto.

umlcat
fonte