Setters ou construtor para muitas variáveis? [duplicado]

4

Eu tenho uma turma com 30 variáveis (é o formulário de inscrição), então me pergunto qual é a melhor prática para organizar a criação de classes.

Devo usar um construtor enorme:

MyClass mc = new MyClass(a, b, c, d)

Ou setters:

MyClass mc = new MyClass();
mc.setA(a);
mc.setB(b);
mc.setC(c);
mc.setD(d);

Qual é a melhor prática em OOP para tal situação? Eu vi uma pergunta semelhante, mas agora não preciso de imutabilidade.

    
por Dracontis 14.06.2012 / 23:05
fonte

6 respostas

17

Existe uma terceira opção que é o idioma mais orientado a objetos

A melhor coisa a fazer é usar o padrão Builder .

A classe tem um construtor no-arg padrão, e você define todos os parâmetros necessários e chama .build() ou .materialize() ou algum método apropriadamente nomeado para validar e finalizar a construção do objeto e obter uma referência para o objeto concluído.

Isso pode ser usado com muito sucesso com o padrão de design Fluent API .

Aqui está um exemplo de como aplicar uma aderência da API de padrão do Construtor para construir apenas objetos válidos . A postagem do blog é sobre Java, mas se aplica a qualquer linguagem orientada a objetos do tipo estaticamente que suporte interfaces. Isso torna muito fácil saber o que você deve fazer em seguida com o preenchimento automático em um IDE também.

Eu não sou um grande fã do padrão Fluent API porque ele pode ser abusado muito facilmente, e quando ele abusou do encadeamento do método torna muito difícil diagnosticar exceções, mas neste caso em particular é muito apropriado.

    
por 14.06.2012 / 23:48
fonte
21

A principal diferença entre seus dois exemplos é que o usuário da classe é forçado a usar o construtor, mas não é forçado a definir seu estado por meio de métodos set.

Você deve colocar todos os argumentos no construtor que irá configurar sua instância no estado correto. Outros métodos de "configuração" devem ser opcionais.

O que eu faria no seu caso é identificar dentro de suas 30 variáveis temas comuns que em si mesmos podem ser divididos em DTO's. Então você pode ter em vez disso (por exemplo):

MyClass mc = new MyClass(personInfo, companyInfo, salaryInfo);

Addtionally você pode querer olhar se a sua classe está fazendo muito e se você pode limitar o uso do estado interno, criando classes de componentes menores em vez de ter uma classe grande.

    
por 14.06.2012 / 23:34
fonte
7

A resposta depende de como você usa a classe ...

  • Se você quiser que sua classe seja imutável, terá que usar parâmetros de construtor.

  • Se você quiser que sua classe seja desserializável por (de) serializadores baseados em releituras, você precisará de um construtor e setters padrão.

  • Se sua classe não for imutável e você quiser que os consumidores possam alterar todas as propriedades durante a vida útil dos objetos, você precisará adicionar setters de qualquer maneira (ou adicionar métodos de modificação, que podem parece menos direta para os consumidores).

  • Se você usar o construtor padrão e a abordagem de propriedades, deverá certificar-se de que os consumidores não possam invalidar o estado do objeto configurando em uma ordem inesperada, que os valores padrão sejam válidos e que todos os setters verifiquem as coisas como intervalos antes de aplicar as alterações.
    Se você tiver duas (ou mais) propriedades dependentes, encapsule-as em uma classe ou certifique-se de que, se alguma delas estiver configurada (por exemplo, X está definida), ela alterará o valor da outra (por exemplo, o valor de Y) valor não vai junto com o novo valor (de X).

Além disso, considere se sua turma deve ser de uma turma:

Se ele tiver 30 parâmetros, você pode estar quebrando o princípio de encapsulamento OO - em que cada classe faz uma coisa e faz tudo por essa única coisa.

Talvez você deva usar composição de algumas classes ou, se tiver muitos parâmetros comuns entre classes, talvez precise de uma ou mais classes verticais que manipulem um aspecto específico e pode atuar em várias classes (usando reflexão ou usando classes adicionais em um padrão de visitante ).

    
por 15.06.2012 / 01:10
fonte
0

Eu iria com o construtor enorme. É mais simples. Se cada chamada ao construtor usar parâmetros diferentes (isto é, você acabaria passando muitos nulos), faça mais construtores. A ideia básica é manter o código no mínimo; torne o mais simples possível. Se você precisa obter valores reais de configuração e os setters seriam mais simples, use-os.

Há algo desleixado em muitos parâmetros, então você pode querer ver se deve passar objetos que contenham vários valores de parâmetros. Não se esforce, mas se você tiver 15 parâmetros, eu aposto que você encontrará uma maneira mais simples de fazê-lo.

Muitos parâmetros são ruins, mas muitos setters insensatos também não são bons; não há resposta correta . Você tem que escolher o menor de dois gorgulhos. Isso aborda os setters melhor do que eu.

    
por 14.06.2012 / 23:39
fonte
0

Eu me pergunto se você realmente estará construindo esse objeto gigante, ou será sempre carregado de um banco de dados?

Não vejo motivos para ter um objeto tão grande construído com valores provenientes de código.

Se essa coisa sempre for salva e carregada de um banco de dados ou de um arquivo, atribua a ela um construtor padrão simples e concentre-se em obter o mapeamento ou a serialização do banco de dados de objetos correto.

    
por 14.06.2012 / 23:57
fonte
0

Supondo que você não esteja em uma linguagem que torne conveniente escrever parâmetros nomeados (por exemplo, Python ou Common Lisp), considere se os objetos são considerados somente leitura ou leitura / gravação. Se o primeiro, você deve definir valores a partir do construtor, mas de outra forma é com você, desde que você tenha setters (ou o equivalente da sua linguagem). Dado que você está lidando com 30 variáveis, eu consideraria o uso de algo que permitiria que você evitasse escrever construtores com tantos argumentos. Mesmo 10 seria um pouco demais para sanidade ...

    
por 15.06.2012 / 00:21
fonte