Construtor com todas as propriedades de classe ou construtor padrão com setters?

StackOverflow https://stackoverflow.com/questions/830657

  •  06-07-2019
  •  | 
  •  

Pergunta

A seguir estão as duas abordagens:

  • construtor com todas as propriedades da classe

Prós: eu tenho que colocar um número exato de tipos de parâmetros, então se eu cometer um erro o compilador avisa-me (a propósito, há uma maneira de evitar o problema de ter erroneamente comutada dois Integer na lista de parâmetros? )

Contras: se eu tiver muitas propriedades da linha de instanciação pode se tornar muito longo e pode abranger mais de duas ou mais linhas

  • setters e o construtor vazio padrão

Pros: Eu posso ver claramente o que eu estou definindo, por isso, se eu estou fazendo algo errado eu posso localizá-lo assim que eu estou escrevendo isso (eu não posso fazer o erro previuos de mudar duas variáveis ??do mesmo tipo)

Contras:. A instanciação de um objeto com muitas propriedades poderiam levar várias linhas (não sei se este é realmente um con) e se eu esquecer de definir uma propriedade o compilador não diz nada

O que você vai fazer e por quê? Você sabe de qualquer padrão de luz (considere que deve ser cada vez que usou um objeto wth 7+ propriedades é instanciado) para sugerir? Estou perguntando isso porque eu tendem a não gostar grandes construtores onde eu não consigo descobrir rapidamente onde é a variável que estou procurando, por outro lado, acho O "conjunto de todas as propriedades" vulneráveis ??à falta de algumas das propriedades.

Sinta livre argumento minhas suposições em prós e contras como eles são apenas meus pensamentos:)

Update - uma pergunta que eu encontrei que está relacionado com esta: grande edifício, objetos imutáveis ??sem usar construtores tendo longas listas de parâmetros

Foi útil?

Solução

Você pode olhar para o padrão Builder defendida por Joshua Bloch, e descrito em Effective Java . Há uma apresentação com os principais pontos em http: //developers.sun .com / aprendizagem / javaoneonline / 2007 / pdf / TS-2689.pdf ; Sem dúvida, você pode desenterrar uma referência melhor.

Basicamente, você tem outra classe, provavelmente uma classe interna, que fornece métodos chamados depois que as propriedades a ser definido, e que retornam o construtor original para que você possa chamadas cadeia. Ele torna-se completamente um pedaço legível do código.

Por exemplo, vamos supor que eu tenho uma Message simples com algumas propriedades. O código do cliente construir este poderia usar um construtor para preparar um Message da seguinte forma:

Message message = new Message.Builder()
    .sender( new User( ... ) )
    .recipient( new User( ... ) )
    .subject( "Hello, world!" )
    .text( messageText )
    .build();

Um fragmento de Message.Builder pode ser semelhante ao seguinte:

public class Builder {

    private User sender = null;
    // Other properties

    public Builder sender( User sender ) {
        this.sender = sender;
        return this;
    }
    // Methods for other properties

    public Message build() {
        Message message = new Message();
        message.setSender( sender );
        // Set the other properties
        return message;
    }

}

Outras dicas

Você perdeu a maior pro de ter um construtor com cargas de parâmetros:. Permite criar tipos imutáveis ??

A maneira normal de criação de tipos imutáveis ?? sem enorme maldade construtor é ter um tipo de ajudante - um construtor que mantém os valores que você quer em seu objeto final, em seguida, constrói o objeto imutável quando estiver pronto.

pesquisa acadêmica recente (CMU e Microsoft) na API usabilidade sugere que construtores padrão com setters seria o caminho a percorrer em termos de usabilidade. Isto é de "Implicações Usabilidade de exigir Parâmetros em Construtores objetos" por Jeff Stylos e Steven Clarke e foi apresentado na Conferência Internacional de Engenharia de Software:

