Archive for the ‘agile’ Category
Google Wave e entrega de software contínua: o que se pode concluir
O Google Wave morreu. Quer dizer, ainda não, mas vai até o fim do ano. Um dos projetos mais “badalados” do Google até pouco tempo depois da sua abertura oficial deixa dois sinais claros: 1) A queda de gigantes na Web pode acontecer de forma muito rápida e 2) Você deve entregar seu software com mais freqüência.
O Google Wave foi anunciado no Google I/O do ano passado e segundo os líderes do projeto, o Google Wave já tinha 2 anos quando foi apresentado ao público pela primeira vez. Dois anos. E isso não foi nem uma entrega, foi um beta super-fechado que o Google fez na conferência.
Houve uma grande corrida para obter novas contas do Google Wave (tinha maluco vendendo conta até no eBay, para se ter noção de quão grande a coisa parecia). Só que este entusiasmo parou nas primeiras semanas de uso do produto. Os principais motivos foram:
- Interface complexa – Muitas funcionalidades em um só lugar, apresentadas de forma “mágica” e que deixaram os usuários confusos
- Lentidão – O Google Wave é super pesado. Quem tinha o Firefox ou o IE não conseguia rodar com uma performance decente. O Chrome e o Safari eram a solução, mas nem todo mundo viam as coisas desta forma.
- Falta de integração com o Gmail (e outros produtos do Google) – Na minha opinião, houve um deslumbramento tão grande com o termo “Email 2.0″ que eles esqueceram do email tradicional e de outras ferramentas populares, que funcionam e que muitas pessoas utilizam.
Os problemas listados acima juntamente com o problema da aceitação do produto poderiam ter sidos resolvidos (ou ao menos amenizados) se o Google fizesse entregas de partes do Wave antes. Como? Eu explico:
- Entrega contínua implica necessariamente em feedback contínuo. A idéia do Wave é genial, mas cada pedacinho dele não pôde ser “devidamente apreciado” pelos seus usuários. Sem contar que à medida que funcionalidades forem sendo lançadas, bugs iriam sendo detectados e corrigidos de forma mais fácil. Agora imagine você corrigindo um bug de um código que você fez há mais dois anos…
- O Google poderia ter mudado o rumo do produto antes, mas mantendo as idéias inovadoras. Que tal ter um chat com timeline no Gmail? E um email com playback? Quem sabe até um email similar a uma Wave onde se pode ver as alterações em tempo real? Tudo isso poderia ter sido acrescentado ao Gmail (e talvez a outros serviços), aumentando muito o nível de satisfação com do usuário
- Compatibilidade de plataformas. Somados, o IE e o Firefox detêm mais de 70% do mercado de navegadores. 70%. E o Wave não funciona tão rápido nestes navegadores quanto ele funciona no Google Chrome ou Safari. Com entregas curtas, o Google poderia ir “sugerindo” a migração para outros navegadores e/ou adaptando o Wave para funcionar melhor com browsers mais lentos.
Concluindo: Entregue seu software com mais frequencia. Você diminui os riscos e deixa seus clientes e usuários mais satisfeitos.
Quando uma deficiência pode se tornar uma feature numa linguagem de programação
Estava lendo um antigo post do Obie Fernandez onde ele lista várias razões do porquê Java é uma porcaria (em tom de brincadeira, claro =). Numa das razões citadas por ele, há o seguinte trecho:
8 ) Java has good debugging support
Java has great and powerful debugging (which is very necessary since most Java code sucks so much ass). Ruby has ridiculously pitiful debugging support, which means our code actually needs to be well-tested and readable.
Traduzindo:
8 ) Java possui um bom suporte a debugging
Java possui um excelente e poderoso debugging (o que é necessário, já que boa parte de códigos em Java são muito ruins). Ruby tem um suporte a debugging lamentavelmente ridículo, o que significa que nosso código realmente precisa ser bem testado e legível.
Vendo por este lado, Ruby é uma excelente linguagem para quem sabe fazer direito e uma droga pra quem está acostumado com IDEs com Intellisense e checagem de erros pelo compilador.
Outras linguagens possuem problemas que são resolvidos facilmente com o uso de testes unitários. Um problema clássico que acontece com o PHP, o White Screen of Death (um erro que acontece com o script que nenhuma informação ou mensagem de erro é apresentada), pode ser resolvido com o uso de testes.
Alguns “problemas” advindos com linguagens dinâmicas é com a mudança de tipo de uma determinada variável, por exemplo:
x = 1
y = 3
def soma(self):
return self.x + self.y
op = Op()
op.y = "aha!"
op.soma() #Ooopss... TypeError
Este é um tipo de problema que vem com a checagem de tipo em tempo de execução, ao invés de ser feito em tempo de compilação. Muitas pessoas que não possuem a mesma visão do Obie, encaram isto como um problema.
Opinionated Software
Um trecho muito conhecido do Getting Real é o trecho que fala sobre opinionated software:
Your app should take sides
Some people argue software should be agnostic. They say it’s arrogant for developers to limit features or ignore feature requests. They say software should always be as flexible as possible.
We think that’s bullshit. The best software has a vision. The best software takes sides. When someone uses software, they’re not just looking for features, they’re looking for an approach. They’re looking for a vision. Decide what your vision is and run with it.
Traduzindo:
Seu aplicativo deve tomar partido
Algumas pessoas defendem que o software deve ser agnóstico. Dizem que é arrogante da parte dos desenvolvedores limitar a funcionalidade ou ignorar pedidos de novos recursos. Dizem que o software deve ser sempre o mais flexível possível.
Para nós isso é papo-furado. O melhor software traz consigo uma visão. O melhor software toma partido. Quando alguém usa um software, não está procurando apenas recursos, está procurando uma abordagem. Está procurando uma visão. Decida qual é sua visão e atenha-se a ela.
Esta mesma idéia permeia linguagens de programação. Você não achará um linguagem que sirva bem para todos os tipos de casos. Python, por exemplo, não é uma boa linguagem se você quiser usar threads pesadamente. Erlang, apesar de ser uma excelente escolha para programação distribuída e paralela, enfrenta um certo preconceito por ser funcional e não ter suporte à orientação a objetos. C#.NET é uma boa linguagem para criação de aplicativos comerciais, mas não é totalmente portável para todas as plataformas (o Mono mal suporta o .NET 3.5 e o framework já está na versão 4).
Conclusão: antes de reclamar de uma linguagem de programação, saiba que toda linguagem tem um approach, um foco e veja se esta “falha” pode ser algo útil… muitas vezes o é ![]()
Parabéns
Parabéns! Você trabalhou de uma forma tão impressionantemente dura durante os últimos sete meses e meio neste projeto. Você atendeu à todas demandas do cliente que vieram. Você completou o projeto no prazo e dentro do orçamento de $30,000, economizando $2000. O cliente está muito satisfeito por isso. Você pode dizer isso pelos sinais de dólar nos olhos dele. O cliente também está satisfeito pois ele foi capaz de colocar o Website no ar para o mundo para crescer e conquista-lo, o website já tem alguns usuários vindos dos convites beta que você mandou no início da semana. Você ainda mantém contato com o cliente quase todo dia. Ele diz que o site está indo muito bem.
Mas.
Há um usuário que está reportando uma falha com uma funcionalidade que você implementou há três meses. O cliente configurou seu email para receber relatórios de bugs. Você os recebeu pouco tempo depois que o usuário mandou. Uma páginas está mostrando “Desculpe-nos mas algumas coisa deu errada”.
Uh oh.
Você entra no website e checa você mesmo. Certo o suficiente que a página está dando erro 500. Mas por quê? Essa funcionalidade foi concluída três meses atrás e funcionou bem, não foi? Você testou na sua máquina local e viu que talvez fosse algo simples. Talvez uma variável digitada incorretamente no controller. Ou talvez não. Talvez isso vai levar mais de dois segundos seus para identificar o problema. Talvez leve uma hora, um dia.
Uma semana.
Então como esse erro pode existir? Você escreveu testes, né?
Oh, eu entendo.
Por causa da deadline iminente você estava pressionado pelo tempo e não se incomodou em aprender nenhum dos frameworks de testes. Você quis aprender. Muitas pessoas falam sobre testes com uma atitude positiva… foi só você que não teve tempo. Quando você fala sobre o assunto, seu chefe diz “o cliente não está pagando para você escrever testes, ele está pagando para você escrever funcionalidades”. Mesmo seu conhecimento sobre Rails cresceu três ou quatro vezes, comparado com o que era antes, durante a vida deste projeto, você ainda não sabe merda nenhuma sobre testes. Talvez seja hora de aprender, você pensa. Ah, mas O Chefe não quer que você gaste seu tempo em coisas que não produzem funcionalidades. “Testes são um desperdício do dinheiro do cliente”, ele diz. Você suspira. “Eu irei fazer melhor no próximo projeto. Eu irei fazer com que ele veja a luz. Eu irei fazer testes de verdade…”, você diz na sua cabeça. Ok, então você não escreveu os testes.
Então aqui vão os fatos:
Há um bug.
Você trabalhou nele no passado.
Você precisa conserta-lo. Agora.
Então como você debuga este bug para garantir que ele não aconteça denovo? Bem, você o conserta e sabe que ele não irá acontecer denovo, certo? Você deixará um comentário decente (na verdade, você irá pensar em deixar um comentário decente) depois que estiver consertado, para que ninguem passe pelo mesmo erro. Certo?
Errado.
Tudo bem, então você sabe que está em algum lugar do passado. Você pode ver a lista de branches e talvez algum dispare um gatilho na sua memória, e você tem certeza que tem branches com nomes memoráveis?
Ah sim, branching no SVN é um pé no saco. Eu concordo. Se você pudesse ao menos convencer seu chefe a usar Git também. Branching no Git é muito mais legal. Talvez você fará que ele “veja a luz” sobre isso no próximo projeto também. Então todas as modificações são no trunk, e navegar regressivamente sobre ele vai, claro, levar bastante tempo. Boa sorte com isso.
Então vamos assumir que você passa pelo trunk. Você se lembra da revisão e conserta o bug. Feito. Morto. Destruído. Vencido. Manda para as profundezas do inferno com um oitavo da sua sanidade. Isso foi um pouco duro. Você escreve um teste de regressão para ter certeza que não irá acontecer denovo, certo?
Oh, eu entendo.
Você comentou no item a fazer do Basecamp dizendo que foi consertado. Eu acho que é um nome procurável, certo? Somente no caso de acontecer denovo. É chamado de “alguma coisa deu errdo” ou “A página está quebrada”?
Uh oh.
Então você vai pra casa, satisfeito que você deu um pé na bunda de um bug que esteve na sua mente por dias. Você venceu.
Parabéns.
Você acorda no dia seguinte, pega seu café/leite/suco de laranja e checa seus emails. Há três do facebook, uns dois de algumas listas de email que você está inscrito e catorze do seu cliente. Esses emails não são catorze cartas de amor. Você vê que o primeiro foi enviado para você 20 minutos depois que você foi pra cama. Se você pelo menos ficasse ficado até tarde…
Você lê o primeiro. É um relatório de erro. O próximo também. E o próximo depois desse também. E adivinha? O próximo também.
Todos os catorze emails que seu cliente enviou a você tarde da noite não foram “Obrigado por seu trabalho fabuloso no site”, eles tinham o linguajar parecido com “Por que essa merda está dando pau?”. Ele acha pagou uma boa grana nisso. Você está feliz sendo pago o quanto que você ganha. De qualquer forma, não faz muito tempo que você está fazendo isso e você tinha que iniciar de algum lugar. As pessoas cometem erros, né?
Parabéns.
Agora você tem alguns relatórios de bugs para lidar quando você chegar no trabalho pela manhã. Oito horas por dia, sendo que cada bug leva uns 30 minutos para consertar. Fácil, com tempo de sobra. “Pfft. Faço até o fim do dia”, você pensa. Você percebe que um dos relatórios de bug que foi enviado foi um bug que você consertou outro dia. Outro desenvolvedor trabalhando no seu projeto teve um conflito com o arquivo e acidentalmente colocou o código quebrado ao invés do código que estava funcionando. Ok, tudo bem. Você conserta denovo. Talvez você não tenha escrito aquele comentário e você irá inseri-lo aogra. Beleza, isso irá fazer com que eles parem de introduzir o bug denovo.
Há uma reunião de duas horas com outro cliente no início do dia, deixando você com apenas 6 horas para consertar aqueles bugs até o fim do dia. Você gasta meia hora a mais no almoço. Cinco horas e meia. Mas até o almoço você “matou” quatro deles. Você estava um pouco grogue nesta manhã e você achou que aquele almoço iria curar aquele sentimento. Você irá conquistar os outros dez nesta tarde.
Você não conquista.
Você terminou quatro, talvez cinco deles e deixou oito, talvez nove bugs consertados. O cliente não está satisfeito. Você fez apenas parte do trabalho. TODOS os bugs eram críticos. Sua empresa é pequena e você é o único com conhecimento do projeto, e, os outros desenvolvedores estão ocupados em seus próprios projetos. O cliente espera… DEMANDA… respostas 7 dias por semana, 24 horas por dia.
Por que você é a puta dele.
Tudo bem. Então seu chefe o envia um grande email de desculpas dizendo que você irá trabalhar duro no futuro para atender todas as demandas porque você não quer perder este cliente. Ele investiu $30,000 nesta empresa e com a versão 2 do site “pronta pra ir ao forno” ele irá investir bem mais.
Então você volta a corrigir aqueles bugs que faltam. Durante a noite mais três chegaram. O número de bugs agora é oito. Oito horas no dia, oito bugs na lista. Feitos até o fim do dia. Você completa cinco durante seu expediente e dois quando chega em casa, depois do jantar. Você está exausto. Eles levaram o dia todo para serem debugados. Você envia um email para o cliente dizendo que você consertou sete dos oito bugs. Ele te envia um email de volta, vinte minutos depois de você ter ido dormir, naturalmente, dizendo que o último bug “deixa o site inutilizável”. Seu chefe vem até você pela manhã e diz que seu trabalho não é bom o bastante. Você não aprecia muito a sugestão dele. Você reclama e diz que consertou treze dos catorze bugs que o cliente enviou no início da semana. Você sente que foi colocado num ritmo de trabalho excepcionalmente duro essa semana. Hoje você completou o décimo quarto, você está muito confiante sobre isso. Ele naturalmente pergunta o porquê de ter catorze bugs. Você não tem uma resposta imediata, embora você pensa em mencionar os testes. Ele continua com seu discurso retórico sobre aquilo que você deveria estar testando o código toda vez que você o coloca em produção. O seu chefe continua com a encheção de saco por uma hora. Você tenta contra argumentar os argumentos dele mas sua visão parece algo de um “ser superior” e pela sua falta de experiência você não pode colocar a culpa nele. Ele é o chefe no fim das contas. Ele chegou aqui de alguma forma. Ele tem que estar certo sobre tudo?
Sua empresa pagou todos estes débitos técnicos que você não tinha orçamento para tal. Todo o processo extra custou um mês a mais e o cliente estourou seu orçamento em $2000. $2000 que ele nunca quis gastar. Ao invés de economizar $2000, ele agora gastou $2000 extra da sua própria conta pessoal para fazer com que o projeto andasse. Ele está falando de deixar sua empresa e ir para uma que pode fazer um trabalho melhor. Este é provavelmente o caso. Seu chefe te chama no canto e te diz como está o projeto. O cliente está saindo. No próximo dia ele demite você.
Parabéns, Freebird. Você está sem emprego e com muito, muito pouco dinheiro. Uns $2000 é tudo o que você ainda tem. Hora de ir à caça denovo.
Então como você pode prevenir que algo assim aconteça?
Você eventualmente pega um novo emprego com uma nova empresa. Você se senta com o cliente e faz as coisas direito. Você cria specs das histórias de usuário usando algo parecido com o Pivotal Tracker. Você é ensinado a escrever testes religiosamente para cada história usando o Cucumber. Não há história sem um teste. Isso reduz o débito técnico a longo prazo Você não tem tantos bugs como você tinha quando não testava com as aplicações anteriores. Embora você ainda tenha alguns bugs, você não irá gastar todas aquelas longas noites os consertando porque você tem testes cobrindo todos eles. Os testes irão mostrar onde alguma coisa deu errado, pois, geralmente, uma parte defeituosa do site significa um teste que não está passando. Viu um bug que não foi coberto por uma história ou teste? Isso acontece algumas vezes, mas você agora tem esse framework fantástico que te dá certeza que não o mesmo erro não irá acontecer denovo: teste de regressão. Escreva o teste. Ele não passa. Conserte o bug. Ele agora passa. Se você ou seu time segue a regra Green is Good, então eles NUNCA MAIS irão reintroduzir este bug. Em teoria. Pessoas cometem erros.
Então você inicia uma história simples como “Login de usuário” e você escreve uma funcionalidade para o cucumber para ela com dois cenários. Um para login e outra para logout. Você escreveu todos os passos para ela mas alguns deles não estão implementados, outros estão quebrados. Isso é devido ao fato que você ainda não escreveu nenhum código para a funcionalidade ainda. Parece meio retrógrado e improdutivo à princípio. Isso é chamado de Desenvolvimento Orientado à Comportamento (Behaviour Driven Development – BDD). Você está aprendendo BDD e você irá fazer certo de agora pra frente. Você está se tornando um Jedi de BDD. Você implementa cada passo por vez e eventualmente sua funcionalidade está toda verde.
Pra que você faz isso?
Para que no futuro, daqui uns três meses, você não veja essa funcionalidade dando pau e não precise trabalhar numa máquina do tempo para voltar e dar um pé na sua bunda.
Você ainda ganha alguns pontos extra se você estiver usando um servidor de Integração Contínua para garantir que esta funcionalidade e seus eventuais irmãos de testes fiquem verde. Um build falho significa uma aplicação falha e seu único objetivo se aquele build está quebrado é fazer com que ele seja consertado.
Parabéns.
Agora você pode marcar como a história como “terminada” no Pivotal. Então você pode implanta-la num staging server e marca-la como “entregue”. Daí o cliente pode logar no no Pivotal e ver que a história está marcada como “entregue” e logar no staging server, testar a feature e apertar aquele amado santo-graal botão “Aceitar”. Você quer ver histórias verdes na sua lista do Pivotal. Verde é a cor que você quer ver em todo canto.
Verde é bom.
Então a próxima funcionalidade vem aí e envolve uma lógica de controller um pouco mais complexa que retorna um hash JSON. Você pode escrever isso em Cucumber, o você pode escrever um teste para seu controller com o RSpec. Este é o tipo de coisa que é realmente legal para discussões com o time. Você sugere o Jeito A de fazer isso, e talvez outra pessoa do do time irá concordar ou sugerir o Jeito B, e essa adorável dinâmica de discussão de idéias produz um resultado melhor. De qualquer forma, você irá escrever o teste primeiro e então o código. Behaviour Driven Development. Então o teste passa. Então você pode refatorar o código se ele ainda não estiver bom o bastante e ele ainda irá passar. Com certeza você irá se sentir mais devagar no início, mas o motivo disso é que você ainda está aprendendo como fazer. Não lute contra isso. Este tipo de coisa irá te poupar muito tempo no futuro, onde é mais importante. Foque-se mais nos ganhos a longo prazo do que a curto prazo.
Eventualmente depois dos sete meses e meio você terá todas aquelas histórias do Pivotal Tracker em verde na seção de “Concluída” e talvez um ou dois no “Backlog” que o cliente quer pronto apenas para a próxima entrega. Você irá rodar todas as specs no seu sistema. Todas elas estão verdes. Você irá rodar todas as funcionalidades. Elas estarão todas verdes. Você irá implantar no server de staging pela última vez nesta release. O cliente adora isso. Você implanta no server de produção e envia os convites. Todo mundo adora isso.
Mas.
Há um bug. Entretanto, desta vez você instalou algo tipo o Hoptoad para o erro ir para sua caixa de entrada na mesma hora que ele ocorre. Você é o time de suporte para esta aplicação, NÃO o cliente. Depois de tudo, você ainda está trabalhando numa empresa pequena. O relatório de erros contem uma stacktrace e você pode ver onde deu errado imediatamente. Você escreve um teste/funcionalidade para garantir que este bug jamais aconteça denovo. O teste falha, pois você ainda não consertou o bug. O erro é o mesmo reportado no email do Hoptoad. Você conserta o bug.
Parabéns. Você escreveu um teste de regressão para o bug com sucesso. Este bug jamais irá ocorrer pelo resto da vida do projeto.
O cliente está feliz. Seu chefe pergunta se o cliente pode bater um papo com você. Você está fazendo um trabalho excelente. Os outros caras tinham um salário maior que o seu porque você foi contratado como um desenvolvedor Junior. Não mais. Você percorreu um caminho surpreendentemente grande. Agora você é igual. O cliente quer que mais coisas sejam feitas na aplicação. O cliente está querendo que seu chefe vá até o escritório dele na próxima semana. Ele requisitou especificamente que você vá junto também, pois você parece estar “ligado”. Você se encontra com o cliente e discute os termos da próxima iteração, uma bem grande. O acordo avança e sua empresa precisa crescer. Massivamente. A aplicação explode, no sentido positivo. Você tem problemas com escalabilidade. Você contrata outros dez caras no próximo ano só para trabalhar nesta aplicação. Você e uns dois do time original os ensina tudo sobre sua aplicação e o processo que vocês desenvolveram. Então eles irão ensinar outras vinte pessoas que você irá contratar nos próximos seis meses.
Parabéns. Agora você está fazendo certo.
UPDATE
Este post é uma tradução do excelente post do Ryan Bigg. Thank you Ryan!
Notem que eu não coloquei nenhum link no texto. Como é um texto mais “educativo”, eu espero que as pessoas que o lerem tenham a iniciativa de pesquisar os termos desconhecidos por conta própria. Links são muito cômodos e não incentivam a pesquisa ![]()
Streaming do Mare de Agilidade na Unimontes
Nos dias 20, 21 e 22 de maio de 2010, o Maré de Agilidade reúne em Belo Horizonte palestras, mini-cursos e workshops com a temática de metodologias ágeis. Participam do evento grandes nomes do segmento, sempre com o apoio de empresas e instituições de destaque no mercado de metodologias ágeis
Infelizmente, as vagas para o Maré de BH já estão esgotadas. Mas a boa notícia é que haverá o streaming do evento (da mesma forma que aconteceu com o Flex For Kids) na Unimontes!
Para participar é super simples: basta se inscrever no evento e apresentar o comprovante de pagamento no dia (sábado, 22 de Maio).
O streaming acontecerá na Unimontes, muito provavelmente no auditório do CCET (mesmo lugar do Flex For Kids. Poderá acontecer também na sala da Infobits, dependendo do número de participantes).
Viste a página oficial do evento e siga-os no Twitter para mais informações.
O que fazer quando seu codigo JavaScript se torna um monstro
Quando eu não conhecia jQuery e seus plugins, JavaScript era um tédio pra mim. É fato que uma biblioteca de alto nível (não só o jQuery, mas o mootools e o prototype, por exemplo) facilitam e deixam o desenvolvimento em JavaScript rápido e divertido, pois você não terá que se preocupar (muito) com detalhes de implementação de browsers.
Mas o que acontece quando, mesmo usando com alguma lib fodástica, seu código começa a ficar grande demais, complexo demais, fragmentado demais ou desorganizado demais? Isso é a minha definição de código monstro. Eis algumas dicas que podem te ajudar se você estiver passando por isso:
1 – Evite o Callback Hell
O jQuery mostra muitos exemplos usando funções anônimas como callback. De certo modo, isso é uma boa prática para situações simples, como o tratamento do evento clique de um botão:
alert('Fui clicado!');
});
Mas nem sempre isso é legal: muitas vezes você quer reaproveitar essa função para outros callbacks, como por exemplo:
$('#meuInput').blur(getClientes);
getClientes = function()
{
$.get('/clientes/get','',
function(data){
//trata os dados recebidos aqui
},'json')
}
Nesse caso, eu estou aproveitando minha função de callback getClientes para dois event listeners. Isso é bem legal, mas quando nosso código começa a crescer, nos esbarramos em outro problema: as funções globais.
2 – Evite funções globais
Isso quer dizer, ao invés disso:
$('#meuInput').blur(getClientes);
getClientes = function()
{
$.get('/clientes/get','',
function(data){
//trata os dados recebidos aqui
},'json');
};
Faça algo assim:
$('#meuInput').blur(Clientes.getClientes);
var Clientes = {
getClientes:function()
{
$.get('/clientes/get','',
function(data){
//trata os dados recebidos aqui
},'json');
}
};
Isto é, coloque suas funções dentro de objetos. Assim você evita funções globais e evita fazer código “estruturado”, passando a usar os recursos da orientação à objetos do JavaScript e deixando o mínimo de globals possível. Essa é a forma mais fácil que eu conheço de se evitar funções globais e organizar melhor seu código, mas há outras formas como o Module Pattern.
3 – O “this” aponta para diferentes lugares em diferentes contextos. Saiba como lidar com isso.
Você não está deixando mais todas as suas funções como globais, está encapsulando tudo dentro de objetos, reaproveitando código e feliz da vida quando percebe que o this não é mais this. Calma que eu explico.
Você já deve ter visto algo assim no jQuery:
$(this).html('fui clicado') ;
});
Isso faz com que, quando um link é clicado, o mesmo fique com o texto “fui clicado”. Deu pra notar que nesse caso, o this aponta para o elemento que disparou o evento. Mas olhe o seguinte exemplo:
{
texto:'Fui clicado',
init:function()
{
//this aponta para o objeto Cliente
$('a').click(this.aClickHandler);
},
aClickHandler:function()
{
//this aponta para o elemento "a" que disparou o evento
$(this).html(Cliente.texto);
}
};
Viu como “this” pode mudar de contexto? No exemplo acima, o problema de não ter o this apontando para o objeto Cliente foi facilmente contornado, mas você poderá precisar acessar o objeto pai de uma forma parecida com a this. Nesse caso, você pode passar um parâmetro para o evento usando o método bind() do jQuery, informando o contexto que ele foi chamado:
{
texto:'Fui clicado',
init:function()
{
//this aponta para o objeto Cliente
$('a').bind('click',{'self':this},this.aClickHandler);
},
aClickHandler:function(event)
{
var self = event.data.self;
//o self aponta para Cliente e o this aponta para
//o elemento "a" que disparou o evento
$(this).html(self.texto);
}
};
4 – Procure pelos patterns corretos.
Quem disse que padrões de projeto criam um vocabulário em comum na equipe não poderia ter dito algo mais pertinente: o uso de padrões faz com que o desenvolvedor foque nas funcionalidades da aplicação sem se preocupar com alguns detalhes de implementação.
O AjaxPatterns contém uma coleção bem legal e bem documentadas de patterns para Ajax e JavaScript em geral. Mas não espere ter problemas pra consultar os patterns: quanto mais se conhece sobre padrões, mais fácil é pensar em soluções de problemas e planejamento em geral.
5 – Deixe apenas um $(document).ready em todo o seu código
Eu diria isso para todos os event listeners que você possa vir a colocar, mas o $(document).ready é o mais crítico na minha opinião. No JavaScript não há sobreposição de eventos: se você colocar dos event listeners para um mesmo evento, os dois serão executados. Isso pode dar problemas, pois você pode deixar o $(docuement).ready em dois arquivos diferentes e você pode desejar que um evento execute antes de outro.
6 – Valide seu JavaScript
Browsers interpretam JavaScript de forma diferente, então é sempre bom ter uma padronização de código para que não tenhamos problemas com sintaxe em diferentes browsers. Uma ferramenta de validação bem legal é o jslint.
– EDIT–
Nem sei onde tava com a cabeça quando esqueci isso:
7 – Escreva testes!
Testes pode ser tido como documentação executável e facilita muito quando você pega um código de outro desenvolvedor que já tenha testes: é fácil de ver os modos de uso do código e você se sentirá seguro ao fazer algo e ver que os testes passam. Além do mais, você não precisa encher seu código de comentário pra explicar como ele funciona (comentar é bom, mas sem exageros);
Entretanto, testar JavaScript pode não ser tão fácil assim. É necessário mais disciplina e paciência do que é necessário para testar seu código backend, mas é algo que se adquire com o tempo.
See ya!
Testes unitarios no Flex usando o FlexUnit 4
O FlexUnit 4 é a mais nova versão (não tem a oficial, só a RC, por enquanto) e apresenta uma série de vantagens sobre o seu antecessor, o FlexUnit 0.9, como os metadados de teste ([Test], [After] e [Before], para citar as mais populares), Theories, DataPoints e Assumptions que são úteis para testar grandes quantidades (talvez até infinita) de dados e ver como a aplicação se comporta e a possibilidade de executar os testes com diferentes Runners.
Este tutorial tem como objetivo mostrar o básico de testes unitários no Flex, sem se aprofundar muito nos recursos avançados do framework de testes. Eu pretendo ir postando mais tutoriais à medida que eu for me aprofundando na tecnologia.
O setup
Para usar o FlexUnit4, você precisa baixa-lo aqui. Após isso, crie um projeto no Flex Builder e adicione todas as libs que vieram no pacote no seu diretório libs:

