Feeds:
Posts
Comentários

Archive for the ‘Desenvolvimento Ágil’ Category

Bem, demorei mais do que havia planejado para escrever esse post. Nesse post eu vou falar sobre TDD com Test Doubles.

Para começar a apresentar os conceitos de Test Doubles, pedi para eles desenvolverem uma aplicação simples que deveria se conectar a um web-service que eu estava disponibilizando. Todos desenvolveram a aplicação utilizando TDD, so far so good. Então eu alterei o código do meu web-service, em um momento dei um sleep de 180 segundos e depois fiz ele lançar uma exceção.

Utilizei essas duas situações para mostrar um exemplo onde a utilização de Test Doubles: quando o sistema/classe depende de um recurso externo e/ou lento (acesso a rede ou disco por exemplo). Em seguida, eles fizeram outros testes, agora utilizando um mock e outro utlizando um stub que nós criamos.

Continuando comentei com eles outros benefícios de se utilizar Test Doubles, como o fato de você poder testar uma classe, sem que todas as classes do qual ela depende já estejam implementadas. Por exemplo, utilizando a idéia do web-service, se você está implementando uma classe que irá utilizar um cliente do web-service para pegar uma lista de tags para apresentar quais são as tags mais utilizadas. Abaixo um pedaço de código, demonstrando como a classe utiliza o cliente do web-service.

class TagsGenerator {
	private $client;
	public function __construct(WebServiceClient $client){
		$this->client = $client;
	}
	private function buildTagList(){
		$list = $this->client->getTagList();
                // código omitido
	}
        // demais métodos omitidos
}

Claro que você está sempre programando para a interface, então WebServiceClient é uma interface e não uma classe. Veja então que eu vou poder testar essa minha classe, antes mesmo que haja alguma implementação para a interface WebServiceClient. Aproveitei também esse exemplo para comentar mais sobre inversão de controle(IoC). Abaixo um exemplo de um método de teste.

	public function testShouldReturnMusicAsTopOneTag(){
        $stub = $this->getMock('WebServiceClient');
        $stub->expects($this->any())
             ->method('getTagList')
             ->will($this->returnValue(array('Music','Games','Videos')));
        // aqui, usando IoC e um stub eu posso testar
        // minha classe que constrói a lista de tags
        $generator = new TagsGenerator($stub);
        // resto do teste abaixo
	}

Outro benefício que pode ser alcançado com uma boa OO e test doubles é o isolamento entre testes. Além disso, comentei sobre o Mocks Aren’t Stubs do Fowler, que fala sobre as diferentes formas de se utilizar TDD, classicist ou mockist e citei que na minha opinião a melhor abordagem é saber utilizar bem as duas formas de TDD.

Final se semana escreverei outro post, comentando como foi feito o TDD com banco de dados.

Anúncios

Read Full Post »

Continuando o assunto do post anterior, dessa vez Uncle Bob resolve dar sua opinião sobre o booom de projetos ágeis” que estão aparecendo (e falhando) por todo lado.

Uncle Bob em Dirty Rotten ScrumDrels.

Read Full Post »

James Shore pra mim é um daqueles autores que quando ele fala em Agile, ele leva em consideração o que Agile é e não quanto dinheiro ele pode ganhar em suas consultorias, então é uma opinião a ser respeitada.

No Brasil, as listas de discussões viraram local para se fazer propaganda do curso X, da consultoria Y ou site Z faz tempo, a única lista onde esse pessoal não se criou, foi a xp-rio (lá você pode fazer perguntas sabendo que o pessoal vai te responder sem pensar que você é um possível cliente). Opiniões são completamente baseadas em “quantos clientes eu posso conseguir afirmando que X é melhor que Y?”.

Toda semana vejo aparecer um curso de Scrum novo, ministrado por alguém certificado PMP e “Certified Scrum Master”, acho que isso acaba gerando uma boa parte do problema. Sua empresa quer Agile com CMMI ? Sem problemas tá cheio de consultor por aí pronto para quebrar os valores ágeis somente para ganhar um dinheiro da sua empresa.

