Help em decisão no diagrama de classes basicas

aew galera…

estou com uma dúvida aqui…
estou com a classe Funcionario que extende User e User extende PessoaFisica
A grande questao é a seguinte… no meu sistema podera existir um User que seja PessoaJuridica
como resolver isto de forma elegante?

vlw

Hum… cuidado que Java não suporta herança múltipla, mas você pode simular herança múltipla com interfaces.

opa…

valeu ai pelo post…
tow lgd q Java nao suporta heranca multipla…
uma solucao q eu tinha feito previamente… foi criar a classe UserPF e UserPJ extendendo, respectivamente, as classes PF e PJ, e as duas classes UserXX implementam a interface User
mas nao gostei muito dessa abordagem por conta da duplicacao de dados nessas 2 classes

pensanso aqui… poderia criar uma classe unica, Pessoa, que seria uma UNIAO das classes Pf e PJ adicionada de um campo que seria TipoPessoa(“PF”,“PJ”). Daí Funcionario extende User e User extende Pessoa.

o que vcs acham desta abordagem?

Esse atributo tipo de pessoa (Fisica ou Juridica) IMHO ficaria mais elegante utilizar um enum.
Seria algo mais ou menos assim:

pessoa.setTipoPessoa( TipoPessoa.FISICA );

Agora precisa ver se nesta classe vai ter CPF, RG e etc. para pessoa fisica e CNPJ, I.E e etc. para pesoa juridica, pois ai sua classe começa a não ficar coesa.

opa rlazoti,

com relacao ao atributo… sim, seria um enum, é verdade!

com relacao a uma classe unica conter atributos relativos a PF e PJ, realmentenao ficaria coesa, visto que conteria dados referentes a diferentes entidades. Mas eu quis lançar ua outra abordagem para ser discutida!
vc sugere uma abordagem melhor para este meu problema?
ou acha q a melhor solucao é a primeira msm q utilizei, de quebrar as classes em 2 (XXPf e XXPJ), duplicando os dados?

vlw cara

Todo funcionario tem que ser do tipo USER?

flws

sim…
todo funcionario é User e deve ser PF
mas nem todos User é PF, podendo ser PJ

Na minha opnião.

Cria uma Interface User
Cria uma classe Pessoa
Cria a classe PessoaFisica e PessoaJuridica que extendem Pessoa
Cria a sua classe Funcionario extendendo de Pessoa e implementando User

e aew Bruno…

rapaz… qual seria a utilidade de colocar essa interface User visto que User é uma classe basica e, inicialmente nao teria la métodos relevantes, além dos get e set ?
o ideal seria colocar uma classe ai User que conteria os dados em comum e ai UserPf e UserPJ herdariam deles, mas ai é utopia visto que Java nao nos da opcao de heranca multipla…

vlw

Herança é utilizada em casos onde se tem uma generalização e especialização.

Não sei exatamente o problema que você está tratando, mas vale a pena se perguntar:

A classe ‘User’ é uma especialização de ‘PessoaFisica’? Ou,
Há algum dado ou comportamento em PessoaFisica que não é aproveitado e estendido pela classe User? Se sim, é porque User não deve ser uma especialização de PessoaFísica. Pensando no domínio do problema, especializações precisam de tudo o que a classe genérica oferece e provê mais comportamentos e/ou mais dados e/ou altera comportamento e dados da genérica.

A impressão que eu fico é que na maioria dos domínios, User e PessoaFisica são entidades independentes quando falamos de Herança. Vejo ‘User’ como a “coisa” que tem acesso ao sistema e, entre outras propriedades, possui um login e senha. ‘User’ pode ser não só uma pessoa física ou jurídica, mas também um outro software da companhia que precisa migrar ou transferir dados. Enfim, não vejo a classe User como uma especialização de pessoa física nem jurídica. Mas, é claro, tudo depende do problema que o seu software está tratando.

Normalmente, surge a necessidade de herança múltipla quando se mistura dois contextos diferentes em um mesmo modelo de classes. O problema de contextos diferentes é discutido no livro DDD (Domain Driven Design de Eric Evans). Veja só:

