Andre Fonseca

artigos, pensamentos e opiniões

about me

Com 15 anos de experiência, tendo trabalhado em diversas empresas sempre lidando com produtos para milhões de acessos, com muito conhecimento de questões de desempenho. Participou de times de desenvolvimento do G1, Portal Rede Globo, Sistema de Comentários, Backend do Appsclub, Sistema de Cobertura de eventos em Tempo Real.

Seu Sistema Irá Falhar

Existe uma coisa que todos nós devemos nos acostumar e começar a aceitar: o nosso sistema irá falhar. Não importa o quanto se preocupe com a arquitetura, o design, coloque testes, monte toda a infra, faça teste de carga (quantidade de acesso, vazão, etc) … nada disso fará com que seu sistema não falha. Para ser sincero seu sistema não falhará desde que ele não tenha usuários, não use mais nenhum sistema externo a ele, ou seja, a não ser que ele simplesmente não exista.

Os sistemas atuais estão cada mais complexos e dependentes de outros sistemas. Hoje é quase impossível fazer qualquer sistema que não acesse uma api externa, use um serviço externo( banco de dados, filas, indexadores, etc), entre outras coisas. Com isso, as variáveis que estão fora de nosso controle, é cada vez maior. Junta a isso o fato que existem casos que não vamos conseguir prever logo nas primeiras releases.

Algo irá falhar! E essa falha irá se espalhar e poderá ser catastrófica, tirar o seu sistema do ar, deixar milhares de usuários sem acesso, fazer alguma operação errada, ou algo semelhante a isso. A questão é aqui é aceitar que poderá haver uma falha e que a melhor forma de lidar com isso e se preparar para quando isso ocorrer.

Quando falo se preparar, é pensar na melhor forma que o sistema vai se comportar em caso de alguma falhar. Por exemplo, o que acontece com o seu sistema caso o banco de dados ficar fora; o que acontece com seu sistema se uma api externa ficar indisponível ou com uma grande lentidão…

Não estou aqui advogando para que sejam todos a partir de agora pessimistas. A questão e sermos mais defensivos. E criarmos mecanismos dentro dos nossos sitemas que eles possam se recuperar rapidamente – algo do tipo, ao reiniciar tudo volta, caches para evitar que o tempo de resposta de uma api externa não atrapalhe o desempenho de seu sistema. Fora isso, no lado mais de operação, criar alarmes, monitoração, logs para que sua equipe fique sabendo de um problema antes de seus usuários e possam agir o quanto antes. Adicione isso, rotinas de backups, políticas de restauração, e logo terá algo que seja realmente estável e capaz de sobreviver no ambiente de produção.

Empresas como o Netflix, Linkedin, Twitter, Facebook, tem áreas inteiras que se preocupam em criar sistemas que sejam tolerantes a falha. Para comprovar isso basta ver a quantidade de projetos open source que essas empresa liberaram e notará um grande número de libs com patterns de integração, sistemas que testam a capacidade do sistema em caso de problemas, etc.

A mensagem final que quero deixar é que sistema irão falhar, banco de dados sairão do ar, apis ficarão lentas, apis ficarão fora, enfim, problemas vão ocorrer. E se estiver consciente que isso irá acontecer, poderá aproveitar o desenvolvimento para colocar boas práticas de integração, formas de se recuperar automáticamente, etc.

written in curso,, estabilidade,, falhas, perfomance,, sistemas,

Seu Sistema Em Produção

Se tudo correr bem, seu sistema irá passar mais tempo em produção do que em desenvolvimento.

Tenho certeza que a maioria das pessoas ao lerem a frase acima dirão: “Isso é óbvio!”. Então, sabendo disso, porque investimos tão pouco nessa fase de nossos sistemas?

A um tempo atrás participei de um projeto de uma nova versão de um sistema. Foram uns 4 meses de levantamento de requisitos, entrevistas com usuários e funcionários da empresa. Após entregar toda a documentação (foi a muito tempo atrás e RUP, waterfall, PMI, estavam na moda), foram quase mais um ano de projeto para desenvolver. No final de tudo, foi feita uma “festa”para colocar esse sistema no “ar”. Era o fim. Acabou! Pelo menos, foi esse sentimento de todos.

Hoje, vejo que na verdade era só o começo. Esse sistema está em produção até hoje (isso já tem quase 10 anos). Ele sozinho precisa de pelo menos um time de 4 desenvolvedores cuidando de evoluir e corrigir os bugs.

Essa história serve para mostrar que devemos nos preocupar com o sistema em tempo de desenvolvimento entretanto lembrar que a maior parte da vida dele será em uso em produção. Por isso, acredito que devemos levar isso em consideração e procurar as melhores arquiteturas, bibliotecas, estratégias, e outras coisas que nos facilitem o diagnóstico, recuperação em caso de falha, etc.

Sendo assim, acredito que podemos melhorar isso, trazendo esse assunto para discutirmos e estudarmos mais. Para isso preciso de sua ajuda. Responda comentando o post com as duas top questões sobre o assunto para me ajudar a formar um material para apresentar depois.

E não se esqueça de se inscrever na lista onde divulgo artigos exclusivos, vídeos, datas de curso, rascunhos do livro que estou escrevendo, etc.

* indicates required

written in curso,, desempenho, estabilidade,, perfomance,

Desempenho E Robustez

Muitos de nós consideramos que o assunto de desempenho e resiliência seja algo que está distante de nossa realidade e de nossos produtos (serviços, apis, e outros similares). Pensamos que a coisa mais importante é que o sistema esteja no ar, com as funcionalidades prontas e funcionais – aderentes aos requisitos e as necessidade de negócio.