Como o Milfont já havia previsto, o Scrum está se tornando cada vez mais o PMBoK de jeans.

Sinceramente, se você esta querendo iniciar com desenvolvimento ágil, Scrum, extreme programming, Lean, crystal… utilize as listas de discussão para fazer perguntar e tirar suas dúvidas. Contudo filtre bem as respostas, tenha em mente que tem muita gente ali que precisa de convencer que X é melhor que Y ou que X é perfeito para seu ambiente, muitos vão mentir deformar o movimento ágil o quanto for necessário, somente para conquistar seu dinheiro 🙂

Isso não quer dizer que você não deva contratar um coach para ajudar com o desenvolvimento ágil em sua empresa, isso com certeza é algo que vai acelerar bastante as coisas. Contudo, preste atenção em quem você está contratando.

Voltando agora para o James Shore, ele escreveu um post que relata muito bem um fato que vem acontecendo devido a toda essa fama do agile, não vou repetir o que ele escreveu lá, então o link é esse The Decline and Fall of Agile.

Read Full Post »

The role of leadership in software development, é uma apresentação feita em 06/05/08 por Mary e Tom Poppendieck. Então, observando quem são os 2 palestrantes, você já sabe que realmente deve assistir isso.

Read Full Post »

Depois de uma semana afastado, retornei a empresa pra ver como as coisas estão andando e para continuar o treinamento. Agora para apresentar o test driven development.

Assim que entrei na empresa, tive uma boa supresa. Eles colocaram mais um quadro na empresa. Agora eles tem um quadro para as tarefas e outro onde ficam os itens das retrospectivas e os itens mais importantes do product backlog.

Além disso, pelo que observei está tudo indo bem, as coisas não estão ótimas, contudo eles estão melhorando aos poucos e isso é o importante.

Como já comentei aqui no blog, eles estão utilizando PHP para desenvolver o projeto novo deles. Então fui dar uma olhada no que havia de novo no PHPUnit, preparei uma apresentação bem simples para explicar os conceitos do TDD.

Comecei com o clássico “TDD não é teste, TDD é uma forma de desenvolver o sistema de uma forma incremental”. Repeti isso umas cinco vezes no início e mais algumas durante os exercícios. Depois disso expliquei o ciclo do TDD, comentei que para classe desenvolvida, deve existir outra classe de testes e falei sobre design, a mudança que é evitar aquele pensamento enorme inicial de como algo deve ser para pensar em um design que vai evoluindo junto com a classe.

Depois fui para uma parte mais prática, expliquei que toda classe de teste vai ser um sub-classe de uma classe do PHPUnit (o que é algo ruim, no JUnit4 não precisa fazer isso) e que todo método de teste tem a assinatura:

public function testMetodoDeveTerComportamentoTal{}

Algo que eu também dei bastante ênfase, é no nome do método de teste. Como o PHPUnit não permite a utilização de contextos, o nome deve ser grande e claro, pra ser facilmente entendido o que o teste está testando. Além disso, também lembrei eles que cada teste deve testar apenas um item. Pra exemplificar isso citei uma classe imaginária Calculadora, nos testes você pode ter os métodos testDeveSomar500Com300 e testNaoDevePermitirDivisaoPorZero mas não deve ter apenas um método de teste que garanta que a calculadora deve somar e não aceita divisão por zero. Ou seja, One Assertion Per Test.

Depois disso já pedi para eles abrirem a IDE por eles utilizada (Zend Studio), ela já tem um suporte legal para o TDD, embora utilizar o PHPUnit que vem junto com a IDE é sofrível, muito, muito lento.

Então o primeiro exercício foi criar uma calculadora. Desenvolver uma calculadora é extremamente simples, mas a idéia era que eles tivessem algum contato com o PHPUnit sem se preocupar com o problema que iriam resolver.

