Fork me on GitHub

Viagens, opiniões e afins

by Andre Fonseca


Estudos Compartilhados IV – Arquitetura Emergente

No artigo anterior a este, da série Estudos Compartilhados,  eu falei um pouco do TDD e a minha compreensão sobre ele. Com isso acabei falando que a arquitetura deve emergir  de acordo com a necessidade é que o TDD era a ferramenta que ajudava nesse processo. Muitas pessoas que leram o texto me pediram para explicar melhor essa questão de arquitetura surgir ao invés de ser definida antes através de análises.

Um dos grandes problemas que encontro em nosso mundo de TI é que, na maioria dos casos, baseamos nossos processos em processo de engenharia. Queremos trabalhar com software da mesma forma que construímos casas; queremos definir as coisas da mesma foram que fazemos para máquinas; e assim por diante. A questão é que, na minha opnião, desenvolver sistemas é algo que é único e tem uma vertente mais artística do que técnica.

Definir fazendo

A natureza abstrata de um código facilita para que  a gente possa experimentas as possíveis soluções fazendo. É como pintarmos um quadro (todo mundo usa esse exemplo, eu sei) : podemos experimentando as cores, posições dos elementos, os elementos, etc no curso da pintura … Se achamos que algo não ficou legal, apagamos e recomeçamos, mudamos, e vamos seguindo. Também como uma obra de arte, não existe um estado perfeito de um sistema – ele sempre poderá ser melhorado; existe um estado que a gente abandona e parte para a próxima.

Sendo assim, querer prever, antever, definir, projetar, arquiteturas, elementos, antes de começar a fazer é uma tarefa muito difícil e que atrapalha muito mais do que ajuda. As necessidades mudam. No decorrer do projeto podemos achar uma solução mais simples, uma interação diferente, novos recursos, e por aí a lista cresce.

Nisso se encaixa o conceito de arquitetura emergente.

Arquitetura emergente

Claro que a gente, principalmente quando falamos em Orientação a Objeto, a gente parte do nada. Quem participou de Dojos até que pode ter experimentado isso – literalmente fazer do zero.  A gente parte de uma premissa razoável. Por exemplo, num sistema para uma escola, a gente tem a idéia que provavelmente teremos uma classe Aluno, classe Professor, classe Disciplina, etc.  Mas saber exatamente como cada um vai interagir, se teremos outras classes além dessas, se vamos ter 20 camadas ou não.

Admiro por demais as pessoas que são capazes em uma reunião com o cliente sair dela com todo o sistema pronto na cabeça com uma arquitetura perfeita. Eu não consigo. Posso ter uma idéia frente a alguns requisitos iniciais de tecnologias, possível carga, etc.

As coisas vão tomando forma mesmo é na construção da funcionalidade. Ali, você vai sentindo as necessidades e conforme as atende a solução surge e com isso temos a arquitetura “ideal” para o caso.

Refactoring

Não dá para falar em TDD, Arquitetura emergente sem falar sobre a questão do Refactoring.  Entendo refatoring como o processo de melhoria onde depois de pronto (testes passando) a gente altera a solução afim de otimizá-la em relação a legibilidade, perfomance, manutenção, e coisas similares.

Fazer refactoring é como fazer a faxina no código para tirar as poeiras, coisas a mais que foram colocadas durante o momento onde o foco era resolver e não fazer o código mais lindo ou melhor do mundo. É o momento de renomear as coisas, separar,  juntar, etc. A arquitetura emergente se alimenta do refactoring. Pois no primeiro momento, como já disse antes, quero resolver o problema.  Se para isso tiver que fazer 3 ou 4 ifs no código; se para isso tiver que escrever uma variável com uma nome bizarro, etc , eu faço. Pois depois de resolvido, de forma disciplinada, eu volto para o código escrito e tento melhorá-lo.