Eu concordo plenamente, embora, veja que a perfomance (desempenho) e a robustez sejam também aspectos importantes que vão influenciar no seu sucesso ou insucesso.

Acredito que se seu sistema (api de um app mobile por exemplo), estiver indisponível, ninguém vai entender que é algo que pode acontecer, que o principal do produto está ali (quando está tudo no ar, funciona perfeito) ou terá paciência de esperar e todo o seu trabalho poderá ter sido em vão. Junte a isso a ansiedade – famoso mal da era – e verá que ninguém irá ficar 1, 2, 5, 10 segundos esperando que sua página carregue.

Se não acredita em mim, faça a experiência com algum parente e tire as suas próprias conclusões.

Uma vez que tenha te convencido que isso é importante, vejo que faltam profissionais com experiência para lidar com esse tipo de problema. Poucos são aqueles que já tiveram até então que lidar com altos tráfegos, muitos requests, muito processamento, etc.

Nos últimos 15 anos de trabalho tenho tido a oportunidade de justamente lidar em “meu dia a dia” com desafios como esses: volume de acesso, tolerância falha, velocidade de resposta. Isso porque trabalhei em empresa líderes em seus setores que lidavam com números de acessos, requisições, etc na casa das dezenas de milhões por dia.

Sendo assim, várias pessoas me procuram pedindo ajuda e consultoria. Nessas consultorias e ajudas, fui percebendo que faltam conceitos e técnicas que se esses pessoas soubesse não precisariam de minha ajuda para resolver seus problemas.

Diante a isso, resolvi montar um curso para preencher essa lacuna: Falar e ensinar sobre resiliência e desempenho.

O curso será de um dia inteiro (carga de 10hs com parada de coffee break) , com muita prática (muitos exercícios, muita experimentação juntos).Nosso objetivo é terminar o curso e fazer um sistema que aguente mais de mil requests por segundo.

A ementa será:

  • Porque se preocupar com robustez, desempenho e resiliência
  • Entendo um pouco mais sobre desempenho e seus buzz words
  • C10K
  • Robustez: entregando sistemas que duram e sobrevivem sem os desenvolvedores. Ou como gosto de falar, como fazer para não ser chamado de madrugada
  • Testes de Carga
  • Patterns de integração
  • Realizando e entendendo profiles
  • Desmitificando questões de banco de dados (NoSql X SQl, Colum Tables, etc)
  • Técnicas de Desempenho e escalabillidade (Deixar por conta só da Amazon não dá e é caro)
  • Caches e Filas.
  • Desempenho de escrita e leitura
  • pré geração
  • etc.

Se tiver interesse, inscreva-se na nossa lista abaixo.

* indicates required

written in curso,, desempenho, perfomance,

Pesquisa Sobre Os Eventos De TI

Na empresa onde trabalho, Globo.com, todo início de ano temos que “escolher” para quais eventos gostaríamos de ir. Esses eventos podem ser no Brasil ou fora, sendo que devem falar sobre assuntos que tenham correlação com seu trabalho ou objetivo de seu time ou área. Diante disso, o que geralmente fazemos, é montar uma planilha com diversos eventos que vamos encontrado. Isso feito, escolhemos a partir dessa lista quais eventos desejamos ir seguindo algumas regras.

Nesse ano, conforme fomos levantando os eventos, acabou surgindo uma discussão quanto a qualidade dos eventos. Ao analisarmos as grades(temas, palestrantes, etc), eu e um grupo ficamos com a sensação ruim de estar vendo mais do mesmo, conteúdos rasos, repetição de tutoriais, e outras coisas similares. Cheguei, inclusive, a postar essa impressão no meu facebook, onde tive um retorno similar de amigos de fora da Globo.com.

Diante disso, após mais um pouco de conversa, resolvi fazer uma pesquisa para ver o quanto essa percepção em relação a qualidade dos eventos era só minha, ou, de fato, há uma certo sentimento geral.

A Pesquisa

Para fazer a pesquisa, optei por um formulário simples no GoogleDocs, onde fiz algumas perguntas como: Você se interessaria por eventos mais técnicos? Quais assuntos desejaria ver? Deixe seu comentário…

A intenção clara era de captar o nível de insastifação com relação as temas, formas, organização e nível dos conteúdos abordados. Outro ponto, é que o direcionamento também foi para pessoas com mais experiência. Publicado o form, fiz um tweet e pedi ajuda a amigos para espalharem o formulário para alcançarmos o máximo de pessoas o possível.

O Resultado

Até o momento em que escrevo esse artigo, tinhamos por volta de 170 respostas. Embora não seja um número muito grande do ponto de vista estatistico – que nos permitiria ver alguma tendência, o grande ponto vou ver o quanto o sentimento de insastifação é compartilhado.

Isso ficou bem claro, nos comentários deixados pelo pessoal no final do formulário: esse de fato foi o campo mais revelador de toda a pesquisa.

Comentários como, “Muita panelinha …”; “Sempre os mesmos assuntos…”; “Coisas que poderia aprender com tutoriais”, surgiram em quantidade expressivas, revelando que precisamos repensar a forma que fazemos evento e montamos nossas grades.

Para exemplificar, na montagem do evento do Front in Rio 2013, nós da organização discutimos muito para saber qual seria a melhor forma de escolher as palestras. Acabamos por fim abrindo um pouco a grade e escolhendo pessoas que trouxeram assuntos (e não currículos) interessantes para a comunidade.

Conclusão

Frente aos dados que levantei, as opiniões e as discussões em cima de todo esse material que tive, a conclusão que chego é que existe espaço e demanda para eventos mais técnicos e de conteúdo mais aprofundado, porém, esses não pode ser no mesmo formato dos atuais, nem invalidam a importância dos mesmos.

