Esta classe seria um modelo anêmico?

Olá eu nao estou querendo aprender DDD só porque e moda do momento, quero aprender porque acho que com DDD a coisa se torna mais OO, além disso o cliente participa mais dando sugestões e contribuindo para o software, além do que acho muito interessante outras coisa pregadas em DDD como o padrão Repository por exemplo.

Quando a questão da satisfação dos cliente eu concordo com você, mais tbm construir sistemas mais OO que permitem mais escalabilidade em conjunto com a satisfação dos cliente nao faz mal nenhum.

Valeu

Daniel, me desculpe se pareceu rude meu comentário.

O que eu quis dizer é que o fato de você querer aprender DDD é totalmente legítimo. O único ponto que vale pesar é se é uma boa aplicar DDD neste projeto onde você já trabalha com todos esses frameworks que já funcionam.

Uma dica interessante que li, se não me engano no livro a respeito de DDD do Jimmy Nilsson, é “Don’t fight your framework”. Se você tem frameworks para alguma tarefa e seu framework a tornou simples não vale a pena brigar com o framework ou até remove-lo só pra ter um modelo mais DDD.

Neste caso, só o fato de você ter separação de classes e nomenclatura de acordo com seus Domain Experts é um grande benefício.

Nada que isso de forma alguma :slight_smile:

Neste projeto e praticamente impossivel mexer visto que teria que mudar o sistema quase todo, e isso eh inviavel, mas penso em usar DDD nos proximos projetos, resta saber realmente se vale a pena. Mas valeu pelas dicas.

Abraço

No caso da validação, pra vc evitar overhead, vc pode deixar isso com o seu framework web, mas vc ñ deve generalizar.
No exemplo que eu citei anteriormente, vamos supor que o usuário possa alterar a senha (e obviamente, o sistema pede a senha atual e a nova senha), caso a senha atual não esteja correta, vc não pode deixar que a alteração ocorra.

Sendo assim, vc poderia fazer:

class User {
     public void chancePassword(String currentPass, String newPass) throws InvalidPasswordException {
          if (!password.equals(currentPass)) {
                throw new InvalidPasswordException();
          } else {
              password = newPass;
          }
     }
}

Entendeu ?

[quote=chicobento]No caso da validação, pra vc evitar overhead, vc pode deixar isso com o seu framework web, mas vc ñ deve generalizar.
No exemplo que eu citei anteriormente, vamos supor que o usuário possa alterar a senha (e obviamente, o sistema pede a senha atual e a nova senha), caso a senha atual não esteja correta, vc não pode deixar que a alteração ocorra.

Sendo assim, vc poderia fazer:

class User {
     public void chancePassword(String currentPass, String newPass) throws InvalidPasswordException {
          if (!password.equals(currentPass)) {
                throw new InvalidPasswordException();
          } else {
              password = newPass;
          }
     }
}

Entendeu ?
[/quote]

Entendi, então o que vou fazer agora e deixar a validação de documentos para o framework como CPF, CNPJ e etc…, e as outras vou colocar todos no model.

Valeu

O problema não é uma ou outra classe no sistema ser assim, isso acontece. O problema é você dizer que a maioria das classes são assim. Creio que você não está conseguindo enxergar suas regras porque elas estão diluídas em muitos lugares, algo bem comum. Dê uma olhada na sua validação de formulário, consultas SQL e outro suspeitos. Procure classes com ifs e iterações. Provavelmente suas regras de negócio que deveriam estar nos objetos de negócio estão espalhadas nestes.

[quote=pcalcado][quote=danielbussade]
Ok philip mas agora veio uma questao na cabeça; E seu precisar persistir este dado no banco, já que uso o Hibernate pra isso, como vou persistir este atributo visto que ele nao faz parte do objeto?
[/quote]

Não entendi, se ele é derivado e se os que o originam são persistidos por que você o precisaria persistir? Talvez não tenha ficado claro mas o que eu sugrei inclui uma mudança também no modelo de dados. Se isto não é possível então é outra história.

Como ponto relevante, se fosse o caso você poderia fazer o Hibernate utilizar métodos get/set (ou talvez métodos anotados, não conheço Hibernate Annotations) ao invés de atributos.[/quote]

Se realmente você precisar persistir esses dados calculados… Você pode anotar o método com @Column(name=“meuatributo”).

Mas se é um valor calculado, é bem estranho que ele seja persistido…

[]´s

[quote=pcalcado][quote=danielbussade]
Nesta classe onde nao tenho regra de negocio, eh um simples CRUD, acaba se tornando anêmica, porque o que acontece eh que recupero os valores que o usuario digitou com input.getParameter(“qualquerCoisa”), vindo de HttpRequest e passo todos os valores no construtor.
Quase todas as classes são assim, ou seja a minha dúvida eh se uma classe eh um simples cadastro ou seja nao tem regra de negocio envolvida acaba se tornando um agrupamento de dados, isso faz dela uma classe anêmica??
[/quote]