Resumo: A usabilidade de APIs é cada vez mais importante para a produtividade do programador. Com base na experiência com estudos de usabilidade de APIs específicas, técnicas foram explorados para estudar a usabilidade do design escolhas comuns a muitas APIs. Um estudo comparativo foi realizado para avaliar como profissional programadores usam APIs com parâmetros necessários em construtores dos objetos ao invés de parâmetros 'default' construtores. Se a hipótese de que os parâmetros necessários criaria APIs mais utilizáveis ??e auto-documentando guiando programadores para o uso correto de objetos e evitando erros. No entanto, no estudo, verificou-se que, ao contrário das expectativas, os programadores preferido fortemente e foram mais eficazes com APIs que não exigem parâmetros do construtor. o comportamento dos participantes foi analisada utilizando o quadro dimensões cognitiva, e revelando que os parâmetros necessários construtor interferir com estratégias de aprendizagem comum, causando comprometimento prematura indesejável.

Você mencionou em seu post, mas acho que este é um ponto importante que merece mais atenção: a menos que cada parâmetro de entrada é um tipo diferente, o grande problema com grandes construtores é que é muito fácil para transpor um par de variáveis. O compilador é uma rede de segurança confiável - ele vai pegar alguns erros, mas aqueles que deslizam através vai ser muito mais difícil identificar e depurar. Especialmente porque a lista de entrada para um grande construtor é bastante opaca, a menos que você tem o aberto API em outra janela.

Getters e setters são muito mais fácil de depurar, especialmente se você instituir salvaguardas que lançam uma exceção de tempo de execução se o objeto não está devidamente preenchido. E eu sou um grande fã de "fácil de depurar."

Antes de esta discussão eu nunca tinha ouvido falar do padrão Builder Rob menciona. Nunca usei-me (obviamente), mas está condenado intrigante.

Eu prefiro tomar argumentos do construtor, pelas razões acima mencionadas imutabilidade. Se isso lhe dá um construtor que leva muitos argumentos (dizem que mais de quatro ou mais), isso é um cheiro de código para mim:. Alguns desses argumentos devem ser agrupados em seus próprios tipos

Por exemplo, se você tem algo parecido com isto:

class Contact
{
    public Contact(string firstName, string lastName, string phoneNumber,
        string street, string city, string state, int zipCode) { ... }
}

Eu refatorar-lo para:

class Contact
{
    public Contact(Person person, PhoneNumber number, Address address) { ... }
}

class Person
{
    public Person(string firstName, string lastName) { ... }
}

class PhoneNumber
{
    public PhoneNumber(string digits) { ... }
}

class Address
{
    public Address(string street, string city, string state, int zipCode) { ... }
}

Too-grandes classes são um problema de design realmente comum em bases de código OOP.

Há outros aspectos também. Se você quer ser capaz de certas coisas com sua classe em tempo de design em vez de apenas em tempo de execução, por exemplo, adicionando a sua classe como um objeto no objeto palette (isso é Java usando o NetBeans), você precisa fornecer um construtor sem argumento em para ser capaz de fazê-lo.

Existem outras estratégias também. Antes de tentar descobrir como lidar com muitos parâmetros, eu acho que é importante para re-visitar o seu design e olhar para saber se a classe está fazendo muito. Veja se você pode agrupar alguns dos parâmetros juntos em uma nova classe, e mover algum comportamento para essa classe.

setters e o construtor vazio padrão

JRL obliquamente tocou nele , mas uma razão para considerar o uso de setters é ter o objeto em conformidade com a rel JavaBean especificação . Isso faz com que casos passíveis de edição através de ferramentas de introspecção e de persistência usando certos href="http://java.sun.com/javase/6/docs/api/java/beans/XMLEncoder.html" .

Quem disse que você não pode fazer as duas coisas? Eu diria propriedades obrigatórias ir para o construtor, os opcionais são tratados com setters. BTW, quem disse que você sempre precisa de um setter por propriedade? Se duas propriedades pertencem juntos conceitualmente, por que não colocá-los juntos?

Eu gosto do padrão Builder também, mas a regra mais importante é: sempre use seu cérebro e encontrar o modelo que melhor se adapta ao problema específico. Não há one-size-fits-all solução.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top