Vamos por parte:

  • Como disse um amigo, eventos grandes, ou para grande massas, eles tem que ser mais abrangentes, mais rasos e contar com pessoas conhecidas e famosas para atrair gente, pois esse é seu real objetivo: atrair pessoas para o meio. Famoso, chamar atenção.
  • Eventos mais técnicos não podem ser grandes pois isso inviabilizaria a discussão e troca… Não existe como conversar com 500 pessoas. Limites de 100 a 150 pessoas(ou até menos) parece-me ser a melhor opção.
  • As pessoas quando buscam por mais conteúdo querem que isso seja lhe entregue de uma forma bem mais flexível e pessoal. Sendo assim, se quisermos eventos com mais qualidade técnica, esse modelo de palco, microfone, slide com monte de imagem e palestrante em sala separada, não funciona. Ainda dentro desse item, rápidas exposições, mais conversas, e ambiente bem descontraído parece ser a melhor escolha

Por fim, é que existem pessoas que querem coisas do genero e arrisco dizer que pagariam por isso. Logo, por que não fazer?

written

Quando Fazer Refactoring

TL; DR; Sempre que falo sobre refactoring, sempre ouço a pergunta de quando fazer e como alocar tempo para realizá-lo.

Para mim não existe um quando e nem quantidade de tempo para refactoring: sempre é momento de fazê-lo. Se simplesmente o refactoring não for considerado, mesmo que tenha a melhor estrutura e arquitetura, seu sistema irá ficar obsoleto e se tornará um grande legado. Fazer refactoring é um dos pilares para mantermos a qualidade da base de código.

REFACTORING

Martin Fowler em seu livro Refactoring, define como sendo a prática de melhorar o código em busca de maior clareza, melhor estrutura para extensão, maior comunicação, etc … sem alterar o comportamento.

Refactoring é a técnica para manter o seu código atual, sem duplcidades (DRY), seguindo boas práticas e princípios como o SOLID).

Uma boa analogia é de sempre buscarmos a melhor forma de resolver o mesmo problema, tendo em vista a clareza, a boa comunicação, facilidade de extensão. Note aqui que não falei de perfomance.

PORQUE REFACTORING

Kent Back, possui uma citação interessante que explica bem o porque:

Programs have two kinds of value: what they can do for you today and what they can do for you tomorrow. Most times when we are programming, we are focused on what we want the program to do today. Whether we are fixing a bug or adding a feature, we are making today’s program more valuable by making it more capable. You can’t program long without realizing that what the system does today is only a part of the story. If you can get today’s work done today, but you do it in such a way that you can’t possibly get tomorrow’s work done tomorrow, then you lose. Notice, though, that you know what you need to do today, but you’re not quite sure about tomorrow. Maybe you’ll do this, maybe that, maybe something you haven’t imagined yet. I know enough to do today’s work. I don’t know enough to do tomorrow’s. But if I only work for today, I won’t be able to work tomorrow at all. Refactoring is one way out of the bind. When you find that yesterday’s decision doesn’t make sense today, you change the decision. Now you can do today’s work. Tomorrow, some of your understanding as of today will seem naive, so you’ll change that, too. What is it that makes programs hard to work with? Four things I can think of as I am typing this are as follows:

1. Programs that are hard to read are hard to modify.

2. Programs that have duplicated logic are hard to modify.

3. Programs that require additional behavior that requires you to change running code are hard to modify.

4. Programs with complex conditional logic are hard to modify.

So, we want programs that are easy to read, that have all logic specified in one and only one place, that do not allow changes to endanger existing behavior, and that allow conditional logic to be expressed as simply as possible. Refactoring is the process of taking a running program and adding to its value, not by changing its behavior but by giving it more of these qualities that enable us to continue developing at speed.

Transcrevendo, seria dizer que todos os sistemas possuem 2 valores: o que pode ser feito hoje e que pode ser feito amanhã. Na maioria dos casos, sempre pensamos no presente. Porém, sistemas evoluem e novas funcionalidades, correções de bugs, vão ocorrendo e o código sendo alterado. Nesses ciclos, acabamos duplicando código, adicionando responsabilidades a métodos, alterando as lógicas, etc. Com isso o código vai ficando confuso e complexo.

A técnica de Refactoring, é justamente olhar para esse sistema e buscar sempre um jeito melhor te atender os requisitos. Jeito esse que leva em conta coisas como comunicação, clareza, facilidade de extensão, e coisas simmilares.

Por isso, se quisermos manter um sistema com uma boa qualidade e simples de ser entendido e extendido, é muito importante sempre realizarmos refactorings.

REFACTORING, TESTES AUTOMATIZADOS e TDD

Não é meu objetivo entrar muito a fundo no assunto, entretanto, é importante dizer que é muito díficil fazer Refactoring em sistemas sem testes automatizados. Não é impossível. Mas extremamente difícil. Isso porque, ao final de um ciclo, você terá que testar se nenhum comportamento esperado foi alterado.

Por isso, de forma a simplificar, não fazemos refactoring sem testes. Caso o seu sistema não tenha testes, primeiro, faça o teste. Depois faça o Refactoring. Nisso podemos encaixar o TDD. O próprio trabalho de escrever os testes te ajudará a decidir o que mudar, a melhor forma, etc.

written

Reinstalando O Vim Na Sua Máquina Com Suporte a Python E Ruby

Esse é um post para ajudar a me lembrar de uma procedimento e quem sabe ajudar alguém com o mesmo problema.

Eu uso como editor padrão o VIM (algumas vezes o MACVim). Além disso uso muito Python e Ruby como linguagens para desenvolver meus projetos. Para facilitar esse meu dia a dia, uso alguns plugins que me ajudam como por exemplo o python-mode e o jedi. O python-mode ajuda com as validações de pep8, pyflakes, etc. Já o jedi ajuda nos imports do python. Para ruby eu tenho o sintaxe highlight mesmo.