Dois livros que tem me ajudado muito nessa questão é já tão falado por mim, Clean Code, e Refactoring do Martin Fowler.  O primeiro me dá a direção para qual quero caminhar com meu código: legibilidade, fácil manutenção,  fácil extensão, praticamente todos os princípios do SOLID. Já o segundo livro me ajuda no como fazer, no como dectetar os pontos onde devo atuar, etc.

Quem quer fazer um sistema descente e com o mínimo de qualidade, na minha opinião, precisa saber bem OO, TDD, buscar uma arquitetura emergente e fazer Refactorings constantes.

Bem por hoje é só pessoal . No próximo pretendo falar um pouco sobre design patterns e como eu os uso para facilitar minha vida.

 

Published by Andre, on dezembro 29th, 2010 at 7:07 pm. Filled under: agil,codigo Tags: , , , , No Comments

TIM mega fail

A poucos dias atrás ( no dia 10 de dezembro) estive na loja da TIM no Barra Shopping (mais precisamente no New York City Center). Chegando lá conversei com o atendente sobre o fato de querer adquirir um Iphone e me refidelizar a empresa para aproveitar os descontos oferecidos.

Minha primeira decepção veio com o fato de que não poderia fazer isso na loja e sim, somente, pelo telefone. Liguei para o tal *144 e após 5 tentativas consegui fazer a operação e fui informado que o prazo seria de, NO MÁXIMO, 7 dias úteis.

Terminado o prazo, entrei em contato com eles novamente pelo *144, com o protocolo 2010218457158,  e o atendente disse que na verdade o prazo era de 15 a 20 dias úteis para o Rio de Janeiro.

Como assim? Mudou a regra? Devem ter vendido mais do que o estoque e agora mudam a regra sem avisos e ponto final.

Bem vindo a república das bananas, onde empresas como a TIM fazem o quer e nada acontece?

O pior dessa história é constatar que não existe uma outra opção válida. Se for para a CLARO terá problemas, se for para a VIVO teremos problemas… Cadê os chupa sangue da ANATEL para resolver isso ? Devem estar de férias pagas com meu dinheiro.

DEsculpem pelo desabafo mas sinceramente acho que temos que contar mais histórias como essa para ver se isso acaba!

ATUALIZAÇÃO:

Liguei para o 155 da Anatel e registrei um chamado. Eles me deram o prazo de 5 dias uteis para que a TIM entre em contato. Sinceramente, acredito que eles estão nem ai para os clientes.  Vi que tem bastante gente reclamando deles.

O serviço de celular não é ruim. O maior problema dela é o SAC. Porque com cliente não posso entrar numa loja e comprar o aparelho?

Sinceramente se não tiver resposta até amanhã cancelo a operação e mudo para outra operadora.

 

ATUALIZAÇÃO 23/12/2010

A Tim mandou um torpedo dizendo que registrou minha reclamação e  que devo aguardar o contato deles. Isso foi na terça-feira dia 21/12. Até agora ninguém entrou em contato comigo. Eles estão pedindo muito um processo.

 

Published by Andre, on dezembro 20th, 2010 at 1:47 pm. Filled under: atualidades1 Comment

Estudos Compartilhados – parte III

No artigo passado da série “Estudo compartilhados”, abordei mais a questão da Orientação a Objeto e como ainda não nos entendemos bem com ela.  No finalzinho do artigo, rapidamente, falei sobre os testes automatizados no famoso TDD.

TDD virou um buzzword. Traduzindo: Uma palavrinha da moda.  Hoje as empresa já colocam nos seus anuncios de vagas que o candidato que conhece TDD é um diferencial, outras até exigem. A questão é: Você sabe realmente o que é TDD?

TDD é a sigla em inglês para TEST DRIVEN DESIGN ou design dirigido por testes.

Mais uma vez para me ajudar com essa questão, pedi a ajuda para meu amigo Alexandre Martins, e ele me recomendou ( meio óbvio), o livro do Kent Beck , criador do TDD,  TEST-DRIVEN DEVELOPMENT . Além desse, Nunes também me recomendou alguns artigos e outros livros como o Growing Object-Oriented Software, Guide by Test, que mostram o caminho das pedras e como o teste pode ser o melhor amigo do desenvolvedor.

