[code]class Nome {
private final String nome;
public Nome(String n) {
if (n == null || n.equals(""))
throw new IllegalArgumentException(“Nome deve ser preenchido.”);
}
public String getNome() {
return nome;
}
public static Nome nome(String n) {
return new Nome(n);
}
}
class Pessoa {
private Nome primeiroNome;
private Nome sobrenome;
public Pessoa(Nome primeiroNome, Nome sobrenome) {
this.primeiroNome = primeiroNome;
this.sobrenome = sobrenome;
}
…
}
[/code]
Neste caso garanto que garanto que não terei nomes vazios (ignorando o fato de poder passar null no construtor). Até ai ok. Recebo sempre a informação de um erro por vez.
Porém, gostaria de poder dar um retorno melhor para o cliente desta classe (uma página web, GUI ou alguma outra rotina no sistema que cria novas pessoas): dizer quais foram todos os problemas, no caso informar de uma só vez que que o nome e o sobrenome deve ser preenchidos. Da forma que está agora, o código cliente ficaria com vários blocos de try/catch, tentando criar o objeto do tipo Nome e caso ocorrer exceção, guardar a mesma. Ou eu deveria receber Strings no construtor e, no mesmo, ter os blocos try/catch, porém, recebendo Strings ficaria sem sentido ter o tipo Nome.
Há também a possibilidade de não realizar a validação na criação, e validar depois com um método, porém deixaria meus objetos por um período em um estado inválido.
Como vocês fazem essas validações? Lembrando: não estou usando nenhum framework.
Muito obrigado!
Você criou uma classe Nome para “modelar” uma String. Não vejo esta necessidade. Para trabalhar com validação há várias coisas que podem ser feitas e as mais simples seriam: criar a classe Pessoa com os atributos primeiroNome e sobrenome ambos do tipo String. Escrever um construtor que receba dois parâmetros e lance a devida exceção. Caso não queira criar o construtor voce pode criar um método para validação ou então voce pode criar o método para validação mesmo se criar um construtor que receba os parametros. Seu código ficaria parecido com isso:
public class Pessoa{
private String primeiroNome;
private String sobrenome;
public Pessoa(String primeiroNome, String sobrenome){
if(primeiroNome == null || primeiroNome.isEmpty()){
throw new IllegalArgumentException("Nome deve ser preenchido.");
}
else{
this.primeiroNome = primeiroNome;
}
if(sobrenome== null || sobrenome.isEmpty()){
throw new IllegalArgumentException("Sobrenome deve ser preenchido.");
}
else{
this.sobrenome= sobrenome;
}
}
//Implementar métodos getter e setters
}
Ou então
public class Pessoa{
private String primeiroNome;
private String sobrenome;
//Métodos getters e setters
public void validar() throws AlgumaExcecao{
if(primeiroNome == null || primeiroNome.isEmpty()){
throw new AlgumaExcecao("Nome deve ser preenchido.");
//Voce define qual excecao voce quer lancar
}
if(sobrenome== null || sobrenome.isEmpty()){
throw new AlgumaExcecao("Sobrenome deve ser preenchido.");
}
}
}
Embora essas alternativas sejam validas eu acho mais elegante criar uma camada de validação. Aí você cria uma classe ValidadorPessoa e implementa as validações necessárias. Neste caso voce pode criar uma classe mãe Validador e fazer todos seus validadores herdarem de tal classe ou então criar uma interface e implementá-la nas classes de validação. Assim se por exemplo voce precisar que uma pessoa tenha um cpf a validação fica mais complexa e nao apenas verifica se não é nula ou vazia e sim se é numérica e se o dígito verificador é valido. Neste caso se vc validar no construtor o mesmo ficará enorme, se crirar um método para validação também não ficara mto legal.
Sugiro criar um método de validação para cada atributo da classe Pessoa, e um método que validarPessoa que na verdade chama os demais métodos.
Hoje há o hibernateValidator que é um “framework” (não sei se a palavra framework cai bem aqui) para validação. Voce pode usar annotations na classe Pessoa do tipo @notNull pra informar que o objeto não deve ser nulo, @Size(min=3, max=50) pra informar o máximo e ainda pode implementar uma classe de validação para casos como o do cpf. A caelum tem um projeto de validadores que pode ser util e é disponibilizado gratuitamente.
Só não sei se o hibernate validator da pra ser usado com aplicacoes desktop, mas para web é show de bola. Seu uso requer um pouco de estudo mas vale a pena
Em alguns casos a classe Nome pode ser overkill mesmo em outros não. Porém, imagine no lugar na classe Nome a classe Cnpj por exemplo, mesma coisa. A idéia é não ter valores inválidos.
No caso, no seu primeiro exemplo, o resultado final seria o mesmo do exemplo que passei: há um problema com os dados, lança exceção. Eu gostaria de informar todos os erros para o cliente da classe, mantendo meu tipo Nome (lembre-se poderia ser Cnpj, Cep, etc).
No segundo exemplo portanto, vejo que você, portanto, optou por manter um objeto Pessoa em um estado inválido por um tempo. Não que seja um problema, mas, se eu recebo um tipo (no caso Nome), eu não conseguiria nem mesmo deixar o objeto de Pessoa em um estado inválido pois, não consegui criar o Nome.
Geane acho melhor vc criar um tópico para sua pergunta. Este tópico é para a pergunta de marvinla. De qualquer jeito acho q vc encontra um monte de função para validação de e-mail com java script (ou em qualquer linguagem q vc imaginar) no google.
marvinla, conforme eu falei não vejo mto sentido vc criar a classe nome para modelar uma String. Um nome é uma String. Se vc quer atrelar sua validação na classe pessoa faça isso no construtor e lance as devidas exceções (conforme meu primeiro exemplo). Mas conforme eu falei na prática pode ser mais coerente voce criar uma classe de validação.
Resumindo a classe que cria um objeto(ou recebe o mesmo por algum método ou construtor) deve criar ou receber objeto do tipo ValidadorPessoa e antes de fazer alguma acao em pessoa, verificar se o mesmo é valido. A menos que vc precise de uma classe mto especifica que realmente precise ser validada diretamente. Neste caso sugiro o primeiro exemplo.