Tudo isso funciona perfeitamente no meu MACVim, porém no vim não estava funcionando. Ambos tinham sido instalados via homebrew. Buscando pelo Google, achei que a solução era compilar o vim manualmente. Isso realmente resolveu meu problema, e segue abaixo os passos que fiz. Primeiro certifique-se tem instalado o mercury no seu computador (hg).

hg clone https://vim.googlecode.com/hg/ vim_source cd vim_source ./configure —disable-nls —enable-multibyte —with-tlib=ncurses —enable-pythoninterp —enable-rubyinterp —with-features=huge make -j 3 && sudo make install

Com isso o sistema irá reinstalar todo o vim com os suportes e links corretos.

Espero que ajuda alguém.

written in python,, ruby, vim,

Code Review

TL; DR;

Embora toda experiência, conhecimento de processos e boas práticas, ninguém está imune a cometer erros, escrever código com BUG e/ou ruim. Todo ser humano é imperfeito e está fadado a cometer erros mesmo que sendo um gênio e tendo um profundo conhecimento. BUGS e códigos mal escritos não são somente fruto de desconhecimento e despreparo mas também, de condições e contextos no qual o desenvolvedor está inserido. Sendo assim, a questão não está em não cometer o erro (bugs, código mal escrito, etc) e sim procurar formas de detectá-lo o mas breve possível evitando assim que esse tenha um ciclo de vida longo.

O problema do código feio

“Escrever código para máquina é fácil.”

Nem sempre os problemas de um sistema estão em BUGs ou aderência aos requisitos. Muitas vezes, para não dizer a maioria, os maiores problema estão em códigos mal escritos, difícies de manter, duplicados, sem padrão, etc. Isso se agrava quando falamos em projetos onde temos mais de uma pessoa envolvida e com mudanças na equipes (entrada de pessoas novas por exemplo). Logo, é preciso buscar formas para que esse tipo de coisas não aconteça.

Escrever código também é uma forma de comunicação e é necessário dar a essa prática a mesma atenção de um texto. Embora, códigos sejam instruções para computadores realizar, é preciso pensar em quem irá ler esse código e ter em mente que essa pessoa tem que ser capaz de entender corretamente a mensagem e propósito da arquitetura e forma deste sitema. Outros além dos autores iniciais, muito provávelmente, irão dar manutenção, e com isso precisarão entender bem como as peças se encaixam para resolver o domínio.

Falhar em escrever um código legível, compreensível, com padrões perceptivos, é escrever código legado e fadado a morte.

Código bem feito leva a todos futuros autores a seguir um padrão e a entender sem grandes esforços como as relações se desenrolam. No oposto, código mal escrito, o efeito é inverso: têm-se um empilhamento de funcionalidades, duplicações, diversos padrões, formas, código obscuro, etc.

Estudos e estudiosos do assunto

Tendo como ponto de partida o fato de que código é uma forma de comunicação semelhante as demais e que é preciso buscar a excelência nisso, muitos estudiosos do assunto buscam formas, processos, ferramentas, para evitar que se produza código ruins (mal escritos). Linguagens como Python, Java, etc criam convensões de boas práticas, code styles (estilo de escrita de software). IDE’s criam validadores de sintaxe. Estudiosos de processo, procuram por práticas para ajudar o desenvolver a não escrever ou achar os defeitos o mais breve possível.

Existe um artigo interessante no site de developer da IBM que lista as 11 praticas provadas que realmente ajudam na revisão de código Leia o artigo.

A revisão de código é uma das práticas, juntamente com o Pair Programming (programação em pares) que vêem de encontro a resolver o problema de código ruim. A programação em par é a prática onde duas pessoas trabalham juntas na concepção e escrita da funcionalidade. Ela resolve em parte o problema pois são dois pares de olhos vendo. Porém, ainda é possível escrever coisas que não sejam “legíveis” a futuros programadores daquele sistema.

A revisão de código tem sido mais eficiente nesse sentido. Revisar um código não consiste apenas em outras pessoas lerem o código escrito antes de alguma determinada etapa. Consiste no uso de ferramentas e analisadores também. Inclusive uma boa prática é se algo pode ser analisado pelo computador é melhor que ele que faça e não outro, como por exemplo, complexidade ciclomática, code styles, duplicação, etc.

Como resolver, como fazer para implementar essa prática

Uma vez que se tenha optador pela revisão de código, o primeiro passo consiste em simplesmente fazer. Começar da forma que o time desejar. Os ajustes, como toda boa prática, vem com tempo, e na medida da maturidade e domínio do processo, vai se mudando e adaptando.

. Como já foi abordado acima, devem buscar ferramentas para analisar a base de código nos mais diversos aspectos. Linguagens como python tem analisadores de pep8(conjunto de boas práticas de escrita de código), analisadores estáticos (analisam variaveis, duplicidade, e outra coisas); já Java tem IDE’s que vem com suite grande de ferramentas nesse mesmo sentido. Já em Ruby e Javascript tais coisas são trabalhos em andamento.que vem com suite grande de ferramentas nesse mesmo sentido. Já em Ruby e Javascript tais coisas são trabalhos em andamento.

. todos tem seu código revisto. Não é só responsabilidade os engenheiros senior revisar. É de todos.

. Uma boa forma é que o código só seja enviado para o repositório (git, svn, etc) se foi revisado. Por isso, o desenvolvedor antes de comitar ou dar push chama outra pessoa e faz.