O problema não é uma ou outra classe no sistema ser assim, isso acontece. O problema é você dizer que a maioria das classes são assim. Creio que você não está conseguindo enxergar suas regras porque elas estão diluídas em muitos lugares, algo bem comum. Dê uma olhada na sua validação de formulário, consultas SQL e outro suspeitos. Procure classes com ifs e iterações. Provavelmente suas regras de negócio que deveriam estar nos objetos de negócio estão espalhadas nestes.[/quote]

Olá Philip analisando o sistema percebi que minhas regras de negócio se encontrava no Controller, ou seja meus objetos eram apenas agrupamento de dados, estou modificando o sistema para ter as regras no model. E então me surgiu umas duvidas uma delas eh o seguinte:

Tenho uma classe Usuario e Administrador, onde uma area no sistema somente Administradores tem acesso porque eh uma area de configuracao do sistema, ai na minha action eu recupera via getParameter o que ele digitou chamo o Repository e recupero o Usuario ai na action eu faço um if desta forma:

if(usuario instanceof Administrador) {
  //permiti acesso
}else{
 //Acesso negado
}

Acho que esta abordagem esta incorreta porque se amanha ou depois eu precisar dar acesso ao Diretor por exemplo vou ter que mudar o if, isso cheira “gambiarra”, porem nao vejo outra forma de fazer

Alguem poderia me dar uma ideia??

Obrigado

if (usuario.possuiAcesso(funcionalidade)) {
  //permiti acesso
} else {
 //Acesso negado
}

Boa idéia a do Bruno. Se você está usando Domain-Driven Design (que eu assumo já que usou a palavra “Repositório”, apesar de muita gente tem chamado seus DAOs de Repositório por um motivo que eu ainda não entendo) uma Specification pode ajudar neste caso.

Não entende mesmo ?

[quote=peerless]
Não entende mesmo ?[/quote]

As vezes as pessoas acham que estao fazendo Domain-Driven Design, que é o tema do post, mas eu tenho visto muita gente que nem ouviu falar de DDD e está passando a chamar DAOs de Repositórios como se fosse um novo nome para uma coisa velha.

Tem dias que acho que as pessoas tem medo de se orientarem à objetos.

Nem é questão de entrar em mérito se é DDD ou não, mas acho que muita gente está afundada em código de baixo nível (no mesmo sentido de linguagens de baixo/alto nível), preferem uma sintaxe rápida(?!?) e burra a uma inteligente, mais humana.

Falo isso por que vejo, todo santo dia, pessoas (também me incluo) comparando suas estruturas com nulo, com variável igual a tal, se os estado deles é igual a xpto, se é maior, menor blah blah. Tudo bem que é isso que acontece mesmo, você é obrigado a trabalhar com essas construções se quiser ter algum resultado, porém esse código não deveria estar no teu negócio. Código de baixo nível deve ser encapsulado.

Existe uma [color=white]doença^W tendência^W[/color] mania de descobrir quem é objeto, o que tem guardado nele, qual é a relação dele com outro. Se quiser saber alguma coisa do objeto, pergunte ao próprio. Se quiser fazer alguma coisa, mande ele fazer.

Outra mania é usar nulos para expressar alguma coisa. Nulos não expressam coisa alguma!

Caso você procurar por um cliente, e o método de procura retornar um Cliente, retorne o objeto nulo ClienteNãoCadastrado caso você não o achar, depois pergunte ao objeto “cliente.estaCadastrado() ?”. Esqueça de comparar (cliente != null), ou pior, gerar uma ClienteNãoCadastradoException.

Não tema objetos (de verdade)! Aliás, não tema programação limpa, ou Dijkstra vai te pegar!

claro que expressa. Expressa “ausência de objeto”

Putz, isso é a maior gambiarra que eu já vi.
Existe um padrão chamado NullObject que cria um objeto especial quando o objeto normal não pode ser criado.
Vc poderia até criar um NullObject que seria esse seu ClienteNãoCadastrado contudo, ele não tem o método “estaCadastrado” por duas razões : 1) se o NullObjet tem esse método o objeto normal tb te que ter o que significa, basicamente , o uso de parametros em vez de OO. 2) estarCadastrado é um conceito que depende do que alguem ( a aplicação) fez com o objeto e não do objeto em si. Logo, um parâmetro que faça isso é uma violação declarada de encapsulamento. Programação orientada a parametros tb não é OO :wink:

Vc pode retornar o NulObject, blz, mas depois vc tem que compara assim:

