TDD substitui ou complementa modelagem?

68 respostas
R

Bom dia, há algum tempo eu tenho lido e praticado (um pouco) de TDD, muito embora até hoje não tenha conseguido trazê-lo totalmente para a minha realidade profissional. Nessa minha pouca experiência, percebo que: mesmo que os testes ajudam na especifação do sistema, rascunhar um UML ou outro vem muito a calhar, especialmente na hora de entender o domínio do sistema ser construído sair aquele 1o teste.

Sendo assim, o que vocês acham ?

obs: haters de TDD e testes unitários são bem vindos! :twisted:

68 Respostas

R

O único livro sobre DDD, do Eric Evans, foi um sucesso de vendas. Para repetir, inventaram uma nova metodologia: TDD. Mais alguém vai ficar rico, não será você. A grande “sacada” dessas metodologias ágeis é justamente não produzir qualquer documentação, incluindo modelagem. Todo o negócio fica na classe de Domínio, mesmo que tenha 1000 linhas. A aplicação “vai saindo” a cada entrega. E não tem problema se ficou ruim ou não atendeu as expectativas do seu cliente. Isso agora é problema da outra equipe, responsável pela manutenção. Você ainda está no time de elite, produzindo apenas coisas novas.

Este novo modelo de criar aplicações a partir de testes, porque o próprio teste passa a ser a história do caso de uso, poderia ser melhor avaliado. Afinal, teste também é fonte. É legal um fonte massaroquento e você começa a fazer testes unitários, produz a sensação de “tudo novo de novo”. No longo prazo, quando for necessário fazer manutenção nos testes, essa situação será o retrato da situação anterior, quando os testes ainda não existiam.

J

Vai da necessidade, se ninguém usa a documentação então não faça por fazer, as vezes quando se pára pra pensar e questionar pode ser a falta da necessidade. Mas se vai usar e vê retorno, então uma coisa pode complementar a outra e não substituir. Importante é não fazer nada só por etiqueta, se algo vai agregar valor ao sucesso do negócio do cliente diante de uma criticidade por exemplo, tendo investimento/recurso para isso então tá valendo.

Profissionalmente na equipe que trabalho não fazemos testes antes de desenvolver, de “documentação” para o antes de desenvolver, só temos especificação escrita junto com o cliente, e de UML no máximo caso de uso e só quando são muitos papeis envolvidos. O ciclo de entrega é pequeno, a presença e parceria do cliente ajuda mais do que fazer os testes antes. Acho que muitas vezes apresentar um item em andamento que não seria o esperado e ajustar seria o mesmo tempo de fazer os testes antes/ver erros/produzir 100%. Claro que para isso o cliente precisa ser parceiro e não aquele que só quer ver a tela perfeita fechada no final.

X

Putz, olha me desculpe mas não acredito que você tem lido qualquer coisa a respeito de DDD ou TDD e até mesmo sobre metodologias ágeis. Em primeiro lugar um não é fruto do outro. TDD é muito antigo, foi criado por Kent Beck muito antes de se ouvir falar de DDD. TDD e DDD não são a mesma coisa, um não substitui o outro! Para ter uma ideia TDD era usado com Smaltalk! Outra coisa TDD e DDD não são metologias ágeis, você deve estar confundindo com Scrum, XP e Kanbam. TDD e DDD fazem parte das metodologias ágeis, testes são obrigatórios para XP por exemplo.

Se você tivesse lido o livro do Evans, vai ver que em lugar algum ele falou que não se deve fazer documentação. Na verdade nenhuma metologia ágil diz que não se deve fazer documentação o que ela falam é da importância da documentação. Com uma metodologia ágil você tem documentação, mas ela é um guia para desenvolvimento.

Bah. Nunca vi isso com alguém que usa TDD e DDD na verdade a ideia é justamente NÃO fazer isso! Se alguém faz isso então não está usando TDD ou DDD!

A ideia de TDD é justamente não ter código massaroquento, pois uma coisa inerente a ele é a refatoração continua. Também não existe manutenção de Teste, não sei da onde vc tirou isso.

X

rmendes08:
Bom dia, há algum tempo eu tenho lido e praticado (um pouco) de TDD, muito embora até hoje não tenha conseguido trazê-lo totalmente para a minha realidade profissional. Nessa minha pouca experiência, percebo que: mesmo que os testes ajudam na especifação do sistema, rascunhar um UML ou outro vem muito a calhar, especialmente na hora de entender o domínio do sistema ser construído sair aquele 1o teste.

Sendo assim, o que vocês acham ?

obs: haters de TDD e testes unitários são bem vindos! :twisted:

TDD não substitui você entender o problema. Nada impede você de rascunhar algumas classes para ter uma idéia do modelo, na verdade acredito que isso seja fundamental para entender o dominio e se comunicar com seu cliente. O problema é você implementar essas as classes antes de fazer os testes! O ideal também é que essas classes do modelo não tenha funções ou somente as necessárias para entender o modelo. Eu costumo usar um quadro branco para criar modelar o dominio e depois implementar.

Uma grande vantagem de TDD é que ela te mostra rapidamente quando você não entendeu o dominio, pois o código começa a ficar complexo e difícill de desenvolver!

J

x@ndy:
Nada impede você de rascunhar algumas classes para ter uma idéia do modelo, na verdade acredito que isso seja fundamental para entender o dominio e se comunicar com seu cliente.

Com certeza, o papel de pão numa mesa redonda é fundamental, a tela vicia a dar alt tab e “partir para implementação”.

H

Acho que não. A modelagem inicial eu acho sempre uma boa abordagem para se ter uma direção.