. Projetos com times grandes podem trabalhar, caso seja usem coisas semelhantes a git, usar patches. Assim, cada um tem seu “repositorio” e na hora de integrar criam e enviam um patch. Esse patch irá ser revisto por algum outro membro.

. Evite fazer com muito código. O ideal, segundo o artigo citado, é não passar de 200 a 400 linhas de código. Isso reforçar o conceito de fazer pequenos passos e ir enviando para o repositorio.

. Evite o efeito Big Brother… Faça reviews abertos e de forma clara. Deixe tudo muito aberto e simples.

. Torne a prática uma cultura do time e não mais um processo a seguir. A revisão de código deve ser desejada por todos e seguida. Pedida.

Concluindo

Independente da forma e de como irá realizar, é importante entender que código deve ser legível. Código deve ser compreensível a outros humanos também, não somente a máquina. Isso irá aumentar a vida do sistema, facilitar novos colaboradores (para os casos de open source), etc.

Code Review é uma boa forma de garantir isso.

Leia mais

Effective Code Review – Alex Gaynor

What Makes Peer Code Review an Agile Process? – Lyndsey Clevessy

Running an Effective Code Review – Esther Schindler

written in boas, de, engenharia, práticas, software,

Criando Widgets Javascript

TL;DR;

Nos projetos atuais nos quais trabalho, muitas vezes acabamos fazendo o que chamados de Widget. Esses widget são feitos para serem “inseridos” e usados outros portais e produtos. Na maioria dos casos, esses widgets são como apps escritas em javascript para consumir uma api e montar um dado dentro da página onde ele foi inserido.

O Leonardo Balter numa palestra que ele deu no Front in Rio 2012, abordou bem o assunto sobre como podemos escrever frontend apps sem inteferir no contexto da página onde está posta. Por isso pretendo apenas extender o conceito.

Contextualizando

Vamos lá, a grande maioria das pessoas, atualmente, que dizem conhecer e saber programar, apps front, faz uso de alguma biblioteca. Sem grandes pesquisas, creio que a maioria delas deva usar algo como JQuery, Mootools, BackBoneJs, AngularJS, ou similares.

Tais libs são “uma mão na roda” e realmente facilitam a codificar, testar, etc.

A pergunta que faço é: Precisamos de todos os recursos disponíveis nesses frameworks/bibliotecas? Acredito que na maioria dos casos, se escrevessemos somente em Javascript puro, usando HTML e CSS, e não mais do que isso, conseguiríamos entregar o desejado.

Entendendo o “Problema”

Ao analisar mais detalhadamente a situação, conversando com alguns colegas especialistas em front end e com outros nem tão especialista assim. Uma das coisas que notei é que muito deles não conhecia de fato Javascript: Sabiam detalhes de cada elemento HTML, funções e motivos de cada linha de CSS; entretando desconheciam recursos básicos da linguagem Javascript, como por exemplo, fazer um laço de for (muito usavam a, por exemplo, a função each do jquery).

Com isso, é possível concluir uma exagerada dependência de bibliotecas, para fazer coisas que são perfeitamente possíveis de serem feitas sem elas, usando apenas JS puro. O resultado disso, são widgets com megas de tamanho, sendo que a lógica deles mesmo são meros kilobytes, o restante são as bibliotecas que eles carregam junto (Jquery tem minificado 93kb, veja o site). Isso pode parecer um detalhe banal num mundo onde casas tem links de Mb… Porém uma nova variável se apresentou no horizonte que é o mundo do mobile.

Outro ponto interessante foi uma pesquisa recente (não consegui achar o link) onde afirma que, sites que são lentos para carregar tem menor taxa de conversão. Isso mesmo, tempo é dinheiro, literalmente. Se o seu site leva mais de 5 segundos para mostrar algo, já se foram quase 50% das pessoas aí (CHUTE!!!!).

Voltando para o mobile, ter sites grandes e pesados de carregar significa mais gasto de 3g e bateria. Maximiliano Firtman, fez numa edição do BrazilJS, uma ótima apresentação sobre o assunto, onde mostar números, dados mais concretos que meus chutes. E as pessoas tem pouca paciência – menos ainda no mobile, pode cre – para esperar seu site gigante carregar todas as libs e processá-las.

Mais aí você pode dizer, que usa a técnica de deixar o carregamento no final de página. Desculpa meu amigo, mas o seu site ainda é pesado de carregar, vai consumir bando e bateria no mobile e pode gerar alguma perda na entrega de conteúdo.

Ok. Dito isso, voltemos paras os widgets.

Se você está criando uma widget e esse tem dependências de centenas de kb de libs (template lib, dom lib, ajax lib, etc) você se encaixa na mesma análise. E pior. Você está fazendo isso com qualquer um que use seu código – as vezes sem saber da âncora que você é no site deles.

Outro aspecto de widget gordos (vou chamá-los assim para facilitar), é que eles também podem gerar conflitos com outras coisa na páginas dos outros: imagine a questão das versões como podem gerar um verdadeiro inferno.

Os conflitos

Para seguir adiante com a discussão é importante que fique claro que menos é mais: ou seja, quão menor for sua app/widget, melhor. Não se iluda, isso dá trabalho. Abrir mão de libs, significa você cuidar de vários detalhes antes abstraídos, porém, posso garantir que o resultado compensa.

Gosto sempre de usar exemplos. Acredito que eles sejam a melhor forma de mostrar um ponto de vista. No meu trabalho fizemos um widget. Esse widget vai em quase todos os produtos e portais e portanto é bem usado. Esse widget, no momento que foi feito, fizeram a escolha de implementá-lo usando libs. Pois bem.

Até aí foi uma escolha simples e até bem intencionada. Com o uso de libs e seus recursos muita complexidade seria resolvida e os desenvolvedores ganhariam tempo para lidar com os desafios do produto e não dos navegadores, etc.