[code]if ( !(obj instanceof ClienteNãoCadastrado)){

}[/code]

convenhamos que é muito mais simples e eficiente

[code]if ( obj !=null )){

}[/code]

O padrão NullObject é usado em circunstanciais particulares especialmente quando vc vai invocar métodos sobre o objeto, mas nunca como opção ao if de null. (aliás o fato de retornar NullObject ainda não garante que não possa vir null )

O uso correto seria não verificar o null e não comprar o parametro , simplesmente assim:

Cliente cliente  = .. // procura cliente retorna NullCliente se não encontrado

cliente.fazalgumacoisa(); // o metodo de NullCliente simplesmente não faz nada.

Isto funciona quando o objeto usa o padrão Strategy por baixo dos panos, mas se vc tentar usar o objeto como um PropertyBag
vc vai ter problemas para encontrar valores default para o NullObject. Sobretudo em cálculos complexos. (mas vai dai vc provavelmente deveria usar Strategy nesse caso… )

Desculpem-me, padrão errado. NullObject é para comportamento padrão. Não chego a esse ponto, ainda estou vários atrás.

O que estou pensando mesmo é que o teu cliente não se importa com “ausência de objetos”, isso não é conceito de domínio; “cliente não cadastrado”, “produto não encontrado” são.

cliente.estaCadastrado() diz mais coisas que cliente == null, que precisa que estar dentro de um contexto para ser entendido. Questão de manutenabilidade.

[quote=Bruno Laturner]Desculpem-me, padrão errado. NullObject é para comportamento padrão. Não chego a esse ponto, ainda estou vários atrás.

O que estou pensando mesmo é que o teu cliente não se importa com “ausência de objetos”, isso não é conceito de domínio; “cliente não cadastrado”, “produto não encontrado” são.

cliente.estaCadastrado() diz mais coisas que cliente == null, que precisa que estar dentro de um contexto para ser entendido. Questão de manutenabilidade.[/quote]

não concordo com essa visão, mas tudo bem…

Estou viajando demais quando eu deveria seguir o principio KISS?

Estou viajando demais quando eu deveria seguir o principio KISS?[/quote]

Existe uma razão para que o ultimo S significa Stupid. É para levá-lo a usar o principio. se o não seguir, ele já lhe chama estupido.
O ponto é que “simples” é uma questão de conhecimento , proeficiencia na linguagem, na plataforma e em API de terceiros.
Basicamente o KISS é um não-principio porque é subjetivo.

O principio é muito comparado com a Navalha de Occam, que é um principio da epistemologia da ciencia que dita que se duas teorias
conduzem aos mesmo resultados, a que for mais simples deve ser preferida. Mas aqui “simples” é objetivo, significa a teoria que contiver menos axiomas ou permissas. Não significa, por exemplo, a que for matematicamente mais simples.
Se entendermos o KISS como a Navalha de Occam aplicada ao mundo da programação, então o programa mais simples não é aquele que tem menos código ou menos classes e sim aquele que é mais intelegivel, aquele que parte de menos permissas( tem menos ifs)

Ou seja, usar NullObject é mais simples que comparar com null a toda a hora, embora significa criar um classe a mais.
quanto ao “estaCadastrado” eu não compartilho do seu gosto por esse método porque viola o encapsulamento, como já expliquei.
Preferiria algo como repositorio.contains(cliente). Se certa este codigo parte de menos permissas que o “estaCadastrado” exactamente por não violar o encapsulamento, mas como disse… tudo bem com o seu estilo se funciona para si. Para mim não funciona.

Olá, voltando a idéia inicial do post sobre classes anêmicas, me surgiu outra dúvida, quando não se usa DDD ou seja o seu modelo não fala a mesma língua do cliente, e suas regras de negócio não estão no Domain, e sim espalhadas entre Controller, Façades, etc. As classes acabam se tornando anêmicas não?? Qual seria um alternativa OO em relação ao DDD, sem deixar as classes anêmicas??

Obrigado

[quote=danielbussade] Olá, voltando a idéia inicial do post sobre classes anêmicas, me surgiu outra dúvida, quando não se usa DDD ou seja o seu modelo não fala a mesma língua do cliente, e suas regras de negócio não estão no Domain, e sim espalhadas entre Controller, Façades, etc. As classes acabam se tornando anêmicas não?? Qual seria um alternativa OO em relação ao DDD, sem deixar as classes anêmicas??

Obrigado[/quote]

Sim, vc usa OO, mas não em sua plenitude.
Por exemplo, vc pode utilizar fábricas, interfaces e etc para seus Façades. Sendo assim vc estará usando OO, mas não estará usando OO na parte que mais importa que é o domínio.