Como o bom e velho TDD manda, vamos primeiro escrever a classe de teste de exemplo antes de escrever nosso código de produção.
A classe de teste
Uma classe de testes é uma classe comum que usa a classe Assert para fazer asserções. No exemplo que irei mostrar, usarei dois tipos básicos de asserção, mas se você observar, o FlexUnit possui vários tipos diferentes de asserções:
package tests
{
import org.flexunit.Assert;
import org.flexunit.runner.manipulation.filters.IncludeAllFilter;
import production.BasicClass;
public class BasicTests
{
public function BasicTests(){}
private var basicClass:BasicClass;
[Before]
public function before():void
{
basicClass = new BasicClass();
}
[Test]
public function Verifica_Se_As_Duas_Strings_Sao_Iguais():void
{
var str:String = "MinhaString";
Assert.assertTrue(basicClass.areStringsEqual(str,"MinhaString"));
}
[Test]
public function Verifica_Se_A_Soma_Retorna_Resultado_Correto():void
{
var soma:int = 10;
Assert.assertEquals(soma,basicClass.somar(2,8));
}
[After]
public function after():void
{
//codigo de after
}
}
}A suíte de teste
A suíte de testes inclui nosso caso de teste descrito acima e será útil para o Flex executar nossos testes. Sendo assim, nossa suíte de testes ficaria mais ou menos desse jeito:
package tests
{
[Suite]
[RunWith("org.flexunit.runners.Suite")]
public class MyTestSuite
{
public var baseTest:BasicTests;
public function MyTestSuite(){}
}
}UITestRunner e o FlexUnitCore
O UITestRunner é um componente do FlexUnit que mostra os testes numa interface gráfica. Ele ficará na nossa aplicação e mostrará os resultados dos testes.
O FlexUnitCore será o responsável por carregar as suítes de teste e por passar os dados de saída de testes para o UITestRunner. No nosso caso, nossa aplicação principal ficaria assim:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="run()" layout="absolute" xmlns:flexUnitUIRunner="http://www.adobe.com/2009/flexUnitUIRunner">
<mx:Script>
<![CDATA[
import tests.MyTestSuite;
import org.flexunit.listeners.UIListener;
import org.flexunit.runner.FlexUnitCore;
public var core:FlexUnitCore;
public function run():void
{
core = new FlexUnitCore();
core.addListener(new UIListener(uiRunner));
core.run(MyTestSuite);
}
]]>
</mx:Script>
<flexUnitUIRunner:TestRunnerBase id="uiRunner" width="100%" height="100%"/>
</mx:Application>O código de produção
Ufa! Depois de escrever a classe de teste, a suíte de teste e o runner, podemos nos focar em fazer nosso código de produção
. Dêem uma olhada em como ficaria o dito:
package production
{
public class BasicClass
{
public function BasicClass(){}
public function areStringsEqual(string1:String,string2:String):Boolean
{
return (string1==string2);
}
public function somar(valor1:int,valor2:int):int
{
return valor1+valor2;
}
}
}E Voilà!
Depois de tudo pronto, a cara da criança ficaria mais ou menos assim:
Legal, não? E ainda dá pra fazer com que o FlexUnit4 exporte o resultado dos testes para um arquivo XML, permitindo que seus testes no Flex sejam importados pelo seu sistema de Integração Contínua, mas isso é assunto para outro post ![]()
Você pode baixar o código fonte aqui e ver os exemplos rodando online aqui.
Good testing!