O problema é que com isso, prendemos nossa solução a uma lib e sua versão. Obrigamos os produtos que queriam usar esse widget e ter essa versão, essa lib.

Os mais experientes já devem estar imaginando o cenário que isso nos levou… Hoje temos diversos produtos usando a implementação e reclamando do tamanho, do fato de termos uma versão muito antiga, conflito com implementações.

Nesse caso em específico, além do uso de libs, houve um sério problema de engenharia de software. Poderíamos ter componentizado melhor, separado melhor e essa mudança para versão mais nova seria mais simples. Entretanto, nos amarramos demais a biblioteca e agora teremos que reescrever tudo.

Para coroar nossa análise, se tivessemos usado simples JS puro – isso daria trabalho mais é totalmente possível – agora teríamos um produto bem mais fácil de evoluir e não atrapalharíamos a vida de nossos clientes/usuários.

No mesmo tempo que essa app foi feita, uma outra app foi feita por outro time. Também é usada por todos os portais. A diferença é que eles optaram por fazer com VanillaJS. Deu muito trabalho, problemas de cross-browser para resolver, ajax, etc. Mas no final eles conseguiram e tem sido um benchmark para nós todos. Eles provaram que a entrega foi bem melhor e com usuários felizes.

A conclusão

Vamos lá a formula de bolo para ajudar a:

  1. Tentar sempre usar somente javascript. Mais nada
  2. Lembre de isolar bem o seu contexto de váriaveis.
  3. Sempre que possível use de namespaces/
  4. Se não der para usar só js, procure por um micro framework para resolver o seu problema de forma bem específica. Embede o código dessa lib na sua.
  5. Menos código, menos bugs.
  6. Seja cuidadoso e sempre se coloque no lugar da pessoar que irá usar.

“Escreva como se a pessoa que fosse usar seja um psicopata e sabe onde mora”

written in app,, engenharia, javascript,

VOCÊ NÃO É O TWITTER

TL;DR

Surgiram atualmente diversos artigos onde grandes e famosos produtos (e players da internet) explicam como o time de engenharia mudou a tecnologia/ linguagens e conseguiu maravilhas em redução de máquina e aumento de carga em seus sistemas.

A grande maioria dos que li, usavam Ruby on Rails e passaram a usar Java (inclua aqui Scala, Groovy, Clojure) ou Go ou até Python em seu lugar, e com isso, reduziram drásticamente o custo de infra (energia, máquinas, resfriamente, etc) e/ou aumentaram sua capacidade carga (quantidade de requisições, conexões, etc). Enfim, foram além da simples troca de arquitetura.

Entretanto, antes que todos comecem a demonizar Ruby e/ou as ditas linguagens modernas é preciso analisar o contexto desses artigos e entender que nem de longe somos um Twitter para nos preocuparmos com esse tipo de coisa agora.

Um pouco sobre mim e porque posso falar sobre o assunto

Tenho em torno de 12 anos de profissão. Hoje, sou desenvolvedor senior da Globo.com, atuando no time de jornalismo – responsável por sites como G1, Ego, Cobertura de Eventos, etc.

A Globo.com é uma empresa onde se desenvolve os maiores portais de jornalismos, esportes e entretenimento do Brasil . Fora isso, temos plataformas de vídeos, imagens, música, em milhares de outras coisa.

Uma das coisas legais de se trabalhar lá é o fato de sempre procurarmos a melhor ferramenta para o trabalho. E com isso, sempre estamos experimentando as tecnologias, linguagens, plataformas, e tudo mais que nos permite sermos mais produtivos e eficientes.

Atualmente a grande maioria dos produtos que desenvolvemos são feitos usando Python e Ruby (e seus frameworks como Tornado, Django, Ruby on Rails, Sinatra, etc).

Nossos produtos tem acessos bem grandes: Portais com milhões de vísitas únicas por dia; streaming de vídeos na faixa de gigabytes por dia, terabytes de arquivos (imagens, html, css, javascripts) e por aí vai.

Diferenciando um pouco …

Diante do relato acima muitos poderiam pensar que Globo.com, deva ter as mesmas preocupações que um Facebook, Twitter ou SoundCloud.

Posso adiantar que, sobre determinados aspectos, sim: Nenhum de nossas aplicações e novas funcionalidades vão para “produção” (para uso do nossos usúarios) sem que antes façamos bons testes de carga, testes de segurança, entre outras coisas relacionadas. Ainda na fase de desenvolvimento, temos a preocupação de fazermos coisa que deverão aguentar milhões de acessos, milhares de conexões simultaneas, picos, etc, sem jamais deixar de atender uma requisição.

Porém se compararmos nosso volume de acesso e nosso tipo de produto, não somos parecidos com o pessoal do Twitter, Google, SoundCloud, entre outros.

Nossos produtos são em sua maioria estáticos: Um vez que são produzidos, nos geramos uma cópia estática e a servimos para os clientes. O Twitter, por exemplo, tem um natureza muito mais dinâmica: o conteúdo é servido por usuário (com toda certeza deve existir um cache no meio do caminho) a cada requisição.

Entendendo o problema e o contexto

Quando pensamos em Google, SoundCloud, logo pensamos em um datacenter gigantesco com milhares de máquinas. Tudo isso para atender a grande demanda de processamento que é gerada pelas milhões de requisições que os usuários fazem. São buscas, buscas por músicas, cadastros de novos usuários, posts, documentos, edição, envio de novo conteúdo, etc.

Para esse tipo de acesso, um pouco que se possa ganhar em desempenho, seja por uma escolha de arquitetura, seja pela troca de linguagem é algo muito significativo.

Lembre-se que estamos falando de parques com milhares máquinas.