Ao criar um novo TestCase, a IDE já criou os métodos setUp() e tearDown() e já fez da classe de testes uma sub-classe de PHPUnit_Framework_TestCase. Aproveitei esse momento para explicar que o método setUp() é chamado sempre antes de cada teste e o tearDown() é chamado sempre depois que cada teste é executado. Também expliquei qual o motivo de existirem esses métodos.

Continuei o exercício explicando as funcionalidades a medida que era necessário. Depois que eles criaram a assinatura do primeiro teste, expliquei como é feito a asserção no PHPUnit e apresentei as mais utilizadas (assertEquals assertTrue assertFalse assertNull assertNotNull). O exemplo da calculadora foi útil também para apresentar como funciona a asserção de exceções no PHPUnit.

No final desse exercício, eles tinha uma boa idéia de como funciona o PHPUnit e como os testes do TDD podem ajudar na garantia que não seja adicionado nenhum bug num sistema com testes. Contudo eles ainda não tinham idéia de como o TDD pode ajudar no desenvolvimento.

Isso eu deixei para o segundo exercício. Deixei 2 horas separadas para esse exercício, que basicamente funcionava da seguinte forma.

Eu, cliente, quero um sistema no qual eu entre um valor numérico, por exemplo 327 e o sistema deve retornar o número por extenso, no caso, trezentos e vinte e sete. Os número podem variar de 0 até 999.999 com duas casas decimais.

Escolhi esse exercício pois considero que o desenvolvimento incremental do TDD se beneficia muito de um exercício como esse.

A primeira reação deles ao ouvir o exercício foi pegar um papel e começar a esboçar a solução, com exceção de um desenvolvedor, que foi para o google procurar algo pronto. Nesse momento pedi para eles sentarem em duplas e conversei para mostrar como TDD ajuda a resolver o problema. Comecei dando a idéia de resolver primeiro de 0 até 10, depois de 11 até 20. Mostrando pra eles que quebrando o problema iria ficar muito mais simples para resolver.

Eles aceitaram a idéia e começaram a escrever código. Foi muito legal que eles pegaram o espírito do TDD, eles foram desenvolvendo um teste de cada vez, fazendo cada teste passar antes de evoluir o código, além de ficar refatorando constantemente.  As duplas também eram trocadas a cada 30 minutos,  para garantir um ritmo parecido em toda equipe.

No final de 2 hoas o resultado foi muito bom. Todos haviam gostado do que haviam produzido e de como haviam produzido. Diferentemente do que aconteceu comigo, que demorei uns 3 meses para cair na real com TDD, aparentemente eles pegaram bem o espírito e gostaram. Já perguntaram como eles vão utilizar no projeto atual deles!

Abri um espaço para dúvidas no final, contudo somente uma apareceu.

TDD é legal, mas quando o código é muito simples, não preciso fazer isso, não é?

A minha opinião é que mesmo códigos muito simples devem ser testados. Códigos muito simples geralmente possuem testes muito simples, então o tempo para escrever somente o código da classe ou a classe e o teste vão ser pequenos. Outro problema é que é comum ter um código simples no início, contudo conforme o sistema cresce o código também cresce. Por último, TDD ajuda a ter um código sem bugs e mesmo em códigos simples podem escapar alguns bugs. Então para mim código simples está longe de ser um motivo para não utilizar TDD em uma classe.

É isso, na próxima semana vou falar sobre dummies, fakes, stubs e mocks.

Read Full Post »

Continuando essa série de post (parte 1 e 2), hoje vou comentar como foi o final da primeira iteração/sprint, reuniões de review, retrospectiva e o planejamento da iteração seguinte.

Cheguei na empresa e antes de começarmos os trabalhos, reuni o pessoal e perguntei como foi a primeira semana utilizando scrum.  O desenvolvedor mais experiênte, comentou que gostou do sistema com o quadro, os cartões e post’it. Ocorria muito mudança de contexto (e mudança de contexto é algo ruim), pois as ordens vinham de cima e não havia uma preocupação de trabalhar em 1 projeto de cada vez. Ele disse que pode se organizar muito melhor. O desenvolvedor menos experiente (1 mês de empresa) também gostou muito do quadro, cartões e post’it. Segundo ele, é sempre complicado ao entrar em um projeto, entender os padrões e ter uma visão geral do sistema. Utilizando cartões, ele precisa aprender apenas pequenas partes do sistema a cada semana, se preocupando com as outras partes somente quando for necessário. O dono da empresa também está satisfeito, ele disse que foi produzido bastante nessa primeira iteração, terminaram todas as tarefas e realizaram o spike planejado.

