Boas Praticas(Construtor)

28 respostas
C

Pessoal,
trabalho atualmente em um empresa na qual desempenho a função de desenvolvedor, e me deparei com um problema no qual meus conhecimentos me impedem de fazer qualquer comentario!, foi adminitdo que neste projeto em que estou no momento devo usar Classes com construtores do seguinte modo:

Ou o construtor da minha classe recebe todos os atributos.
 Ou não recebe nada.

não posso mesmo usar construtores parciais? O motivo citado foi que isso fere as boas praticas de programação.

Grato pela atenção de todos!!!

28 Respostas

F

Entao do ponto de vista do seu pessoal isso é errado?

public Room(String number, double price) {
     this(number, price, false);
}

public Room(String number, double price, boolean isSmoking) {
     this.number = number;
     this.price = price;
     this.smoking = isSmoking;
}

Pra mim, o que nao tem sentido em alguns casos é um construtor vazio.

R

penso que construtores parciais sao para classes onde se
pode trabalhar com seus objetos sem todas as informacoes completas, ou seja,
do modo default funciona, ou voce pode personalizar.

no caso de classes de modelo, de negocio, eh dificil nao se usar todos os
atributos. nao sao manipuladas partes, mas o todo

C
Pois é pessoal,  do ponto do vista do pessoal aqui o exemplo dado pelo fabiocsi esta errado! segundo me disseram, o motivo é que isso não atende as boas praticas de programação. Como não estou certo disso, resolvi perguntar se alguem já se deparou com algo semelhante. No meu caso essas classes as quais cito aqui, são classes utilizadas para reunir atributos de entrada/saida dos meus componentes, ou como o exemplo abaixo.
Query query = EntityManager.createQuery("select new MeuConstrutor(o.nome, o.endereco, o.telefone) from Cliente_Table");
No caso real eu recebo elementos de tabelas distintas e por isso uso o construtor parcial, sei que existe outra maneira de fazer isso, mas o que eu fiz esta errado mesmo? vai contra as boas praticas de programação?

Valeu!!!

S

Canhoto:
Pessoal,
trabalho atualmente em um empresa na qual desempenho a função de desenvolvedor, e me deparei com um problema no qual meus conhecimentos me impedem de fazer qualquer comentario!, foi adminitdo que neste projeto em que estou no momento devo usar Classes com construtores do seguinte modo:

Ou o construtor da minha classe recebe todos os atributos.
 Ou não recebe nada.

não posso mesmo usar construtores parciais? O motivo citado foi que isso fere as boas praticas de programação.

Ter vários construtores é potencialmente perigoso se vc não souber o que está fazendo. Seguindo essas regras acima ha garantias que mesmo que o programador não saiba o que está fazendo, a coisa funciona.

O construtor deve inicilizar o estado do objeto. O estado do objeto tem que ser consistente a todo o momento.
Se o construtor é sem parametros, significa que o estado inicial do objeto é padrão e determinado pelo proprio construtor.

Se o construtor tem todos os parametros , o estado do objeto é únicamente determinado pelo valor desses parametros. O problema aqui é que não devem passar todos os dados do estado do objeto no construtor. apenas aqueles , sem os quais o estado seria inconsistente.
Se existem muitos parametros deve ser usado o padrão Builder ou Prototype.

Por exemplo:

class Displayer {

    public void display(String s);
}

class Writer {

   private Display display;
   private String message = "";

   public Writer(){} // ERRADO

   public Writer(Display display){ // OK
    this.display = display;
   } 

   public  void write (){
       display.display(message);
  }

   public void setMessage(String message){ 
  this.message=message;
  }
}

A classe write depende do display. Se ele não for passado no construtor vai dar erro em write(). Então, obrigatoriamente o construtor tem que ter esse parametro. Contudo, o writer pode funcionar corretamente
sem que “message” seja passada como parametro no construtor.

Cada atributo é um caso. Usar tudo ou nada é limitativo, mas impõe mais controle para programadores inexperientes. Contudo, do ponto de vista puro de design é errado.

Z

Pra ser sincero, nunca vi isso na minha vida… haha

Para que existe sobrecarga de construtor então?!

A Sun criou a sobrecarga de construtor para os programadores usufruir desse recurso de acordo com sua necessidade!

T

Você não leu o título do post - “Boas práticas”.
“Boas práticas” é aquela lista de coisas que você tem de fazer porque se você fizer tudo que é possível pode ter problemas depois (nem que seja com seu chefe).