Numa conversa com outra pessoa, Rafael Martins (Cabra) da Globo.com,  concluímos que muita gente acaba por ter uma visão torta do que vem ser testar antes. Testar antes parte da premissa, na minha concepção, de que é preciso um problema para procurarmos a solução. Seria mais ou menos assim:  Você tem que comer quando sentir fome, pois do contrário, você está sendo guloso e indo além de suas capacidades.

Quando você cria os seus teste antes, baseado em suas necessidades, está de certa forma, criando um problema a ser resolvido. Se for disciplinado e apenas resolver aquele problema e repetir esse ciclo até que todos os requisitos sejam atendidos, a solução literalmente emerge. Isso mesmo: EMERGE.

Muitas das pessoas que me ouviram falar disso, respondem dizendo que é mentira ou exagero da minha parte que a solução EMERGE. Convido, os descrentes, a assistir e participar de uma sessão de dojo.

No livro Agile Software Development, também do UncleBob,  existe um capítulo em que ele descreve o desenvolvimento de um sistema para pontuação de boliche em que faz um par (pair programming) com outra pessoa e segue  conceitos como TDD e baby steps. É simplesmente revelador. Sei que exagerado mas é isso mesmo: REVELADOR ; pois ele simplesmente vai fazendo o sistema “sem pensar”. Dando pequenos passos, e sempre mantendo um dialogo e trocas constante com seu amigo, o design vai surgindo diante deles e se mostrando diferente do que se imaginava de inicio.

TDD evita desperdício

Um outro livro que recomendo muito é o Pragmatic Programmer. Nesse livro ele procura mostrar que o pragmatismo é uma boa filosofia para nós que fazemos software. Dentro disso, uma das coisas é a questão de evitar o desperdício.

Evitar desperdício é algo muito amplo e engloba diversas atitudes que devemos ter como: automatizar tarefas repetitivas,  tornar simples fazer o certo,  não fazer mais do que é preciso, etc.

Muitos se perguntam o que fazer para ser um programador ou ter um time altamente eficiente. Eu acredito que a solução vem de evitar desperdício e fazer o “justo necessário”. Isso também é conhecido como evitar o OverDesign. Sabe aquela aplicação simples para enviar arquivo para um servidor que o pessoal quer fazer com um monte de camada, abstrações, etc, justificando que isso facilitará uma possível modificação futura…Isso é um excelente exemplo de gasto desnecessário.

Quando fazemos TDD e nos disciplinamos a fazer o teste passar (isso mesmo) a gente fica focado; ao ficar focado evitamos desvios e perdas de tempos fazendo coisas para necessidades que não existem ainda.

ATENÇÃO: ISSO NÃO SIGNIFICA QUE VOCÊ DEVE FAZER ARQUITETURA PORCA. SEU CÓDIGO DEVE SER LIMPO.

Testar depois é apenas automatizar. TDD é mais uma ferramenta de design.

Até a próxima pessoal.

 

Published by Andre, on dezembro 17th, 2010 at 7:20 pm. Filled under: atualidades,engenharia de softwares,Informática,python,ruby Tags: , , , No Comments

Dividindo algumas experiências

Nestes últimos dias em meu trabalho estamos desenvolvendo uma aplicação para receber vídeos e fotos. Essa aplicação, na nossa intenção, tem como objetivo servir de plataforma para qualquer produto que queira receber mídia. Por isso, várias escolhas de implementação, infra, etc foram feitas nesse sentido e algumas gostaria de compartilhar com vocês e também alguns desafios que encontramos.

Antes de mais nada deixa eu explicar o porque fazer um produto para upload de foto e vídeo.  Quanto ao vídeo, todo eles devem ser processados para que fiquem disponíveis. Esse processamento é algo lento e custoso. Assim, não queríamos que ao fazer um envio de vídeos nosso usuário ficasse um tempão esperando o processamento da mídia para ter o seu cadastramento feito. Logo, decidimos que esse processo deve ser feito de forma assíncrona, ou seja, ao receber o arquivo colocamos ele numa fila para ser processado e o feedback para o usuário é quase que imediato.