Você sugeriu que Funcionario é uma especialização de User. É necessário avaliar o que isso quer dizer… Se Funcionario é um User que tem acesso limitado há algumas funcionalidades do sistema, beleza, ele realmente tem cara de ser uma especialização de User.
Entretanto, você coloca que Funcionario também é uma especialização de PessoaFisica. O que isso quer dizer? Que Funcionario faz as mesmas coisas (ou tem os mesmos dados) que PessoaFisica? Beleza mais uma vez, ele tem cara de ser uma especialização também.

Mas os contextos podem ser diferentes:
Um ‘Funcionário’ do departamento de pessoal (DP) é um ‘User’ do sistema de folha de pagamento, mas, um ‘Funcionário’ da TI não o é. Mas, ambos os funcionários aparecem na folha de pagamento. O problema é que estamos falando de contextos diferentes: A primeira classe funcionário trata de autenticação no sistema e a segunda classe trata do negócio de folha de pagamento. Ambas as classes têm o mesmo nome, mas, não têm os mesmos objetivos.

É como se você criasse duas classes com nome ‘Funcionário’ em pacotes java diferentes. Uma classe trata das questões de usuário como, por exemplo, qual a primeira tela após o login irá aparecer para ele. E a segunda classe ‘Funcionário’ trata de questões de DP como, por exemplo, qual o seu salário e quantos dias foram trabalhados.

É necessário conhecer melhor o problema para saber se vale a pena ou não criar uma associação simples (não uma herança) entre User e outra classe do seu sistema.

[quote]estou com uma dúvida aqui…
estou com a classe Funcionario que extende User e User extende PessoaFisica
A grande questao é a seguinte… no meu sistema podera existir um User que seja PessoaJuridica
como resolver isto de forma elegante? [/quote]

Criar a classe Pessoa.
Criar a classe PessoaFisica que herda de Pessoa.
Criar a classe PessoaJuridica que herda de Pessoa.
Criar a classe User COM UMA ATRIBUTO do TIPO PESSOA.
---- Desta maneira vc pode atribuir ao objeto da classe User qualquer um dos dois tipos de objetos:
---- user.setPessoa(pessoaFisica);
---- user.setPessoa(pessoaJuridica);
Criar a classe Funcionario que herda de User

Essa opção pode ficar mais “elegante” e de acordo com as melhores práticas utilizando interfaces.

Que vc acha?

flws

legal sergio…
ainda nao tinha pensado dessa forma…
bem… pensando na possibilidade de Funcionario nao herdar de User… tenho essa abordagem q lanço para discussao aqui:

Funcionario extends PessoaFisica
Funcionario – User (Funcionario possui um atributo User)
Cliente – User (Cliente possui um atributo User)

O que acha desta abordagem?

  • Bem… me surge um novo questionamento aqui…: Cliente pode ser PF ou PJ. Qual a melhor abordagem? criar 2 classes: ClientePF e ClientePJ?

vlw

opa fantomas…

essa sua abordagem é semelhante a q eu postei por último… mas creio que a minha abordagem foi um pouco mais feliz… pelo fato de que força Funcionário a ser PessoaFísica, que é o caso da minha aplicacao (pode ser q em outro contexto a sua seja melhor :wink: ) e da sua forma Funcionario poderia ser PF ou PJ. E na sua abordagem sugiro um enum em Pessoa que informa qual o tipo (PF ou PJ)

vlw cara

E os PJs?

[quote=danilo.dct]opa fantomas…

essa sua abordagem é semelhante a q eu postei por último… mas creio que a minha abordagem foi um pouco mais feliz… pelo fato de que força Funcionário a ser PessoaFísica, que é o caso da minha aplicacao (pode ser q em outro contexto a sua seja melhor ) e da sua forma Funcionario poderia ser PF ou PJ. E na sua abordagem sugiro um enum em Pessoa que informa qual o tipo (PF ou PJ)

