Inspirado por esse post estou colocando o seguinte problema de arquitetura para discussão:
Tenho clientes que podem ser pessoas jurídicas (company) ou físicas (individual).
OBS: Abaixo descreverei a minha opinião que não é a palavra final, apenas a semente para o debate.
Como um Teórico que gosta de Complexidade atacaria o problema:
public interface Person {
public int getId();
public String getName();
public Address getAddress();
}
public abstract class AbstractPerson implements Person {
private final int id;
private final String name;
private final Address address;
public AbstractPerson(int id, String name, Address address) {
this.id = id;
this.name = name;
this.address = address;
}
public int getId() { return id; }
public String getName() { return name; }
public Address getAddress() { return address; }
}
public class Company extends AbstractPerson {
private final String cnpj;
public Company(int id, String name, Address address, String cnpj) {
super(id, name, address);
this.cnpj = cnpj;
}
public String getCnpj() {
return cnpj;
}
}
public class Individual extends AbstractPerson {
private final String cpf;
public Individual(int id, String name, Address address, String cpf) {
super(id, name, address);
this.cpf = cpf;
}
public String getCpf() {
return cpf;
}
}
public class Client implements Person {
private int refererId;
private final Person person; // decorator pattern (see GOF page 634)
public Client(int refererId, Person person) {
this.refererId = refererId;
this.person = person;
}
public int getRefererId() {
return refererId;
}
public int getId() {
return person.getId();
}
public String getName() {
return person.getName();
}
public Address getAddress() {
return person.getAddress();
}
public String getCpf() {
if (person instanceof Individual) {
return ((Individual) person).getCpf();
}
return null; // ou throw exception
}
public String getCnpj() {
if (person instanceof Company) {
return ((Company) person).getCnpj();
}
return null; // ou throw exception
}
}
Notas:
- Ele encheria a boca para falar que usou o pattern Decorator
- Ele teria duas tabelas no banco-de-dados, uma para Companies e outra para Individuos. E teria uma para Client e fazendo join em ambas.
- Ele pensaria em transformar Client numa interface para deixar a coisa ainda mais transparente e bem arquitetada.
O que o Prática que gosta de Simplicidade faria:
public class Customer {
public static enum Type { INDIVIDUAL, COMPANY };
private int id;
private String name;
private Address address;
private String cpf;
private String cnpj;
private Type type;
private int refererId;
public Customer() {
}
public Customer(Type type) {
this.type = type;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String getCpf() {
return cpf;
}
public void setCpf(String cpf) {
this.cpf = cpf;
}
public String getCnpj() {
return cnpj;
}
public void setCnpj(String cnpj) {
this.cnpj = cnpj;
}
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
public int getRefererId() {
return refererId;
}
public void setRefererId(int refererId) {
this.refererId = refererId;
}
}
Notas:
- Ele teria apenas uma tabela no banco-de-dados.
- Ele entenderia e aceitaria que o seu sistema pode ter um erro de inconsistência: um Customer to tipo company com um cpf.
- Porque o sistema pode ter não significa que ele terá. Assim como porque um banco-de-dados não tem chave-estrangeira não quer dizer que ele terá inconsistências.
Perguntas:
-
Qual dos dois sistemas é mais fácil de entender?
-
Qual dos dois sistemas é mais fácil de testar de forma automatizada via testes unitários e testes funcionais?
-
Qual sistema terá uma estrutura de tabelas mais simples?
-
Qual sistema está mais correto do ponto teórico?
-
Qual é a chance de no futuro você introduzir um novo tipo de cliente?
-
Onde vc está usando polimorfismo?
7 ) Qual que vc escolheria? O teórico ou o prático?
-
Você vê alguma terceira opção?
-
Pra que existe enumeration na linguagem Java?
-
Você não acha que o teórico é um cara muito fera? Um verdadeiro arquiteto de sistemas?