P

use construtor para receber dependencias! assim ninguem te cria num estado incosistente!

C

Poderia dar um exemplo, não entendi mto bem.

C

thingol:

Pra ser sincero, nunca vi isso na minha vida… haha

Para que existe sobrecarga de construtor então?!

A Sun criou a sobrecarga de construtor para os programadores usufruir desse recurso de acordo com sua necessidade!

Você não leu o título do post - “Boas práticas”.
“Boas práticas” é aquela lista de coisas que você tem de fazer porque se você fizer tudo que é possível pode ter problemas depois (nem que seja com seu chefe).

Voltando às boas práticas quanto aos construtores de classe, qual sua opnião?

T

Digamos que você tenha um objeto Cliente que represente um registro do banco de dados, e nenhuma das colunas possa ser NULL. Exemplo:

class Cliente {
    int codigo;
    String nome;
    String endereco;
    public Cliente (int c, String n, String e) {
        codigo = c; nome = n; endereco = e;
    }
}

Se você tiver um construtor que não inicialize todos os campos, só alguns deles, isso quer dizer que os outros campos vão ficar com valor indefinido (null).
Digamos que você precise depois desse objeto para inserir no banco de dados. Aí você vai ter um problema, porque ou você tem de ficar checando todos os dados antes de pôr o tal objeto como registro no banco, ou então vai receber um erro na inserção.

C

Entendi.

Pelo que pude ver aqui, reunindo todas as informações, o(s) construtor(es) tem que manter a consistência da classe para uso posterior. Seja para persistência no banco ou utilização no negócio.

É isso?

Z

thingol:
Digamos que você tenha um objeto Cliente que represente um registro do banco de dados, e nenhuma das colunas possa ser NULL. Exemplo:

class Cliente {
    int codigo;
    String nome;
    String endereco;
    public Cliente (int c, String n, String e) {
        codigo = c; nome = n; endereco = e;
    }
}

Se você tiver um construtor que não inicialize todos os campos, só alguns deles, isso quer dizer que os outros campos vão ficar com valor indefinido (null).
Digamos que você precise depois desse objeto para inserir no banco de dados. Aí você vai ter um problema, porque ou você tem de ficar checando todos os dados antes de pôr o tal objeto como registro no banco, ou então vai receber um erro na inserção.

Mas isso é o mínimo que se espera do kra meu!!! Você poderia nos dar uma boa explicação do POR QUÊ várias sobrecargas de um construtor fere as boas práticas…!

S

Se a dúvida é só essa então a resposta é: Sobrecarregar o construtor não fere boas práticas.

Boas Práticas de construtor:

) Não deve lançar exceções além de IllegalArgumentException
) Não deve produzir objetos com estado inconsistente.
) Não deve invocar métodos do objeto que possam ser sobre-escritos (não final).
) Não deve ser sincronizado
) Deve ser explicitamente definido mesmo quando não ha nada a fazer (ou: não use o constutor padrão)
) Não deve inicializar campos para valores padrão.

Além disso eu acho que não deve aceitar todos os campos que representam seu estado quando eles são muitos. Deve ser usando o padrão Builder ou Factory Method

T

Eu acho que essa história de “Boas práticas” é um substituto grosseiro e preguiçoso para o correto entendimento e compreensão dos problemas.

(Eu costumo sempre dizer que até o “goto” é válido, desde que você saiba o que está fazendo. É o dito “zen da programação”).

Você não pode ter várias sobrecargas para um construtor só porque o programador preguiçoso vai fazer m***?

Em vez disso, seria interessante ensinar cada programador por que é que ele não deve abusar de certas coisas.

S

thingol:
Eu acho que essa história de “Boas práticas” é um substituto grosseiro e preguiçoso para o correto entendimento e compreensão dos problemas.

(Eu costumo sempre dizer que até o “goto” é válido, desde que você saiba o que está fazendo. É o dito “zen da programação”).

Você não pode ter várias sobrecargas para um construtor só porque o programador preguiçoso vai fazer m***?

Em vez disso, seria interessante ensinar cada programador por que é que ele não deve abusar de certas coisas.

Não entendi exactamente qual é a tua posição. O goto não é válido. Se fosse ainda seria usado. Programação estruturada não pode conter uma instrução não-estruturada. Isso é que dá m@#@#. Por isso o goto é reservado em Java. Não é para usar. Java tem labels que é uma especie de goto sem usar goto. É estruturado.