Isso porque se conseguirmos, num cenários desses, reduzir em 10% a quantidade de máquinas e processamento, imaginem o quanto de dinheiro que isso representa na conta no final do mês. Muito né.

Por isso que empresas e aplicativos desse porte, precisam, constantemente, buscar por meios de reduzir processamento e atender mais requisições. Por que empresas como essas correm atrás de tecnologias, arquitetura, linguagens, etc que possam ajudá-las nessa missão, nem que sejam em 1%.

Onde eu entro nisso tudo? Porque eu não sou o twitter?

A grande maioria das pessoas, hoje em dia, está desenvolvendo sistemas que mal atenderão um milhar de pessoas. Existe uma infinidade de pessoas estão trabalhar em projetos de aplicações internas a empresas, os ditos corporativos.

Pouquíssimos são aqueles que estão desenvolvendo algo para uma quantidade superior a centenas de milhares. Nem vou falar naqueles que estão desenvolvendo para milhões.

Enfim, a grande maioria, está criando produtos para no máximo milhares de acessos.

Alguns podem dizer: eu tenho a minha startup e estou desenvolvendo um produto . E quero muito que ele atinja milhões de usuários como um Facebook. Entretando, novamente, a grande maioria em seu lançamento contará com centenas de acesso e terá um crescimento bem linear e vegetativo.

Mesmo que ocorra um boom no acesso, isso é bem pouco provável, não é preciso pensar nisso quando nem o produto existe ainda.

O que quero dizer é que antes que comecemos a fazer a guerra de dizer que agora todos nós devemos largar o Ruby on Rails, ou Django, ou PHP, etc e partir para desenvolver em Assembly, precisamos entender que isso ainda não é o nosso problema.

Nosso problema é ainda entregar valor para o cliente o mais rápido possível. Para grande maioria de nossas aplicações o custo de infra é infimo – quase desprezível – frente ao custo de desenvolvimento. Por isso usar de tecnologias de nos dê produtividade ainda é a melhor escolha.

Fazendo referência ao título do POST, não somos o Twitter, e por isso não devemos ainda nos perder nessas dicussões.

Um grande porém …

Porém, mesmo que a gente não esteja na equipe de desenvolvimento da engine de busca do Google, precisamos estar antenados com que acontece a nosso redor. É legal saber que mudanças de arquitetura e tecnologia podem ter um impacto em nosso produtos.

Mais importante é saber das opções existente e a experiência de missão crítica desses grandes players e quem sabe, quando precisarmos, seguir por um caminho menos obscuro.

Hoje na Globo.com já estamos discutindo usar outras coisa além de Python e Ruby. Não descatarmos por completo JVM e estamos já criando coisas com Go.

Esse era o recado que gostaria de deixar para vocês.

written in engenharia,, infra,, jvm, ruby,

Sistemas Com Responsabilidades únicas

Introdução

Muitos desenvolvedores já estão familiarizados com diversos princípios de engenharia de software, como por exemplo alguns enunciados pelo livro Clean Code . Tais princípios ficaram eternizados com a sigla SOLID, que é acronimo e significa:

Single Responsability Principle ( Principio de Responsabilidade Única);

Open Close Principle ( Principio do aberto para extensão e fechado para modificação);

Liskov Substitution Principle (A classe filha pode ser substituida pela classe pai);

Interface Segregation Principle (expor interfaces não objetos);

Dependency Inversion Principle ( Dependencias baseadas na abstração e não nas implementações concretas )

Para saber um pouco mais, siga clicando aqui*

Aplicando essa definições em nossos código, a idéia é ter um código mais limpo: código legível; fácil de compreender por outros desenvolvedores; simples de evoluir; simples de manutenciar; etc. A questão é que, mesmo usando toda essa engenharia, todos nossos sistemas atuais tendem a crescer e ganhar complexidade.

Todos os sistemas nascem simples: com responsabilidades únicas e bem definidas. Assim após a nossa primeira release, nosso sistemas evolui, ganhando novas funcionalidades, acertos, melhorias , ajustes para melhorar perfomance, refactorings, etc. Com o passar do tempo, nosso pequena e bem escrito aplicativo, torna-se um megazord de complexidade, duplicidade de código, e outras coisas que nenhum de nós gosta. Enfim, ele se torna um grande legado que ninguém quer mais mexer.

Tenho certeza que todos tem algum projeto que trabalhou que serve de exemplo para a situação descrita acima. Lembra daquele sistema que tinha, lá no início, algumas centenas de linha de código apenas e já de milhares (até milhões); ou/e daquele projeto super bem arquitetado e hoje é uma bagunça sem fim que até mesmo que trabalhou desde início se perde para entender como as chamadas trafegam para completar uma requisição.

Mesmo que esse ditos projetos estejam usando testes automatizados e tenha sidos feitos seguindo princípios como TDD. Mesmo que eles sofram refactorings constantes, o fato é que eles crescem e vão adquirindo novas responsabilidades antes não previstas. Com isso, vamos torcendo aquele modelo original e amontando código.

Diante disso, o que vejo e vivencio é que a medida que essas bases de código crescem, fica impossível de manter principios de reutilização, DRY, padrões de nomes, code style, e diversas outras coisas importantes. Enfm, acabamos um imenso legado que é caro demais de evoluir, muito caro de reescrever e muito importante para nosso cliente que não abra mão dele e tem novas necessidades a serem atendidas.

Nosso dilema atual

Como disse, os sistemas crescem. E com eles suas bases de código.

