[quote=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.
[/quote]
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.
[quote=YvGa][quote=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.
[/quote]
Com isto vc quer dizer que no livro o próprio autor diz que TDD facilita arquitetura ruim?[/quote]
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.
[quote=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.[/quote]
Ó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!!
Organização das classes e suas relações e responsabilidades num sistema.
Está bem definido?[/quote]
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.
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.
[quote]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.
[/quote]
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.
“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.
“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.
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.
Organização das classes e suas relações e responsabilidades num sistema.
Está bem definido?[/quote]
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.
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.
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.[/quote]
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.
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.[/quote]
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
[quote=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.[/quote]
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!
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.
[quote]rogelgarcia wrote:
Em TDD você toma decisões tardiamente.
Não entendo por que isso é ruim?[/quote]
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.
[quote=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??? [/quote]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.[/quote] 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
[quote=rogelgarcia][quote]rogelgarcia wrote:
Em TDD você toma decisões tardiamente.
Não entendo por que isso é ruim?[/quote]
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)[/quote]
Isso está fora de contexto. Pegando o que o fowler disse[quote]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."[/quote]
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.[/quote] 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.[/quote]
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][/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.
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.
[quote]
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.[/quote]
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.