Seria interessante ensinar se o programador qer aprender. Se ele aprender as regras básicas ele consegue chegar nas boas práticas. São apenas corolários dessas regras. É só dar à manivela.
A lista de boas práticas é para ser lida pelo programador novato ou perguiçoso ( ou ambos) para não fazer m#$%#$% em programas sérios. E pode ser seguida por qualquer fazer as coisas bem à primeira.

Claro, existem exceções às boas práticas exactamente por elas serem corolários das regras principais e portanto não cobrem todas as hipoteses.

Eu ficaria contente se o programador soubesse que existem listas de boas práticas. Mais do que se ele soubesse que existem padrões de projeto.

G

Qaundo eu preciso criar objetos dos quais pode haver confusão na hora de outra pessoa construi-lo COMO BOA PRÁTICA eu abstraio a construção do objeto para os outros desenvolvedores. Exemplo:

public class Cliente{

Integer id;
String nome;
String idade;
Double contaBancaria;

public Cliente(Integer id){
   this.id = id
}

public Cliente(Double contaBancaria, Integer id){
   this.id = id;
   this.contaBancaria = contaBancaria;
}
}

Então eu quero consultar o nome do cliente via JPA…Será que eu preciso passar no construtor a ContaBancaria ??? NÃO. Apenas o ID.

Então eu poderia explicar isso aos progamadores sem noção ou criar uma fábrica com métodos auto explicativos:

public getCliente {

public Cliente novoClienteComID(Integer id){
return new Cliente(id);
}

public Cliente novoClienteComContaBancaria(Double conta, Integer id){
return new Cliente(conta,id);
}
}

A idéia que eu quis passar talvez não se resuma ao código apresentado, então o que eu quis tratar é que DIZER QUE NÃO EXSITEM CONSTRUTORES VAZIOS É FALTA DE EXPERIÊNCIA EM JAVA.

Construtor como muitos disseram serve para garantir o estado do objeto.

S

Ainda bem que vc optou pela segunda. Porque a primeira não funciona. Vc não pode explicar a mesma coisa a todos os usuários da classe. (imagine um projeto opensource)

Isso que vc usou é a aplicação do factory method mas para seria melhor assim

class Cliente{

public static Cliente cliente(Integer id){
// valida parametros null não são aceitos
Cliente c = new Cliente();
c.id = id;

return c;
}

public static Cliente cliente(Double conta, Integer id){
// valida parametros null não são aceitos
Cliente c = new Cliente();
c.id = id;
c.conta = conta;

return c;
}

 private Cliente(){}
}

Agora sim. Não tem como criar clientes não usem um desses métodos.

G

O código foi só de exemplo então não era pra se basear nesses detalhes…como eu disse a idéia era passar os conceitos mesmo.

editado: erro de leitura meu.

C

ahm!?

P

O q eles estão querendo dizer é q num tem nada a ver usar construtores parciais…

F

Cara, a questão é vc assegurar a consistência de estado da sua classe no momento da criação do objeto da mesma. Ou por todo tempo de vida(se ela não tiver accessors que possam comprometer seu estado). Mas ai vai da implementação e do padrão que vc está seguindo.

Se vc possui uma classe Cliente e quer assegurar a consistência dela na sua criação vc utilizaria:

public class Cliente {

   private Integer id;
   private String nome;

   public Cliente(Integer id, String nome) {
      this.id = id;
      this.nome = nome;
   }

   //Setters e getters   

}

Nessa situação só é possível criar um objeto da classe Cliente passando o id e o nome. Aí estamos assegurando a consistência do estado do objeto apenas na criação.
Deixando os setters em sua forma padrão facilmente o estado do objeto poderia ser comprometido, por exemplo:

cliente.setNome(null);
cliente.setId(null);

Porém isso pode ser verificado através de um tratamento no setter da classe:

public void setId(Integer id) {
   if (id == null) {
      throw new IdClienteInvalidoException();
   }

   this.id = id;
}

Eu poderia ter um construtor sem argumentos(default), isso permitiria criar um objeto sem estado inicial. Ou um construtor parcial. A questão é que meu código deve assegurar a consistência do estado do objeto. Pode-se fazer isso de N maneiras.

P