Poderíamos dizer que este problema já é conhecido e muito bem abordado pelo Michael Feathers em seu livro sobre código legado: podemos sim isolar e aplicar todas as técnicas sugeridas, mas bases de código grandes, são bases de código grandes e ponto final. Pdemos melhorar os métodos, encapsular melhor algumas, etc … a questão que ainda temos um modelo que não foi feito para aqueles novos casos, ainda temos situações novas que não estavam previstas e poucas possibilidades de interface do nosso sistema.

Se não existessem os problemas financeiros ou quaisquer outras constraints tenho certeza que a maioria dos desenvolvedores, diriam que está na hora de reescrever todo o sistema. Todos nós adoramos projetos Green Field (projetos que estão começando do zero).

Em novos projetos, temos as oportunidade de desenhar bem a nossa arquitetura, aplicar novos conceitos e utilizar novas tecnologias.

A questão é que fazer isso com sistemas de milhares de linhas de código é uma tarefa árdua e que custa bastante caro – nenhum gerente, cliente, PO… vai querer pagar por isso – até porque você não estará entregando nenhum valor novo (estará sim se pensarmos em infra, mais request, e outras coisas parecidas, mas poucos clientes percebem isso logo de cara)

Motivos para reescrever sistemas

  1. Tecnologias caducam, envelhecem:

Muitas tecnologias se tornam ao longo do tempo obsoletas e ultrapassadas. Sempre temos uma nova versão da linguagem, um novo servidor, um banco de dados mais moderno ou que utilize um outro paradigma que resolve melhor o seu problema… enfim a tecnologia evolui e traz novas soluções – e melhores – para os nosso problemas.

  1. Nós aprendemos:

Com o passar do tempo e com a experiência vemos que, nem sempre o caminho que adotamos foi o melhor. Também vemos que existem jeitos melhores de implementar determinada lógica.

Existe o fato também, que evoluímos como profissionais: com isso vemos que aquele sistema que fizemos a um tempo atrás, poderia ter sido feito de um jeito diferente. Infelizmente mudanças desse tipo não dá para fazer de forma gradual. Geralmente, eles são mudanças radicais e temos que fazer tudo de uma vez só.

  1. todo sistema tem prazo de validade:

Um outro bom motivo para reescrevermos nosso sistema é ligado ao negócio. Muitas vezes vemos que a forma de nosso negócio mudou e que o sistema atual com sua base de código infinita não nos atende mais. Mesmo que façamos diversos apendices, o sistema não é mais capaz de nos atender com proficiencia. Se tornam aqueles sistemas cheios de jeitinhos para fazer coisas. O usuário tem que fazer um cursinho para saber todos os “pulos do gato” para ele conseguir concretizar uma operação. Sistemas ERPs são os melhores exemplos disso. Você acaba torcendo o seu problema para caber dentro daquele sistema que é impossível de mudar ou reescrever.

Vamos ao que interessa

Fica um bom tempo falando sobre a questão de engenharia de software e do problema de sistemas com muitas linhas de código. Falei também dos motivos que podemo nos levar a querer reescrever um sitemas. Mas para que?

Escrevi sobre tudo isso para mostrar que precisamos dar o passo seguinte no desenvolvimentos de software. Precisamos pensar em sistemas como peças únicas de um conjunto para resolver problemas. Sendo assim, essas unidade deve ser responsavel por resolver um e somente um aspecto do problema e não todo ele. A solução se dá pela soma das partes que agindo em conjunto atendem ao nosso domínio.

Precisamos aplicar os conceitos de SRP (veja acima) na concepção de nosso sistemas. Ao invés de fazermos uma peça única e monolítica que aborde todo o nosso dominio, fazmemos pequenas partes que cuidam de cada aspecto.

Ganhamos com isso sistemas pequenos, e simples de manter. Num caso que li recentemente, cada peça ficou com poucas centenas de linhas. Isso facilita manter pois bases pequenas são mais simples. Bases pequenas são mais fácil de entender e manter seu padrões; bases pequenas são mais fácil de jogar fora e fazer de novo. No mesmo case que citei acima, eles reescrevem uma parte em uma semana e foi imperceptível para o cliente.

Outro aspecto é que se fizermos com pequenas partes e essas partes existirem independentes uma das outras, podemos ir além. Imagine que eu quebre o sistema em diversos serviços que se falem via REST: eu posso literalmente escrever cada serviço numa linguagem diferente que não vai causar nenhum problema. Com isso posso escolher a melhor tecnologia/linguagem para o meu problema. Além disso, mantendo as interfaces, eu posso refazer todo a parte interna sem afetar as outras peças do conjunto.

Isso é simplesmente o céu de todo desenvolvedor.

Em meu trabalho atual estamos caminhando para algo parecido. Ou seja, uma forma mais orientada a serviços, onde cada sistema tem uma responsabilidade e essa é simples. Manter essa coisa simples e com pouca coisa para resolver é a grande chave do sucesso.

Se olhar arquitetura de grandes portais, produtos web (como [Twitter][4], basecamp, SoundCloud, etc) verá um monte de pequenos sistemas conversando para atender a demanda do usuário.

Se uma parte se tornar o gargalo, podemos melhorar só aquela parte: colocando mais servidores, reescrevendo, etc.

Isso é aplicavel a qualquer contexto.

A alguns anos atrás trabalhei numa empresa que tinha diversos sistemas que eram integrados através de troca de mensagens (queue e brokers). Claro que nem chega perto do que estou propondo mais foi uma semente e vi que dava muito certo.

Cenas do próximos capítulos …

Mais a frente – estou terminando de organizar tudo – pretendo publicar um novo post explicando melhor como implementar essa questão de sistemas pequenos e com pouco responsabilidade.

Só para deixar curioso, existem formas de fazer sem necessáriamente escrever um monte de sistemas; como existem formas de fazer de forma bem desacoplada. Enfim fiquem ligados.

written in engenharia., software