Terça-feira, Maio 20, 2008

Princípios de OO segundo Alan Knight (e Dilbert) (parte 1)

(nossa como faz tempo que não posto... :p)

Faz uns anos eu achei um artigo artigo obscuro escrito por Alan Knight por volta de 2000 ou 2001 que é um excelente resumo de como deve ser um bom código orientado a objetos. O mais interessante é que o artigo faz analogia aos princípios "Dilbert", e por incrível que pareça, a analogia encaixa como uma luva.

O texto é curto e muito divertido, recomendo a leitura!

Como sempre mostro esse artigo pra todo mundo que eu conheço, achei que já era hora de citar ele no blog e fazer um resumo em português pra quem não conhece bem o gringolês. Como posts grandes ninguém lê, vou postando os princípios aos poucos.

Nota: AS IDÉIAS AÍ EMBAIXO NÃO SÃO MINHAS, OKAY? EU GOSTO MUITO DELAS, MAS O AUTOR ORIGINAL É O "TIUZÃO TOP FODA" ALAN KNIGHT!

Avisados? Ótimo! Senão depois o TaQ briga comigo por estar levando crédito por idéias alheias :).




Princípio 1: Nunca faça nada que alguém possa fazer para você.



Esse é basicamente o princípio do "tell, don't ask". Basicamente, objetos não podem ser caras legais. Nada de "Olha, preciso do total dos custos desde o começo do mês, mas não se incomode, me dê os dados aí que eu mesmo faço o cálculo, não deve ser muito complicado, não é?"

total = centro_de_custo.itens.inject(0) do|soma, item|
if item.data > Date.parse('2008-05-01')
soma += item.valor
else
soma
end
end

Objetos devem ser grandes FDPs. Objeto bom é grosso como seu chefe: "Cara, quero o total dos custos desde o começo do mês! Não quero nem saber e não me interessa como você calcula isso, quero o resultado, e quero JÁ!".

total = centro_de_custo.total_desde('2008-05-01')

Em Java, vejo muito uma coisa um pouco mais esquisita, normalmente envolve um DAO, injeção de dependência e costumeiramente um Date que não se pode construir diretamente pois o construtor está "deprecated":

// getCentroDeCustoDAO foi alimentado antes pelo Spring
// e "new Date" costuma ser gerado via Calendar, pq esse
// construtor está deprecated faz tempo...
List itens = getCentroDeCustoDAO().procurarPorDataDesde(new Date(2008, 4, 1));
BigDecimal resultado = new BigDecimal(0);
for(Item item : itens) {
resultado = resultado.add(item.getCusto());
}

Mesmo que você goste muito desse padrão, seria um pouco melhor do jeito abaixo. Embora já tenha ouvido que isso é regra de negócio e não deveria ser feita no DAO.

// getCentroDeCustoDAO foi alimentado antes pelo Spring
// e "new Date" costuma ser gerado via Calendar, pq esse
// construtor está deprecated faz tempo...
BigDecimal resultado = getCentroDeCustoDAO().calcularCustoTotalPorDataDesde(new Date(2008, 4, 1));

"Tell, don't ask" <= "Mande, não peça"...