Certo, depois da conversa inicial, fomos para o review, que na verdade serviu para eles entenderem como funciona um review (agora em mais detalhes do que na apresentação teórica inicial). Como eles trabalham para vários clientes durante a iteração, eles foram desenvolvendo e apresentando (disponibilizando no site) para os clientes. Ou seja, para esses projetos não irá ocorrer aquela apresentação formal durante o review (isto também seria dificultado pelo fato da maior parte dos clientes residirem em outras cidades).

O fato de não ter essa apresentação acabou gerando um problema. A funcionalidade é desenvolvida, atualizada no servidor e então o cliente é comunicado da mudança. O problema é que  nessa primeira iteração algumas funcionalidades (4 ou 5) não ficaram pronta, pois o cliente ainda não aprovou.

Além destes projetos menores, há o projeto maior, no qual o cliente pode estar presente para a reunião de review. Nessa primeira iteração não ocorreu, pois eu aproveitei pra explicar como fazer a review. Deve ser uma apresentação simples, utilizando diretamente o software (nada de slides, diagramas…) e que preferencialmente o cliente  fique utilizando o software durante a explicação do que foi desenvolvido.

Como a definição de pronto, inclui aprovação do cliente, nesta primeira semana, o que foi desenvolvido nesse projeto principal, foi apresentado para o cliente. Contudo ele achou muito mais interessante o review meeting. Segundo o cliente, ao ser informado que uma nova funcionalidade estava pronta, ele acessou o sistema utilizou de forma superficial e somente isso. Ele estava ocupado e não poderia perder muito tempo naquilo. Respondeu que estava tudo certo com a funcionalidade. Agora, com um horário reservado para essa apresentação, ele irá utilizar e (importante) fornecer um feedback muito maior para a equipe de desenvolvimento (o feedback anterior havia sido um “ok”). O cliente utilizou novamente a funcionalidade por alguns instantes durante nossa review e deu algum feedback, a funcionalidade não estava exatamente como ele queria e ele decidiu gastar algum tempo na próxima iteração melhorando isso.

Assim terminamos nosso review meeting. Já combinado para a próxima semana as funcionalidades serem apresentadas para o cliente.

Após o review, iniciamos a retrospectiva. Expliquei que a retrospectiva é a hora de melhorar. Melhorar o processo (avisando que primeiro você deve praticar corretamente o processo, somente depois pode melhorar –  Shuhari), melhorar o ambiente, melhorar o código, a documentação ou qualquer outra coisa.

Além de identificar o que pode ser melhorado, é importante atacar um ou poucos problemas em cada iteração, tentar resolver tudo em uma única iteração não é uma boa idéia, provavelmente você terá nada resolvido, ou vários problemas quase resolvidos (quase resolvido significa não resolvido). Após identificar o que será melhorado, deve-se definir quais ações/atitudes serão tomadas para melhorar o ponto escolhido. Finalmente, é importante que seja definida uma forma de saber se as ações trouxeram alguma melhoria ou não.

Por exemplo, você pode identificar que o problema que será atacado na próxima iteração é que somente um desenvolvedor pode trabalhar em alguns sistemas, porquê os outros não conhecem o sistema. Isso é seu problema, uma ação/atitude que você pode tomar é definir que a equipe irá utilizar programação em dupla, principalmente com esse desenvolvedor quando estiver trabalhando em um sistema que só ele tem conhecimento. Para saber se essa atitude/ação teve algum resultado, você (junto com a equipe) define que até a próxima retrospectiva deverá ser feito ao menos 20 horas dessa programação em dupla. Assim na próxima retrospectiva você checa quantas horas de programação em dupla foram feitas, podendo verificar se o problema encontrado na retrospectiva anterior foi atacado ou não.