Sim. Então é possivel afirma q um costrutor parcial não é uma pratica ruim, é uma opção que depende do model em questão.

P

Essa aqui que o Sergio deu, e que o Foxtol foi alem, é sem duvida a regra “maxima”.

Nao entendi essa Sergio. Se da na mesma, porque escrever? So pra ter legibilidade de que voce quer mesmo um construtor como o default?

S

Paulo Silveira:

Nao entendi essa Sergio. Se da na mesma, porque escrever? So pra ter legibilidade de que voce quer mesmo um construtor como o default?

Exato. Quando a classe não tem construtor, ela não tem porque não precisa ou ela não tem porque o programador errou em não colocar ? Se o construtor não está lá quem garante que o estado é consistente ? Posso asumir que o estado default é consistente ?

A propria declaração do construtor vazio singifica : “Esta classe sabe manter seu estado coerente na inicilizalização e esse estado é igual ao estado padrão de todos os seus atributos”.
A falta da declaração não significa “estou usando o construtor implicito” significa “não sei qual construtor usar”.

Uma boa prática em qualquer area : implicito == ruim. explicito == bom

P

Ate concordo com esse caso Sergio, e eu gosto ate de escrever this mesmo quando implicito (talvez isso seja vicio depois de tanto tempo que dei aula);mas voce tem de tomar cuidad, senao vai comecar a escrever extends Object em tudo que é classe “sem mae” e public abstract do lado de metodos de interfaces :slight_smile:

S

Paulo Silveira:

Ate concordo com esse caso Sergio, e eu gosto ate de escrever this mesmo quando implicito (talvez isso seja vicio depois de tanto tempo que dei aula);mas voce tem de tomar cuidad, senao vai comecar a escrever extends Object em tudo que é classe “sem mae” e public abstract do lado de metodos de interfaces :)

São coisa completamente diferentes. Escrever this está evitando um problema de shadowing. Colocar “extends Object” não está evitando problema algum. Não tem como o programador criar uma classe que não extende Object, mas tem como esquecer de colocar um construtor numa classe e isso destruir a integridade de estado.
Extends Object = burocracia do java
Constutor sem parametros = regra de integridade de estado.

É bem diferente. Vc só pode usar implicitos quando eles são burocráticos. O resto, vc tem que usar explicitos.
Quando mais novato vc for na linguagem mais explicitos deve usar. (Lembra do Implicit None ?)

D

Pela mãozinha gorda, acho que é o Moisés. E pelo apelido (nick) de mau gosto, acho que é o Diego.

Mas vamos lá!

O pessoal aqui já disse muito a respeito dos construtores e os seus argumentos e explicaram bem.

Como disseram, pode não ser por "boas práticas", mas sim por conta do modelo de desenvolvimento adotado para o projeto. O que concordo.

Como eu sei que estamos falando do mesmo projeto, neste caso, não vejo como adequado criar N variantes do construtor da classe de uma entidade, o que pode levar ao uso equivocado dessas diferentes variantes.

Em alguns casos, algumas IDEs podem não interpretar corretamente os nomes dos parâmetros, possibilitando erros na implementação.

Exemplo:

public class Pessoa {
  String nome;
  String cpf;
  String email;

  public Pessoa() {}
  
  public Pessoa( String nome, String cpf, String email ) {}

  public Pessoa( String nome, String cpf ) {}

  public Pessoa( String nome, String email ) {} // NÃO COMPILA!!!
}

Além do mais, no auto complete de alguma IDEs, você não consegue saber se os nomes dos argumentos dos construtores. Eles acabam colocando algo como "param1, param2".

Está vendo a possibilidade de problemas que se abrem?

Neste caso, se precisar passar apenas alguns argumentos na criação do objeto, por exemplo, nome e cpf, faça assim:

Pessoa p = new Pessoa( nome, cpf, null );

Fica explícito e é menos suscetível a erros, na minha opinião.

Abraços a todos de Mococa!
Daniel Destro

T

Ou com aquele esqueminha de “programação fluente” que o pessoal costuma usar:

Pessoa p = new Pessoa().setNome("João").setCpf("123.456.789/00");

Isso é mais uma das coisas herdadas do C++. Como seria mais fácil se pudéssemos usar algo como

Pessoa p = new Pessoa (nome = "João", cpf = "123.456.789/00");
Criado 16 de abril de 2008
Ultima resposta 17 de abr. de 2008
Respostas 28
Participantes 11