Depois disso eu penso que pode-se partir para TDD direto para começar a criar classes e outros relacionamentos, mas ainda assim eu gosto de ter um diagrama de classe (pelo menos a um nível mais abstrato, sem ter que mostrar métodos e coisas do tipo). O diagrama é bom para quem está iniciando ter uma idéia do sistema. [=

X

Hebert Coelho:
Acho que não. A modelagem inicial eu acho sempre uma boa abordagem para se ter uma direção.

Depois disso eu penso que pode-se partir para TDD direto para começar a criar classes e outros relacionamentos, mas ainda assim eu gosto de ter um diagrama de classe (pelo menos a um nível mais abstrato, sem ter que mostrar métodos e coisas do tipo). O diagrama é bom para quem está iniciando ter uma idéia do sistema. [=

Concordo. O que não se pode é se prender ao diagrama e nesse caso ter um diagrama mais “abstrato”, mais para ver os relacionamentos é ótimo! O modelo deve ser guiado pelo entendimento do domínio e um modelo inicial pode estar errado. O bom de TDD é que ele indica facilmente quando seguimos um caminho errado e não entendemos o domino pois normalmente nesses casos os testes começam a se tornar complexos com alto acoplamento de classes e baixa coesão e nesse momento deve-se parar e refletir o que se está fazendo! Por que o sistema está ficando tão complexo? Realmente entendemos o dominio do cliente? Ele é tão complexo quanto estamos implementando?

O maior problema de se criar um diagrama é se prender a ele. Isso acontece muito no desenvolvimento tradicional, principalmente em fabricas de software. Nesses casos a documentação é a regra e não se pode quebra-la. O problema é que diagrama de classes não interage com você, não de tá feedback. O papel aceita tudo, mas nem tudo que está no papel pode ser feito ou se pode é muito complexo. O que mais gosto em TDD é o feedback rápido que me mostra quando estou desviando do caminho.

PS: Pegando um gancho, gostaria a opnião de vcs a respeito de uma coisa! A algum tempo tenho usado diagramas de classes (sem funções, somente com os relacionamentos) para se comunicar com o cliente. Tirando a herança que eles não entendem e que tenho evitado tenho obtido muito sucesso. Depois se uma explicação inicial de como funciona a classe (eu digo normalmente que é um documento ou objeto que ele usa) e como funciona os relacionamentos, eles entendem perfeitamente e me corrigem quando estou fazendo algo errado! Com isso tento levar o q estou fazendo para mundo deles em busca de feedback. Alguém por acaso já tentou? Se sim como foi?

Y

Hebert Coelho:
Acho que não. A modelagem inicial eu acho sempre uma boa abordagem para se ter uma direção.

Depois disso eu penso que pode-se partir para TDD direto para começar a criar classes e outros relacionamentos, mas ainda assim eu gosto de ter um diagrama de classe (pelo menos a um nível mais abstrato, sem ter que mostrar métodos e coisas do tipo). O diagrama é bom para quem está iniciando ter uma idéia do sistema. [=

Acho que esse eh o ponto, voce deve fazer da forma com que se sente mais a vontade. TDD, em nenhum momento proibe, nem encoraja, o uso de UML seja lá o quão aprofundada for. Eu, por exemplo, não costumo modelar nada em UML antes, quando estou fazendo algo sozinho, eu imagino o modelo e o implemento com os testes. Quando estou em equipe, procuro ter certeza de que estamos todos falando da mesma coisa, entao faço alguns rabiscos em UML, se necessario, pra ajudar a “unificar” o modelo.

Resumindo: Se voce se sente mais a vontade com um modelo de classes já desenhado, isso nem de longe fere o TDD. O único cuidado é pra não se ater a ele como se fosse lei e recusar melhoras nesse modelo, sugerida pelos testes, só porque não estavam no documento inicial.

Y

x@ndy:

PS: Pegando um gancho, gostaria a opnião de vcs a respeito de uma coisa! A algum tempo tenho usado diagramas de classes (sem funções, somente com os relacionamentos) para se comunicar com o cliente. Tirando a herança que eles não entendem e que tenho evitado tenho obtido muito sucesso. Depois se uma explicação inicial de como funciona a classe (eu digo normalmente que é um documento ou objeto que ele usa) e como funciona os relacionamentos, eles entendem perfeitamente e me corrigem quando estou fazendo algo errado! Com isso tento levar o q estou fazendo para mundo deles em busca de feedback. Alguém por acaso já tentou? Se sim como foi?

Não sei, já tentei isso e o cara ficou completamente perdido, embora dissesse que entendia. Não sei se por culpa minha, mas ele não entendia. Talvez não seja possível com todos os clientes.

Eu, particularmente, prefiro protótipos. Mas eu acho, e provavelmente você vai concordar, que o importante é você falar a mesma lingua do cliente, seja la em que idioma for.

X

YvGa:
x@ndy:

PS: Pegando um gancho, gostaria a opnião de vcs a respeito de uma coisa! A algum tempo tenho usado diagramas de classes (sem funções, somente com os relacionamentos) para se comunicar com o cliente. Tirando a herança que eles não entendem e que tenho evitado tenho obtido muito sucesso. Depois se uma explicação inicial de como funciona a classe (eu digo normalmente que é um documento ou objeto que ele usa) e como funciona os relacionamentos, eles entendem perfeitamente e me corrigem quando estou fazendo algo errado! Com isso tento levar o q estou fazendo para mundo deles em busca de feedback. Alguém por acaso já tentou? Se sim como foi?

Não sei, já tentei isso e o cara ficou completamente perdido, embora dissesse que entendia. Não sei se por culpa minha, mas ele não entendia. Talvez não seja possível com todos os clientes.

Eu, particularmente, prefiro protótipos. Mas eu acho, e provavelmente você vai concordar, que o importante é você falar a mesma lingua do cliente, seja la em que idioma for.

No inicio notei que eles não entediam, mas refinei o modo de exibir o modelo e nem digo que são classes. Como uso palavras do dominio dele para as classes e normalmente elas representam documentos fica fácil. Mas não dá para colocar funções, no máximo alguns campos.

G

TDD não substitui você entender o problema. Nada impede você de rascunhar algumas classes para ter uma idéia do modelo (…)
[/quote]
Pensando bem essa dúvida do rmendes faz bastante sentido. Se você estiver seguindo o TDD à risca, como manda o livro, acaba realmente ficando mais difícil planejar com antecedência.
Segundo o TDD você deve fazer a implementação (simultaneamente ao design) em passos pequeninos: um pequeno incremento no teste, um pequeno incremento no código para passar no teste, uma refatorada para eliminar duplicidades. Sempre baseando um ciclo no resultado do anterior. E uma coisa que ele coloca muita ênfase: PASSOS PEQUENINOS! Idealmente, não mais de um minuto de planejamento + codificação em cada ciclo. E mais: não pode “atropelar”, ou seja, tentar prever coisas que não fazem parte do incremento atual.

E aí, como conciliar esse procedimento com um planejamento inicial? Se eu reunir a equipe, desenhar alguns diagramas e chegarmos a uma solução completa (ou quase completa) quando for começar a programar estarei “trapaceando” o TDD, não? Pois acabei de atropelar e pensei de antemão em como todo o programa deverá funcionar.

G

Também queria saber do pessoal sobre isso:

Vocês tem conseguido aplicar o TDD de forma razoavelmente rigorosa?

Eu particularmente tenho dificuldades para me adaptar ao modo de pensar do TDD, especialmente quanto aos “small steps”, é difícil olhar só para o passo atual sem planejar mais à frente. Acabo escrevendo um teste que pega a funcionalidade quase completa do método que estou criando, e depois preciso escrever uma grande quantidade de código para passar o teste.
Acho essa mudança mais difícil do que passar da programação procedural para OOP…

X

TDD não substitui você entender o problema. Nada impede você de rascunhar algumas classes para ter uma idéia do modelo (…)

Pensando bem essa dúvida do rmendes faz bastante sentido. Se você estiver seguindo o TDD à risca, como manda o livro, acaba realmente ficando mais difícil planejar com antecedência.
Segundo o TDD você deve fazer a implementação (simultaneamente ao design) em passos pequeninos: um pequeno incremento no teste, um pequeno incremento no código para passar no teste, uma refatorada para eliminar duplicidades. Sempre baseando um ciclo no resultado do anterior. E uma coisa que ele coloca muita ênfase: PASSOS PEQUENINOS! Idealmente, não mais de um minuto de planejamento + codificação em cada ciclo. E mais: não pode “atropelar”, ou seja, tentar prever coisas que não fazem parte do incremento atual.

E aí, como conciliar esse procedimento com um planejamento inicial? Se eu reunir a equipe, desenhar alguns diagramas e chegarmos a uma solução completa (ou quase completa) quando for começar a programar estarei “trapaceando” o TDD, não? Pois acabei de atropelar e pensei de antemão em como todo o programa deverá funcionar.[/quote]

Ops, vejo um problema ai! Em momento algum do livro do Kent ele fala que você não deve fazer um rascunho ou que não deva entender o dominio! TDD é parte do desenvolvimento de software e não é tudo! É fundamental entender o dominio, ou seja, entender o negócio que você está implementando. Não tem como implementar algo que você não conheça. TDD fala da parte de implementação, mas implementar oq? Ai entra o DDD que fala justamente que você deve entender o dominio do seu cliente, que você deve falar a mesma língua que ele e que isso deve ser representado em código. Você deve fazer de tudo para entender o dominio, não da para sair simplesmente programando.

Se seu chefe pedisse para você programar um simulador de motor de carro oq você faria? Eu iria estudar como o um motor funciona, de quais peças ele é constituído e como elas se relacionam. Muito provavelmente eu criaria um rascunho com as classes que esse domínio tem. Mas seria apenas um rascunho algo que me ajuda-se a entender o problema. Um rascunho não é nd mais que um rascunho, se for feito em papel eu posso amassa-lo e joga-lo fora a qualquer momento e começar do zero, se for feito em um quadro (eu faço os meus assim pois fica mais fácil) é só apagar e começar de novo.

O problema é perder tempo precioso modelando classes, definindo métodos e depois ir para o código, seguindo fielmente o modelo feito! Um modelo documental você tem que seguir fielmente um rascunho não, é uma ideia e se não deu certo joga fora ou altera! A ideia do rascunho assim como dos Testes é ter um feedback rápido. Você faz um rascunho e cria uma duzia de testes para implementar aquele rascunho ou melhor, para implementar uma classe do rascunho! Com esses testes você tem um feedback rápido se aquilo que você pensou está certo, se você realmente entendeu o dominio!

Y

Também queria saber do pessoal sobre isso:

Vocês tem conseguido aplicar o TDD de forma razoavelmente rigorosa?
[/quote]

Depende do que voce considera rigorosa. Sim, eu tenho aplicado e tem funcionado. O TDD em si é bem simples, a dificuldade está em tentar por testes em algo complexo, isso torna os testes complexos. Simplifique o modelo e os testes ficarao simples.

gomesrod:

Eu particularmente tenho dificuldades para me adaptar ao modo de pensar do TDD, especialmente quanto aos “small steps”, é difícil olhar só para o passo atual sem planejar mais à frente. Acabo escrevendo um teste que pega a funcionalidade quase completa do método que estou criando, e depois preciso escrever uma grande quantidade de código para passar o teste.
Acho essa mudança mais difícil do que passar da programação procedural para OOP…

É muito dificil julgar baseado em alguns parágrafos sem ver nada de código, mas o teu comentário me passa a impressão de que você está com problemas de atribuição de responsabilidade nos seus objetos. Se você pega a funcionalidade completa e tenta testar e tem dificuldade em separar isso, talvez elas estejam emaranhadas umas nas outras.

Vamos supor que voce tenha na sua mais alta camada um metodo que executa uma tarefa extremamente complexa. Ainda que ela, por força da regra de negócio, seja extremamente complexa, ela irá executar uma série de tarefas bem definidas. Se cada passo é bem definido, você tem em cada um desses passos, algo simples. E são nesses passos que estarão seus testes.

Lógico, nada impede que você tenha testes que integrem estas partes e confirmem que juntas elas estão funcionando corretamente, mas haverá testes unitários para cada um dos passos simples que irão compor a tarefa complexa.

O foco dos small steps não é necessáriamente no teste, mas na prórpia funcionalidade que você está implementando. E como disse o Xandy, para fazer a parte você terá que entender o todo, mas entender os small steps é compreender que esse todo é divido em partes e cada uma delas pode ser testada.

Supondo que você queira fazer uma venda().

La no mais alto ponto de abstracao voce terá um vender(), que recebera as informacoes vindas do usuario, como o que, para quem, a que preço, em que condições, com quais restricoes e etc…

Nesse vender(), podem estar muitos passos como:
estoque suficiente
cliente mora em uma regiao que permite entrega expressa
cliente nao possui pendencia financeira com a empresa
cliente tem direito a 10% de desconto para compras acima de 1000 reais

E assim por diante. Cada passo desse é independente do outro e pode ser testado separadamente. E se algum deles puder se subdividir, essas subdivisoes tambem podem ser testadas isoladamente. Note que para saber se o cliente mora em determinada regiao, nao se precisa saber se ele esta comprando alguma coisa ou nao. Ele mora ou não mora. Se ha estoque suficiente, há e pronto, nenhuma dessas funcionalidades precisa saber porque esta sendo chamada. Elas são independentes.

E você concentra seus testes nas partes independentes primeiro. Depois voce pode, e deve, integra-las, mas as responsabilidades estarão isoladas e sendo testadas separadamente.

X
gomesrod:
rmendes08:
(...)tenho lido e praticado (um pouco) de TDD, muito embora até hoje não tenha conseguido trazê-lo totalmente para a minha realidade profissional.(...)
Também queria saber do pessoal sobre isso:

Vocês tem conseguido aplicar o TDD de forma razoavelmente rigorosa?

Eu particularmente tenho dificuldades para me adaptar ao modo de pensar do TDD, especialmente quanto aos "small steps", é difícil olhar só para o passo atual sem planejar mais à frente. Acabo escrevendo um teste que pega a funcionalidade quase completa do método que estou criando, e depois preciso escrever uma grande quantidade de código para passar o teste. Acho essa mudança mais difícil do que passar da programação procedural para OOP...
Não sei como você desenvolve, mas para TDD é necessário planejar! Isso é feito escrevendo quais testes devem ser feitos! Você escreve os testes, ai pega o primeiro teste da lista e implementa! Para Testar uma funcionalidade você tem saber o que está testando, no mínimo o resultado esperado! No livro do kent ele da varios exemplos. Uma forma é implementar o q vai se testar no próprio teste. Por exemplo se você vai implementar uma soma vai fazer isso
// Criando o teste - e rodando (sinal vermelho)
int x = 5;
int y = 7

int somaEsperada = x + y; 
int resultadoSoma = soma(x, y);

assertEquals(somaEsperada, resultadoSoma)
...
int soma(x, y){
  return 0;
}
// Sinal verde.
int x = 5;
int y = 7

int somaExperada = x + y; 
int resultadoSoma = soma(x, y);
assertEquals(somaExperada, resultadoSoma)
...
int soma(x, y){
  return 10;
}
// Refatore.
int x = 5;
int y = 7

int somaExperada = x + y; 
int resultadoSoma = soma(x, y);
assertEquals(somaExperada, resultadoSoma)
...
int soma(x, y){
  return (x + y);
}
Esses são os pequenos passos! Mas nem sempre é necessário fazer assim. Eu sei como é uma soma eu posso primeiro criar o teste de uma forma mais simples e simplesmente refatorar, fazendo a refatoração junto com o sinal vermelho. Isso tudo depende da minha confiança no que estou fazendo:
// Criando o teste - e rodando (sinal vermelho)
assertEquals(12, soma(7, 5));
...
int soma(x, y){
  return 0;
}
// Refatore, Sinal verde.
assertEquals(12, soma(7, 5));
...
int soma(x, y){
  return (x + y);
}

Você planeja as funcionalidades mas não como implementar essa funcionalidade! Cada funcionalidade é testada e durante a criação do teste você implementa a funcionalidade. Testes devem ser mínimos, testes grandes é sinal de algo errado, muito provavelmente baixa coesão. Poucas classes e testes longos é complicados é um grande indicativo de problemas. TDD evita isso fazendo com que você implemente somente aquilo que seja necessário no momento

R

O autor do tópico quer a discussão… então… vou jogar uma bombinha… :twisted: rs

Comentem a seguinte afirmação:
Testes unitarios não testam a arquitetura do sistema. Como TDD é baseado em testes de pequenos pedaços funcionais, e de acordo com o que foi falado aqui, não deve-se planejar. Desenvolver com TDD é um facilitador para que seu sistema termine com uma arquitetura questionável.

H

rogelgarcia:
O autor do tópico quer a discussão… então… vou jogar uma bombinha… :twisted: rs

Comentem a seguinte afirmação:
Testes unitarios não testam a arquitetura do sistema. Como TDD é baseado em testes de pequenos pedaços funcionais, e de acordo com o que foi falado aqui, não deve-se planejar. Desenvolver com TDD é um facilitador para que seu sistema termine com uma arquitetura questionável.

Mas tdd é >>>>>unitário<<<< o próprio nome diz.
Se você quer teste da arquitetura, vá para outros testes como o de integração. uai!

R

Hebert Coelho:
Mas tdd é >>>>>unitário<<<< o próprio nome diz.
Se você quer teste da arquitetura, vá para outros testes como o de integração. uai!

Então… seguindo esse raciocínio… o que acontece…

Você tem uma funcionalidade. Então, você cria um teste. Faz todos os procedimentos até ele passar.
Depois, pega outra funcionalidade, e repete o processo.
Faz isso mil vezes.
No final, onde está a arquitetura do sistema?

O problema que levantei não é a falta de teste da arquitetura. O que quiz dizer é: seguindo o TDD, você não terá uma boa arquitetura.

obs: Só estou fazendo o papel de advogado do diabo…

X

rogelgarcia:
O autor do tópico quer a discussão… então… vou jogar uma bombinha… :twisted: rs

Comentem a seguinte afirmação:
Testes unitarios não testam a arquitetura do sistema. Como TDD é baseado em testes de pequenos pedaços funcionais, e de acordo com o que foi falado aqui, não deve-se planejar. Desenvolver com TDD é um facilitador para que seu sistema termine com uma arquitetura questionável.


Putz…nada haver! Esse tipo de afirmação embora lógica é uma falácia e demostra um total desconhecimento de TDD!

  1. Arquitetura não é só desenvolvimento. Envolve um conjunto de coisas. O desenvolvimento é somente parte é parte do processo arquitetural!
  2. O que TDD tem haver com falta de planejamento! Por quê usando TDD eu não posso fazer um planejamento? O que eu não tenho é uma documentação especificando exatamente o que deve ser implementado e isso não é planejamento é artefato da análise
  3. Da onde TDD é testar pequenos pedaços do sistema? Cada teste deve testar uma pequena parte, uma funcionalidade. Mas eu devo testar todas as funcionalidades, de modo que acabo por testar totalmente o sistema!
  4. A grande sacada do TDD é justamente ter um sistema com uma arquitetura coerente! Os testes de tão feedback rápido, indicando problemas na arquitetura do modelo ou na arquitetura geral do sistema.

O pessoal, se você quer saber oq é TDD tem que ler o livro do Kent Beckman - Que uma referência no assunto.

H

rogelgarcia:
Hebert Coelho:
Mas tdd é >>>>>unitário<<<< o próprio nome diz.
Se você quer teste da arquitetura, vá para outros testes como o de integração. uai!

Então… seguindo esse raciocínio… o que acontece…

Você tem uma funcionalidade. Então, você cria um teste. Faz todos os procedimentos até ele passar.
Depois, pega outra funcionalidade, e repete o processo.
Faz isso mil vezes.
No final, onde está a arquitetura do sistema?

obs: Só estou fazendo o papel de advogado do diabo…

Mas mano, são papeis totalmente diferentes.
Com o TDD você testa os pedaços pequenos… Depois você junta tudo.

Você pode testar uma classe, depois testa persistência, depois testar a view…

Seria horrível e ridículo ter testes unitários apenas para as classes sem depois fazer algo que envolvesse integrações…

Não vejo como ligar TDD com problemas de arquitetura…

H

x@ndy:
rogelgarcia:
O autor do tópico quer a discussão… então… vou jogar uma bombinha… :twisted: rs

Comentem a seguinte afirmação:
Testes unitarios não testam a arquitetura do sistema. Como TDD é baseado em testes de pequenos pedaços funcionais, e de acordo com o que foi falado aqui, não deve-se planejar. Desenvolver com TDD é um facilitador para que seu sistema termine com uma arquitetura questionável.


Putz…nada haver! Esse tipo de afirmação embora lógica é uma falácia e demostra um total desconhecimento de TDD!

  1. Arquitetura não é só desenvolvimento. Envolve um conjunto de coisas. O desenvolvimento é somente parte é parte do processo arquitetural!
  2. O que TDD tem haver com falta de planejamento! Por quê usando TDD eu não posso fazer um planejamento? O que eu não tenho é uma documentação especificando exatamente o que deve ser implementado e isso não é planejamento é artefato da análise
  3. Da onde TDD é testar pequenos pedaços do sistema? Cada teste deve testar uma pequena parte, uma funcionalidade. Mas eu devo testar todas as funcionalidades, de modo que acabo por testar totalmente o sistema!
  4. A grande sacada do TDD é justamente ter um sistema com uma arquitetura coerente! Os testes de tão feedback rápido, indicando problemas na arquitetura do modelo ou na arquitetura geral do sistema.

O pessoal, se você quer saber oq é TDD tem que ler o livro do Kent Beckman - Que uma referência no assunto.

+1

R

x@ndy:

Putz…nada haver! Esse tipo de afirmação embora lógica é uma falácia e demostra um total desconhecimento de TDD!

Se tem lógica… tem a ver!! Não é não? rs

Eu não defini o que é arquitetura. O ponto não é esse. De qualquer forma, não disse nada contrariando essa frase.

Quote xandy->“nada para TDD é necessário planejar”.

Veja minha frase: “TDD é baseado em testes de pequenos pedaços”. Eu não disse que é apenas testar pequenos pedaços, ou apenas uma parte do sistema. Um sistema totalmente testado pode ser baseado em testes de pequenos pedaços. Logo, minha afirmação está correta.

Como um teste unitário informa sobre problemas na arquitetura, se esse não é o propósito dele?

Você falou falou e pouco contestou da minha afirmação…

E “Putz…nada haver!” não é argumento. rs

Acho que talvez você tenha levado pelo lado pessoal devido ao furor da sua resposta… Não leve pelo lado pessoal, só fiz um questionamento… :slight_smile:

R

Estamos começando a nos entender… :slight_smile:

Mas mano, são papeis totalmente diferentes.
Com o TDD você testa os pedaços pequenos… Depois você junta tudo.

Você pode testar uma classe, depois testa persistência, depois testar a view…

Seria horrível e ridículo ter testes unitários apenas para as classes sem depois fazer algo que envolvesse integrações…

Eu não estou discordando de nada… Mas considerando o que você falou

"Com o TDD você testa os pedaços pequenos… DEPOIS você junta tudo. "

Esse depois é o que eu estou chamando de arquitetura ruim. Pois, antes, o que você fez foi, gerar um punhado de testes para um punhado de funcionalidades. E onde ficou a arquitetura do sistema nessa história?

Nesse ponto: "Você pode testar uma classe, depois testa persistência, depois testar a view… "
Se você tem persistencia, view, que são conceitos “grandes” vamos dizer assim… Você já saiu do TDD, não?!
Primeiro você criou uma arquitetura… e não o teste. E o TDD não testa arquitetura (acho que isso é consenso na discussão).

Pode ter parecido que eu sou um hatter de TDD pela minha hipótese inicial picante. Mas não… não sou hater, e nem lover… Só estou criticando para ver se quem é a favor do TDD está considerando certas hipóteses…

H

rogelgarcia:
"Com o TDD você testa os pedaços pequenos… DEPOIS você junta tudo. "

Esse depois é o que eu estou chamando de arquitetura ruim. Pois, antes, o que você fez foi, gerar um punhado de testes para um punhado de funcionalidades. E onde ficou a arquitetura do sistema nessa história?

Desculpe, mas a inda não vejo lógica. Isso para mim está parecendo pão com durex. :lol: :lol: :lol:

Me explique então como testar arquitetura sem ter nenhum código? O.o

Se você não ter os métodos mais simples, como você terá uma arquitetura? O TDD você começa pelo simples, e depois vai para o complexo. E fora do TDD também!!!

Onde já se viu ter uma EJB + Hibernate com persistência em pleno funcionamento sem antes ter uma entidade e alguns métodos? O.o

R

Não acho que seja possível… Mas você vai testar a arquitetura depois de ter todas as funcionalidades prontas???

De acordo com o TDD, a implementação começa no teste. Se a implementação começa no teste, a primeira coisa que você tem que implementar é uma funcionalidade. Desenvolvimento Bottom-Up. (acho que agora cheguei num ponto interessante… desenvolvimento bottom-up)

Como é que você começa implementando uma arquitetura?! Pela classe concreta ou pela interface?

Eu pelo menos, geralmente começo pela interface. Top-Down.

TDD é teste de métodos concretos. Ou seja, desenvolvimento baseado em testes de funções implementadas. Não dá pra desenvolver arquiteturas usando TDD pois a forma de desenvolver arquiteturas (top-down) e de testar (teste integração) é diferente da metodologia (bottom-up) e tipo de testes (teste unitário) propostos por TDD.

PS: O que é pão com durex?

H

Não acho que seja possível… Mas você vai testar a arquitetura depois de ter todas as funcionalidades prontas???
Pois é… então por isso creio que seu questionamento não foi válido…

rogelgarcia:
De acordo com o TDD, a implementação começa no teste. Se a implementação começa no teste, a primeira coisa que você tem que implementar é uma funcionalidade. Desenvolvimento Bottom-Up. (acho que agora cheguei num ponto interessante… desenvolvimento bottom-up)

Como é que você começa implementando uma arquitetura?! Pela classe concreta ou pela interface?

Eu pelo menos, geralmente começo pela interface. Top-Down.

TDD é teste de métodos concretos. Ou seja, desenvolvimento baseado em testes de funções implementadas. Não dá pra desenvolver arquiteturas usando TDD pois a forma de desenvolver arquiteturas (top-down) e de testar (teste integração) é diferente da metodologia (bottom-up) e tipo de testes (teste unitário) propostos por TDD.


Outro assunto… deixar o assunto para outra pessoa…

rogelgarcia:
PS: O que é pão com durex?
Expressão mineira para coisa sem nexo. [=

I am out of here…

Y

Não acho que seja possível… Mas você vai testar a arquitetura depois de ter todas as funcionalidades prontas???

De acordo com o TDD, a implementação começa no teste. Se a implementação começa no teste, a primeira coisa que você tem que implementar é uma funcionalidade. Desenvolvimento Bottom-Up. (acho que agora cheguei num ponto interessante… desenvolvimento bottom-up)

Como é que você começa implementando uma arquitetura?! Pela classe concreta ou pela interface?

Eu pelo menos, geralmente começo pela interface. Top-Down.

TDD é teste de métodos concretos. Ou seja, desenvolvimento baseado em testes de funções implementadas. Não dá pra desenvolver arquiteturas usando TDD pois a forma de desenvolver arquiteturas (top-down) e de testar (teste integração) é diferente da metodologia (bottom-up) e tipo de testes (teste unitário) propostos por TDD.

PS: O que é pão com durex?

Antes de começar: TDD não garante qualidade de arquitetura, nem qualidade de código, nem qualidade de nada. Ele ajuda, mas tudo isso depende mais das skills do programador do que de qualquer outra coisa.

Quanto a composicao da arquitetura de um sistema, voce pode usar TDD, mesmo desenvolvendo Top-Down, uma boa referência é http://www.manning.com/koskela/, tambem um bom livro sobre o assunto. Outra boa referência é http://www.amazon.co.uk/xUnit-Test-Patterns-Refactoring-Signature/dp/[telefone removido]. Ambos falam sobre desenvolvimento top-down e bottom-up.

Sobre TDD e arquitetura: Primeiro, é difícil definir o que de fato é arquitetura, eu sempre imagino como integracao entre a aplicação e a infra-estrutura, depois se vai ser usado, e mesmo se vale a pena usar testes unitarios em cada passo da infra-estrutura de um sistema. Para testar arquitetura, testes de integração são mais úteis, na minha opinião, do que testes unitários cheios de mocks.

Mas o que me chamou atenção no seu comentário é que por achar que TDD não ajuda na arquitetura, ele automáticamente atrapalha, e a partir daqui eu não entendi mais nada. Os testes ajudam a manter o seu dominio limpo, fácil de entender e manter. E ali estarão os testes, independente da arquitetura pela qual voce optou, do framework, linguagem, servidor, sistema operacional voce vai usar, voce terá regras de negócio em algum lugar. E não é por voce partir de uma arquitetura top-down que as regras basicas de responsabilidade dos seus objetos deixarao de existir, que as operações sobre eles deixarao de existir, que os principios e boas práticas deixarão de existir.

E se voce tem esses objetos, suas operacoes sobre eles, a maneira como eles interagem entre si, em que TDD pode ferir a implementação disso?

Se voce se refere a arquitetura como, a arquitetura dos seu dominio, nesse caso TDD ajuda muito, mesmo top-down. Nada que impede que voce desenhe a interface de cima pra baixo, mesmo nao havendo implementação, ou com implementacao fake, para que passe nos testes e a cada passo va detalhando e implementando as partes menores, sempre usando testes.

Voce pode inclusive, eu uso bastante, integrar varias funcionalidades, com teste unitarios. Desde que consiga isolar e remover da sua regra qualquer coisa que precise de acesso externo, como banco de dados, arquivos, web services e etc…

Então, TDD atrapalha na arquitetura? Antes, o que é arquitetura? Mas seja lá qual for a sua resposta, acho pouco provável que atrapalhe.

G

x@andy:

TDD é parte do desenvolvimento de software e não é tudo! É fundamental entender o dominio, ou seja, entender o negócio que você está implementando. (…) Você deve fazer de tudo para entender o dominio, não da para sair simplesmente programando. (…) Muito provavelmente eu criaria um rascunho com as classes que esse domínio tem. Mas seria apenas um rascunho algo que me ajuda-se a entender o problema. Um rascunho não é nd mais que um rascunho, se for feito em papel eu posso amassa-lo e joga-lo fora a qualquer momento e começar do zero (…) O problema é perder tempo precioso modelando classes, definindo métodos e depois ir para o código (…) Um modelo documental você tem que seguir fielmente um rascunho não, é uma ideia e se não deu certo joga fora ou altera!
x@ndy:
Você escreve os testes, ai pega o primeiro teste da lista e implementa!

Beleza, considero que essa explicação resolve a tal “contradição”. Inclusive já peguei uma falha minha aqui, essa parte de listar os testes antes eu tinha esquecido completamente! Não vinha fazendo isso, e nem lembrava que é um procedimento que faz parte do TDD. Curiosamente, é algo que só confirma a necessidade de um pequeno planejamento…

Yvga:

É muito dificil julgar baseado em alguns parágrafos sem ver nada de código, mas o teu comentário me passa a impressão de que você está com problemas de atribuição de responsabilidade nos seus objetos. Se você pega a funcionalidade completa e tenta testar e tem dificuldade em separar isso, talvez elas estejam emaranhadas umas nas outras. (…) Ainda que ela, por força da regra de negócio, seja extremamente complexa, ela irá executar uma série de tarefas bem definidas. Se cada passo é bem definido, você tem em cada um desses passos, algo simples (…)

Valeu, vou pensar melhor em tudo isso na próxima vez que tentar implementar uma funcionalidade usando TDD. Se tiver dificuldade eu volto em um novo tópico mostrando um caso concreto para vocês darem uma ajuda.

R

YvGa: Boa resposta… Está mais centrada em responder o meu questionamento.

Hebert Coelho: Acho que houve uma confusão. Eu não disse que era obrigatório testar a arquitetura. Eu disse que TDD não testa a arquitetura. E que de acordo com o sistema de desenvolvimento TDD, não se teria o desenvolvimento da arquitetura adequadamente. Pelas diferenças de filosofia que expliquei anteriormente. Mas, o YvGa disse que mesmo com TDD é possível implementar a arquitetura de forma satisfatória.

S

rmendes08:
Bom dia, há algum tempo eu tenho lido e praticado (um pouco) de TDD, muito embora até hoje não tenha conseguido trazê-lo totalmente para a minha realidade profissional. Nessa minha pouca experiência, percebo que: mesmo que os testes ajudam na especifação do sistema, rascunhar um UML ou outro vem muito a calhar, especialmente na hora de entender o domínio do sistema ser construído sair aquele 1o teste.

Sendo assim, o que vocês acham ?

obs: haters de TDD e testes unitários são bem vindos! :twisted:

Primeiro que tudo não confundir TDD com Test First. Test First é um prática de orientação a testes, vinda do XP que significa que primeiro vc escreve o código que testa e depois vc escreve a funcionalidade sendo testada.
TDD é um modelo de design assistido por testes. A ideia é usar o Test Fisrt e depois iterar várias vezes, com refactoring até vc ter um bom design. Isto só é possivel se vc sabe os casos de uso com antecedência. O TDD não é explorativo.

TDD não substitui o cérebro. O verdadeiro design acontece no cérebro. O TDD é mais uma forma de experimentar se suas ideias são válidas, antes de programar as funcionalidades. Programando o cliente do código primeiro (que é o teste) vc identificada pontos que escaparam de sua analise mental. E como o processo é iterativo à um retroalimentação em que o seu design verdadeiro ( o que está na sua cabeça) vai sendo enrriquecido pela experiencia adquirida durante as sessões de TDD.

O Test First é um necessidade, diria, mas o TDD é apenas uma ferramenta - muito menos relevante que o Test First. Portanto, não confundir. E não se iludir que o TDD o levará ao software melhor simplesmente dando à manivela. Não funciona assim, A repetição não leva à perfeição. É necessário conhecimento de design real e embutir esse conhecimento (patterns por exemplo, ioc, separação de responsabilidade, etc…) para realizar o design de fato.

R

rogelgarcia:
YvGa: Boa resposta… Está mais centrada em responder o meu questionamento.

Hebert Coelho: Acho que houve uma confusão. Eu não disse que era obrigatório testar a arquitetura. Eu disse que TDD não testa a arquitetura. E que de acordo com o sistema de desenvolvimento TDD, não se teria o desenvolvimento da arquitetura adequadamente. Pelas diferenças de filosofia que expliquei anteriormente. Mas, o YvGa disse que mesmo com TDD é possível implementar a arquitetura de forma satisfatória.

Na verdade, alguns autores defendem que a construção de um sistema deve começar com um teste end-to-end (teste de ponta-a-ponta) que teria como objetivo justamente testar a arquitetura. Um teste end-to-end é um teste automatizado feito em um ambiente semelhante ao ambiente de produção (por exemplo, um .war deployado em servidor de aplicação real, apontado para um banco de dados real) e que deve exercitar desde a interface até banco de dados (ou outra fonte de dados que seja).

Acho que alguns pontos comuns do que discutimos até agora:

1 - TDD não trata exclusivamente de testes unitários: quando necessário podemos escrever testes de integração ou outros tipos de teste.

2 - TDD não exclui outras ferramentas para o entendimento do domínio: rascunhos de diagramas (UML, DER’s, etc.) , entrevistas com clientes, estórias e casos de usos ainda são válidos

3 - Planejamento ainda é necessário: não aquele planejamento detalhado e que deve ser seguido à risca, mas dado uma estória ou caso de uso, é preciso pelo menos planejar quais testes devem ser escritos para implementar a funcionalidade.

Bom, o ponto que realmente me intriga é a questão desenvolvimento top-down x bottom-up. Na minha pouca experiência, o desenvolvimento top-down se mostrou muito melhor do que o desenvolvimento bottom-up, por um simples motivo: com um desenvolvimento top-down você é muito mais objetivo. Você concentra seu esforço unicamente em desenvolver a funcionalidade necessária, seja ela uma aplicação com interface, um serviço ou API. Mesmo que você divida a implementação em funções e classes, cada função ou classe terá somente o código necessário para aquela funcionalidade. Já tentei, na faculadde, fazer um sistema no estilo bottom-up. O resultado foi que eu perdi um tempo enorme implementando funções e sobrecargas que nunca seriam usadas.

Mas qual a ligação com o TDD ?

Bom, se seguirmos a linha de desenvolvimento top-down com o TDD, começaríamos então com o teste de interface (ou teste end-to-end) , e seguiríamos com teste de granularidae mais fina até a etapa para implementar as classes de domínio do sistema, onde prevalecem os testes unitários; Por outro lado, testes de interface ou testes de integração muitas vezes são difíceis de escrever e manter. Sendo assim, é mais interessante concentrar o esforço de testes nos teste unitários e nas classes de domínio, que de certa maneira, porém, receio que isso encorajar um estilo bottom-up de desenvolver.

Fui claro ?

R

S

Realmente o TDD usa um estilo diferente do bottom-up ou do top-down. Ele usa um esquema mais inside-out. Começa pelo Dominio ( e o domínio é muito grande, entidades, validações, especificações, serviços, repositórios, ou seja, o core). Depois do dominio ( que é onde o TDD realmente pode brilhar porque um junit da vida resolve, vamos para as integrações. A integrações dos repositoros ao banco de dados (seja SQL ou NoSQL ou uma mistura dos dois). Aqui começam as dores de cabeça nos testes. Porque banco = estado e estado é uma porcaria para testes. AS realações entre as entidades começam a pesar, etc…

Do outro lado temos a apresentação. É gráfica ? ou é um serviço ? ou ambos ? Talvez precisamos de uns façadades. Depois o cliente. Se for ui temos que testar os gestos do usuário … chato. Se for serviço temos que simular a chamada vinda de fora. Mais simples. Nos dois casos é preciso ter muita noção dos casos de uso porque só assim é possivel criar fluxos de teste que realment testam alguma coisa. Aqui também pode haver uma dependência com o estado, e isto tb é problemático.

Porem TDD não é cobertura de testes. O Objetivo do TDD não é cobrir todos os testes necessários. Isso é Test First. O objetivo do TDD é auxiliar o desenvolvimento e o design. Mesmo após o design ter sido definido mais testes são adicionados, mas isso já não é TDD. Não é porque se criam testes que fazemos TDD. isso é só o T. Faltou os DD.

R

Posso estar viajando, mas pra mim o que você diz ser Test First é o que eu vejo como o TDD.

Já que o ‘D’ ali no meio corresponde a Driven, que significa conduzido ou orientado a.

O próprio Kent Beck define o ciclo do TDD assim:

“Kent Beck”:
Test-driven development (TDD) is an alternative programming workflow where features are divided into a series of automated tests. The tests are chosen so that satisfying the spirit of all the tests implies that the feature as a whole works correctly. The cycle goes like this:

Write the next test (while several tests may be outlined, only one is written at a time)
In pessimistic languages, add enough stubs so the test compiles. It should fail when run.
Refactor, if necessary, to prepare for the implementation.
Change the logic of the system so the test passes.
Refactor to eliminate duplication and other excess complexity
Repeat until no more of the tests implied by the feature would fail. Then the feature is complete.

Não é isso que você disse que é Test First? Ou estou enganado.

Eu sou bem novo nesse conceito, portanto desculpem se falei alguma bobagem, é que como o Kent Beck foi o criador dos 2 (XP e TDD), eu imagino que ele possa ter pensado na mesma coisa, não sei.

S

Rodrigo Sasaki:
Posso estar viajando, mas pra mim o que você diz ser Test First é o que eu vejo como o TDD.

Já que o ‘D’ ali no meio corresponde a Driven, que significa conduzido ou orientado a.

O próprio Kent Beck define o ciclo do TDD assim:

“Kent Beck”:
Test-driven development (TDD) is an alternative programming workflow where features are divided into a series of automated tests. The tests are chosen so that satisfying the spirit of all the tests implies that the feature as a whole works correctly. The cycle goes like this:

Write the next test (while several tests may be outlined, only one is written at a time)
In pessimistic languages, add enough stubs so the test compiles. It should fail when run.
Refactor, if necessary, to prepare for the implementation.
Change the logic of the system so the test passes.
Refactor to eliminate duplication and other excess complexity
Repeat until no more of the tests implied by the feature would fail. Then the feature is complete.

Não é isso que você disse que é Test First? Ou estou enganado.

Isso é o ciclo de testes. é O T. Cadê o Development ?
Está na frase "Change the logic of the system so the test passes."
Isto é muito vago. Isto não é Desenvolvimento.

O Beck tem este problema de super-iteração. Se vc seguir à risca o que ele escreveu, vc começa com um main vazio depois coloca int = 1. Não funciona. depoiis int = 5 etc… até vc entender que precisa de System.out.println() e assim vai.
Ele mesmo já falou (eu vi num video não tenho a referencia) que não é isto que ele quiz dizer. Existe um design prévio que acontece na sua cabeça. Vc já sabe que tem que chamar println , já sabe que tem que usar um for. então vc coloca isso no código.
Ai vc usa o ciclo. Quando vc chegan o verde vc pára ? Sim. Vc pssa para o proximo teste. Ai o próximo teste exige que afora o for fique numa classe. E ai vc refatora o primeiro teste tb. E assim via. Quando chegar no ultimo teste, em tese, todos os testes estão refatoradsos para a mesma logica e modelo e funcionam. Vc atingiu um design supremo ? Não. Vc atingiu o design que é mínimo para aqueles testes. Para melhorar o design vc precisa de mais requisitos e portanto mais testes.

Com Teste First, apenas, vc tem o modelo desenhado na sua cabeça. Vc vai lá e implementa. Só que começando pelos testes. Mas por exemplo, vc já sabe que tem a classe X e Y, e como elas se relacionam etc… O teste pode identificar algunss detalhes que precisam ser melhorados (normalmente isolamento e inversão de dependência), mas o teste não é usado para desenvolver. Ele é , ora bem , um teste. Ele testa que a sua ideia funciona. Ele não provoca a ideia, ele provoca modificações.

TDD inclui Teste First, mas Test First não inclui TDD.

TDD é como CAD ( computer assisted design) e poderia-se chamar Test Assisted Development

Pensando de outa forma, no modelo padrão vc quer colocar um pattern X vc vai e coloca. Em TDD vc não faz isso. Vc escreve um código qualquer e depois quando for refactorar é que vc identifica o padrão e o usa. O TDD é reactivo e não pro-activo. E isso pode ser bom quando vc quer ser minimalista como o Beck gosta de ser, mas implica em muitos passos desncessários. Ai ele fala que a pessoa pode pular para o passo que deseja ( no caso, pode colocar o padrão logo de inicio). Mas isso para mim não é desenvolvimento assistido, é simplesmente ter uma ideia e colocar um teste à volta dela (Test First).

R

Estou aqui lendo o livro do Kent sobre TDD para poder opinar melhor… olha que frase legal que encontrei…

“This is the opposite of architecture-driven development”

:slight_smile:

X

rogelgarcia:
x@ndy:

Putz…nada haver! Esse tipo de afirmação embora lógica é uma falácia e demostra um total desconhecimento de TDD!

Se tem lógica… tem a ver!! Não é não? rs

Não! Por isso é uma falácia! Um exemplo. A algum tempo foi feito uma pesquisa na Universidade Federal de Pelotas na qual foram utilizados ratos que foram alimentados com grãos de feijões crus o que levou ao óbito desses. A pesquisa descobriu que existe uma proteina que matava esses animais, porém durante o cozimento ela se transformava em outra coisa que não afetava os seres humanos! Bom, a partir disso surgiu uma estória, muito difundida na internet, que feijão cru poderia ser usado como raticida, pois se na pesquisa os ratos morreram ao comerem feijões porque se eu espalhar pela casa eles não vão comer e morrer?!!

O argumento de que o feijão seja um raticida (embora tenha por trás algo lógica, uma pesquisa) é uma falácia! “E por que?” Porque os ratos não comem feijão! Os anos de evolução levaram esses animais a evitar esse tipo de alimento, pois eles instintivamente sabem que vão morrer! Mas por quê na pesquisa eles comeram? Porque foi feita sob um ambiente controlado. Provavelmente eles só forneceram feijões como alimento e entre morrer de fome e comer o feijão o rato comeu o feijão!

O seu argumento é muito similar. A partir dos comentários feitos vc desenvolveu uma teoria, que embora tenha um “contexto” lógico é uma falácia! Aqui é importante notar a palavra contexto e não embasamento! Sua teoria foi baseada em um contexto lógico assim como na estória do rato, mas não tem um embasamento lógico (não foi feita nenhuma pesquisa em cima, por exemplo) para determinar que ela está certa!

Eu não defini o que é arquitetura. O ponto não é esse. De qualquer forma, não disse nada contrariando essa frase.
Ai que tá! Sem definir arquitetura e sem dizer em aspecto que TDD afeta a arquitetura, isso perde o valor pois se torna algo muito vago! Isso me lembra do Hibernate! Antes mesmo de mexer com ele eu ouvia dizer que era lento, que não dava para usar pq era lento, etc. Só que ninguém conseguia dizer pq era lento! Na verdade eu comecei a mexer e nunca foi lento! A unica coisa que me faz pensar que poderia deixar ele lento era “carregar o banco inteiro” através de referências de classes. Mas ai tem Lazy… Bom a discussão não essa! Mas os dois tem algo parecido, pois expõem uma opinião sem conhecimento real do assunto

Quote xandy->“nada para TDD é necessário planejar”.
Eu escrevi isso errado, deve se ignorar a palavra nada, mas no contexto geral eu disse que é necessário planejar e isso era feito se escrevendo quais testes devem ser ser implementados. Na verdade a última frase eu digo exatamente isso. . vou corrigir lá…

Veja minha frase: “TDD é baseado em testes de pequenos pedaços”. Eu não disse que é apenas testar pequenos pedaços, ou apenas uma parte do sistema. Um sistema totalmente testado pode ser baseado em testes de pequenos pedaços. Logo, minha afirmação está correta.
Realmente, por algo ser algo vago, entendi que você queria dizer que o problema era pq só se testava parte do sistema!

Como um teste unitário informa sobre problemas na arquitetura, se esse não é o propósito dele?

Por que você não está simplesmente testando algo que você ou outra pessoa implementou. Durante os testes você também está modelando. Os testes são seguidos de refatorações e ao refatorar você muda o sistema e o vai melhorando. Se você simplesmente testar código pronto pode se deparar com algo dificil de ser testado pois vai necessitar de um monte de classes para criar um testes, algo extremamente acoplado e sem qualquer coesão! Isso faz com que um simples teste necessite de um numero de enorme de de passos! Com TDD ao encontrar um acoplamento durante um teste você refatora de modo a corrigir o problema. Os testes também de tão feedback. Durante o a implementação você pode ter uma idéia que melhora o código, então refatora para isso e testa e continua o ciclo!

Bom o seu argumento também era muito pequeno e bem vago!

rogelgarcia:
E “Putz…nada haver!” não é argumento. rs
Realmente é uma interjeição! Quis desmonstrar incredulidade…rsrsrsr :smiley:

De modo algum! O problema é que você destacou um problema que não existe de forma extremamente vaga. Quando realmente se conhece a finalidade de TDD você vê que isso que você está dizendo não faz o menor sentido!

Y

sergiotaborda:

Pensando de outa forma, no modelo padrão vc quer colocar um pattern X vc vai e coloca. Em TDD vc não faz isso. Vc escreve um código qualquer e depois quando for refactorar é que vc identifica o padrão e o usa. O TDD é reactivo e não pro-activo. E isso pode ser bom quando vc quer ser minimalista como o Beck gosta de ser, mas implica em muitos passos desncessários. Ai ele fala que a pessoa pode pular para o passo que deseja ( no caso, pode colocar o padrão logo de inicio). Mas isso para mim não é desenvolvimento assistido, é simplesmente ter uma ideia e colocar um teste à volta dela (Test First).

Certo, Sergio, entendo seu ponto de vista, mas deixa eu fazer uma defesa ao Beck, ou uma acusação, já que o livro dele não deixa isso claro. Mas foi a maneira que eu sempre entendi, lendo principalmente ele e os outros dois autores que eu citei no meu post anterior.

Não existe um jeito certo de começar a implementação, você pode começar por onde quiser, outside-in ou inside-out (o que pra mim parece o mesmo que top-down ou bottom up), você pode desenhar primeiro a interface de uma calculadora, pode implementar as teclas com infra-estrutura fake e ir aos poucos descendo para as operacoes matematicas. Ou então você pode fazer inside-out, começar pelas operações e vir para as teclas e a interface depois.

Mas o que você não pode, nem vai conseguir, de jeito nenhum, e é o que parece muita gente ter entendido da proposta do TDD é planejar inside-out. Não se pode planejar inside-out, não é possível imaginar uma calculadora começando simplesmente pelas operações matemáticas, sem pensar em como um ser humano irá interagir com ela (não se iludam pela aparencia de que no caso de uma calculadora seria possivel). Eu não posso somar dois numeros, se eu ainda nem sei se serão inteiros, pontos flutuantes, binários ou seja lá que formato for quando chegar a hora de fazer a soma. Você precisa, necessáriamente, pelo menos de uma boa noção do todo para começar a implementar, seja de um jeito ou de outro.

O planejamento não é top-down, ou bottom-up, ele precisa de integridade, precisa das teclas tanto quanto das operações, preciso ser único e bem definido, ainda que só um esboço, um esboço claro. E isto nada tem a ver com TDD, TDD trata de código, quando se diz que TDD ajuda na melhora do design é no design do código e não da solução em si. Você pode ter um código excelente para uma porcaria de solução, você pode errar o planejamento completamente e ainda ter centenas de testes comprovando a besteira que você fez.

Para implementar você tem que necessariamente planejar, e nunca ninguem, seja ágil, lean, tradicional, cascata ou scrumzeiro, disse que não é necessario planejamento antes de implementar. O que se discute é o tempo gasto nesse planejamento e a reverência que se faz a ele nos métodos tradicionais. Mas você vai sim, planejar antes de implementar, ainda que seja com um esboço do modelo na sua cabeça, ou um rabisco no papel ou no quadro, mas vai ter algum planejamento.

Ninguem comeca com um void main, é preciso ter uma boa ideia do que vai ser feito e já alguma noção do como. Tendo uma ideia do que vai ser feito e uma noção do como, tanto faz começar de dentro ou de fora, tanto faz começar pelas camadas mais altas e descer, como pelas mais baixas e subir.

E seja qual for o caminho que voce escolher a partir dali, TDD não vai te atrapalhar, muito pelo contrário, porque uma vez tendo “rascunhada” a solução, você passa para a implementação que é onde ele brilha.

R

x@andy, meu questionamento sobre TDD facilitar uma arquitetura ruim faz tanto sentido, que no próprio livro do criador do TDD ele diz que TDD é oposto a desenvolver direcionado a arquiteturas.

Seguindo TDD (e eu li isso no livro), decisões de design são tomadas tardiamente no desenvolvimento. Tomar decisões importantes de design tardiamente, acho que não preciso convencer que é problemático. Um fato que contribui para essa afirmação, é que TDD é fortemente baseado em refatorações. Isto é, você fatalmente implementará algo ruim e DEPOIS ajusta. Por isso eu falei, TDD é um facilitador para arquiteturas ruins. Pode ser, que depois de ter implementado um monstro de funcionalidades chegue a conclusão que o design do sistema não comporta a nova funcionalidade. E aí você fará uma refatoração para atender esse novo requisito.

Y

rogelgarcia:
x@andy, meu questionamento sobre TDD facilitar uma arquitetura ruim faz tanto sentido, que no próprio livro do criador do TDD ele diz que TDD é oposto a desenvolver direcionado a arquiteturas.

Com isto vc quer dizer que no livro o próprio autor diz que TDD facilita arquitetura ruim?

Voce questiona, mas como o Xandy observou, voce sequer definiu o que quer dizer com arquitetura. Arquitetura, em software, pode significar muita coisa.

Voce mesmo disse que independe do contexto, mas como sabemos se atrapalha ou não se não sabemos nem de que contexto estamos falando? E a frase no livro do Beck é usada em que contexto? Provavelmente diferente daquele que estamos tentando usar aqui?

Ok, TDD é, segundo Beck, o oposto de Architeture driven devolopment, mas o que é isso?

Vamos estabelecer conceitos antes de continuarmos, porque senão daqui a pouco vão dizer que se os arquitetos usassem TDD, os edifícios seriam terríveis.

R

YvGa:
rogelgarcia:
x@andy, meu questionamento sobre TDD facilitar uma arquitetura ruim faz tanto sentido, que no próprio livro do criador do TDD ele diz que TDD é oposto a desenvolver direcionado a arquiteturas.

Com isto vc quer dizer que no livro o próprio autor diz que TDD facilita arquitetura ruim?

Não. Quem sugeriu a hipótese de que TDD facilita uma arquitetura ruim fui eu. Porém, a fato de TDD ser contrário ao desenvolvimento direcionado a arquiteturas, contribui para minha hipótese.

R

Arquitetura no meu conceito:

  • Organização das classes e suas relações e responsabilidades num sistema.

Está bem definido?

X

sergiotaborda:

TDD não substitui o cérebro. O verdadeiro design acontece no cérebro. O TDD é mais uma forma de experimentar se suas ideias são válidas, antes de programar as funcionalidades. Programando o cliente do código primeiro (que é o teste) vc identificada pontos que escaparam de sua analise mental. E como o processo é iterativo à um retroalimentação em que o seu design verdadeiro ( o que está na sua cabeça) vai sendo enrriquecido pela experiencia adquirida durante as sessões de TDD.

Ótima explicação :D! Só acrescentaria a a refatoração a isso! Ao identificar os pontos que faltaram refatoro o código, como tenho uma base de testes não preciso me preocupar em estragar algo!!

Y

rogelgarcia:
Arquitetura no meu conceito:

  • Organização das classes e suas relações e responsabilidades num sistema.

Está bem definido?

Ok, perfeito. Então você não poderia estar mais errado. Leia meu ultimo post para o Sergio que entederá mais ou menos o que eu penso sobre isso.

Eu disse que você não poderia estar mais errado por causa desse post aqui.

Primeiro ponto: a parte que você critica, inclusive enfáticamente com o “não preciso convencer que é problemático”, é um conceito muito além do TDD, que não nasceu ali, nem vai morrer ali. Adiar as decisões até o limite é uma prática do desenvolvimento Lean, usada muito antes de ser adotada em ambiente de software e de eficácia mais do que comprovada. Honda e Toyota que o digam. Já ouviu falar em Just In Time? É o mesmo conceito.

Segundo ponto: Não é TDD que é baseado em refatorações, software é baseado em refatorações e se um software é vivo, você vai ter que refatorá-lo, queira ou não, tenha testes ou não.

Isto vai acontecer de qualquer forma, com TDD ou não, certo ou errado, vai chegar o dia em que o cliente vai pedir algo para o qual o sistema não estava preparado, isto é inevitável. E ai voce vai ter que refatorar e não haverá testes pra te apoiar.

Terceito ponto (e onde está o seu maior equívoco - muito comum aliás):

Muita gente confunde “a mais simples solução para o problema” com “a primeira coisa que vier na cabeça”. Você não implementará algo ruim pra refatorar depois, você implementará algo que atenda a funcionalidade no momento, para depois refatorar (se precisar) para acomodar uma funcionalidade futura. Isso é tomar decisões importantes tardiamente, tomar a decisão somente quando for a hora e não antes, porque é só naquela hora, e não antes, que você vai saber exatamente o que tem que fazer. Do contrário pode acabar com algo que ainda não é usado, logo você não sabe exatamente como será usado, mas que você terá que levar em conta quando for mexer no que é usado. Mesmo que aquilo só venha a servir no futuro, de um jeito que você só saberá no futuro o código já está ali te atrapalhando. Esse conceito vai muito além do TDD.

Sendo esta a definição, TDD é excelente para definir uma boa arquitetura, porque força o desacoplamento, conduz a algo mais coeso, funcionalidades mais independentes e reaproveitáveis e, além de tudo, funcionando da forma como você espera que funcione.

R

Linhas de montagens de carros são completamente diferentes de software. Você buscou um argumento de outro cenário para aplicar em software tentando rebater minha argumentação. Numa linha de montagem de carros, todos os carros são iguais. Decisões foram tomadas no projeto do carro e não na montagem. Just In Time é uma conceito relacionado a produção. Onde você entrega os produtos quando eles forem necessários. Exemplo: na produção do carro a chapa de aço será entrega quase no momento em que o carro iniciar na linha de montagem.

TDD é baseado em refatorações sim. Existe um passo no TDD que é refatorar. O fato de existir refatoração fora do TDD não anula essa etapa obrigatória do TDD. (Red/green/refactor?the TDD mantra. (está no livro isso))

A diferença é que usando TDD você vai adiar essa decisão. Usando outras metodologias, você pode antecipar essa decisão. E com isso, evitando um refactor mais trabalhoso.

Muita gente confunde “a mais simples solução para o problema” com “a primeira coisa que vier na cabeça”. Você não implementará algo ruim pra refatorar depois, você implementará algo que atenda a funcionalidade no momento, para depois refatorar (se precisar) para acomodar uma funcionalidade futura. Isso é tomar decisões importantes tardiamente, tomar a decisão somente quando for a hora e não antes, porque é só naquela hora, e não antes, que você vai saber exatamente o que tem que fazer. Do contrário pode acabar com algo que ainda não é usado, logo você não sabe exatamente como será usado, mas que você terá que levar em conta quando for mexer no que é usado. Mesmo que aquilo só venha a servir no futuro, de um jeito que você só saberá no futuro o código já está ali te atrapalhando. Esse conceito vai muito além do TDD.

Eu não confundi. “Clean code that works is the goal of Test-Driven Development (TDD)”. Você só precisa implementar um código que funciona no TDD, não precisa criar uma boa arquitetura. Se você postergar as decisões, possivelmente terminará com uma arquitetura ruim. Se você teve que refatorar é porque a primeira implementação é ruim. Caso contrário, não precisaria refatorar.

R

“Architecture” is a term that lots of people try to define, with little agreement. There are two common
elements: One is the highest-level breakdown of a system into its parts; the other, decisions that are hard to
change. [FOWLER, Patterns of Enterprise Application Architecture]

Ralph Johnson: A shared understanding of a system’s design by the expert developers on a
project. Commonly this shared understanding is in the form of the major components of the system and how
they interact. It’s also about decisions, in that it’s the decisions that developers wish they could get right early
on because they’re perceived as hard to change. In the end
architecture boils down to the important stuff�whatever that is. [FOWLER, Patterns of Enterprise Application Architecture]

Decisões na arquitetura são difíceis de ser alteradas. Quanto mais cedo decisões arquiteturais forem tomadas melhor.

Não sou eu que estou dizendo: É Fowler e Johnson.

R

Todas as citações são do livro de Beck

“Clean code that works is the goal of Test-Driven Development (TDD).”

Nessa frase já podemos perceber que não necessariamente um dos objetivos de TDD está na construção da arquitetura. Uma vez que se o código simplesmente funcionar já atinge os objetivos do TDD. Ou seja, não importa as decisões difíceis de serem tomadas ou os grandes blocos do seu sistema se seu código funcionou.

Ainda considerando essa afirmativa, o colega fez um comentário que condiz com essa proposição.

Quote YvGa
"TDD trata de código, quando se diz que TDD ajuda na melhora do design é no design do código e não da solução em si. Você pode ter um código excelente para uma porcaria de solução, você pode errar o planejamento completamente e ainda ter centenas de testes comprovando a besteira que você fez. "

Outra frase presente no livro:
“We must design organically, with running code providing feedback between decisions”

Aqui percebemos que em TDD as decisões são tomadas a medida que o software é construido. As decisões são tomadas com base em códigos que já foram implementados e estão rodando.

“Test-driven development is a way of managing fear during programming. I don’t mean fear in a bad
way but fear in the legitimate, this-is-a-hard-problem and-
I-can’t-see-the-end-from-the-beginning sense”

Aqui, existe uma motivação para utilizar o TDD, o medo. Medo no sentido de não enxergar a solução completa. TDD te ajuda a gerenciar situações onde você não enxerga o todo. Para mim, se você desenvolve uma arquitetura, você tem que enxergar o todo. Caso contrário, as decisões de design (aquelas difíceis de serem alteradas posteriormente) não serão acertadas.

R

Recapitulando o que eu disse:

Desenvolver com TDD é um facilitador para que seu sistema termine com uma arquitetura questionável.

Em TDD você toma decisões tardiamente.
Em TDD você não precisa entender o todo.
Em TDD as decisões são feitas baseadas em código já implementado.
Tudo isso está no livro do TDD.

TDD não te ajuda na arquitetura. Inclusive propõe um comportamento que de certa forma é oposto ao desenvolvimento orientado a arquiteturas (definido no livro). Então, minha afirmação que TDD é um facilitador para ter uma arquitetura questionável é valido, uma vez que TDD não limita suas ações na arquitetura e incentiva a construção de forma oposta.

X

rogelgarcia:
Arquitetura no meu conceito:

  • Organização das classes e suas relações e responsabilidades num sistema.
    Está bem definido?

Bom blz, então agora eu entendo sua preocupação e tem sentindo.

Porém o ciclo é incremental e você vai ver isso no livro. Você faz algum, ruim para ter o VERDE, mas logo em seguida refatora. Vermelho, Verde, Refatore. O mantra do TDD!

Você não implementa um monte de coisas e só depois refatora, isso não é TDD! Como já falei antes, a medida que você vai implementando se a arquitetura estiver errada (na verdade eu prefiro o termo modelo do dominio, nesse caso) você vai ter problema para implementar os testes, pois esses vão se tornar complexos para coisas simples. O acoplamento aumenta e a coesão diminui.

Mas isso comigo só ocorre quando eu não entendi o que deveria fazer, quando eu não consegui modelar o dominio do cliente da maneira correta! Ai eu tenho que reunir com o cliente e conversar com ele e entender o que estou fazendo de errado, mas ai não é mais TDD e sim DDD, embora eu acredite que um complemente o outro.

Pela minha experiência é mais fácil obter uma arquitetura ruim sem TDD! Com ele consegui obter alta coesão das classes e baixíssimo acoplamento. Isso ocorre por que eu tenho que pensar no micro, no que eu tenho que fazer na hora para implementar algo e porque é dficil testar uma classe acoplada. Pensando no micro eu tenho a coesão, minhas classes só fazem o que necessitam fazer e a dificuldade de implementar uma lógica que dependa de muitas classes evita o acoplamento.

Outra coisa que consegui com ele foi pensar mais orientado a objetos. Um exemplo é o calculo de uma média! Se fosse solicitado a um programador que implementa-se uma média provavelmente ele faria usando uma função, muito provavelmente estática, que passado uma lista de valores retornaria a média. Eu já criaria um objeto valor. A meu ver é mais simples pois tenho que criar um objeto de qualquer forma para conter a função estática e se necessitar alterar e evoluir é mais fácil também.

Acho que vou escrever esse findi um exemplo de TDD explorando a implementação de uma média e posto aqui.

R

O cenário que eu quis descrever é o seguinte.

Você já implementou 100 testes e funcionalidades.

A funcionalidade 101 pode requerer uma refatoração pesada na sua solução.

Essa funcionalidade 101 poderia ser prevista antes? Pode ser que sim, pode ser que não. Mas o caso, é que em TDD não importa, essa funcionalidade 101 não é levada em consideração no inicio do desenvolvimento. Podendo ser prevista ou não.

J

Acho que to ficando velho, to tentando acompanhar mas é complicado a parada mesmo.

R

Há fi… esquenta não… tudo isso que a gente está discutindo aqui é uma balela dos infernos… kkk :slight_smile:

X

rogelgarcia:
Recapitulando o que eu disse:

Desenvolver com TDD é um facilitador para que seu sistema termine com uma arquitetura questionável.

Em TDD você toma decisões tardiamente.
Em TDD você não precisa entender o todo.
Em TDD as decisões são feitas baseadas em código já implementado.
Tudo isso está no livro do TDD.

TDD não te ajuda na arquitetura. Inclusive propõe um comportamento que de certa forma é oposto ao desenvolvimento orientado a arquiteturas (definido no livro). Então, minha afirmação que TDD é um facilitador para ter uma arquitetura questionável é valido, uma vez que TDD não limita suas ações na arquitetura e incentiva a construção de forma oposta.


Com exceção de “Em TDD as decisões são feitas baseadas em código já implementado.” Que não me lembro disso no livro e não entendi o que você quis dizer com isso. Não vejo porque isso conduz a uma arquitetura questionável pois:

Não entendo por que isso é ruim? Afinal é mais fácil, e comum, eu criar implementar um monte de funcionalidades que não serão usadas! Por que devo implementar algo de que não preciso, para que testar algo que não preciso? Aonde isso piora a arquitetura? Por que tomar decisões prematuras melhoram a arquitetura?

É possível entender o todo de um projeto antes de implementa-lo? Acredito que não, pois se fosse possível realmente TDD não seria necessário e todos os projetos seriam um sucesso! Ao não me preocupar com o todo poderei ter erros na arquitetura? Sim, mas eu posso refatorar o código quando descobri que errei e terei uma base de testes para me dar segurança quanto a isso. Se eu pensar no todo não terei problemas de arquitetura? Não, terei os mesmos problemas, só não terei um base de testes para me ajudar no Refatoramento!
Outra coisa, ao planejar tudo e depois de implementar e só ai testar faz com os problemas da arquitetura só sejam descobertos tardiamente. Com TDD os problemas aparecem mais cedo, de modo que é mais fácil corrigi-los! Como eu não implemente um monte coisas desnecessárias também não preciso me preocupar com elas também o que facilita a refatoração.

X

O cenário que eu quis descrever é o seguinte.

Você já implementou 100 testes e funcionalidades.

A funcionalidade 101 pode requerer uma refatoração pesada na sua solução.

Essa funcionalidade 101 poderia ser prevista antes? Pode ser que sim, pode ser que não. Mas o caso, é que em TDD não importa, essa funcionalidade 101 não é levada em consideração no inicio do desenvolvimento. Podendo ser prevista ou não.

A sim, com certeza e digo mais, isso acontece o tempo todo! Porém eu tenho uma base enorme de testes que me dão segurança no refatoramento!
Só que mesma coisa se aplica ao método tradicional de desenvolvimento. Pensar antes não garante que não vai ter que refatorar, e se tiver que refatorar não se tem o suporte dos testes. Já passei muito por isso.

Claro, e já disse isso, que TDD não sinônimo de programação a “moda louco”! Não da para sair simplesmente codificando. É necessário entender o dominio, na verdade para fazer TDD de maneira correta é necessário ter conhecer DDD

X

rogelgarcia:

Linhas de montagens de carros são completamente diferentes de software. Você buscou um argumento de outro cenário para aplicar em software tentando rebater minha argumentação. Numa linha de montagem de carros, todos os carros são iguais. Decisões foram tomadas no projeto do carro e não na montagem. Just In Time é uma conceito relacionado a produção. Onde você entrega os produtos quando eles forem necessários. Exemplo: na produção do carro a chapa de aço será entrega quase no momento em que o carro iniciar na linha de montagem.

Mas você sabe como é feito um projeto de um novo carro, por exemplo? O conceito de TDD e por tabela DDD tem muito similar ao projeto de engenharia. O projeto não é todo pensado e depois ele vai para linha de produção! Não feitos vários protótipos, desde de pequenos veículos em escala, até grandes, representando o esqueleto, que são continuamente evoluídos e muita coisa é alterada e modificada durante o processo para corrigir problemas! O projeto não é pensado no todo, são muitas cosias envolvidas! Sei disso por que fiz engenharia e trabalhei bastante tempo na área e fui por ai que entrei no mercado de software.

Na verdade acredito que o desenvolvimento de software seja uma atividade de engenharia, mas isso é uma outra discussão!

R

Pois então x@andy… se você afirma que para usar TDD você tem que usar DDD também… você já não está usando somente um TDD concorda? Isso porque ele não deve ser adequado a qualquer situação. De acordo com o que coletei uma dessas situações é a etapa de decisões arquiteturais. Será que essa etapa de decisões arquiteturais você está usando DDD???

Coloquei a citação no post anterior: We must design organically, with running code providing feedback between decisions
Não fui eu quem disse. Está no livro.

rogelgarcia wrote:
Em TDD você toma decisões tardiamente.

Não entendo por que isso é ruim?


Está no outro post sobre arquitetura onde citei Fowler. Decisões de arquitetura são difíceis de serem alteradas. Quanto mais tempo demorar para tomar a decisão mais problemas terá. (Fowler disse)

Tomar decisões de design previamente não quer dizer implementar coisas que nunca serão utilizadas. Tomar decisões antes é analisar o conjunto todo e pensar em uma solução que atenda a situação. Veja, pensar em solução e não em funcionalidades picadas.

Essa é a filosofia do TDD… há não me preocupo com o todo… se der problema futuramente … eu refatoro. (você disse isso aqui)

Discordo, se você pensar numa solução previamente, você não terá os mesmos problemas. Pode ter problemas, mas não serão os mesmos. Você, prevendo situações e agindo proativamente pode evitar refatorações que teriam que ser feitas caso agisse reativamente.
Eu não preciso usar TDD para ter testes na minha aplicação.

Eu não disse que deve-se implementar tudo e só depois testar. Pode-se testar soluções intermediárias, mesmo não seguindo o TDD.

R

.

X

rogelgarcia:
Pois então x@andy… se você afirma que para usar TDD você tem que usar DDD também… você já não está usando somente um TDD concorda? Isso porque ele não deve ser adequado a qualquer situação. De acordo com o que coletei uma dessas situações é a etapa de decisões arquiteturais. Será que essa etapa de decisões arquiteturais você está usando DDD???
Primeiro eu não tomo decisões arquiteturais, não como definido por você! Utilizo DDD para ter um modelo coerente com o dominio do cliente e uso TDD para implementar esse modelo.

Coloquei a citação no post anterior: We must design organically, with running code providing feedback between decisions
Não fui eu quem disse. Está no livro. Como disse não sei o que ele quis dizer com isso. Está fora de contexto! Por favor poste o que ele quis dizer com isso, ou melhor, poste o capitulo e a página para que eu possa ler

rogelgarcia:
rogelgarcia wrote:
Em TDD você toma decisões tardiamente.

Não entendo por que isso é ruim?


Está no outro post sobre arquitetura onde citei Fowler. Decisões de arquitetura são difíceis de serem alteradas. Quanto mais tempo demorar para tomar a decisão mais problemas terá. (Fowler disse)

Isso está fora de contexto. Pegando o que o fowler disse
Arquitetura é um termo que muitas pessoas, com pouca concordância entre si, tentam definir. Existem dois elementos comuns: um é a decomposição em alto nível de um sistema em suas partes; o outro são decisões difíceis de alterar."

e continuando

Ou seja, ele não disse que que seu tomar decisões depois vou ter problemas, na verdade ele diz justamente o contrário!

Tomar decisões de design previamente não quer dizer implementar coisas que nunca serão utilizadas. Tomar decisões antes é analisar o conjunto todo e pensar em uma solução que atenda a situação. Veja, pensar em solução e não em funcionalidades picadas. Ok, mas quem disse que a solução que pensei esta correta? E TDD não é funcionalidade picada!

Essa é a filosofia do TDD… há não me preocupo com o todo… se der problema futuramente … eu refatoro. (você disse isso aqui)

Discordo, se você pensar numa solução previamente, você não terá os mesmos problemas. Pode ter problemas, mas não serão os mesmos. Você, prevendo situações e agindo proativamente pode evitar refatorações que teriam que ser feitas caso agisse reativamente.
Eu não preciso usar TDD para ter testes na minha aplicação.
Podem não ser os mesmos, mas os problemas continuarão existindo. Você mesmo disse! Porém com TDD e a refatoração continua pequenos erros de arquitetura são encontrados facilmente o que não acontece no seu modelo, pequenos problemas de design passam desapercebidos. Esses problemas dificultam a evolução e a manutebilidade do sistema!

Eu não disse que deve-se implementar tudo e só depois testar. Pode-se testar soluções intermediárias, mesmo não seguindo o TDD.
[/quote] Só que ai você só está implementando testes para verificar problemas, você não esta modelando através dos testes! Se você só se preocupa em verificar os erros não vai corrigir os problemas de arquitetura. Se usar refatoração para isso então qual o problema com TDD?

Outra coisa, TDD não perfeito não é bala de prata! Com certeza tem problemas, mas as vantagens são maiores que as desvantagens! Com TDD posso não ver o todo e talvez cometer alguns erros com isso, mas ele me permite evoluir o modelo continuamente de modo que eu tenha um codigo mais limpo coerente e fácil de manter o que não é possivel com a sua abordagem.

Y

Lean nao e usado so em linha de montagem, é usado hoje em todas as areas, inclusive no desenvolvimento de produtos, onde usa conceitos parecidos.

Eu nao disse que TDD nao usa em refactoring, eu disse que o refactoring estará la, use você TDD ou nao. Voce acusa TDD de ser ruim por usar muito refactoring, mas desenvolvimento de software PRECISA de muito refactoring.

Adiar a decisao não é TDD, é muito mais amplo, argumentar contra isso é argumentar contra o Agil, não contra TDD. Essa antecipação da decisão é tambem tradicionalmente conhecido como Big Design Up Front, e é mais do que comprovada a sua ineficácia. TDD não inventou isso e usando TDD ou não, ter uma solução sem experimentá-la para saber se funciona é um grande passo para o desastre. E quanto mais detalhada for, pior, pois mais tempo tera sido gasto em algo não experimentado.


Eu não confundi. “Clean code that works is the goal of Test-Driven Development (TDD)”. Você só precisa implementar um código que funciona no TDD, não precisa criar uma boa arquitetura. Se você postergar as decisões, possivelmente terminará com uma arquitetura ruim. Se você teve que refatorar é porque a primeira implementação é ruim. Caso contrário, não precisaria refatorar.

Sim, voce confundiu, ele disse CLEAN code that works. Então voce não precisa só implementar um código que funciona, voce precisa implementar um código LIMPO que funciona, e isso não eh "fazer algo ruim e depois refatorar. Sim, confundiu.

Nenhuma dessas duas definicoes significa o mesmo que voce havia definido anteriormente. Nós, como arquitetura, acordamos la atras que tratávamos do modelo de classes de domínio e estas definicoes nem passam perto disso. Aí você vem e usa essas definicoes pra defender sua tese de que TDD prejudica arquitetura, mas sem definir arquitetura.

Eu vejo arquitetura como a relacao da aplicacao com suas fronteiras. Em qual linguagem sera implementada? Isso eh decisao de arquitetura e dificil ser mudada, qual framework sera usado, qual tipo de persistencia, relacional, documentos. Estas são decisoes de arquitetura, essas são dificeis de mudar e essas são as que se referem que deve ser tomada com antecedencia.

O seu modelo de classes e a forma como interagem TEM QUE SER FACIL de alterar, a natureza dinamica do software exige isso, queira voce ou não. Então vamos mudar o termo de arquitetura para modelo de objetos, para sabermos do que estamos falando e voce parar de trazer definicoes de arquitetura para definir o que não está sendo discutido como arquitetura. Se não daqui a pouco voce vai trazer alguma frase do Niemeyer aqui e dizer que TDD a fere.

Y

rogelgarcia:
Pois então x@andy… se você afirma que para usar TDD você tem que usar DDD também… você já não está usando somente um TDD concorda? Isso porque ele não deve ser adequado a qualquer situação. De acordo com o que coletei uma dessas situações é a etapa de decisões arquiteturais. Será que essa etapa de decisões arquiteturais você está usando DDD???

Mas quem foi que disse que voce não pode usar mais nada se usar TDD? E, por favor, pare de usar o termo arquitetura porque voce o esta visivelmente usando fora de contexto, e misturando as definicoes.

Não, não está no livro. Voce não está entendendo nada do que está lendo. " We must design organically, with running code providing feedback between decisions" não significa “Em TDD as decisões são feitas baseadas em código já implementado”, significa que código sendo executado provém feedback para decisoes tomadas, o que é bem diferente de tomar decisoes em cima de código implementado.

Mas ninguem disse que voce não pode pensar no que fazer, voce pode e deve. O que voce não deve é hoje implementar uma funcionalidade que voce não precisa hoje. É só isso.

Não, ele não disse isso, ele disse que não é possivel prever o todo e tentar é perda de tempo. Voce parte de uma ideia do todo e experimenta. E mais uma vez, este não eh um coneito de TDD, é um conceito Lean. Voce está rosnando para a ferramenta errada.

Olha o BDUF ai de novo, quanto mais detalhes no meu planejamento, menos problemas terei no futuro. Doce ilusao.

Pode, mesmo sem seguir TDD, mas nao pode usar a desculpa de que ele atrapalha na construcao do modelo de objetos.

G

rogelgarcia:
“Architecture” is a term that lots of people try to define, with little agreement. There are two common
elements: One is the highest-level breakdown of a system into its parts; the other, decisions that are hard to
change. [FOWLER, Patterns of Enterprise Application Architecture]

Ralph Johnson: A shared understanding of a system’s design by the expert developers on a
project. Commonly this shared understanding is in the form of the major components of the system and how
they interact. It’s also about decisions, in that it’s the decisions that developers wish they could get right early
on because they’re perceived as hard to change. In the end
architecture boils down to the important stuff�whatever that is. [FOWLER, Patterns of Enterprise Application Architecture]

Decisões na arquitetura são difíceis de ser alteradas. Quanto mais cedo decisões arquiteturais forem tomadas melhor.

Não sou eu que estou dizendo: É Fowler e Johnson.


Aqui você está se referindo a arquitetura no sentido que usamos mais tradicionalmente, quer dizer, as decisões técnicas de mais alto nível, aquelas que não podem ser alteradas (linguagem, frameworks, banco de dados, servidor de aplicação, infraestrutura, etc). Então como o TDD se relaciona com isso?

É muito mais simples do que parece, você está colocando no TDD uma culpa que ele não tem, que é tentar interferir na arquitetura.

Programar em TDD não quer dizer que essas decisões não possam ter sido tomadas de antemão. Pelo contrário, você está sempre subordinado à arquitetura que foi definida para o sistema!

Vou tentar dar um exemplo:
A arquitetura do projeto define que as operações de negócio estarão em um EJB. Você chega para desenvolver uma nova funcionalidade, e o que vai fazer?

Começa programando a partir da interface/implementação do EJB, aplicando testes e desenvolvendo sobre a implementação do serviço (regras de negócio).
A arquitetura prevê a utilização de DAO? Tudo bem, você cria a interface do DAO, injeta um mock no seu teste e continua a trabalhar nas regras de negócio (ainda na classe do EJB).
Enquanto implementa você acha melhor mover determinada operação para uma classe de negócio auxiliar, um POJO, e aí começa a desenvolver essa classe criando testes para ela. Nesses testes trabalha os cenários que forem apropriados e implementa o código correspondente. Depois injeta essa classe de negócio no EJB para que ambos passem a funcionar juntos…
E assim por diante.

Veja que no final você tem uma funcionalidade toda desenvolvida através do TDD mas respeitando as regras da arquitetura do sistema, que mandam usar Framework Web X -> EJB -> DAO
Se quiser desenvolver outros componentes usando TDD vale o mesmo princípio (se bem que ainda é questionável se ele se aplica bem a elementos que contenham GUI ou IO)

Bom, é isso aí… não sou um expert em TDD (aliás nesse mesmo tópico manifestei algumas dúvidas básicas…), mas espero que esse tenha sido um exemplo claro para demonstrar que ele não interfere na arquitetura.

S

rogelgarcia:
Arquitetura no meu conceito:

  • Organização das classes e suas relações e responsabilidades num sistema.

Está bem definido?

Arquitetura define-se assim : aquilo que não está no código.
Se vc pode inferir lendo o código, não é arqutetura, é design. Isso que vc falou é design.
Arqutetura estaria na razão para o fato de vc ter classes e OO em vez de programação funcional, por exemplo.
Do codigo vc pode saber que usa classes, mas nunca vai saber porquê.

S

YvGa:
sergiotaborda:

Pensando de outa forma, no modelo padrão vc quer colocar um pattern X vc vai e coloca. Em TDD vc não faz isso. Vc escreve um código qualquer e depois quando for refactorar é que vc identifica o padrão e o usa. O TDD é reactivo e não pro-activo. E isso pode ser bom quando vc quer ser minimalista como o Beck gosta de ser, mas implica em muitos passos desncessários. Ai ele fala que a pessoa pode pular para o passo que deseja ( no caso, pode colocar o padrão logo de inicio). Mas isso para mim não é desenvolvimento assistido, é simplesmente ter uma ideia e colocar um teste à volta dela (Test First).

Certo, Sergio, entendo seu ponto de vista, mas deixa eu fazer uma defesa ao Beck, ou uma acusação, já que o livro dele não deixa isso claro. Mas foi a maneira que eu sempre entendi, lendo principalmente ele e os outros dois autores que eu citei no meu post anterior.

Não existe um jeito certo de começar a implementação, você pode começar por onde quiser, outside-in ou inside-out (o que pra mim parece o mesmo que top-down ou bottom up), você pode desenhar primeiro a interface de uma calculadora, pode implementar as teclas com infra-estrutura fake e ir aos poucos descendo para as operacoes matematicas. Ou então você pode fazer inside-out, começar pelas operações e vir para as teclas e a interface depois.

Mas o que você não pode, nem vai conseguir, de jeito nenhum, e é o que parece muita gente ter entendido da proposta do TDD é planejar inside-out. Não se pode planejar inside-out, não é possível imaginar uma calculadora começando simplesmente pelas operações matemáticas, sem pensar em como um ser humano irá interagir com ela

Aqui que vc se engana. A definição do dominio não depende da interação. Uma calculadora não é o que vc vê na tela, são as regras colocadas no codigo. Vc pode usar essas mesmas regras e colocar num servidor com um webservice na frente. Não ha necessidade de interação com o ser humano para definir o dominio. Isto é DDD. O Dominio é o ponto de partida porque é ele que atente dos requisitos que os usuários pedem. O resto é decoração e UX. Mas se o dominio não está bem modelado, não ha UX que salve.

Eu sim posso somar dois numeros sem saber se são float ou double ou int. Vc cria uma abstração. Vc pode criar uma classe com operação de soma e subtração que produzem objetos da mesma classe, e nunca, por baixo dos panos realmente fazer nenhuma conta. Mas vc abstraio o conceito de “operação” e é isso que é seu dominio.

Em nenhum momento eu falei de planejamento. Eu falei de design. Design não é planejamento, ele já é o produto final. Planejar o design é algo impossivel. Ou vc realiza o design ou não realiza. Vc pode realizar e se arrepender, mas não pode evitá-lo.
Frases como “Daqui a um mes implementamos o serviço de conversão” já implica que o design foi feito e existe um tal de “serviço de conversão”.

TDD realmente não tem que ver com planejamento, pois não é uma disciplina de gerencia.

S

YvGa:
rogelgarcia:

Linhas de montagens de carros são completamente diferentes de software. Você buscou um argumento de outro cenário para aplicar em software tentando rebater minha argumentação. Numa linha de montagem de carros, todos os carros são iguais. Decisões foram tomadas no projeto do carro e não na montagem. Just In Time é uma conceito relacionado a produção. Onde você entrega os produtos quando eles forem necessários. Exemplo: na produção do carro a chapa de aço será entrega quase no momento em que o carro iniciar na linha de montagem.

Lean nao e usado so em linha de montagem, é usado hoje em todas as areas, inclusive no desenvolvimento de produtos, onde usa conceitos parecidos.

Eu nao disse que TDD nao usa em refactoring, eu disse que o refactoring estará la, use você TDD ou nao. Voce acusa TDD de ser ruim por usar muito refactoring, mas desenvolvimento de software PRECISA de muito refactoring.

Não. Muito refactoring é sinônimo de más decisões e falta de robustez da solução. Muito refactoring é sinônimo de tentativa e erro. Quando vc coloca “refactoring” num loop vc está criando um mecanismo tentativa-e-erro (try-and-miss)
É como vc tentar decorar uma casa por tentativa e erro. Vc consegue, mas é muito mais fácil chamar um especialista que faz a decoração de primeira.

Mas estão esquecendo o básico, que o próprio autor defende. TDD é para quando vc não conhece a solução. Vc quer experimentar. E isso é comum quando está na camada de domínio. Por exemplo, todo o mundo sabe camadas e serviços e RMI e tal, mas como se modela um sistema que simula um cricuito integrado ? Como se simula um sistema que simula um coração ? Como se simula um sistema de controle de transito ? São estes problemas específicos que o TDD vai ajudar a resolver e não problemas do tipo “uso singleton ou registry?”, “uso dao ou domainsotre” não é nada disto que é o foco do TDD. E nestes cenários é aceitável tentativa e erro. Mas dizer que TDD é uma forma de desenvolver todo o sistema é absurdo. Ele só serve para desenvolver uma parte.

De facto o refactoring é uma ferramenta do programador e se começou a passar essa ideia que é bom e certo fazer refactoring. De fato é. Mas quando ele se repete muitas vezes torna-se um vicio da mente do tipo “não preciso pensar agora porque posso refactorar depois”. Se isso fosse real não precisaríamos de patterns, nem de centena de livros nos dizendo quais são as melhores práticas. Seria o equivalente a usar concatenação de string em vez de stringbuilder porque “não preciso fazer issso agora, posso fazer refactoring depois” e as pessoas ainda acrescentam “quando isso for um problema”. Mau código é um problema, assim que ele existe.
Portanto, um refacroring é pouco, dois é bom, três é de mais. Muito refactoring é sinal de mau desenvolvimento. Torna as equipes lentas e não produtivas. Repare que não estou falando de refactoring necessário devido a novos requisitos. Estou falando de mau codigo escrito sob a ideia que pode ser mudado depois.

O TDD usa muito refactoring, ou pelo menos ele aceita que isso exista. Contudo ele não aceita mau código (clean code foi mencionando ai). O que ele aceita é que devido a mudança nos requisitos , seja necessário mudar. E os requisitos , são aqui, os testes.
Mas ele também define que o painel de testes é conhecido à priori, logo, deve ser obvio, que antes do primeiro teste ser escrito eu já sei que o ultimo existe. E porque escolher uma design no primeiro teste que não encaixa no segundo ? simples burrice. Vc já ordena a implementação dos testes para implementar um depois do outro e implementar primeiro aquele que parece ser prominente na definição da estrutura. Isso é planejamento, e acontece antes do TDD.

O TDD não substitui a modelagem, no máximo ele a complementa. Contudo usando Test First e os passos normais de desenvolvimento chegamos no mesmo lugar. O TDD é apenas uma de se referir e vender a ideia de um ciclo de escrita de código baseado em testes. Só isso. Não é a oitava maravilha.

Y

sergiotaborda:
YvGa:
sergiotaborda:

Pensando de outa forma, no modelo padrão vc quer colocar um pattern X vc vai e coloca. Em TDD vc não faz isso. Vc escreve um código qualquer e depois quando for refactorar é que vc identifica o padrão e o usa. O TDD é reactivo e não pro-activo. E isso pode ser bom quando vc quer ser minimalista como o Beck gosta de ser, mas implica em muitos passos desncessários. Ai ele fala que a pessoa pode pular para o passo que deseja ( no caso, pode colocar o padrão logo de inicio). Mas isso para mim não é desenvolvimento assistido, é simplesmente ter uma ideia e colocar um teste à volta dela (Test First).

Certo, Sergio, entendo seu ponto de vista, mas deixa eu fazer uma defesa ao Beck, ou uma acusação, já que o livro dele não deixa isso claro. Mas foi a maneira que eu sempre entendi, lendo principalmente ele e os outros dois autores que eu citei no meu post anterior.

Não existe um jeito certo de começar a implementação, você pode começar por onde quiser, outside-in ou inside-out (o que pra mim parece o mesmo que top-down ou bottom up), você pode desenhar primeiro a interface de uma calculadora, pode implementar as teclas com infra-estrutura fake e ir aos poucos descendo para as operacoes matematicas. Ou então você pode fazer inside-out, começar pelas operações e vir para as teclas e a interface depois.

Mas o que você não pode, nem vai conseguir, de jeito nenhum, e é o que parece muita gente ter entendido da proposta do TDD é planejar inside-out. Não se pode planejar inside-out, não é possível imaginar uma calculadora começando simplesmente pelas operações matemáticas, sem pensar em como um ser humano irá interagir com ela

Aqui que vc se engana. A definição do dominio não depende da interação. Uma calculadora não é o que vc vê na tela, são as regras colocadas no codigo. Vc pode usar essas mesmas regras e colocar num servidor com um webservice na frente. Não ha necessidade de interação com o ser humano para definir o dominio. Isto é DDD. O Dominio é o ponto de partida porque é ele que atente dos requisitos que os usuários pedem. O resto é decoração e UX. Mas se o dominio não está bem modelado, não ha UX que salve.

Eu sim posso somar dois numeros sem saber se são float ou double ou int. Vc cria uma abstração. Vc pode criar uma classe com operação de soma e subtração que produzem objetos da mesma classe, e nunca, por baixo dos panos realmente fazer nenhuma conta. Mas vc abstraio o conceito de “operação” e é isso que é seu dominio.

Em nenhum momento eu falei de planejamento. Eu falei de design. Design não é planejamento, ele já é o produto final. Planejar o design é algo impossivel. Ou vc realiza o design ou não realiza. Vc pode realizar e se arrepender, mas não pode evitá-lo.
Frases como “Daqui a um mes implementamos o serviço de conversão” já implica que o design foi feito e existe um tal de “serviço de conversão”.

TDD realmente não tem que ver com planejamento, pois não é uma disciplina de gerencia.

Acho que estamos falando a mesma coisa de jeitos diferentes. Ok, vc acha que é possivel ter a funcionalidade de soma da calculadora, sem a interface humana e etc, etc, etc. Mas o ponto em que eu queria chegar é que voce não consegue planejar inside-out ou outside-in, voce necessariamente precisa da visão do todo antes de implementar. Mas visao nao eh ter o todo detalhado, minuciosamente descrito, visão do todo é simplesmente a visão, existem N possibilidades da implementação dessa visão e o TDD vai te ajudar a caminhar por elas.

Só quanto ao “voce não pode planejar o design” que talvez eu não concorde, ou talvez não tenha entendido. Essa visão do todo é um planejamento do design. Eu digo para um companheiro: “que tal se fizermos com que o pedido possua uma lista de itens e interaja com os produtos da seguinte maneira:…” Isto é planejamento de design. Depois eu vou implementar isso e ver se está de acordo.

De resto acho que estamos dizendo a mesma coisa de jeitos diferentes, sobre planejamento-implementação

Y

Refactoring é diferente de tentativa e erro e muito refactoring é muito vago, pois não se sabe o quanto é muito. Refactoring não é indicativo de problema, refactoring é a solução de problemas de design. Tentativa e erro vem da falta de experiência, e o refactoring pode diminuir o estrago. Erro é erro e refatorar o que está errado é sinal de melhora, o erro em si é o problema. Mas isso vem, como eu ja disse, mais da capacidade do programador do que da ferramenta que ele usa.

Refactoring é sempre um bom sinal (considerando que se segue as práticas indicadas pra isso), porque indica que se há algo ruim, esta sendo melhorado. Pior que isso é o padrão corrente de tentativa-erro-tudo ok pode por em produção.

Concordo, TDD e basicamente para implementar o meu modelo de domínio, ele pode ir além, mas quanto mais longe dessas fronteiras ele estiver, menos efetivo será. Mas há quem discorde e antes de eu decretar isto como fato, gostaria de ver algo do trabalho de quem discorda

Esse tipo de ideia vem do mal entendimento da prática de “a mais simples solução para o problema”. Muita gente entende isso, como comprovamos nesse topico, muita gente mesmo, com “faça a primeira porcaria que te vier a cabeça que depois você refatora.”

Se o segundo teste está logo ali abaixo, talvez não faça sentido mesmo, faço o primeiro, pensando que haverá um outro que deverá se encaixar ali, porque eu já tenho a visão do todo. Eu tenho uma boa noção de para onde estou indo. Mas e quando o segundo está só na próxima iteração ou na outra ainda. Faz sentido eu me preocupar com ele, se eu ainda nem sei exatamente como ele vai ser? E mais ainda, ele é menos importante do qual eu estou fazendo agora. Tanto é que ficou para a próxima sprint. É certo então que ele venha atrapalhar o que eu estou fazendo agora, se na verdade, eu ainda nem sei se ele de fato existirá.

Acho que o bom senso na hora de interpretar o que está escrito num livro vale muito, pois do contrário irá se postar cada frase da obra do Kent Beck aqui, removida de contexto, ou num contexto incompreendido para tentar mostrar o quanto ele fere algo que nosso amigo achou por bem chamar de arquitetura.

sergiotaborda:

O TDD não substitui a modelagem, no máximo ele a complementa. Contudo usando Test First e os passos normais de desenvolvimento chegamos no mesmo lugar. O TDD é apenas uma de se referir e vender a ideia de um ciclo de escrita de código baseado em testes. Só isso. Não é a oitava maravilha.

Ele não substitui, nem complementa, ele auxilia na sua construção. E se não é a oitava maravilha, ele ajuda muito, uma vez compreendido e bem utilizado.

S

YvGa:

Só quanto ao “voce não pode planejar o design” que talvez eu não concorde, ou talvez não tenha entendido. Essa visão do todo é um planejamento do design. Eu digo para um companheiro: “que tal se fizermos com que o pedido possua uma lista de itens e interaja com os produtos da seguinte maneira:…” Isto é planejamento de design. Depois eu vou implementar isso e ver se está de acordo.

Quando vc falou essa frase, vc já fez o design. Já definiu que itens “itens” , “lista de itens” que elas está num “produto”. O design está feito. Isto é o design. O colega por falar “não usa lista, vamos usar set, porque assim assim,” ou map, sei lá. Ou ainda "não, é melhor termos um serviço que recebe um pedido e obtem os itens " (não tou dizendo que é melhor, é uma frase hipotética e comum). Isto é discutir o design. E tudo isto acontece nos vossos cérebros. Mesmo que usem uml para comunicar, ou qq outro artificio, o modelo é o que fica no cerebro de cada um. É por isso que mesmo desenhando N esquemas, o cara ainda implementa errado. Porque no cérebro dele não ficou a mesma ideia que no seu.

Então, esse tipo de interessão é desenhar, e o que resulta dai é o design. Planejamento envolve o conceito de tempo e não existe esse conceito quando vc desenha. Planejamento de design, seria, no seu exemplo, vc dizer para o colega “Cara, amanha precisamos pensar como vamos fazer o modelo do produto e itens” E mesmo assim vc já tem um design base onde existe “produtos” e “itens”.

É só tirar a palavra “planejamento” e tá tudo certo.

S

Se vc está usando scrum e decidiu colocar o teste mais relevante no final, bom, isso é uma escolha, mas não é a melhor escolha. E entenda que quando vc planeja o scrum vc faz isso de posse de informação sobre o todo. Todos os “majors” estão identificados. Se não estiverem, então é erro de processo. Ou seja, não é suposto, num planejamento bem feito, que seja o ultimo teste que comanda o design. Concordo com vc no seu exemplo, só não concordo que isso é exemplo do que deveria acontecer na prática. Se acontecer, a prática está errada.

Em relação ao refactoring vc falou que “refactoring é a solução de problemas de design”. O que é correto.
Mas se ha um erro no design, porquê vc o cometeu ? Esse é o ponto.
Se vc cometeu o erro porque desconhecia a sua existência, tudo bem. É chato, mas “não é culpa de ninguém”.
Se vc cometeu o erro porque descuidou de cuida da solução no momento que o criou, isso é mau desenvolvimento.
Se vc cometeu o erro porque pensou “vou fazer refactoring depois” significa “vou fazer a correção do problema de design depois” , o que singifica que vc está conscientemente incluindo débito tecnico, o que é mau desenvolvimento.

Ou seja, a necessidade de refactroing está relacionada à existência de débito técnico ou á falta de consciência de um requisito que o código atual não atende.
O único uso legítimo do refactoring é para o segundo caso. Quando um novo requisito aparece. Se o requisito já estava lá e vc se esqueceu dele, isso é simples mau desenvolvimento. Refactoring é explicitamente uma solução para trasnformar um design em outro, e a única necessidade legitima para fazer isso é quando o seu design anterior não suporta o novo requisito. Ou seja, o seu design anterior, não era robusto o suficiente.

Dai que o excesso de uso de refactoring representa excesso de “requisitos surpresa” ou “muito débito tecnico”. O primeiro pode não estar na sua mão, mas o segundo está.
Vc sabe que está fazendo muito refactoring quando toda a a funcionalidade que vc inclui necessita dele. Um sistema feito do zero ,para um conjunto N de requisitos não deve souber nenhum refactoring para esse conjunto N de requisitos. Apenas quando houver um requisit N+1 que o refactoring é licito. Se o refactoring aconteceu para os mesmos N requisitos, então é porque havia débito técnico. E isso nunca é desculpável. Utilizar refacrtoring para evoluir um sistema até cumprir os N requisitos já conhecidos não é o que se pretende, simplesmente porque é gastar tempo e dinheiro à toa. é como o exemplo que dei de decorar por tentativa. Não tente, faça.

Mas agora que vem o truque. Se vc desenha bem, vc não deseja fechado (open-close principle). Logo, o bom design é aquele que pode ser expandido a suportar coisas paras as quais não foi feito de principio. Se vc precisa refactorar a cada N+1 , então seus design são péssimos. Sua capacidade de abstração é ruim. Vc pode refactorar e eventualmente vai fazê-lo, mas aceitar que é legitimo refactorar a cada momento é simplesmente dizer que vc não precisa saber pensar com antecedência, e essa mensagem que eu acho ruim. A mensagem não é essa. Nada desculpa o programador que muda o código todos os dias. Está faltando informação para esse sujeito. Pode ser informação sobre os requisitos ( e ai pode não ser culpa dele) ou pode informação técnica de como fazer melhor (, e ai sim é culpa dele).

O TDD usa o refactoring no sentido de que são necessários ajustes porque os requisitos aumentaram, não porque a abstração OO , ou a implementação são uma porcaria.

Na prática refactorar é diferente de refazer. E refazer é que o que a maioria das pessoas faz por ai. Refactorar é lago mais simples, que uma IDE pode fazer sozinha. Refazer é jogar ideias fora, e o codigo que as traduz, e incluir outras e o codigo que as traduz. É bom não confundir as duas.

Criado 27 de janeiro de 2013
Ultima resposta 30 de jan. de 2013
Respostas 68
Participantes 10