Continuando… antes do tradicional “O que foi bom”, “O que pode ser melhorado” e “O que foi mal”. Fiz outra atividade. Comentei novamente sobre o que é desperdício no Lean e apresentei as 7 formas mais comum de desperdício no desenvolvimento de software:

  • Trabalho particialmente finalizado
  • Processos extras
  • Funcionalidades extras
  • Mudança de contexto
  • Espera
  • Movimentação
  • Defeitos

Depois disso, utilizei a idéia de votação por pontos, onde cada desenvolvedor pode escolher 2 desperdícios e votar neles, os mais votados (ou o mais votado) seria escolhido para discussão do porquê (análise da raiz do problema) ele ocorre e o que pode ser feito para que não aconteça mais. Os mais votado foi “Defeitos”. Ficamos alguns minutos discutindo sobre isso, você pode atacar esse desperdício de várias formas, por ser algo muito abrangente. Depois de alguma discussão, eles concluiram que se utilizassem melhor as funcionalidades do Zend Framework (o problema, não conhecem a fundo o framework utilizado), eles poderiam reduzir o número de defeitos. Como isso também estava muito vago, conversamos mais uns 3 minutos e ficou definido que para a próxima semana (a ação/atitude) eles irão estudar o Zend_DB_Table. Para verificar se o problema foi atacado na iteração atual, na nossa próxima retrospectiva além de verificar se as horas foram gastas estudando o componente, também ficou combinado que, se for vantajoso utilizar o componente, deverá estar escrito em algum lugar alguns exemplos das situações que serão mais utilizadas no dia-à-dia, facilitando assim a utilização. Se não for vantajoso, será discutido onde o componente falha.

Depois seguimos para o “O que foi bom”, “O que pode ser melhorado” e “O que foi mal”. Combinamos que faríamos essa atividade, mas não iríamos atacar nenhum problema levantado nessa atividade, pois para a próxima iteração o Zend_DB_Table já irá ocupar bastante tempo. Essa atividade foi mais leve e rápida, na coluna “o que foi bom” apareceram coisas como “utilizar quadro e post’it” até coisas mais específicas como “fazer a validação do usuário utilizando ajax”. Eu acho ótimo isso, nessa hora é preciso pensar desde o processo até detalhes de implementação. Os pontos negativos levantados foram a mudança de contexto, que segundo eles diminui bastante mas ainda incomoda, além de um cliente que parece ser daqueles bem chatos.

Além disso, durante a retrospectiva, resolvemos criar mais uma coluna no quadro de tarefas. Atualmente, enquanto uma funcionalidade estava esperando a aprovação do cliente, ela ficava na coluna “Impedimentos”. O problema é que essa coluna ficou com bastante itens (4 ou 5) que eram apenas aguardo de aprovação do cliente, e havia também um pequeno impedimento de verdade, que quase sumia no meio de tanta espera por aprovação do cliente. Como a idéia é que impedimentos existem para serem eliminados, essa dificuldade em ver facilmente que existe um impedimento além de aprovação do cliente me incomodou. Então agora o quadro tem mais uma coluna: “Aprovação”, que identifica os itens que estão pendentes de aprovação. Assim a coluna de impedimentos tem novamente a atenção necessária.

Depois disso, falei para eles que estava na hora do cafézinho!

Para finalizar, fomos para o planejamento da próxima iteração. Novamente algo foi alterado. Quem realiza o papel do cliente, também é desenvolvedor. Sendo assim, ele não precisa que a equipe estime uma user story (ou funcionalidade) para saber se é maior ou menor do que outra. Ou seja, ele pode organizar o product backlog (lista de funcionalidades) sem o auxílio da equipe, pois ele tem noção do quanto uma user story é maior que outra.

Contudo eu acho que é interessante que eles continuem estimando as user stories utilizando pontos, pois caso eles comecem a desenvolver outro projeto,  com outro cliente, eles já vão saber como funciona a estimativas por pontos. Esse é o único motivo pelo qual eles estão estimando por pontos as user stories, somente para conhecer bem o funcionamento para que possam usar, quando for necessário.