Esse parte do processamento assíncrono foi desenvolvido por outras pessoas que já estavam na equipe antes de mim. São elas Emerson Macedo, Rodrigo Lopes e Elton Okada.

Quanto as fotos embora elas não sejam processadas após seu upload, queremos poder manipulá-las. Assim, por exemplo, dado uma foto, quero poder, pela url, informar alguns parametros que façam com que receba o arquivo na dimensão desejada, rotacionada, cropada e etc.

Outros aspecto é que queremos que nosso sistema seja holístico, ou seja, seja simples de usar e fácil de integrar em qualquer tecnologia/linguagem. A escolha óbvia para isso foi implementar nosso produto com uma interface REST.

Dado o conhecimento do time em Ruby, Sinatra e Ruby on Rails, decidimos que nossa aplicação deve ser escrita em Ruby. Por ser simples do ponto de vista web, optamos por fazê-la em Sinatra.  O Rails seria um tiro de canhão e nos oferece mais recursos do que precisamos. A escolha pelo Sinatra também se deu pois a versão anterior também foi feita nele e funcionava muito bem.

Escolhido o Sinatra, passamos a escolher qual gem nos ajudaria na missão de tratar o upload dos arquivos. Antes já existia algo desenvolvido que fazia somente o tratamento de vídeos, também em Sinatra e eles usavam o CarrieWave.

O CarrieWave é muito bom e bem simples de implementar, o problema dele, para nós, era a questão dos arquivos temporários que ficavam. Isso acabava enchendo o disco e nos dava uma boa dor de cabeça. Para resolver isso, o pessoal fez um monkey patch que após salvar o arquivo no store definitivo apagava o arquivo temporário.

Alexandre Nunes, pesquisando, encontrou uma nova gem que tem sido recomendada. É o dragonfly.  Ela tem um conceito interessante de aplicação que deixa seu uso mais simples. Além disso, aparentemente, resolvia do problema dos arquivos temporários.

Os problemas

Bom vamos para a parte chata e triste da história.

A primeira decepção foi que ao contrário do que pensávamos o problema de arquivos temporários continuava.  Não era um problema exclusivo da gem CarrieWave. A origem do mal está em outra parte.

Bom, tendo esse mega desafio em mãos, partimos para resolvê-lo.  Conversei com várias pessoas que dominam o Ruby mais do que eu.  Ainda não tenho um causa clara para isso mas várias hipóteses.

Sabemos que, nosso sistema usa a classe tempfile do ruby mesmo. (tempfile.rb, veja documentação). Com isso, a gestão do ciclo de vida dela é feita pelo Garbage Colector do Ruby.  Isso significa que, quem apaga o arquivo tmp é o Ruby (o interpretador ativo) e não o sistema operacional.

Assim, lembrando de minha época como programador java, e conversando com o Rafael Martins (mais conhecido com o Cabra da Globo.com) vimos que possívelmente algo ainda fazia referencia aos arquivos e com isso o GC não conseguia apagar os arquivos.

Lendo a documentação do Ruby, vi que existe diferenças entre a forma de fechar o arquivo. Uma delas, close!, o interpretador além de fechar o stream ele executa um unlink: ele zera todas as referencias àquele arquivo e com isso o GC pode apagá-lo depois.

Outra coisa que o Rafael Martins me explicou é que, no caso do REE (ruby enterprise edition) ele guarde a referencia dos objetos numa tabela. Provavelmente é isso que pode estar dando o problema dos arquivos temporário não serem apagados.

Bem é isso que temos até o momento. Prometo que assim que avançarmos mais um pouco coloco mais novidades

Published by Andre, on dezembro 14th, 2010 at 9:53 am. Filled under: atualidades3 Comments