vlw cara [/quote]

Concordo completamento com vc.

Então nós entramos nas questões citadas pelo smarcelo_br.

flws

++

[quote=danilo.dct]Funcionario extends PessoaFisica
Funcionario – User (Funcionario possui um atributo User)
Cliente – User (Cliente possui um atributo User)

O que acha desta abordagem?[/quote]

Preciso de mais informações sobre que tipo de SW você está construindo. Por que Funcionario e Cliente têm um atributo do tipo User? Em que funcionalidade do sistema estas classes precisam de User? Eu não consegui imaginar um exemplo.

[quote=danilo.dct]

  • Bem… me surge um novo questionamento aqui…: Cliente pode ser PF ou PJ. Qual a melhor abordagem? criar 2 classes: ClientePF e ClientePJ?[/quote]

Só separe em duas classes ClientePF e ClientePJ se houver regras específicas para cada um como Cliente. Nos sistemas que eu já trabalhei nunca foi necessária a separação.
Eu faria como o fantomas sugeriu para User:
Cliente.setPessoa(Pessoa pessoa); // pessoa pode ser tanto uma instância de PessoaJuridica ou PessoaFisica.

Outra coisa: Dependendo da aplicação que você esteja construindo, você nem precisa das especializações PessoaFisica e PessoaJuridica no seu modelo de classes. Se o CPF e o CNPJ são sempre usados com o mesmo objetivo, eles não precisam ser atributos separados da classe Pessoa e nem precisa de duas especializações. Por exemplo, numa nota fiscal, normalmente, o campo CPF e CNPJ é o mesmo! Em arquivos que são enviados para o governo, estes dois campos aparecem sempre na mesma posição. Chame então o atributo de ‘codCpfCnpj’ e seja feliz! Tudo depende da aplicação.
Outro exemplo: Se o login de um usuário PF e PJ é o seu CPF e CNPJ respectivamente, crie um único atributo ‘login’ e grave lá o CPF ou o CNPJ dependendo do tipo da pessoa ao cadastrar o usuário. Eu tinha dito no meu post anterior que coisas que têm o mesmo nome (Funcionario) não precisam ser necessariamente implementadas na mesma classe e agora estou dizendo que coisas com nomes diferentes (CPF e CNPJ) podem ser a mesma coisa no contexto da sua aplicação. Arquitetura de SW é isso aí!

Um conselho: você terá muitas dificuldades se estiver tentando criar um único conjunto de classes para atender todos os sistemas de todas as áreas da empresa. Isso não funciona, pois, numa empresa existem vários contextos diferentes.

opa thingol,

os PJ ficam, por exemplo, para os Clientes que são PJ ou PF. Daí a abordagem que o fantomas sugeriu pode ser legal… visto que Cliente pode ser PF ou PJ. No caso Cliente teria um atributo Pessoa que pode ser PF ou PJ. Sugiro, como já havia falado, colocar um enum TipoPessoa em Pessoa para podermos saber de forma mais fácil/pratica que tpio de Cliente estamos tratando.

valeu galera

Bom,

ja passei por isso umas duas vezes e resolvi da seguinte forma.

abstract class Pessoa { } // atributos basicos que uma pessoa pode ter ( endereco… nome… cep etc )

interface PessoaFisica {} // cpf, rg, sexo…
interface PessoaJuridica {} // cnpj, inscricao estadual …
interface Usuario {} // login, senha…

public class Funcionario extends Pessoa implements PessoaFisica, Usuario {
}

caso vc tenha outras entidades como cliente ( que pode ser pessoa fisica e juridica )

public class Cliente extends Pessoa implements PessoaFisica, PessoaJuridica { // implements tambem Usuario, caso ele possa logar no sistema.
}

Creio que assim possa resolver seu problema.

abraco

Eu gosto de solucionar problemas assim usando o Role Actor Pattern, não achei muito coisa em java, mas não é nada dificil de montar

um link de referencia
http://www.cs.sjsu.edu/faculty/pearce/modules/patterns/analysis/Actor.htm