Então o planejamento ficou um pouco diferente, cada cartão contendo uma user story era apresentado, os detalhes eram explicados para a equipe. A equipe então estimava utilizando pontos (story points), em seguida quebrava a user story em tarefas e já estimava em horas ideais. Antes de iniciarmos o planejamento, foram calculadas quantas horas cada desenvolvedor tinha disponível, feito alguns descontos (suporte e horas ideais não representam horas reais) para chegar ao que acreditamos ser o total de horas ideais disponíveis essa semana. Então fomos estimando cada user story, quebrando em tarefas e estimando as tarefas até o total de horas disponíveis para a semana.

E foi isso, tudo devidamente estimado, cartões e post’it fixados no quadro, hora de trabalhar. Quinta-feira estarei de volta lá para ver  como as coisas estão andando.

Read Full Post »

Antes de começar, só vou adicionar algo importante que esqueci de escrever no post anterior. Antes da reunião para gerar as user stories, nós conversamos e geramos uma definição de pronto. Como são projetos diferentes, alguns mais antigos estão com códigos estruturados e os novos utilizando o Zend Framework, a definição de pronto ficou um pouco diferente para os dois tipos de projetos. Basicamente, a definição de pronto dos projetos utilizando o Zend Framework é a definição de pronto dos projetos estruturados, mais a necessidade de testes de unidade e de aceitação.

Bem, dito isto, vamos em frente. Hoje fiz novamente uma visita na empresa. Precisava corrigir um problema no subversion deles (esse problema estava corretamente identificado na coluna “Impedimentos” do quadro deles). Além disso também queria acompanhar o andamento semanal e o stand up meeting (ou daily scrum, ou reunião de pé).

Cheguei lá e vi que eles já tinham definido um horário para o stand up. 15 minutos após o horário de início de trabalho. Pude observar também que eles não ficaram enrolando, lendo emails e essas coisas até a hora da reunião, eles estavam trabalhando normalmente, quando um deles falou “Vamos lá?”, todos levantaram, deram uma rápida olhada para o quadro de tarefas e responderam as famosas perguntas, ponto positivo. Em 3 desenvolvedores a reunião demorou uns 4 minutos, outro fator positivo. Eles conseguiram entender que o espírito é manter o foco e gerar comprometimento. Distribuí apenas um aviso, (depois que a reunião encerrou) pois um deles aproveitou que estava de pé e foi ligar a impressora enquanto outro falava. Durante a stand up meeting, não se pode fazer outras coisas, nada de telefone, impressora, café, nada! É hora da stand up meeting.

Depois fui observar o quadro para ver como está o andamento da semana deles. Segundo eles, algumas estimativas foram bem diferentes do tempo que realmente levou. Tarefas estimadas em 3 horas ideais demorando 2 horas reais e algumas estimadas em 1 ou 2 horas ideais demoraram 4~6 horas reais. Mesmo assim o andamento está legal, provavelmente amanhã pelo meio dia eles devem terminar as user stories planejadas.

O único problema é que na definição de pronto deles, está a necessidade de aprovação do cliente. Essa necessidade de aprovação é porque eles trabalham com o design do site, e essa parte geralmente é mais complicada e o cliente acaba pedindo algumas pequenas modificações. Além disso, trabalhando com múltiplos clientes e as alterações são geralmente pequenas, não é possível fazer uma review meeting com todos eles, então para algo ser considerado pronto, é necessária essa aprovação. Continuando, o problema é que geralmente o cliente demora para fazer a aprovação. Não tendo aprovação, essa tarefa não está pronta nem em andamento, ela vai para a coluna de  impedimentos no quadro.

Claramente existe um problema aí, essa demora de aprovação do cliente está gerando muitos itens na coluna impedimento, contudo logo teremos nossa reunião de retrospectiva e vamos conversar sobre isso.

Read Full Post »

Older Posts »