Quantcast
Channel: AkitaOnRails.com
Viewing all 481 articles
Browse latest View live

[Off-Topic] Lean está Morto, longa vida à Eficiência

$
0
0

Atualização (29/03/14): Publiquei um post em Outubro de 2013 que colocar argumentos muito mais detalhados sobre este tema. Leia "Matemática, Trolls, Haters e Discussões de Internet".

O ano foi 2001. Um grupo de programadores sêniores se reuniu numa estação de esqui em Snowbird, Utah. Estavam ali os principais nomes da programação dos Estados Unidos. Kent Beck, Alistair Cockburn, Ward Cunningham, Martin Fowler, Jim Highsmith, Ron Jeffries, Brian Marick, Bob Martin, Ken Schwaber, Jeff Sutherland, Andy Hunt, Dave Thomas, Mike Beedle, Arie van Bennekun, James Greening, Jon Kern, Steve Mellor. É uma lista de "quem é quem" da programação.

Desse encontro histórico surgiu um manifesto de 4 valores e 12 princípios. Ele ficou conhecido como o "Manifesto Ágil".

Treze anos depois, Dave Thomas, o senhor "Pragmatic Programmer" - que inclusive foi um dos mais diretamente envolvidos na redação propriamente dita do texto do manifesto -, publicou um artigo de desabafo chamado "Agile is Dead, Long Live Agility".

Karl Popper

A intenção dos agilistas originais foi causar uma quebra na forma antiquada de se pensar e executar a engenharia de software - o mesmo tipo obsoleto que ainda é ensinado hoje na maioria da Universidades do país. Isso causou um enorme furor na indústria. Criaram-se derivações, treinamentos, ferramentas, certificações, conferências, consultorias. Um enorme portfolio de opções para qualquer tamanho a qualquer preço. E no meio de todo esse circo esqueceu- se o que é de fato ser um agilista.

E como bem resumiu Dave Thomas em seu desabafo, você não "faz" Ágil ou "compra" Ágil. Agilidade é uma qualidade, um adjetivo. Para ser ágil temos que voltar aos princípios, citando:

  • Descubra onde você está.
  • Ande um pequeno passo em direção ao seu objetivo.
  • Ajuste seu entendimento baseado no que aprendeu.
  • Repita

Como fazer isso:

"Quando se deparar com duas ou mais alternativas que entregam mais ou menos o mesmo valor, escolha o caminho que facilite modificações futuras."

E é apenas isso, 4 linhas e 1 prática.

Treze anos depois que algo simples foi publicado pela primeira vez parece que o mundo se tornou extremamente complicado. Scrum, Kanban, Scrumban, Lean Programming, Lean Six Sigma, Agile PMI. E num momento onde o caos reina, quem "parece" conseguir explicar o caos se torna um guru. E assim surgem as associações, certificações, treinamentos, conferências. Funciona assim para dietas, funciona assim para terapias, funcionou assim para engenharia de software. E é isso que Dave Thomas lamenta. Mas é um resultado inevitável. As pessoas são fáceis de se enganar, elas sempre procuram alguém ou alguma coisa para seguir e raramente questionam - foram dogmatizadas a nunca questionar a autoridade e torcer para times de futebol sem nenhum critério.

Em 2010 eu estive numa conferência em Baltimore, onde tive a oportunidade de conversar com Bob Martin, que organizou o encontro em Snowbird. Foi no seu escritório da Object Mentor que se deu o primeiro treinamento de certificação Scrum do Ken Schwaber. Eu já era imune ao "Agile Hype". Mas eu queria dizer ao Bob Martin o que achava disso. Para quem não sabe o treinamento "oficial" de Scrum Master é um curso de 2 dias e no final você é certificado. Não precisa nem comparecer, basta pagar pelo curso. Eu lhe disse, cinicamente, que provavelmente a ideia do Ken saiu pela culatra. "Provavelmente o Ken pensou 'puxa, como convencer essas grandes corporações a adotar práticas ágeis?' e aí ele pensou 'claro, empresas grandes gostam de certificações', e então criou um Cavalo de Tróia, um curso-piada de 2 dias onde pessoas sérias saberiam que não dá para aprender nada sério em 2 dias mas aí ele poderia inserir a ideia nas empresas. Porém todo mundo levou isso a sério, e é aí que o tiro saiu pela culatra." Pule diretamente para o minuto 6:24 do vídeo abaixo se quiser ouvir essa história.

Aprendendo a Aprender

Agora vamos sair um pouco de software e entrar no mundo de "startups". Esse mundo tem seu próprio "Agile" no que se chamou de "Lean Startup". Eric Ries, tornou o termo famoso em 2009, em seu livro de mesmo nome, e é derivado direto dos princípios de Lean da Toyota. Não é uma idéia nova, só uma nova embalagem. Esse Lean tem origem nas mesmas ideia de W. Edwards Deming sobre PDCA - "Plan, Do, Check, Act" - "Planejar, Fazer, Checar, Agir". Você vai notar a semelhança com os 4 princípios de Dave Thomas que citei acima.

Não importam nomes pomposos, celebridades, gurus, ferramentas caras, cargos de destaque. Os princípios básicos de Agile e Lean são os mesmos: entregar valor o mais rápido possível causando o menor desperdício possível, aprendendo e usando esse aprendizado no processo, planejando e replanejando para atingir objetivos que se tornam mais claros durante o processo. É só isso.

O maior problema é quando um programador amador pensa: "qual o próximo passo?" E a resposta é: "o objetivo é montar um Kanban." Ou quando um empreendedor amador pensa: "qual o próximo passo?" E a resposta é: "o objetivo é montar um Business Canvas."

Não, esses não são objetivos, são meios. E se esses meios não colaboram para atingir os fins, de entregar valor ao cliente, conseguir lucro no seu empreendimento, então eles são descartáveis. Seu objetivo nãoé criar um MVP/protótipo, criar um Lean UX, criar um Business Canvas. Seu objetivo é ter lucro. Quais os meios para se obter lucro?

Se quiser aprender qualquer coisa os passos para começar são simples:

  • Não crie ídolos, nunca "idolize" ninguém, pelo menos não seriamente.
  • Ignore tudo que você vê ou ouve em grupos. Faça anotações, mas não leve tudo a sério.
  • Ignore conselhos e mentorias. É como gerente de banco aconselhando em ações de investimento: se eles fossem bons seriam ricos. Mas não são. São apenas vendedores com outro nome.
  • Tudo, absolutamente tudo, começa com poucos princípios. Você nunca vai ser um cirurgião cardíaco querendo aprender primeiro a cortar a aorta sem nunca ter aprendido a lavar as mãos primeiro. Procure os princípios. Ignore os títulos pomposos.
  • Assuma que você sabe pouco, sempre. Você não sabe nada. Encare qualquer coisa com os olhos de um ignorante. Se achar que já sabe alguma coisa, não vai aprender mais nada. Mas não precisa ser um ignorante idiota, seja um ignorante esperto.

Aprenda a questionar. O monumental mundo geral das Ciências, que vai do absolutamente pequeno mundo quântico, até o infinito e imenso mundo cosmológico só existe se você aceitar seu único princípio: o Método Científico. Ele é basicamente o PDCA: defina o problema, faça hipóteses, faça experimentos controlados, descarte hipóteses provadas erradas, repita. Ou sendo mais exato: o PDCA de Deming é diretamente inspirado pelo Método Científico. Eis o princípio de tudo, de Agile a Lean a PDCA, voltamos a Karl Popper e sua filosofia de"Racionalismo Crítico" que nos ensina que tudo deve ser aberto a ser racionalmente criticado.

Por isso mesmo Lean, enquanto guarda-chuva de venda de produtos e serviços que você não precisa, está morto. Longa vida ao princípio: alcançar valor evitando desperdícios com aprendizado contínuo, ou seja, Eficiência. Não existem fórmulas mágicas. Se as dietas mágicas funcionassem não existiria obesidade no mundo.

Karl Popper

PS: Eu sei, tem #tongueincheek no título e no artigo, mas a intenção - pra variar - é dar uma provocada mesmo ;-)


[Off-Topic] Comentando o Marco Civil Aprovado

$
0
0

Como disse em redes sociais antes, estou bem em cima do muro quanto a este Marco Civil. Sendo um pouco cínico, claro, se vem do governo, de um governo petista e ainda com apoio da oposição, não pode cheirar bem. O timing e a urgência, claro, é para tirar vantagem dos recentes acontecimentos de escutas da governo norte-americano em território brasileiro e a controvérsia Snowden. O objetivo é aparecer como o salvador da pátria e ao mesmo tempo embutir salva-guardas que legalizem atividades governamentais que são, no mínimo, escusas.

Vou publicar o texto na íntegra e fazer alguns poucos comentários. Muita gente tem muita opinião sobre esse Marco Civil e meu palpite é que 99% sequer leram o texto antes de opinar. Então recomendo que leiam. A fonte de onde tirei o texto é este PDF. Se por acaso eu estiver com um texto defasado me avisem.

Não deixem de comentar.

SUBEMENDA SUBSTITUTIVA GLOBAL ÀS EMENDAS DE PLENÁRIO AO PROJETO DE LEI No 2.126, DE 2011

Estabelece princípios, garantias, direitos e deveres para o uso da Internet no Brasil.

O Congresso Nacional decreta:

CAPÍTULO I

DISPOSIÇÕES PRELIMINARES

Art. 1o Esta Lei estabelece princípios, garantias, direitos e deveres para o uso da Internet no Brasil e determina as diretrizes para atuação da União, dos Estados, do Distrito Federal e dos Municípios em relação à matéria.

Art. 2o A disciplina do uso da Internet no Brasil tem como fundamento o respeito à liberdade de expressão, bem como:

I – o reconhecimento da escala mundial da rede;

II – os direitos humanos, o desenvolvimento da personalidade e o exercício da cidadania em meios digitais;

III – a pluralidade e a diversidade;

IV – a abertura e a colaboração;

V – a livre iniciativa, a livre concorrência e a defesa do consumidor; e

VI – a finalidade social da rede.

Não tem como garantir "a finalidade social da rede". Logo abaixo fala-se em liberdade de expressão, livre concorrência. A finalidade não pode ser definida por decreto, ela será o que seus usuários fizerem dela. Para garantir uma "finalidade social" exige manipulação restritiva. A Internet só é o que é pela sua não-finalidade, todos fazem o que bem entenderem, o livre mercado faz os ajustes sozinhos e não precisa haver nada definindo pseudo-finalidades. A Internet é um meio de transporte de dados, todos pagam por ela, seu uso é determinado por esse livre acesso. Ao definir objetivo, não importa quão bons sejam suas intenções, automaticamente está se criando restrições. E toda restrição precisa ser regulamentada. E toda regulamentação precisa de "alguém" para auditar.

Art. 3o A disciplina do uso da Internet no Brasil tem os seguintes princípios:

I – garantia da liberdade de expressão, comunicação e manifestação de pensamento, nos termos da Constituição;

II – proteção da privacidade;

III – proteção aos dados pessoais, na forma da lei;

IV – preservação e garantia da neutralidade de rede;

V – preservação da estabilidade, segurança e funcionalidade da rede, por meio de medidas técnicas compatíveis com os padrões internacionais e pelo estímulo ao uso de boas práticas;

VI – responsabilização dos agentes de acordo com suas atividades, nos termos da lei; VII – preservação da natureza participativa da rede;

VIII - a liberdade dos modelos de negócios promovidos na Internet, desde que não conflitem com os demais princípios estabelecidos nesta Lei.

Parágrafo único. Os princípios expressos nesta Lei não excluem outros previstos no ordenamento jurídico pátrio relacionados à matéria, ou nos tratados internacionais em que a República Federativa do Brasil seja parte.

Os parágrafos II e III são redundantes e a III na verdade restringe a II pois a primeira define privacidade e a III quebra a privacidade e dá o monopólio da quebra ao governo.

O V deveria ser irrelevante. Seguir qualquer tipo de padrão, por decreto, não funciona. Pois fica a pergunta: quem define o que são "técnicas compatíveis com os padrões internacionais" ou "uso de boas práticas"? Significa que algum órgão do governo vai deter o monopólio dessa regulamentaçõa.

Novamente, o parágrafo VII não tem como definir. Quem define "natureza participativa"? Esses parágrafos garantem a necessidade de mais um cabide de empregos burocrático. Anatel ou similar. Para "garantir" esses "direitos". Todo "direito" não-fundamental significa a necessidade de um órgão regulador. E todo órgão regulador é prejudicial.

Art. 4o A disciplina do uso da Internet no Brasil tem os seguintes objetivos:

I – promover o direito de acesso à Internet a todos;

II – promover o acesso à informação, ao conhecimento e à participação na vida cultural e na condução dos assuntos públicos;

III – promover a inovação e fomentar a ampla difusão de novas tecnologias e modelos de uso e acesso; e

IV – promover a adesão a padrões tecnológicos abertos que permitam a comunicação, a acessibilidade e a interoperabilidade entre aplicações e bases de dados.

Este artigo inteiro é ruim. Não dá para "garantir" direito de acesso à Internet por todos. Da mesma forma que não dá para garantir comida, educação ou qualquer outra coisa a ninguém. A partir do momento que se define o direito de alguém, também está se decretando a subserviência de outro pois o Governo não tem os meios para garantir isso, nós cidadãos temos. E quando se define quem alguém tem direito a algo que é nosso, infrige-se nossos direitos também.

Sinto muito, Internet não é de graça. Nem mesmo eletricidade, água e saneamento básico são de graça, temos que pagar. Coloque um órgão regulador governamental e vamos ter o mesmo nível de serviço da Sabesp, Eletropaulo. Falta de água. Blackouts e queda de luz quando chove. Porque sofremos isso? Regulamentação governamental.

Não é e nem deve ser atribuição do governo fomentar "inovação". Inovação é uma consequência natural de livre concorrência e livre mercado. Ao colocar inovação como uma atribuição do governo estamos dando permissão para gastar nosso dinheiro de impostos e jogar fora. Novamente, quem define o que é "inovação"? Outro órgão regulador governamental, outro cabide de burocratas.

Até aqui, a única coisa que os artigos garantem é a criação de órgãos reguladores.

Art. 5o Para os efeitos desta Lei, considera-se:

I – Internet: o sistema constituído de conjunto de protocolos lógicos, estruturado em escala mundial para uso público e irrestrito, com a finalidade de possibilitar a comunicação de dados entre terminais por meio de diferentes redes;

II – terminal: computador ou qualquer dispositivo que se conecte à Internet;

III – administrador de sistema autônomo: pessoa física ou jurídica que administra blocos de endereço Internet Protocol – IP específicos e o respectivo sistema autônomo de roteamento, devidamente cadastrada no ente nacional responsável pelo registro e distribuição de endereços IP geograficamente referentes ao País;

IV – endereço IP: código atribuído a um terminal de uma rede para permitir sua identificação, definido segundo parâmetros internacionais;

V – conexão à Internet: habilitação de um terminal para envio e recebimento de pacotes de dados pela Internet, mediante a atribuição ou autenticação de um endereço IP;

VI – registro de conexão: conjunto de informações referentes à data e hora de início e término de uma conexão à Internet, sua duração e o endereço IP utilizado pelo terminal para o envio e recebimento de pacotes de dados;

VII – aplicações de Internet: conjunto de funcionalidades que podem ser acessadas por meio de um terminal conectado à Internet; e

VIII – registros de acesso a aplicações de Internet: conjunto de informações referentes à data e hora de uso de uma determinada aplicação de Internet a partir de um determinado endereço de IP.

Bom, pelo menos mostra que alguns políticos não são totalemente analfabetos. Esses parágrafos são apenas definições técnicas. Bem cruas, diga-se de passagem, mas acho que servem para os efeitos deste documento. Ênfase a "endereço IP", como se isso garantisse a identificação positiva de alguém. O que faltou foi definir que endereço IP não pode ser usado como base para se identificar ninguém.

Art. 6o Na interpretação desta Lei serão levados em conta, além dos fundamentos, princípios e objetivos previstos, a natureza da Internet, seus usos e costumes particulares e sua importância para a promoção do desenvolvimento humano, econômico, social e cultural.

CAPÍTULO II

DOS DIREITOS E GARANTIAS DOS USUÁRIOS

Art. 7o O acesso à Internet é essencial ao exercício da cidadania e ao usuário são assegurados os seguintes direitos:

I – à inviolabilidade da intimidade e da vida privada, assegurado o direito à sua proteção e à indenização pelo dano material ou moral decorrente de sua violação;

II – à inviolabilidade e ao sigilo do fluxo de suas comunicações pela Internet, salvo por ordem judicial, na forma da lei;

III – à inviolabilidade e ao sigilo de suas comunicações privadas armazenadas, salvo por ordem judicial; IV– à não suspensão da conexão à Internet, salvo por débito diretamente decorrente de sua utilização;

Defina "inviolabilidade" como sendo "o provedor de acesso não deve violar a menos que seja obrigado pelo Judiciário".

V – à manutenção da qualidade contratada da conexão à Internet;

A manutenção da qualidade contratada deveria ser foro dos Direitos do Consumidor.

VI – a informações claras e completas constantes dos contratos de prestação de serviços, com detalhamento sobre o regime de proteção aos registros de conexão e aos registros de acesso a aplicações de Internet, bem como sobre práticas de gerenciamento da rede que possam afetar sua qualidade; e

VII – ao não fornecimento a terceiros de seus dados pessoais, inclusive registros de conexão, e de acesso a aplicações de Internet, salvo mediante consentimento livre, expresso e informado ou nas hipóteses previstas em lei;

VIII – a informações claras e completas sobre a coleta, uso, armazenamento, tratamento e proteção de seus dados pessoais, que somente poderão ser utilizados para finalidades que:

a) justificaram sua coleta;

b) não sejam vedadas pela legislação; e

c) estejam especificadas nos contratos de prestação de serviços ou em termos de uso de aplicações de Internet.

IX – ao consentimento expresso sobre a coleta, uso, armazenamento e tratamento de dados pessoais, que deverá ocorrer de forma destacada das demais cláusulas contratuais;

X – à exclusão definitiva dos dados pessoais que tiver fornecido a determinada aplicação de Internet, a seu requerimento, ao término da relação entre as partes, ressalvadas as hipóteses de guarda obrigatória de registros previstas nesta Lei;

XI – à publicidade e clareza de eventuais políticas de uso dos provedores de conexão à Internet e de aplicações de Internet;

XII - à acessibilidade, consideradas as características físico-motoras, perceptivas, sensoriais, intelectuais e mentais do usuário, nos termos da Lei; e

XIII - à aplicação das normas de proteção e defesa do consumidor nas relações de consumo realizadas na Internet.

Os parágrafos desse artigo são todos redundantes. Em resumo: o provedor de serviço deve declarar explicitamente o uso dos dados coletados de usuários e, se não está claro, o governo tem monopólio sobre aquisição desses dados (já que todo parágrafo termina com "salvo por ordem judicial, na forma da lei"). Novamente, todo mundo já faz isso. Temos "Termos de Serviço" que ninguém lê e todo mundo aceita mas que, tecnicamente, está lá.

Não chega a ser um artigo totalmente ruim, ele ratifica alguns comportamentos que já são padrão em qualquer bom serviço. E todos sabemos que por ordem judicial qualquer um pode obter qualquer coisa neste país, já que não existe limitação de privacidade para o governo. E se o governo pode acessar qualquer coisa, qualquer um também pode. Portanto, Não existe garantia de privacidade em nenhum lugar neste documento.

Art. 8o A garantia do direito à privacidade e à liberdade de expressão nas comunicações é condição para o pleno exercício do direito de acesso à Internet.

Parágrafo único. São nulas de pleno direito as cláusulas contratuais que violem o disposto no caput, tais como aquelas que:

I - impliquem ofensa à inviolabilidade e ao sigilo das comunicações privadas pela Internet; ou

II – em contrato de adesão, não ofereçam como alternativa ao contratante a adoção do foro brasileiro para solução de controvérsias decorrentes de serviços prestados no Brasil.

CAPÍTULO III

DA PROVISÃO DE CONEXÃO E DE APLICAÇÕES DE INTERNET

Seção I

Da Neutralidade de Rede

Art. 9o O responsável pela transmissão, comutação ou roteamento tem o dever de tratar de forma isonômica quaisquer pacotes de dados, sem distinção por conteúdo, origem e destino, serviço, terminal ou aplicação.

§ 1o A discriminação ou degradação do tráfego será regulamentada nos termos das atribuições privativas do Presidente da República previstas no inciso IV do art. 84 da Constituição Federal, para a fiel execução desta Lei, ouvidos o Comitê Gestor da Internet e a Agência Nacional de Telecomunicações, e somente poderá decorrer de:

I – requisitos técnicos indispensáveis à prestação adequada dos serviços e aplicações; e

II – priorização a serviços de emergência.

§ 2o Na hipótese de discriminação ou degradação do tráfego prevista no § 1o, o responsável mencionado no caput deve:

I – abster-se de causar dano aos usuários, na forma do art. 927 do Código Civil;

II – agir com proporcionalidade, transparência e isonomia;

III – informar previamente de modo transparente, claro e suficientemente descritivo aos seus usuários sobre as práticas de gerenciamento e mitigação de tráfego adotadas, inclusive as relacionadas à segurança da rede; e

IV– oferecer serviços em condições comerciais não discriminatórias e abster-se de praticar condutas anticoncorrenciais.

§ 3o Na provisão de conexão à Internet, onerosa ou gratuita, bem como na transmissão, comutação ou roteamento, é vedado bloquear, monitorar, filtrar ou analisar o conteúdo dos pacotes de dados, respeitado o disposto neste artigo.

Em resumo este é o artigo que deve impedir um provedor de internet de criar um plano "Facebook", onde o tráfego ao Facebook seria de alta prioridade e o acesso ao resto seria ou mais lento ou inexistente. Ou também impedir que, sem o usuário saber, exista "traffic shaping" onde o provedor monitora seu tráfego e torna o acesso a alguns lugares (como Pirate Bay) mais lentos.

O princípio é até válido, acho que ninguém em sã consciência seria contra uma "neutralidade" ou isonomia.

Só que isso levanta a pergunta: temos internet comercial no Brasil a mais de 20 anos. Antes da aprovação deste documento nada disso era ilegal. Por que você não vê uma Claro ou Net vendendo planos "YouTube"?

Faça-se essa pergunta, e a resposta não é simples. Você vai começar a se perguntar qual o objetivo real desse artigo.

Seção II

Da Proteção aos Registros, Dados Pessoais e Comunicações Privadas

Art. 10. A guarda e a disponibilização dos registros de conexão e de acesso a aplicações de Internet de que trata esta Lei, bem como de dados pessoais e do conteúdo de comunicações privadas, devem atender à preservação da intimidade, vida privada, honra e imagem das partes direta ou indiretamente envolvidas.

§ 1o O provedor responsável pela guarda somente será obrigado a disponibilizar os registros mencionados no caput, de forma autônoma ou associados a dados pessoais ou outras informações que possam contribuir para a identificação do usuário ou do terminal, mediante ordem judicial, na forma do disposto na Seção IV deste Capítulo, respeitado o disposto no artigo 7o.

§ 2o O conteúdo das comunicações privadas somente poderá ser disponibilizado mediante ordem judicial, nas hipóteses e na forma que a lei estabelecer, respeitado o disposto nos incisos II e III do art. 7o.

§ 3o O disposto no caput não impede o acesso, pelas autoridades administrativas que detenham competência legal para a sua requisição, aos dados cadastrais que informem qualificação pessoal, filiação e endereço, na forma da lei.

§ 4o As medidas e procedimentos de segurança e sigilo devem ser informados pelo responsável pela provisão de serviços de forma clara e atender a padrões definidos em regulamento, respeitado seu direito de confidencialidade quanto a segredos empresariais.

Esse artigo explicita que todo dado está à disposição do Judiciário. Não existe privacidade, ela está quebrada por lei. E o governo detém o monopólio dessa quebra. Isso abre todo tipo de corrupção. Se só alguém do governo pode abrir as informações de alguém, espionagem corporativa ficou mais fácil: basta molhar a mão de um juíz, emitir um mandato e quem puder pagar vai ter acesso a qualquer informação.

Art. 11. Em qualquer operação de coleta, armazenamento, guarda e tratamento de registros, dados pessoais ou de comunicações por provedores de conexão e de aplicações de Internet em que pelo menos um desses atos ocorram em território nacional, deverá ser obrigatoriamente respeitada a legislação brasileira, os direitos à privacidade, à proteção dos dados pessoais e ao sigilo das comunicações privadas e dos registros.

§1o O disposto no caput se aplica aos dados coletados em território nacional e ao conteúdo das comunicações, nos quais pelo menos um dos terminais esteja localizado no Brasil.

§2o O disposto no caput se aplica mesmo que as atividades sejam realizadas por pessoa jurídica sediada no exterior, desde que oferte serviço ao público brasileiro ou pelo menos uma integrante do mesmo grupo econômico possua estabelecimento no Brasil.

§3o Os provedores de conexão e de aplicações de Internet deverão prestar, na forma da regulamentação, informações que permitam a verificação quanto ao cumprimento da legislação brasileira referente à coleta, guarda, armazenamento ou tratamento de dados, bem como quanto ao respeito à privacidade e ao sigilo de comunicações.

Mais um mecanismo que garante a criação de um órgão regulador. E aqui diz explicitamente "na forma de regulamentação". Quem vai "verificar o cumprimento da legislação brasileira referente à coleta, guarda, armazenamento, etc"? Isso sempre foi desnecessário, continua sendo desnecessário, mas agora vamos pagar algum vagabundo auditor para não fazer nada, e ainda ser bully de serviços menores, restringindo a livre concorrência. Quer atrapalhar os negócios de alguém, chame essa "polícia" dizendo que empresa X não está cumprindo este parágrafo.

§4o Decreto regulamentará o procedimento para apuração de infrações ao disposto neste artigo.

Art. 12. Sem prejuízo das demais sanções cíveis, criminais ou administrativas, as infrações às normas previstas nos artigos 10 e 11 ficam sujeitas, conforme o caso, às seguintes sanções, aplicadas de forma isolada ou cumulativa:

I – advertência, com indicação de prazo para adoção de medidas corretivas;

II – multa de até dez por cento do faturamento do grupo econômico no Brasil no seu último exercício, excluídos os tributos, considerados a condição econômica do infrator e o princípio da proporcionalidade entre a gravidade da falta e a intensidade da sanção;

III – suspensão temporária das atividades que envolvam os atos previstos no artigo 11; ou IV – proibição de exercício das atividades que envolvam os atos previstos no artigo 11. Parágrafo único. Tratando-se de empresa estrangeira, responde solidariamente pelo pagamento da multa de que trata o caput sua filial, sucursal, escritório ou estabelecimento situado no País.

Subseção I

Da Guarda de Registros de Conexão

Art. 13. Na provisão de conexão à Internet, cabe ao administrador de sistema autônomo respectivo o dever de manter os registros de conexão, sob sigilo, em ambiente controlado e de segurança, pelo prazo de um ano, nos termos do regulamento.

§ 1o A responsabilidade pela manutenção dos registros de conexão não poderá ser transferida a terceiros.

§ 2o A autoridade policial ou administrativa ou o Ministério Público poderá requerer cautelarmente que os registros de conexão sejam guardados por prazo superior ao previsto no caput.

§ 3o Na hipótese do § 2o, a autoridade requerente terá o prazo de sessenta dias, contados a partir do requerimento, para ingressar com o pedido de autorização judicial de acesso aos registros previstos no caput.

§ 4o O provedor responsável pela guarda dos registros deverá manter sigilo em relação ao requerimento previsto no § 2o, que perderá sua eficácia caso o pedido de autorização judicial seja indeferido ou não tenha sido protocolado no prazo previsto no § 3o.

§ 5o Em qualquer hipótese, a disponibilização ao requerente, dos registros de que trata este artigo, deverá ser precedida de autorização judicial, conforme disposto na Seção IV deste Capítulo.

§ 6o Na aplicação de sanções pelo descumprimento ao disposto neste artigo, serão considerados a natureza e a gravidade da infração, os danos dela resultantes, eventual vantagem auferida pelo infrator, as circunstâncias agravantes, os antecedentes do infrator e a reincidência.

Entendo que este artigo se refere somente a provedores de acesso à internet. Isso é apenas justificativa para aumentar os custos e, novamente, quebrar a privacidade.

Subseção II

Da Guarda de Registros de Acesso a Aplicações de Internet na Provisão de Conexão

Art. 14. Na provisão de conexão, onerosa ou gratuita, é vedado guardar os registros de acesso a aplicações de Internet.

Subseção III

Da Guarda de Registros de Acesso a Aplicações de Internet na Provisão de Aplicações

Art 15. O provedor de aplicações de Internet constituído na forma de pessoa jurídica, que exerça essa atividade de forma organizada, profissionalmente e com fins econômicos, deverá manter os respectivos registros de acesso a aplicações de internet, sob sigilo, em ambiente controlado e de segurança, pelo prazo de seis meses, nos termos do regulamento.

§ 1o Ordem judicial poderá obrigar, por tempo certo, os provedores de aplicações de Internet que não estão sujeitos ao disposto no caput a guardarem registros de acesso a aplicações de Internet, desde que se tratem de registros relativos a fatos específicos em período determinado.

§ 2o A autoridade policial ou administrativa ou o Ministério Público poderão requerer cautelarmente a qualquer provedor de aplicações de Internet que os registros de acesso a aplicações de Internet sejam guardados, inclusive por prazo superior ao previsto no caput, observado o disposto nos §§ 3o e 4o do art. 13.

§ 3o Em qualquer hipótese, a disponibilização ao requerente, dos registros de que trata este artigo, deverá ser precedida de autorização judicial, conforme disposto na Seção IV deste Capítulo.

§ 4o Na aplicação de sanções pelo descumprimento ao disposto neste artigo, serão considerados a natureza e a gravidade da infração, os danos dela resultantes, eventual vantagem auferida pelo infrator, as circunstâncias agravantes, os antecedentes do infrator e a reincidência.

Este artigo é mais Orwelliano ainda. Ela garante que o governo pode obrigar um provedor a rastrear mais informações, por período indeterminado, de forma indiscriminada. Veja bem, o governo já poderia fazer isso antes, por influência da Anatel e outros lobbys, mas agora assegura-se por lei.

Art. 16. Na provisão de aplicações de Internet, onerosa ou gratuita, é vedada a guarda:

I - dos registros de acesso a outras aplicações de Internet sem que o titular dos dados tenha consentido previamente, respeitado o disposto no art. 7o; ou

II – de dados pessoais que sejam excessivos em relação à finalidade para a qual foi dado consentimento pelo seu titular.

Art. 17. Ressalvadas as hipóteses previstas nesta Lei, a opção por não guardar os registros de acesso a aplicações de Internet não implica responsabilidade sobre danos decorrentes do uso desses serviços por terceiros.

Seção III

Da Responsabilidade por Danos Decorrentes de Conteúdo Gerado por Terceiros

Art. 18. O provedor de conexão à Internet não será responsabilizado civilmente por danos decorrentes de conteúdo gerado por terceiros.

Art. 19. Com o intuito de assegurar a liberdade de expressão e impedir a censura, o provedor de aplicações de Internet somente poderá ser responsabilizado civilmente por danos decorrentes de conteúdo gerado por terceiros se, após ordem judicial específica, não tomar as providências para, no âmbito e nos limites técnicos do seu serviço e dentro do prazo assinalado, tornar indisponível o conteúdo apontado como infringente, ressalvadas as disposições legais em contrário.

§ 1o A ordem judicial de que trata o caput deverá conter, sob pena de nulidade, identificação clara e específica do conteúdo apontado como infringente, que permita a localização inequívoca do material.

§ 2o A aplicação do disposto neste artigo para infrações a direitos de autor ou a diretos conexos depende de previsão legal específica, que deverá respeitar a liberdade de expressão e demais garantias previstas no art. 5o da Constituição Federal.

§ 3o As causas que versem sobre ressarcimento por danos decorrentes de conteúdos disponibilizados na Internet relacionados à honra, à reputação ou a direitos de personalidade bem como sobre a indisponibilização desses conteúdos por provedores de aplicações de Internet poderão ser apresentadas perante os juizados especiais.

§ 4o O Juiz, inclusive no procedimento previsto no § 3o, poderá antecipar, total ou parcialmente, os efeitos da tutela pretendida no pedido inicial, existindo prova inequívoca do fato e considerado o interesse da coletividade na disponibilização do conteúdo na Internet, desde que presentes os requisitos de verossimilhança da alegação do autor e de fundado receio de dano irreparável ou de difícil reparação.

Isso não parece totalmente ruim, já acontece hoje, mas é mais confuso. Na prática, se um usuário do seu site faz um comentário ofensivo e quem se sentiu ofensivo consiga uma ordem judicial, o site não é criminalmente responsável pelo conteúdo se ele retirar quando ordenado.

As pessoas que mais usam esse recurso são os imbecis candidatos de cargos públicos que soltam ordens judiciais o tempo todo para tudo que é site que tem conteúdo político. O problema é que ofender um político é contra a lei. Nossa constituição em si, é um problema hoje em dia.

Art. 20. Sempre que tiver informações de contato do usuário diretamente responsável pelo conteúdo a que se refere o art. 19, caberá ao provedor de aplicações de Internet comunicar-lhe os motivos e informações relativos à indisponibilização de conteúdo, com informações que permitam o contraditório e a ampla defesa em juízo, salvo expressa previsão legal ou salvo expressa determinação judicial fundamentada em contrário.

Parágrafo único. Quando solicitado pelo usuário que disponibilizou o conteúdo tornado indisponível, o provedor de aplicações de Internet que exerce essa atividade de forma organizada, profissionalmente e com fins econômicos, substituirá o conteúdo tornado indisponível, pela motivação ou pela ordem judicial que deu fundamento à indisponibilização.

Art. 21. O provedor de aplicações de Internet que disponibilize conteúdo gerado por terceiros será responsabilizado subsidiariamente pela violação da intimidade decorrente da divulgação, sem autorização de seus participantes, de imagens, vídeos ou outros materiais contendo cenas de nudez ou de atos sexuais de caráter privado quando, após o recebimento de notificação pelo participante ou seu representante legal, deixar de promover, de forma diligente, no âmbito e nos limites técnicos do seu serviço, a indisponibilização desse conteúdo.

Parágrafo único. A notificação prevista no caput deverá conter, sob pena de nulidade, elementos que permitam a identificação específica do material apontado como violador da intimidade do participante e a verificação da legitimidade para apresentação do pedido.

Seção IV

Da Requisição Judicial de Registros

Art. 22. A parte interessada poderá, com o propósito de formar conjunto probatório em processo judicial cível ou penal, em caráter incidental ou autônomo, requerer ao juiz que ordene ao responsável pela guarda o fornecimento de registros de conexão ou de registros de acesso a aplicações de Internet.

Parágrafo único. Sem prejuízo dos demais requisitos legais, o requerimento deverá conter, sob pena de inadmissibilidade:

I – fundados indícios da ocorrência do ilícito;

II – justificativa motivada da utilidade dos registros solicitados para fins de investigação ou instrução probatória; e

III – período ao qual se referem os registros.

Esse artigo extende o que já foi definido em artigos anteriores: o acesso irrestrito e indiscriminado de dados que deveria ter "privacidade" garantida.

Art. 23. Cabe ao juiz tomar as providências necessárias à garantia do sigilo das informações recebidas e à preservação da intimidade, vida privada, honra e imagem do usuário, podendo determinar segredo de justiça, inclusive quanto aos pedidos de guarda de registro.

"Cabe ao juiz", ou seja, esqueça sua privacidade. Juizes podem ser, e são, comprados. É um mercado.

CAPÍTULO IV

DA ATUAÇÃO DO PODER PÚBLICO

Art. 24. Constituem diretrizes para a atuação da União, dos Estados, do Distrito Federal e dos Municípios no desenvolvimento da Internet no Brasil:

I – estabelecimento de mecanismos de governança multiparticipativa, transparente, colaborativa e democrática, com a participação do governo, do setor empresarial, da sociedade civil e da comunidade acadêmica;

II – promoção da racionalização da gestão, expansão e uso da Internet, com participação do Comitê Gestor da Internet no Brasil;

III – promoção da racionalização e da interoperabilidade tecnológica dos serviços de governo eletrônico, entre os diferentes Poderes e níveis da federação, para permitir o intercâmbio de informações e a celeridade de procedimentos;

IV – promoção da interoperabilidade entre sistemas e terminais diversos, inclusive entre os diferentes níveis federativos e diversos setores da sociedade;

V – adoção preferencial de tecnologias, padrões e formatos abertos e livres;

VI – publicidade e disseminação de dados e informações públicos, de forma aberta e estruturada;

VII – otimização da infraestrutura das redes e estímulo à implantação de centros de armazenamento, gerenciamento e disseminação de dados no país, promovendo a qualidade técnica, a inovação e a difusão das aplicações de Internet, sem prejuízo à abertura, à neutralidade e à natureza participativa;

VIII – desenvolvimento de ações e programas de capacitação para uso da Internet; IX – promoção da cultura e da cidadania; e

X – prestação de serviços públicos de atendimento ao cidadão de forma integrada, eficiente, simplificada e por múltiplos canais de acesso, inclusive remotos.

Este artigo sanciona a parte Orwelliana: a criação de órgãos reguladores, a "Thought Police". Vai ser responsável por "garantir" o que está nos parágrafos: estabelecer mecanismos de governança, racionalização da gestão, promoção da interoperabilidade, etc. Aqui você sancionou por lei a criaçõa de um órgão de corrupção, reserva de mercado, quebra da livre concorrência e livre mercado e sucateamento do mercado de Internet.

Entenda, não há como definir "governança multiparticipativa", "colaborativa", "racionalização", etc. Quem define o que é colaborativo ou não? Quem define o que é interoperável ou não? Quem define o que é eficiente ou não? Alguém precisa interpretar. E se está aberto à interpretação é um mecanismo que só trás benefício a quem tem o poder de fazer valer sua interpretação. Portanto, é um mal texto, por definição.

Art. 25. As aplicações de Internet de entes do Poder Público devem buscar:

I – compatibilidade dos serviços de governo eletrônico com diversos terminais, sistemas operacionais e aplicativos para seu acesso;

II – acessibilidade a todos os interessados, independentemente de suas capacidades físico- motoras, perceptivas, sensoriais, intelectuais, mentais, culturais e sociais, resguardados os aspectos de sigilo e restrições administrativas e legais;

III – compatibilidade tanto com a leitura humana quanto com o tratamento automatizado das informações;

IV – facilidade de uso dos serviços de governo eletrônico; e

V – fortalecimento da participação social nas políticas públicas.

Isso não deveria estar aqui. São cláusulas técnicas para licitações de projetos de software que já existem. Não vejo a utilidade. Em alguns casos alguns desses ítens são desnecessários e, novamente, criamos uma restrição desnecessária.

Art. 26. O cumprimento do dever constitucional do Estado na prestação da educação, em todos os níveis de ensino, inclui a capacitação, integrada a outras práticas educacionais, para o uso seguro, consciente e responsável da Internet como ferramenta para o exercício da cidadania, a promoção de cultura e o desenvolvimento tecnológico.

Não é dever do estado garantir isso.

Art. 27. As iniciativas públicas de fomento à cultura digital e de promoção da Internet como ferramenta social devem:

I – promover a inclusão digital;

II – buscar reduzir as desigualdades, sobretudo entre as diferentes regiões do País, no acesso às tecnologias da informação e comunicação e no seu uso; e

III – fomentar a produção e circulação de conteúdo nacional.

Art. 28. O Estado deve, periodicamente, formular e fomentar estudos, bem como fixar metas, estratégias, planos e cronogramas referentes ao uso e desenvolvimento da Internet no País.

Novamente, não é dever do estado. Este capítulo inteiro é restritivo e não deveria existir. Ela garante o uso irrestrito do nosso dinheiro para programas de governo. Como contribuinte e pagador de impostos, sou contra qualquer programa de governo que gaste meu dinheiro. E eis o exemplo: o direito de um quebrando o direito do outro. Por definição, isso não pode ser um direito garantido.

CAPÍTULO V

DISPOSIÇÕES FINAIS

Art. 29. O usuário terá a opção de livre escolha na utilização de programa de computador em seu terminal para exercício do controle parental de conteúdo, entendido por ele como impróprio a seus filhos menores, desde que respeitados os princípios desta Lei e da Lei no 8.069 de 13 de julho de 1990.

Parágrafo único. Cabe ao Poder Público, em conjunto com os provedores de conexão e de aplicações de Internet e a sociedade civil, promover a educação e fornecer informações sobre o uso dos programas de computador previstos no caput, bem como para a definição de boas práticas para a inclusão digital de crianças e adolescentes.

Art. 30. A defesa dos interesses e direitos estabelecidos nesta Lei poderá ser exercida em juízo, individual ou coletivamente, na forma da lei.

Art. 31. Até a entrada em vigor da lei específica prevista no § 2o do art. 19, a responsabilidade do provedor de aplicações de Internet por danos decorrentes de conteúdo gerado por terceiros, quando se tratar de infração a direitos de autor ou a direitos conexos, continuará a ser disciplinada pela legislação autoral em vigor aplicável na data da entrada em vigor desta Lei.

Art. 32. Esta Lei entrará em vigor sessenta dias após a data de sua publicação.

Deputado ALESSANDRO MOLON. Relator

Sinceramente, não vejo a vantagem desse texto. Na parte que é relevante, a neutralidade, ela deveria ser regulada pelos Direitos do Consumidor. Todo o resto está sancionando a legalidade da quebra de privacidade e dando monopólio dessa quebra ao governo. E também está criando "direitos" que vão exigir mais gastos públicos e mais aparelhamento do estado a nossos custos e sem nenhum benefício aparente. Basicamente é um documento de propaganda para fazer o governo parecer bom, e às minhas custas e às suas custas. Parabéns.

Vídeos de algumas de minhas Palestras

$
0
0

Faz quase 8 anos desde que resolvi iniciar minhas atividades como evangelista de Ruby e de assuntos relacionados à tecnologia. Já fiz algo em torno de 100 palestras contando eventos grandes como Encontro Locaweb, Campus Party, Rails Summit, além de diversas semanas da computação em faculdades pelo país e até oportunidade de palestrar nos EUA, Holanda, Japão e Israel.

Aproveitando que temos um "LONGO" feriado prolongado de amanhã até segunda, talvez seja uma boa oportunidade para colocar tudo que já foi gravado das minhas palestras até hoje num mesmo lugar para que vocês possam assistir tudo de uma só vez ;-) Está em ordem cronológica, de 2007 até 2013 e pretendo continuar atualizando este post quando novas gravações aparecerem. Se conhecerem alguma gravação que eu não listei aqui me avisem nos comentários.

Se gostaram não deixem de curtir e compartilhar para que mais possam assistir também. Boa diversão!

RejectConf 2007 | Apresentando Ruby on Rails

May 11, 2012

[Arquivo] Rails Summit 2009 | Agile, além do Caos

Nov 14, 2013

Consegi 2010 | Dicas de Desenvolvimento Web com Ruby

May 3, 2013

[Arquivo] RubyConf Brasil 2010 | Ruby on Rails Rocks!

Nov 14, 2013

CPBR3 - Ecossistema. Cultura e Ruby on Rails

Feb 15, 2010

[Arquivo] 11° Encontro Locaweb - Agilidade e qualidade de projetos

Nov 14, 2013

[Arquivo] 12° Encontro Locaweb | Desmembrando Pessoas

Nov 14, 2013

TDC 2011 | Discutindo Rails e Arquiteturas

Jul 15, 2011

TDC 2013 SP | Ecossistema Ruby

Oct 10, 2013

DNAD 11 | Discutindo Rails e Arquiteturas

Agile Vale 2011 | A semente não entendida de todas metodologias as ágeis

Aug 23, 2011

Campus Party 2011

Jan 28, 2011

Techtalk Klarna | The Origins of the Brazilian Rails Community What's New in Rails 4

Nov 27, 2012

(este foi gravado em Israel e o autor não habilitou embed, segue o link)

https://www.youtube.com/watch?v=tm1EBuMIacc

Secot V 2013 | Startups & Softwares

May 14, 2013

TV O Povo | Programa Conectado l Fábio Akita

Apr 18, 2013

Startup Vale 2013 | Startup e Software por Fabio Akita

Jul 19, 2013

Rupy 2013 | Tendências de hoje e amanhã no mundo ruby

Dec 11, 2013

Eventials

Como não fazer pesquisas usando "LIKE"

Nov 2013

(o embed fica muito grande, segue o link direto)

https://www.eventials.com/akitaonrails/como-nao-fazer-pesquisas-usando-like/

[Off-Topic] Carreira em Programação - Codificar não é Programar

$
0
0

Um assunto que sempre discuto é sobre a formação de programadores. A grande maioria (se não todos) os artigos que se encontra na internet hoje em dia lista apenas "técnicas", ou "como ser um montador", "como pegar peças que existem e montá-las". Apesar de existir muito valor nisso, vamos deixar bem claro que isso não constitui toda a carreira de "programação", apenas uma minúscula fração.

Sempre podemos pegar algum conhecimento inicial, por exemplo, web e HTML, juntar alguns frameworks e bibliotecas (Rails, Django, Wordpress) e de fato colocar alguma coisa funcional no ar. Mas isso é pouco, muito pouco.

O fato de ser tão "simples", beirando o trivial, colocar "alguma coisa funcional" no ar, esconde todo o potencial que existe na carreira de programação. Pior do que isso, o imediatismo de se ter um resultado leva à ilusão de que só isso é o suficiente e que qualquer conhecimento mais "avançado" é completamente desnecessário. O reflexo disso é o crescimento dos cursos técnicos de programação e a baixa adesão a cursos de bacharelado de Ciências da Computação. Isso é péssimo porque quanto menos gente tivermos trabalhando nos fundamentos, na origem de tudo, mais sucateado fica o mercado daqui pra frente.

Só porque neste instante você tem um emprego de codificador (recortador de photoshop, montador de HTML, colador de plugins de Wordpress, etc), pare para pensar como sua carreira vai evoluir daqui pra frente. Você vai ser sempre só um montador? Vai pegar o caminho fácil de virar um "gerente" meia-boca de montadores?

Infelizmente, em um único post, é impossível listar e explicar todos os aspectos importantes da Ciência da Computação. Mas quero experimentar listar pelo menos alguns dos assuntos que a maioria acha desnecessário para provocá-los a procurar mais.

Aprenda a pelo menos "LER" fluentemente em Inglês

Sinto muito, eu gosto da língua portuguesa, sempre vai ser minha primeira língua. Porém pseudo-patriotismo ou pura preguiça não vai eliminar o fato de que se você não se dedicar desde já a ser fluente na leitura do Inglês, você sempre estará defasado num nível lastimável.

A primeira razão é que no mundo Ocidental (estou excluindo o que acontece no Oriente, porque eu não sei ler Chinês e o mercado lá também é gigantesco) tudo que sai de novo sai primeiro em inglês. Se for esperar alguém se interessar em traduzir, pense no trabalho que isso dá e o tempo que leva. Você vai estar necessariamente vendo material defasado se esperar sair em português. E quando começar a se interessar pelo material pode ser que ele já esteja inclusive obsoleto. Você não vai estar um passo atrás, vai estar centenas de quilômetros atrás.

A segunda razão é que o mundo da internet é globalizado. Não é incomum pegar código feito em outros países para continuar e não é incomum o código que você fizer ter que ser dividido com programadores de outros países. Se faça um favor: não passe vergonha.

Guerras Religiosas

Programação não é torcida de futebol, nem numerologia, nem astrologia. Não tem horóscopo, não tem guru. Lembre-se isso se chama CIÊNCIA da Computação, não Astrologia da Computação.

Todo mundo tem gostos subjetivos, só que é estupidez transformar gosto em dogma. A preguiça de ter que aprender algo novo faz o famoso "Sou bom em Clipper, essa linguagem vai evoluir no futuro e sempre vai existir, basta eu defender com unhas e dentes que não importa o que surgir depois."

Substitua "Clipper" por qualquer outra, de Cobol, Basic, Pascal, Algol, Eiffel, Smalltalk, etc até as mais recentes, Java, C#, Javascript, Python, etc. Só porque alguma coisa existe hoje não há absolutamente nenhuma garantia que vai continuar existindo. Pense quão ridículo alguém que disse a frase acima não deve estar se sentindo agora. Não faça esse papel. Em Ciências não somos leais a "times", torcemos sempre para quem está ganhando e trocamos tão logo ele se prove errado. É por isso que Ciência sempre evolui.

E surpresas acontecem. Durante os anos 80 e 90 ninguém deu atenção à Objective-C. Estava fadado ao fracasso. Do nada, em 2007, surge o iPhone que - surpresa, precisa saber Objective-C. De repente ela se torna uma das linguagens de maior sucesso do fim da primeira década do Século XXI. De 10 em 10 anos o mercado se transforma de alguma forma. A "Lei de Bell".

Aceite: suas soluções hoje são Ruins

Continuando o tema do "Ignore as Guerras Religiosas", como fazer para entender o que fazer? Atenha-se aos princípios. Jogue fora o que os gurus falam, não idolatre ninguém e nem siga cegamente o que alguém diz, desça às perguntas fundamentais e vai encontrar uma direção mais óbvia.

Quando você sabe como as coisas funcionam, retira o verniz, abre o capô, desmonta o motor, entende a química da combustão, só então vai conseguir dominar a arte. Se você, male-male, lembra pra que diabos serve trocar o óleo, vai ser sempre só um motorista medíocre, no melhor dos casos. Qual é seu objetivo? É ser engenheiro do carro? Porque se for, simplesmente ouvir gurus falando da cor do volante dificilmente vai te levar muito longe.

A Ciência da Computação é normalmente ignorada porque parece que aprender Matemática não só é chato como é inútil.

Vamos dar alguns exemplos. Se eu perguntar a um iniciante como procurar por palavras dentro de um texto, as coisas mais óbvias que devem vir à cabeça são:

  • usar funções de substring e um loop para vasculhar o texto (solução brute-force)
  • usar uma expressão regular ou num banco de dados usar um "LIKE" (solução genérica)
  • instalar um SOLR ou Elasticsearch (solução correta em muitos casos, mas "magia negra" no entendimento)

A maioria nem pensaria na 3a solução. E se pensar não sabe porque. E se eu disser que - obviamente de forma absolutamente crú e resumida - a solução está em transformar um documento e os termos de pesquisa em vetores e calcular a relevância entre os termos de procura e os documentos por similaridade de cosseno? Pois é exatamente isso que significa Vector Space Model (VSM) que você vai encontrar em diversas engines de procura.

O conhecimento que leva a isso se chama Álgebra Linear. Lembra-se disso do PRIMEIRO ano de Ciência da Computação? Em particular sobre esse assunto recomendo assistir uma palestra que fiz sobre isso chamado "Como não fazer pesquisas usando LIKE".

E quando você precisa criar um processo para filtrar conteúdo? Para evitar conteúdo impróprio? A maioria das pessoas pensaria no seguinte:

  • criar um blacklist de palavras e ir adicionando à medida que se lembra de palavras ofensivas. E usar a primeira ou segunda opção do que listei antes para buscar essas palavras.

Como você já deve imaginar, a resposta mais "óbvia" ou "simples" (considerando a falta de conhecimento), provavelmente é a errada, e nesse caso de fato essa não é a mais eficiente.

Conheça sobre machine learning e uma das formas mais simples disso chamada Classificador Bayesiano Ingênuo. Alguém pode pensar "puts, mas isso de machine learning é avançado demais pro dia a dia." De maneira alguma. Aliás, qualquer filtro anti-spam vagabundo que você encontra num site de downloads gratuitos usa um classificador.

A idéia é que simplesmente palavras simples não são suficiente para determinar se um conteúdo é impróprio ou não. A forma da construção de frases, o "tom" da forma de se escrever. Tudo isso forma um padrão que pode ser classificado e aprendido. Quanto mais conteúdo impróprio é classificado mais eficiente o algoritmo fica. Se quiser experimentar uma forma simples em Ruby veja este blog. Se quiser aprender sobre classificadores mais avançados, veja o projeto Apache Mahout.

E o que é isso? É uma matéria de Estatística e Probabilidade. Os fundamentos para entender isso estão de novo no PRIMEIRO ano de Ciência da Computação.

"Ah, mas você está falando coisas que ninguém precisa saber. Pra fazer sites web isso é desnecessário."

Uma coisa que qualquer bom framework web precisa saber fazer com eficiência hoje em dia é mapear rotas com a programação por baixo (controllers). O Ruby on Rails tem um componente de rotas chamado Journey, que configuramos via o arquivo "config/routes.rb". Abaixo temos um trecho disso:

123456789101112131415
ImageUploadDemo::Application.routes.draw do
  devise_for :admin_users, ActiveAdmin::Devise.config

  resources :photos

  authenticated :userdo
    root :to => 'photos#index'end
  root :to => "photos#index"
  devise_for :users

  require 'sidekiq/web'
  mount Sidekiq::Web => '/sidekiq'ActiveAdmin.routes(self)end

Quão difícil isso pode ser? O que a maioria poderia imaginar?

  • Fácil, basta fazer um conjunto de arrays ou um hash (dicionário) e quando chegar a URL basta quebrar os termos via uma regular expression e encontrar o controller passando os parâmetros pra executar.

Vamos nos repetir novamente? Sim, isso funciona, para aplicações bem pequenas. Qualquer coisa muito maior do que o exemplo acima já vai dar problemas de performance.

Que tal ver um trecho do código do Journey?

12345678910111213141516171819202122232425262728293031323334353637383940414243
classJourney::Parser

token SLASHLITERALSYMBOLLPARENRPARENDOTSTAROR

rule
  expressions
    : expressions expression  { result = Cat.new(val.first, val.last) }
    | expression              { result = val.first }
    | or
    ;
  expression
    : terminal
    | group
    | star
    ;
  group
    : LPAREN expressions RPAREN { result = Group.new(val[1]) }
    ;or
    : expressions OR expression { result = Or.new([val.first, val.last]) }
    ;
  star
    : STAR       { result = Star.new(Symbol.new(val.last)) }
    ;
  terminal
    : symbol
    | literal
    | slash
    | dot
    ;
  slash
    : SLASH              { result = Slash.new('/') }
    ;
  symbol
    : SYMBOL             { result = Symbol.new(val.first) }
    ;
  literal
    : LITERAL            { result = Literal.new(val.first) }
  dot
    : DOT                { result = Dot.new(val.first) }
    ;end

Em bom português, agora fodeu. Parte do Journey se utiliza do Racc um gerador de parsers.

Se você passou pelo menos pro SEGUNDO ano de Ciências da Computação então passou pelas matérias de Algoritmos e Estruturas de Dados e Montadores. E se chegou ao TERCEIRO ano deve ter aprendido sobre Compiladores (e visto o famoso livro do Dragão). Racc deve ter te lembrado de Yacc, Flex, Bison.

Para arrematar, você deve achar que sabe o que é Orientação a Objetos, certo? Certamente acha que sua linguagem favorita (seja Java, C# ou Javascript) são orientados a objetos. Se eu pedir para definir o que isso significa, está na ponta da sua língua:

  • Minha linguagem suporta Encapsulamento, Herança e Polimorfismo, portanto é orientada a objetos.

E se eu lhe disser que linguagens procedurais, imperativas, funcionais também suportam encapsulamento, herança (seja via delegação ou não) e polimorfismo? E se é esse o caso então o que define orientação a objetos?

Alguns que se entreteram no assunto talvez se lembrem de Alan Kay, que cunhou o termo "orientação a objetos". Mas quantos pararam para pesquisar a linguagem Simula 67? O que o Simula introduziu em 1967? Objetos, classes, herança, subclasses, métodos virtuais, corotinas, simulação de eventos discretos, garbage collection.

E quantos já ouviram falar dos criadores do Simula 67, Kristen Nygaard e Ole-Johan Dahl?

Não sabem quem são? Tenho certeza que não. Bem, eis que lhes apresento os pais da orientação a objetos.

Sobre os Ombros de Gigantes

O que mencionei na seção anterior não é nem a ponta do iceberg, é uma gota d'água nessa ponta. O importante é você ganhar consciência de que tudo que você acha que sabe é perto de nada. Quero que você aceite que tudo que você acha que sabe ou está errado ou é totalmente incompleto.

Isso é importante porque qualquer um que ache que já sabe tudo ou perto disso nunca vai aprender nada. Você precisa esvaziar o copo para poder enchê-lo. (by Bruce Lee)

Bruce Lee Quote

Além disso quero que você entenda que você não está sozinho. Antes de você vieram dezenas de grandes mentes. E não estou falando desses gurus superficiais ensinando meramente técnicas e ferramentas. Esqueça-os, todo mundo vai esquecê-los em breve também.

Todo mundo sabe quem é Linus Torvalds, Bill Gates, Steve Jobs, Zuckerberg. Esqueça-os por enquanto. Atenha-se aos imortais. Nomes que realmente fizeram a diferença na história da Ciência da Computação. Alguns exemplos:

E isso apenas para listar alguns poucos. Ciência é um campo amplo, onde o trabalho de um cientista complementa o trabalho do anterior. Passo a passo andando sempre para frente. É um trabalho acumulativo de dezenas, centenas de anos. Nossa vantagem? Centenas de pessoas já trilharam esse caminho no passado e podemos nos utilizar do que eles aprenderam e deixaram para nós, em vez de nós mesmos cometermos os mesmos erros até aprendermos.

Quase tudo que você vê por aí que se chama "inovação" não é mais do que a redescoberta de coisas que já estão documentadas no passado mas estavam à frente do seu tempo. Foi assim com o mouse: Douglas Engelbart, que criou o mouse em 1968 precisou esperar até Steve Jobs lançar o Macintosh, 16 anos depois, para ver sua invenção ser popularizada. Pare para pensar: quantas descobertas estão no passado apenas esperando para que nós a desenterremos para finalmente realizá-las?

Quer saber sobre os livros imortais da Ciência da Computação? Vamos a alguns:

Não quer fazer uma faculdade? Não tem problema, tente acompanhar o material disponível online do MIT de Electrical Engineering and Computer Science. Se você ainda é completamente amador mesmo no mundo da programação veja este curso introdutório à Ciência da Computação no Coursera.

Note que não estou citando neste artigo nenhum dos nomes que muitos poderiam esperar como Martin Fowler, Bruce Eckel, Robert Martin, Michael Feathers, Kent Beck, Steve McConnel, Tom DeMarco, Dave Thomas, etc. Esqueça-os. Se não ver os anteriores, estes farão pouca diferença.

Não coloque o carro na frente dos bois, vá um passo de cada vez.

Carreira em Programação

Uma coisa que eu sempre repito é o seguinte:

"Programar não é escrever qualquer código da mesma forma que culinária não é jogar qualquer ingrediente numa panela."

Entenda: é muito simples escrever código, qualquer um que tenha o mínimo de coordenação motora pra não tentar passar uma peça quadrada num buraco circular, ou que minimamente já tenha empilhado uma peça de lego em cima da outra, tem condições de escrever código. Não há absolutamente nenhum mérito nisso.

Baixar um Twitter Bootstrap, usar um gerador do Yeoman, instalar um MySQL no Ubuntu, copiar e colar um trecho de JQuery, qualquer um consegue fazer.

Quando se fala em carreira, o que "qualquer um" consegue fazer significa que é um mero "commodity". Ser um commodity significa que o valor que o mercado está disposto a pagar só vai decair, não vai subir. Temporariamente surge alguma novidade para tentar criar uma diferenciação ("veja, Angular JS", "veja, HTML 5"), mas elas rapidamente se dissolvem na tendência de queda do valor.

O valor não está na montagem. Está na criatividade da solução: conseguir extrair o maior valor pelo menor custo. E criatividade só existe quando você tem domínio sobre todos os elementos ao seu redor. Quando 1 hora para trocar um algoritmo idiota de procura de palavras por um vector space model reduz seu parque de máquinas de 10 para 2, e responde ao seu usuário em 1/5 do tempo. Aí não é força bruta, é de fato conhecimento. E isso tem valor e cresce.

Ter uma caixa de ferramentas cheia só o torna um "faz-tudo com muitas ferramentas", não o torna um engenheiro/arquiteto capaz de construir o próximo World Trade Center/Freedom Tower.

Mas, como todo mundo que quer evoluir, todos começamos como faz-tudo. Não há nada de errado nisso, apenas não se iluda achando que ter uma caixa de ferramentas com mais ferramentas o torna qualquer coisa diferente disso.

Segurança em Rails

$
0
0

O assunto segurança é bem complicado, este post não tem a intenção de ser a fonte completa de tudo relacionado a segurança no mundo Ruby on Rails mas apenas listar algumas informações e ferramentas úteis. Antes de começar alguns links importantes que, se você ainda não conhecia, precisa ter nos seus favoritos:

  • Ruby on Rails Security Guide - este é o guia oficial básico sobre as diversas brechas de segurança que o Rails, por padrão, já previne mas que você pode desativar acidentalmente. É o "Hello World" da segurança, como Session Hijacking, CSRF, SQL Injection, XSS, etc.

  • Ruby on Rails Security Group - este é o grupo oficial de segurança. Toda vez que uma nova vulnerabilidade é corrigida é aqui que primeiro aparece seu anúncio e você pode avaliar os detalhes para saber se precisa atualizar sua aplicação imediatamente ou não.

  • Brakeman - como disse antes, você pode se descuidar e deixar passar um string com interpolação que pode causar um SQL Injection, por exemplo. Para evitar isso execute este scanner de tempos em tempos. O Code Climate implementa o Brakeman para dar as mesmas métricas de brechas de segurança.

  • RubySec - mantém um banco de dados de vulnerabilidades não só do framework Ruby on Rails mas de diversas Rubygems que usamos todos os dias. E daqui vem uma das ferramentas que vou sugerir neste artigo.

Aliás, um comentário sobre o termo. Nunca se pode dizer "minha aplicação está segura", o máximo que podemos dizer é "minha aplicação parece não ter nenhuma vulnerabilidade conhecida." Só porque você não conhece, não significa que as vulnerabilidades não existam, e as chances são que existam e você simplesmente a ignora. O único tipo de aplicação "segura" é aquela que está completamente off-line numa localização geográfica desconhecida em um bunker anti-nuclear. Tirando isso, qualquer outra coisa é "quebrável".

Bundler Audit

Como disse antes, não é fácil manter um projeto. Depois de algum tempo as gems são atualizadas e você não fica sabendo disso. Quando são apenas adições de algumas novas funcionalidades, não há com o que se preocupar, mas como você fica sabendo se uma das dezenas de gems que sua aplicação utiliza recebeu atualizações de segurança.

Para isso o pessoal do RubySec mantém um banco de dados, o Ruby Advisory DB que concentra e organiza os diversos security advisories. Você pode contribuir se tiver gems de código aberto que receberam contribuições para fechar vulnerabilidades.

E para quem quer automatizar o processo de encontrar esses advisories, o RubySec também tem o Bundler Audit. Ele funciona usando o Advisory DB e cruzando com as versões específicas de gems que estão listadas no Gemfile.lock do seu projeto.

Apenas instale a gem com

1
gem install bundler-install

E execute a partir da raíz do seu projeto:

1
bundle-audit

Ele vai lhe dar uma saída parecida com esta:

123456789101112131415161718192021222324252627282930313233343536373839404142
Insecure Source URI found: git://github.com/Codeminer42/axlsx.git
Name: actionpack
Version: 3.2.16
Advisory: OSVDB-103440
Criticality: Unknown
URL: http://osvdb.org/show/osvdb/103440
Title: Denial of Service Vulnerability in Action View when using render :text
Solution: upgrade to >= 3.2.17

Name: actionpack
Version: 3.2.16
Advisory: OSVDB-103439
Criticality: Unknown
URL: http://osvdb.org/show/osvdb/103439
Title: XSS Vulnerability in number_to_currency, number_to_percentage and number_to_human
Solution: upgrade to ~> 3.2.17, ~> 4.0.3, >= 4.1.0.beta2

Name: mini_magick
Version: 3.5.0
Advisory: OSVDB-91231
Criticality: High
URL: http://osvdb.org/show/osvdb/91231
Title: MiniMagick Gem for Ruby URI Handling Arbitrary Command Injection
Solution: upgrade to >= 3.6.0

Name: nokogiri
Version: 1.5.10
Advisory: OSVDB-101458
Criticality: Unknown
URL: http://www.osvdb.org/show/osvdb/101458
Title: Nokogiri Gem for Ruby External Entity (XXE) Expansion Remote DoS
Solution: upgrade to ~> 1.5.11, >= 1.6.1

Name: nokogiri
Version: 1.5.10
Advisory: OSVDB-101179
Criticality: Unknown
URL: http://www.osvdb.org/show/osvdb/101179
Title: Nokogiri Gem for JRuby Crafted XML Document Handling Infinite Loop Remote DoS
Solution: upgrade to ~> 1.5.11, >= 1.6.1

Unpatched versions found!

Seguindo o exemplo acima, precisaríamos fazer o seguinte:

1
bundle update nokogiri mini_magick rails

Você pode precisar alterar o arquivo Gemfile se a versão específica estiver declarada antes de realizar o update. E depois rode o bundle-audit novamente para ter certeza que está tudo bem. Apenas cuidado com os casos onde você aponta diretamente para um repositório do Github em vez do Rubygems.org, pois ele não tem como checar se o que você está puxando do Github tem vulnerabilidades conhecidas ou não.

Para atualizar seu bundler-audit antes de realizar um novo scan, faça:

1
bundle-audit update

Bônus: Rack-Attack

Além da análise estática de código para avaliar segurança, uma adição que pode ser interessante dependendo do tipo de site que você usa é o Rack-Attack.

Digamos que avaliando seus logs você perceba que seu site está sendo muito consumido por web scrappers, robôs do tipo que ficam capturando seu conteúdo. Se for robôs de motores de busca como Google, Bing, tudo bem, mas você vai encontrar mais do que isso.

Imagine que além de scrappers consumindo demais, você tenha tentativa de ataques de força-bruta, como scripts automatizados tentando diversas combinações de usuários e senhas até conseguir acertar um.

Ou imagine simplesmente que você quer ou criar uma lista de IPs que você quer permitir (se seu site estiver em beta fechado, por exemplo) ou uma lista negra que você já sabe que quer bloquear.

Tudo isso pode ser feito diretamente no web server ou balanceador de carga. Mas se você estiver fazendo deployment em ambientes fechados como Heroku, não vai ter acesso à essa configuração.

Para isso existe o Rack::Attack, que é um middleware Rack que você instala de modo simples diretamente na sua aplicação Rails e pode customizá-lo de diferentes formas. A instalação básica é simples. Apenas acrescente à sua Gemfile:

1
gem 'rack-attack'

E adicione ao arquivo config.ru, antes da linha do comando run:

1
use Rack::Attack

E se quiser customizar, comece adicionando o arquivo config/initializers/rack-attack.rb com o seguinte:

123
classRack::AttackRack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new # defaults to Rails.cacheend

A documentação no Github tem muito mais detalhes. Nos aspectos de detectar padrões de invasão por força bruta ele se inspira no famoso fail2ban (que você pode usar para proteger, por exemplo, o SSH de seu servidor).

Vale a pensa aprender mais sobre esse assunto.

Swift para Rubistas, Rápida Introdução

$
0
0

Como vocês devem ter assistido no keynote de abertura da WWDC 2014, a Apple lançou uma nova linguagem, mais moderna, para substituir o Objective-C como linguagem padrão para desenvolvimento de aplicações tanto OS X quanto iOS. Não se trata de uma nova "camada" mas uma linguagem que tecnicamente compila para o mesmo tipo de binário que o próprio Objective-C e mesmo C. Graças ao compilador que é implementado sobre LLVM isso se torna possível.

A linguagem Swift é um Objective-C com funcionalidades mais modernas e uma sintaxe mais elegante e menos verbosa. Já havia publicado neste blog anos atrás como o Objective-C e Ruby tem conceitos muito similares. E isso se deve à herança comum da linguagem Smalltalk.

Antes que algum afobado comece a trolar: o artigo não tem como objetivo dizer que Swift tem inspiração em Ruby ou que Ruby tem algum tipo de relação com Swift. Apenas aproveitando o fato de terem origens similares e funcionalidades que fazem sua programação ser próxima, quero usar o artigo para mostrar a rubistas algumas nuances do Swift.

Todos os exemplos de código foram extraídos do eBook “The Swift Programming Language.” que é uma boa introdução à linguagem. Mas para realmente tirar proveito é melhor conhecer a fundo Objective-C, C e obviamente, toda a documentação de APIs dos frameworks para iOS e OS X.

Exemplos de Sintaxe

Do ponto de vista da sintaxe, a linguagem está bem mais atraente. Vejamos um trecho muito simples em Swift:

123456
if let actualNumber = possibleNumber.toInt() {
    println("\(possibleNumber) has an integer value of \(actualNumber)")
} else {
    println("\(possibleNumber) could not be converted to an integer")
}// prints "123 has an integer value of 123”

E em Ruby:

123456
if actual_number = possible_number && possible_number.to_i
  puts "#{possible_number} has an integer value of #{actual_number}"else
  puts "#{possible_number} could not be converted to an integer"end# prints "123 has an integer value of 123”

Statements como "if" ou "for" não tem parênteses como em C, embora cada seção ainda seja separado por chaves "{}". Visualmente falando a diferença é bem pequena. Interpolação em strings tem uma sintaxe um pouco diferente mas no geral é muito semelhante.

As convenções de nomenclatura são diferentes: no Ruby usamos tudo em caixa baixa separado por underline e Swift ainda tem a herança de Objective-C de camel casing. Além disso Swift identa código com 4 espaços e Ruby com 2.

Vejamos outro exemplo em Swift:

1234567891011
func alignRight(var string: String, count: Int, pad: Character) -> String {
    let amountToPad = count - countElements(string)for _ in 1...amountToPad {
        string = pad + string
    }return string
}
let originalString = "hello"
let paddedString = alignRight(originalString, 10, "-")// paddedString is equal to "-----hello"// originalString is still equal to "hello”

E o equivalente em Ruby seria:

123456789
defalign_right(string, count, pad)
  amount_to_pad = count - string.size
  (1..amount_to_pad).each do
    string = pad + stringend
  stringend
original_string = "hello"
padded_string = align_right(original_string, 10, "-")

A primeira semelhança é que Swift possui "Ranges" como em Ruby embora a notação seja oposta. Usamos ".." em Ruby para um range que inclui ambos os números extremos e "..." (3 pontos) para não incluir o último número. Em Swift é o contrário.

Em Swift, o correto é declarar os tipos dos argumentos e do valor de retorno e o "return" é explícito. No Ruby não tempos tipos pré-declarados e o retorno padrão é sempre o valor da última coisa executada. E falando em Ranges, tanto em Ruby quanto Swift podemos ter pattern matching de valores em intervalos:

1234567891011121314151617181920
let count = 3_000_000_000_000
let countedThings = "stars in the Milky Way"
var naturalCount: Stringswitch count {case0:
    naturalCount = "no"case1...3:
    naturalCount = "a few"case4...9:
    naturalCount = "several"case10...99:
    naturalCount = "tens of"case100...999:
    naturalCount = "hundreds of"case1000...999_999:
    naturalCount = "thousands of"default:
    naturalCount = "millions and millions of"
}
println("There are \(naturalCount) \(countedThings).")

Em Ruby é praticamente a mesma coisa:

12345678910111213
count = 3_000_000_000_000
counted_things = "stars in the Milky Way"
natural_count = case countwhen0then"no"when1..3then"a few"when4..9then"several"when10..99then"tens of"when100..999then"hundreds of"when1000..999_999then"thousands of"else"millions and millions of"end
puts "There are #{natural_count}#{counted_things}."

Swift e Ruby não precisam de "break" porque ele não cai para o próximo match. Ambos tem capacidade de comparar não só valores mas intervalos ou outros elementos. No caso, como Ruby tem return por default, não precisamos repetir a variável "natural_count" em cada ítem e o resultado geral do "case" vai para a única atribuição no topo.

Este outro trecho também é curioso:

123456
if let roomCount = john.residence?.numberOfRooms {
    println("John's residence has \(roomCount) room(s).")
} else {
    println("Unable to retrieve the number of rooms.")
}// prints "Unable to retrieve the number of rooms.”

O "equivalente" em Ruby (se estivermos no Rails) seria:

12345
if room_count = john.residence.try(:number_of_rooms)
  puts "John's residence has #{room_count} room(s)."else
  puts "Unable to retrieve the number of rooms."end

Não é exatamente a mesma coisa. No Swift o "?" denota uma propriedade opcional e enviar uma mensagem a um objeto opcional devolve "nil". Na prática é quase a mesma coisa que o método #try do ActiveSupport do Rails.

E falando em ActiveSupport o Swift herda Categories de Objective-C com o nome de Extensions, que é uma forma de estender a funcionalidade de uma classe que já existe:

12345678910111213
extension Double {
    var km: Double { return self * 1_000.0 }
    var m: Double { return self }
    var cm: Double { return self / 100.0 }
    var mm: Double { return self / 1_000.0 }
    var ft: Double { return self / 3.28084 }
}
let oneInch = 25.4.mm
println("One inch is \(oneInch) meters")// prints "One inch is 0.0254 meters"
let threeFeet = 3.ft
println("Three feet is \(threeFeet) meters")// prints "Three feet is 0.914399970739201 meters”

Em Ruby podemos facilmente fazer a mesma coisa diretamente porque classes são sempre abertas:

123456789101112
classNumericdefkm; self * 1_000.0; enddefm; self; enddefcm; self / 100.0; enddefmm; self / 1_000.0; enddefft; self / 3.28084; endend

one_inch = 25.4.mm
puts "One inch is #{one_inch} meters"
three_feet = 3.ft
puts "Three feet is #{three_feet} meters"

Novamente, o resultado é similar mas os princípios são diferentes. A começar que no caso do Ruby estou abrindo a classe que é pai de todos os números, não só dos Floats (Doubles), caso contrário o segundo exemplo que é um Integer não funciona ("3.ft", teria que ser explicitamente "3.0.ft").

Além disso no Swift ele declara uma variável de processamento dinâmico. Nas semelhanças veja que tanto Swift quanto Ruby usam "self" para se referir ao objeto interno. Ambos permitem usar a notação de underline para delimitar milhares ("1_000", por exemplo).

Um outro exemplo mais prático em Swift seria este:

1234567891011121314
extension Int {
    func repetitions(task: () -> ()) {for i in 0..self {
            task()
        }
    }
}3.repetitions({
    println("Hello!")
    })// Hello!// Hello!// Hello!

E em Ruby já temos o equivalente ao método "repetitions" desta extension já implementada:

123
3.times do
  puts "Hello!"end

Em particular veja que o Swift define um método que recebe uma função anônima, um bloco propriamente dito. Ele passa esse bloco entre chaves como parâmetro do método. É o equivalente no Ruby que passamos o bloco também entre chaves ou entre "do; end".

Outras coisas que lembram muito Ruby é como ele trata tipos de coleções:

123
var shoppingList = ["Eggs", "Milk"]
shoppingList += ["Chocolate Spread", "Cheese", "Butter"]
shoppingList[4...6] = ["Bananas", "Apples"]

Esse trecho quase que inteiramente se converte em como Ruby lida com arrays:

123
shopping_list = ["Eggs", "Milk"]
shopping_list += ["Chocolate Spread", "Cheese", "Butter"]
shopping_list[4...6] = ["Bananas", "Apples"]

O mesmo pode-se dizer de dicionários do Swift que são semelhantes a Hash no Ruby:

12345
var airports = ["TYO": "Tokyo", "DUB": "Dublin"]
airports["LHR"] = "London"for (airportCode, airportName) in airports {
    println("\(airportCode): \(airportName)")
}

Em Ruby seria:

12345
airports = {TYO: "Tokyo", DUB: "Dublin"}
airports[:LHR] = "London"for airport_code, airport_name in airports
  puts "#{airport_code}: #{airport_name}"end

Em particular este último trecho, em Ruby, seria mais comumente escrito como:

123
airports.each do |airport_code, airport_name|
  puts "#{airport_code}: #{airport_name}"end

A diferença é que Swift inicializa dicionários com a mesma sintaxe de arrays, com colchetes. Em Ruby diferenciamos arrays com colchetes e hashes com chaves. Além disso é comum usar chaves como strings em Swift e Objective-C pois eles são imutáveis por padrão. Em Ruby strings são tecnicamente mutáveis e o equivalente a uma "string imutável" em Ruby são symbols. Ao ser interpolado dentro de uma string, um symbol automaticamente se converte em string.

Já um tipo que Swift e outras linguagens como Python tem, e Ruby não tem, são Tuples. De forma simplificada, se trata de uma lista heterogênea (como um array) de constantes. Em Ruby usamos um Array para o mesmo fim. E temos, novamente, usos similares:

123456
let http404Error = (404, "Not Found")
let (statusCode, statusMessage) = http404Error
println("The status code is \(statusCode)")// prints "The status code is 404"
println("The status message is \(statusMessage)")// prints "The status message is Not Found”

Veja que podemos decompor um Tuple de volta em variáveis de maneira similar em Ruby:

1234
http_404_error = [404, "Not Found"]
status_code, status_message = http_404_error
puts "The status code is #{status_code}"
puts "The status message is #{status_message}"

Conclusão

Isso foi apenas um rápido "tour" sobre as partes mais superficiais da linguagem. Swift ainda tem:

  • tipos Enum (diferente de funcionalidades de Enumeration do Ruby, não confundir)
  • propriedades (getter, setter, weak references, etc)
  • inicialização, deinicialização, ARC (procedimentos para automatic reference counting)
  • tipos (type casting, nested types, generics, extensions, protocols)

Diferente de linguagens como Go ou Scala, ela não tem diretamente na linguagem nenhuma construção para abstrair atores ou outras coisas de concorrência. Isso porque no Objective-C e no Swift vamos subir para o nível dos frameworks, em particular para o Grand Central Dispatch que basicamente funciona como um sistema de filas de processamento.

Como podem ver, Swift em si é uma linguagem bem minimalista. Sua intenção é ser um "sugar coating" sobre a cansada sintaxe do Objective-C, a cansativa rotina de lidar com arquivos de header e implementação, declaração estática de tipos em todos os lugares. Mas o que a linguagem não tem como "consertar" é a extensiva quantidade de APIs do Cocoa. Não se engane, é tudo muito bem organizado e consistente, diferente de outras plataformas.

Por exemplo, hoje (1 dia depois do anúncio da linguagem, para verem como a sintaxe é trivial de simples) já saiu um pequeno demo que é basicamente um clone do famigerado Flappy Bird, usando o SpriteKit como fundação. E veja um trecho mais realista:

12345678910111213141516
// skyline
var skyTexture = SKTexture(imageNamed: "sky")
skyTexture.filteringMode = SKTextureFilteringMode.Nearest

var moveSkySprite = SKAction.moveByX(-skyTexture.size().width * 2.0, y: 0, duration: NSTimeInterval(0.1 * skyTexture.size().width * 2.0))
var resetSkySprite = SKAction.moveByX(skyTexture.size().width * 2.0, y: 0, duration: 0.0)
var moveSkySpritesForever = SKAction.repeatActionForever(SKAction.sequence([moveSkySprite,resetSkySprite]))for var i:CGFloat = 0; i < 2.0 + self.frame.size.width / ( skyTexture.size().width * 2.0 ); ++i {
    var sprite = SKSpriteNode(texture: skyTexture)
    sprite.setScale(2.0)
    sprite.zPosition = -20;
    sprite.position = CGPointMake(i * sprite.size.width, sprite.size.height / 2.0 + groundTexture.size().height * 2.0)
    sprite.runAction(moveSkySpritesForever)
    self.addChild(sprite)
}

Não é nada do outro mundo, só precisa se acostumar com as APIs. A documentação da Apple é muito bem feita e fácil de usar.

Swift para Rubistas, Funções e Closures

$
0
0

Se tem uma coisa que nós rubistas estamos muito acostumados e gostamos bastante são closures, blocos ou fechamentos. Expliquei esse mecanismo pela primeira vez em 2007 aqui no blog, então se ainda não conhece bem o conceito, releia meu post.

Em 2010 a Apple adicionou a funcionalidade de closures ao Objective-C também e modificou muitas de suas APIs para aproveitar esse recurso. Também postei sobre isso 3 anos atrás, então releia meu post para aprender sobre isso.

Finalmente, Swift é basicamente Objective-C melhorado então temos o mesmo recurso.

Entendendo Funções e Blocos

A idéia é poder criar funções "customizáveis", ou seja, um pedaço de código que espera outro pedaço de código. Existem duas formas de se fazer isso. No mundo C podemos passar diretamente uma função como parâmetro para ser executada dentro de outra função. Isso não é uma closure, é o que chamamos de "callback". Em Objective-C e Swift, podemos passar uma função como parâmetro ou mesmo fazer uma função retornar uma função.

1234567891011
func soma(x: Int, y: Int) -> Int {return x + y
}

func calculadora(calculo: (Int, Int) -> (Int), a: Int, b: Int) {
    let resultado = calculo(a, b)
    println(resultado)
}

calculadora(soma, 10, 20)// "30"

Veja o código acima, definimos uma função de soma, que recebe dois inteiros como parâmetro e retorna um inteiro. Depois definimos uma função genérica chamada "calculadora" que recebe como parâmetro uma função com a assinatura (Int, Int) -> Int que significa "uma função que receba dois inteiros e retorne um inteiro" e depois dois parâmetros inteiros.

Ao executar calculadora(soma, 10, 20), passamos a função soma, os números 10 e 20 e internamente atribuímos a função soma a uma variável chamada "calculo" e executamos passando os dois inteiros, que, obviamente, serão somados. E a resposta no final será 30.

123456
func multiplicacao(x: Int, y: Int) -> Int {return x * y
}

calculadora(multiplicacao, 3, 5)// "15"

Podemos agora criar quaisquer funções com a mesma assinatura e depois mandar para a calculadora. Em Ruby não temos a mesma funcionalidade:

12345678910111213
defsoma(x, y)
  x + yenddefcalculadora(calculo, a, b)
  puts calculo(a, b)end

calculadora(soma, 10, 20)# ArgumentError: wrong number of arguments (0 for 2)#         from (irb):1:in `soma'#         from (irb):9#         from /usr/bin/irb:12:in `<main>'

Em Ruby, parênteses são opcionais e ao tentar passar o método "soma" como parâmetro, na verdade ele está já tentando executar o método. Existe uma forma, não ortodoxa, que podemos ter um efeito similar, mas não é a mesma coisa, seria assim:

12345
defcalculadora(calculo, a, b)
  puts send(calculo, a, b)end

calculadora(:soma, 10, 20)

O método sendé uma das formas de se enviar mensagens a objetos (Objective-C também tem isso, na forma de seletores e do método performSelector que expliquei neste outro post). Então, em vez de passar diretamente o método, passamos apenas o nome dele como um symbol e internamente executamos o método passando os parâmetros. Isso é só "similar" porque na prática o método em si nunca foi passado como parâmetro.

O que podemos fazer em Ruby é não usar métodos, mas blocos:

123456789
soma = lambda do |x, y|
  x + yenddefcalculadora(calculo, a, b)
  puts calculo.(a, b)end

calculadora(soma, 10, 20)

Aqui a semântica é diferente. Primeiro criamos um bloco, literalmente o que seria o "corpo de um método" usando lambda. Depois passamos o bloco com parâmetro ao método calculadora. E dentro dela executamos o bloco com um "ponto" antes dos parênteses, que é a forma curta de se fazer soma.call(a, b)

Um bloco, em Ruby, é diferente de uma método ou função. Isso porque ele também é um fechamento do estado ao redor do bloco. Blocos não são métodos. Em Ruby, o método está associado ("binding") à classe que a define (mesmo sem definir um class, estamos dentro sempre dentro de um objeto, diferente de Swift ou Objective-C ou mesmo outra linguagem). Um bloco está associado à uma variável e por isso podemos mais facilmente repassá-la para outros métodos.

Em Swift também podemos devolver funções ou ter "Nested Functions", por exemplo:

1234567891011121314151617181920
func calculo(tipo: String) -> (Int, Int) -> Int {
    func soma(x: Int, y: Int) -> Int {return x + y
    }
    func multiplicacao(x: Int, y: Int) -> Int {return x * y
    }if tipo == "soma" {return soma
    } else {return multiplicacao
    }
}

func calculadora(calculo: (Int, Int) -> Int, a: Int, b: Int) {
    println(calculo(a, b))
}

calculadora(calculo("soma"), 10, 20)// 30

Em Ruby, o mais próximo, usando blocos, seria:

12345678910111213141516
defcalculo(tipo)
  soma = lambda { |x, y| x + y }
  multiplicacao = lambda { |x, y| x * y }if tipo == :soma
    somaelse
    multiplicacaoendenddefcalculadora(c, a, b)
  puts c.(a, b)end

calculadora(calculo(:soma), 10, 20)# 30

Entendendo Blocos em Swift

Sabendo dessa base podemos prosseguir para o próximo passo, blocos em Swift.

Primeiro, vejamos o uso mais comum de blocos em Ruby:

12345678
defnumero(bla)yield(bla) if block_given?end

numero 20do |x|
  x * 10end# 200

Definimos um método chamado numero que recebe um parâmetro "bla". Internamente chamamos yield que pega o bloco passado como último parâmetro do método e repassa o parâmetro "bla" a ele. Fora, executamos o método frase, passando 20 como parâmetro e um bloco (delimitado por "do..end") que recebe uma variável x e apenas multiplica ela por 10.

Podemos reescrever o mesmo código da seguinte forma:

123456
defnumero(bla, &bloco)
  bloco.(bla) if blocoend

numero(20) { |x| x * 10 }# 200

É exatamente o mesmo código mas agora o bloco está definido como parâmetro mais explicitamente. O "&" diz que vamos passar o bloco fora dos parênteses do método. Executamos o bloco dentro com o "ponto" (no lugar de "call", como explicamos antes). E ao executar o método, desta vez deixei os parênteses opcionais e no lugar de "do..end" usei "{}", que é a mesma coisa. Por convenção, em Ruby, usamos "{}" quando um bloco tem somente uma linha de implementação e usamos "do..end" quando tem múltiplas linhas.

Obs, o @josevalim me explicou que há outra sintaxe que podemos usar e são equivalentes (embora pareça que só funcione em one-lines):

12
numero.map { (var x: Int) -> Int in return x * 10 }
numero.map { $0 * 10 } // equivalente ao de cima

Confinuando, podemos fazer a mesma coisa em Swift, assim:

12345
func numero(bla: Int, bloco: (Int) -> Int) {
    println(bloco(bla))
}

numero(20, { (x: Int) -> Int in return x * 10 } )

Por causa da necessidade de definir o seletor/assinatura, com parâmetros e tipo de retorno, a execução da closure em Swift é bem mais verbosa do que em Ruby. A sintaxe é semelhante, usando chaves "{}" para delimitar o bloco, a assinatura para delimitar a função anônima e o corpo do bloco depois de "in". Na prática é quase a mesma coisa.

Do livro oficial da Apple temos o seguinte exemplo que pode demonstrar um pouco melhor (eu mudei o exemplo pois no livro ele usa um Dictionary para "digitNames" mas as chaves são exatamente a posição num Array, então achei melhor usar diretamente um Array):

12345678910111213141516
let digitNames = ["Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"
]
let numbers = [16, 58, 510]

let strings = numbers.map {
    (var number) -> String in
    var output = ""while number > 0 {
        output = digitNames[number % 10] + output
        number /= 10
    }return output
}// strings is inferred to be of type String[]// its value is ["OneSix", "FiveEight", "FiveOneZero"]

A mesma coisa em Ruby ficaria assim:

12345678910111213
digit_names = ["Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"
]
numbers = [16, 58, 510]
strings = numbers.map do |number|
  output = ""while number > 0
    output = digit_names[number % 10] + output
    number = number / 10end
  outputend# ["OneSix", "FiveEight", "FiveOneZero"]

Veja como a lógica em si é bastante semelhante, se ignorar a definição mais exata de tipos do Swift, os dois códigos são praticamente idênticos.

No meu post de 2010 sobre como implementar o equivalente a "method_missing" em Objective-C eu parti deste exemplo comum de DSL do mundo Ruby:

12345678910111213
require 'builder'
x = Builder::XmlMarkup.new(:target => $stdout, :indent => 1)
x.html do |h|
  h.body do |b|
    b.h1 "Hello World"
    b.p "This is a paragraph."
    b.table do |t|
      t.tr do |tr|
        tr.td "column"endendendend

E cheguei neste equivalente em Objective-C:

123456789101112
XmlBuilder* xml = [[XmlBuilder alloc] init];
[xml htmlBlock:^(XmlBuilder* h) {
    [h bodyBlock:^(XmlBuilder* b) {
        [b h1:@"Hello World"];
        [b p:@"This is a paragraph."];
        [b tableBlock:^(XmlBuilder* t) {
            [t trBlock:^(XmlBuilder* tr) {
                [tr td:@"column"];
            }];
        }];            
    }];
}];

Absolutamente verborrágico! Não era divertido usar blocos em Objective-C pela quantidade de delimitadores com chaves, parênteses, colchetes. Em Ruby é bem mais simples porque parênteses são todos opcionais e blocos são delimitados quase como métodos.

Ainda não reimplementei esse experimento que fiz em Objective-C para Swift (fica como lição de casa). Farei isso num próximo artigo sobre metaprogramação e seletores em Swift. Mas se tivéssemos reescrito, provavelmente o código ficaria mais ou menos assim:

12345678910111213
// Swift:                            // Ruby:
xml = XmlBuilder()                   // x = Builder::XmlMarkup.new
xml.html({ (var h) -> Void in        // x.html do |h|
    h.body({ (var b) -> Void in      //   h.body do |b|
        b.h1("Hello World")          //     b.h1 "Hello World"
        b.p("This is a paragraph")   //     b.p "This is a paragraph."
        b.table({ (var t) -> Void in //     b.table do |t|
            t.tr({ (var tr) -> Void  //       t.tr do |tr|
                tr.td("column")      //         tr.td "column"
            })                       //       end
        })                           //     end
    })                               //   end
})                                   // end

Veja que comparado à versão em Objective-C é "muito" melhor. Mesmo assim, se comparado ao que fazemos em Ruby, continua sendo mais verboso do que gostaríamos por causa dos parênteses obrigatórios e declaração de tipos das funções, mas agora sim fica muito mais prático ver que podemos fazer DSLs em Swift também.

Isso deve dar uma luz sobre como a nova sintaxe do Swift é de fato um real ganho de legibilidade e produtividade para programadores acostumados a Objective-C e como nós, de Ruby, podemos rapidamente nos adaptar a essa nova linguagem para produzir bibliotecas e frameworks. Uma vantagem do Swift é que ele é imediatamente compatível com toda a API escrita em Objective-C, portanto onde antes era chato escrever as closures, agora fica imediatamente mais simples.

Usando Polymer com Rails

$
0
0

Depois do Google I/O 2014 apresentando a nova linguagem de interface unificada "Material Design" espero que desenvolvedores de Android implementem em seus aplicativos o quanto antes. Acredito que o Android L será uma excelente nova versão, seguindo de onde o Holo no KitKat ficou.

Em paralelo, o Google implementou a mesma UI para aplicações Web com o Polymer, usando a nova possível tendência de Web Components. Aprenda sobre custom elements, shadow DOM, HTML imports, web animations.

Depois do Google I/O imagino que muitos vão querer fazer pelo menos aplicações web mobile parecidas com o Topeka - aliás, Topeka pode ser o novo "Hello World" de aplicações web responsivas.

O Polymer usa muitas funcionalidades novas que apenas os Chrome e Firefox mais recentes realmente implementam, o resto vai polyfills. Mesmo assim a compatibilidade ainda não é 100%, especialmente para Internet Explorer, obviamente, e Safari, surpreendentemente (que é mais relevante pois não só deixa OS X um nível pra trás, mas pode dificultar Web Components em dispositivos iOS por enquanto).

Isso tudo dito, imagino que muitos queiram integrar esse novo tipo de interface em sua aplicações Rails. Uma coisa que de cara me deixou um pouco nervoso é o fato de que cada Web Component é um trecho de HTML, e cada um deles tem seus próprios imports de CSS, Javascript. Em Web, isso é horrível pois significa que se você tem 10 web components, cada um com 2 CSSs cada, só isso já significa 10 + 10 * 2 = 30 requisições para puxar assets.

Estamos já acostumados a concatenar, minificar, criar nomes CDN-friendly para assets em um único arquivo com objetivo de diminuir drasticamente esse overhead, para isso serve nosso bom e velho Asset Pipeline. Mas como funciona isso com Polymer no Rails?

Solução: iniciando com emcee

TL;DR: O emcee "quase" resolve todos os problemas em usar Web Components, mas falta um pequeno aspecto que vou descrever no fim do artigo.

Entra a gem Emcee. Para usá-lo é simples, apenas adicione na sua Gemfile, rode bundle install e execute o generator para criar o boilerplate:

12
# coloque no seu Gemfile e execute bundle install
gem 'emcee', github: 'ahuth/emcee'

Estamos puxando direto do master do Github porque pelo a versão publicada na época deste artigo está com um bug no gerador, mas o master funciona. E como Web Components ainda está em evolução, esse procedimento deve evoluir ainda, então preste atenção à documentação no README do Emcee antes de usar.

1
rails generate emcee:install

Agora você pode usar Bower para instalar components em 'vendor/assets/components'

Em todo projeto você precisa pelo menos começar instalando o próprio Polymer e os polyfills:

12
bower install Polymer/polymer
bower install Polymer/platform

Agora adicione em 'app/assets/components/application.html':

1
*= require polymer/polymer

E adicione o polyfill em 'app/assets/javascripts/application.js':

1
require platform/platform

Prototipando com Polymer

Para rapidamente desenhar um protótipo de layout, você pode usar a ferramenta open source Designer:

Designer

Veja o tutorial do Google I/O para começar a se aquecer no Designer. Ela é uma IDE WYSIWYG onde você pode simplesmente arrastar os componentes num canvas e customizar como quiser. A vantagem é poder ver o que está fazendo já que ainda é tudo muito novo. E no final você pode salvar o que fizer na sua conta Github e ele vai lhe dar o código-fonte para servir de base. Ela estará disponível como um Gist, como no meu exemplo:

Gist

Veja a imagem acima, vamos parte por parte. O bloco "A" mostra quais web components do Polymer estamos usando. No nosso projeto precisamos instalar cada um usando o Bower. Lembre-se se usar o namespace "Polymer" antes, desta forma:

123456
bower install Polymer/core-drawer-panel
bower install Polymer/core-menu
bower install Polymer/core-item
bower install Polymer/core-icon-button
bower install Polymer/core-toolbar
bower install Polymer/core-scroll-header-panel

Agora vamos inserir as dependência de componentes em 'app/assets/components/application.html':

123456789
<!--
 *= require polymer/polymer
 *= require core-drawer-panel/core-drawer-panel
 *= require core-menu/core-menu
 *= require core-item/core-item
 *= require core-icon-button/core-icon-button
 *= require core-toolbar/core-toolbar
 *= require core-scroll-header-panel/core-scroll-header-panel
-->

Veja que existe um bloco colapsado de stylesheets. No meu exemplo de Rails criei um controller básico chamado "Post" com uma única action para "index", somente para ter um ponto de partida. E o stylesheet pode ser colocado no padrão 'app/assets/stylesheets/post.css.sass':

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
// PlaceallthestylesrelatedtothePostcontrollerhere.
// Theywillautomaticallybeincludedinapplication.css.
// YoucanuseSass (SCSS) here: http://sass-lang.com/:host {position: absolute;width: 100%;height: 100%;box-sizing: border-box;
}#core_drawer_panel {position: absolute;top: 0px;right: 0px;bottom: 0px;left: 0px;width: 100%;height: 100%;
}#section {box-shadow: rgba(0, 0, 0, 0.0980392)0px2px4px, rgba(0, 0, 0, 0.0980392)0px0px3px;background-color: rgb(250, 250, 250);
}#section1 {height: 100%;box-sizing: border-box;background-color: rgb(221, 221, 221);
}#core_scroll_header_panel {width: 100%;height: 100%;position: absolute;top: 0px;left: 0px;
}#core_toolbar {color: rgb(241, 241, 241);fill: rgb(241, 241, 241);background-color: rgb(66, 133, 244);
}#section2 {height: 5000px;background: linear-gradient(rgb(214, 227, 231), rgb(173, 216, 230));
}#core_menu {font-size: 16px;position: absolute;top: 0px;left: 0px;width: 100%;height: 100%;
}

Finalmente, o bloco C é o miolo de componentes. O designer, por padrão, define um custom-element e um template, a intenção é que tudo que você desenhar no Designer será por padrão um novo web component inteiro. Mas não precisamos fazer isso, podemos pegar somente o miolo e colocar em 'app/views/post/index.html.erb' assim:

123456789101112131415161718192021222324252627
<core-drawer-panelid="core_drawer_panel"><sectionid="section"drawer><core-menuselected="0"selectedindex="0"id="core_menu"><core-submenuactivelabel="Topics"icon="settings"id="core_submenu"><core-itemlabel="Topic 1"id="core_item"horizontalcenterlayout></core-item><core-itemlabel="Topic 2"id="core_item1"horizontalcenterlayout></core-item></core-submenu><core-submenulabel="Favorites"icon="settings"id="core_submenu1"><core-itemlabel="Favorite 1"id="core_item2"horizontalcenterlayout></core-item><core-itemlabel="Favorite 2"id="core_item3"horizontalcenterlayout></core-item><core-itemlabel="Favorite 3"id="core_item4"horizontalcenterlayout></core-item></core-submenu></core-menu></section><sectionid="section1"main><core-scroll-header-panelcondensesheaderheight="192"condensedheaderheight="64"id="core_scroll_header_panel"><core-toolbarid="core_toolbar"class="tall"><core-icon-buttonicon="arrow-back"id="core_icon_button"></core-icon-button><divid="div"flex></div><core-icon-buttonicon="search"id="core_icon_button1"></core-icon-button><core-icon-buttonicon="more-vert"id="core_icon_button2"></core-icon-button><divid="div1"class="bottom indent">AkitaOnRails.com</div></core-toolbar><sectionid="section2"content></section></core-scroll-header-panel></section></core-drawer-panel>

Só para garantir, veja se seu 'app/views/layouts/application.html.erb' está assim:

123456789
<head><title>PolymerTest</title><metaname="viewport"content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"><%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %><%= javascript_include_tag 'application', 'data-turbolinks-track' => true %><%= html_import_tag "application", "data-turbolinks-track" => true %><%= csrf_meta_tags %></head>

Isso deve ser suficiente. Se subir seu servidor de desenvolvimento com "bundle exec rails s" e abrir o "localhost:3000/post/index" no seu browser, teremos algo parecido com o que vimos no Designer:

localhost test

Se abrirmos o código-fonte deste HTML veremos todos os components expandidos, como com qualquer outro asset:

Assets em desenvolvimento

Você pode ver isso rodando no Heroku em http://polymer-demo.herokuapp.com/.

Problema Temporário: HTML Compressor

Havia um problema na versão de quando este artigo foi escrito onde os ícones em SVG como a lupa de pesquisa não apareciam em produção. Conversando com o autor do projeto Emcee, o @ahuth. Citando o que ele respondeu no meu issue no Github, quando o HTML compressor encontra esta linha no core-iconset-svg:

1
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');

Ele acaba removendo tudo após o "http://" e nos deixa com este javascript quebrado:

1
var svg = document.createElementNS('http:

O @ahuth resolveu esse problema num branch do Emcee, portanto, se tiver o mesmo problema em produção, use esta versão no seu 'Gemfile':

1
gem 'emcee', github: "ahuth/emcee", branch: "fix-compressor-removing-urls"

Isso deve resolver! E não deixe de seguir esta thread sobre paths de assets que pode ser relevante em alguns componentes.

O código de exemplo deste artigo está no meu Github. Quando problemas como o caso dos ícones SVG do core-icons não estarem aparecendo no core-icon-button forem resolvidos a combinação Emcee+Bower-Rails pode ser a solução canônica para usar Polymer completo no Rails.


Web Components é uma Revolução?

$
0
0

Existe uma nova celebridade na cidade, e seu nome é "Web Components". Ultimamente muitos apresentam esta nova tecnologia como o 'Santo Graal' que vai resolver todos os problemas da Web. Este artigo não é um apoio incondicional, não é uma crítica negativa irrefutável, mas meramente uma apresentação de perspectivas com o objetivo de dar clareza. Nenhuma discussão pode funcionar onde os gritos mais altos são simplesmente "Isso vai revolucionar a Web!" (sem explicar porque) ou "O Google e a Mozilla estão por trás então é foda!" (sem comentários).

Do ponto de vista puramente técnico é muito simples entender o que é um "Web Component". Ele é o conjunto de 4 tecnologias de navegadores web.

  • Custom Elements
  • HTML Imports
  • Templates
  • Shadow DOM

Colocando em ordem de importância, eu resumiria da seguinte forma:

  • Custom Elements - permite criar tags diferente dos canônicos como "body", "input" e evitar o classes-hell ou div-hell onde tudo é um punhado de divs dentro de divs criando os horrendos macarrões de tags. A idéia é encapsular tudo dentro de tags simples e mais fáceis de manusear.
  • Shadow DOM - para o fator encapsulamento, precisamos primeiro conseguir eliminar o sangramento de estilos e comportamentos por tudo que existe numa página. Shadow DOM permite criar trechos de nós de elementos de DOM que são independentes e isolados entre si, onde o estilo de um trecho não interfere com outro. Somente o Chrome e Firefox mais novos suportam isso. WebKit/Safari deixou de suportar a implementação incompleta que tinham (mas talvez voltem) e o IE, para variar, nunca nem tentou implementar isso. Para funcionar na maioria dos navegadores existem projetos como o Polymer/Platform e X-Tag para servir como "polyfill" para navegadores legados.
  • Templates - como o nome diz, para criar componentes dinâmicos, é importante ter trechos de DOM inertes, diferentes de somente uma string, para conseguir manipular e instanciar conforme necessário. Por exemplo, linhas de uma tabela dinâmica. Existem várias bibliotecas de templates, como Mustache, mas para Web Components funcionar, era importante ter um padrão.
  • HTML Imports - e uma vez tendo um trecho de DOM isolado, com estilos e comportamentos independentes de outros componentes, agora precisamos empacotar isso. E para isso servem esses imports que basicamente é um arquivo HTML que declara os arquivos CSS e Javascript que ele depende, e o HTML Import sabe como carregar tudo de uma vez. Aqui fica uma das minhas maiores preocupações - que vou tentar explicar mais para o fim.

Existem já dezenas de artigos e documentação de como é um Web Component, como construir um do zero e onde encontrar componentes. Não é foco deste artigo explicar os detalhes técnicos de um Web Component.

Por si só, devo dizer que são tecnologias interessantes que todo bom nerd gosta de brincar. Porém não deveria ser novidade que só porque alguma coisa é tecnicamente interessante, por si só, não garante absolutamente nada. A principal pergunta é: "o que eu ganho com isso?" Antes de responder a essa pergunta, toda tecnologia é somente uma solução procurando um problema.

Infelizmente nem eu, nem ninguém, temos como prever o futuro, então neste artigo quero avaliar qualquer proposta baseado no que temos no presente, relembrar o passado e o que isso pode representar no curto prazo. O longo prazo deixo para os profetas e quem gosta de apostar em loteria. Então vou tentar quebrar alguns dos grandes problemas do desenvolvimento Web que temos hoje.

O Problema do HTML/CSS macarrônicos

A forma de desenhar uma página Web mudou bastante nos últimos 20 anos. As tecnologias básicas ainda são as mesmas: HTML 5 para estruturar um documento. CSS 3 para estilizar os elementos nesse documento. Javascript para adicionar comportamento. Acho que a esta altura todos já sabemos que devemos separar estilização/apresentação da estrutura e conteúdo. Também sabemos que não devemos nem usar tabelas para tudo e nem usar divs com float para tudo.

Passamos pela era da Web Semântica e Web Responsiva. Quando os navegadores implementaram tables no Netscape Navigator 1.1 e IE 2.0 em 1995 e 1996 ainda não se falava em acessibilidade e semântica apareceriam a partir de 1997 com o HTML 3.2. Estávamos criando a Web e usando ao mesmo tempo, como hoje as implementações apareciam antes de se ter uma especificação mais geral. A W3C é lenta não é de hoje.

Acho que a evangelização de Responsive Web também merece um "rant" mas fica para outro artigo.

Mesmo assim ainda somos reféns de códigos como deste exemplo de tabs do framework Bootstrap:

12345
<ulclass="nav nav-tabs"role="tablist"><liclass="active"><ahref="#">Home</a></li><li><ahref="#">Profile</a></li><li><ahref="#">Messages</a></li></ul>

E vejamos um trecho para tabs mas usando um web component do novíssimo Polymer/Paper:

12345
<paper-tabsselected="0"selectedindex="0"id="paper_tabs"><paper-tabid="tab_home"active>Home</paper-tab><paper-tabid="tab_profile">Profile</paper-tab><paper-tabid="tab_messages">Messages</paper-tab></paper-tabs>

Esse é o resultado da primeira tecnologia de Web Components: Custom Elements. De fato isso acrescenta uma clareza enorme. No primeiro exemplo o que temos é:

"Uma lista não ordenada com classes nav e nav-tags e dentro delas itens de lista."

Se você souber o que são as classes "nav" e "nav-tabs" vamos saber que se trata de uma lista de tabs. No caso do exemplo do Paper podemos ler claramente:

"Um conjunto de tabs, implementado com Paper."

Isto é um exemplo pequeno mas imaginando como páginas Web são complexas, tirar a ambiguidade de para que servem cada conjunto de tags numa árvore infinita de tags é muito importante. Perdemos muito tempo em tentativa e erro de retirar pedaços e tentando inserir outros pedaços no meio da árvore de HTML e decifrando nomes de classes CSS.

Na prática, sem ter Custom Elements para tornar as tags mais amigáveis, outra forma é encapsular a inicialização usando um marcador simples numa tag HTML (como uma classe CSS ou ID) e ativar o resto via Javascript. É como todo plugin JQuery funciona. Um exemplo simples é como encapsulamos o Google Maps com o plugin Gmap3 do JQuery:

12345678910111213141516171819
<divid="my-map"></div><script>$("#my-map").gmap3({map:{address:"Cupertino, CA",options:{zoom:4,mapTypeId: google.maps.MapTypeId.SATELLITE,mapTypeControl: true,mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
        },navigationControl: true,scrollwheel: true,streetViewControl: true
      }
    }
  });</script>

E outro exemplo com a alternativa com o Web Component Google-Map (lembrando que esta versão é mais simples do que o plugin Gmap3):

12345
<google-maplatitude="37.77493"longitude="-122.41942"fitToMarkers><google-map-markerlatitude="37.779"longitude="-122.3892"draggable="true"title="Go Giants!"></google-map-marker><google-map-markerlatitude="37.777"longitude="-122.38911"></google-map-marker></google-map>

Estamos movendo parte do que faríamos via Javascript de volta ao HTML. Mas somente isso não é suficiente e já sabemos disso. A tecnologia de "Cascading Style Sheet versão 3", comumente conhecida como CSS 3 até hoje permanece arcaica. Felizmente inventamos uma forma de tornar os malditos macarrões de CSS gerenciáveis. Agradecimentos são devidos à Hampton Catlin, um grande rubista que - em 2007 - inventou a linguagem de script SASS, que é um "super-set" de CSS e gera CSS 3, adicionando variáveis, nesting, partials, import, mixins, extensão/herança, operadores.

SASS foi a primeira linguagem de pré-processamento que acelerou a idéia da possibilidade de novas formas de gerenciar assets Web como CSS. Depois dele vieram LESS e toda uma gama de frameworks e bibliotecas como Singularity, Bourbon Neat, Susy, Zurb Foundation, Compass. Foi uma pena terem escrito o Twitter Bootstrap original em LESS em vez de SASS, mas acho que o projeto LibSass (SASS escrito em C) ainda não existia. Mas pelo próprio exemplo acima fica claro porque você deveria escolher outro framework em vez de Bootstrap.

Porém SASS não foi a primeira vez que alguém criou um pré-processador para a Web. Provavelmente a primeira foi a Wiki Markup implementada junto com o primeiro Wiki, o WikiWikiWeb de Ward Cunningham em 1995. Depois disso ainda tivemos o MediaWiki da Wikipedia até chegarmos atualmente a pré-processadores de HTML como Markdown, que praticamente usamos sem pensar em comentários de Github.

No mundo Rails já tentamos melhorar o HTML também, com pré-processadores como o HAML (do próprio Catlin) ou outros mais recentes como Slim. Mas nesse caso ainda não estamos melhorando o HTML tão drasticamente como SASS faz com CSS, por isso ainda não há uma boa alternativa e Custom Elements é o mais próximo de uma boa alternativa neste momento.

Estou trazendo estes pontos porque Web Components não declara nenhum pré-processador de CSS como padrão, por convenção. Assumimos CSS 3 puro. Não é um problema, mas se estamos falando de reuso, atualmente a melhor forma é usando mixins de SASS encapsuladas em bibliotecas como Compass ou Bourbon.

O Problema do Sangramento de Estilos e Comportamentos

Este é um dos aspectos mais irritantes de desenvolvimento front-end depois da compatibilidade de navegadores: como organizar as milhares de linhas de CSS? (seja ele puro, escrito em SASS ou LESS).

Antes de continuar, se nunca ouviu falar de CSS Anti-patterns, leia a respeito antes. E também que todos já pelo menos ouviram falar nas diversas metodologias para organizar CSS (OOCss , SMACSS, BEM). Eu honestamente não usaria ACSS e me foram dados bons argumentos para preferir BEM.

Essa introdução foi somente porque também não sou ainda um bom desenvolvedor front-end mas até aqui é o mínimo para começar. Vamos assumir que já passamos desses pontos também. Meu raciocínio começa pelo seguinte caso de uso: "quero criar CSS para um elemento visual, composto de diversos tags, e que não deve se deformar aleatoriamente por estilo de fora e nem deformar outros elementos ao redor." Seria o caso de um Widget ou o que poderia ser um "Web Component", ao pé-da-letra.

Passamos anos fazendo Widgets. As duas grandes formas são usando um iframe com postMessage() ou zerar os estilos de um trecho do DOM com Cleanslate e garantir que você está isolando seu CSS e Javascript usando namespaces e torcendo pra acidentalmente não sobrar nada global no meio do caminho ou outro desenvolvedor sobrescrever o que você fez.

Isso mudou em 2012 quando surgiu a implementação de Shadow DOM. Os novos elementos do HTML 5 como "audio" ou "video" ou "range" foram criados dessa forma em muitos navegadores. Em resumo mencionamos que uma página Web é uma árvore de tags, essa árvore que chamamos de Document Object Model ou "DOM". Imagine se pudéssemos isolar um trecho de nós, uma sub-árvore, que não fosse influenciada pelos estilos externos e cujos estilos internos não "vazassem" para fora. Para isso criamos um novo elemento, um "ShadowRoot" que delimita uma sub-árvore isolada e independente e que, para todos os propósitos, não aparece no DOM principal, mas tem sua própria raíz de DOM isolada. Esse é o conceito.

No momento deste artigo, somente o Chrome a partir da versão 25 (hoje no 35), o Firefox a partir da versão 31 (hoje no 30) e Ópera versão 15 (hoje no 22) suportam Shadow DOM. A Apple retirou o suporte do WebKit em fevereiro. A Microsoft sequer considerou começar a implementar ainda.

Shadow DOM não é obrigatório para criar Custom Elements, mas é um recurso interessante e importante para atingir o objetivo de componentes Web independentes e isolados que não precisem recorrer a recursos como reiniciar o CSS de uma sub-árvore com artifícios como Cleanslate. De qualquer forma, seja via as convenções listadas acima e outras, ou seja via Shadow DOM, hoje temos como criar um nível razoável de isolamento e facilidade de manutenção. O problema é que isso não é inerente a HTML 5 e CSS 3, mas uma camada acima que não tem um consenso geral ainda.

O Problema de Reusar Elementos

Num mundo onde fazíamos praticamente tudo via server-side, esse era um problema praticamente resolvido. Seja com Rails e ERB/HAML/Slim, seja com templates de Django, seja com Blade em Laravel, seja com Razor em Asp.Net. Porém hoje temos aplicações mistas, onde deferimos muita lógica para a camada do navegador usando mais Javascript. Em vez de devolver pedaços prontos de HTML, agora devolvemos dados semi-estruturados em JSON e deixamos o Javascript criar os elementos no DOM.

Significa que no navegador temos um conjunto de dados e precisamos de uma forma de declarar os elementos de DOM onde vamos aplicar esses dados antes de instanciar o trecho no DOM. Do mundo Ruby surgiu uma das formas mais populares, Mustache, criado pelo co-fundador do Github, Chris Wanstrath. Depois outro rubista, Yehuda Katz, trouxe outra alternativa com o Handlebars. A idéia geral é criar um elemento "script" e dentro dela colocar templates usando a notação do Mustache. Então um Javascript pode pegar o conteúdo string dessa tag script e criar o elemento no DOM depois de mesclar com os dados que quiser.

Está claro que estamos fazendo uma "gambiarra" elegante. A parte não tão elegante é ter que injetar HTML usando "innerHTML", mas funciona muito bem. O outro problema é controlar manualmente coisas como imagens e javascripts que um elemento pode precisar mas antes dele ser usado, ou seja, talvez sem necessidade. Para isso precisamos controlar via Javascript.

Na definição de Web Components foi criado um novo elemento para resolver alguns desses problemas, o "template". Sua definição é bem recente, de fevereiro de 2014. Serve basicamente o mesmo propósito de colocar um template dentro de uma tag "script" mas em vez de ser somente um string injetável ele realmente é uma sub-árvore de DOM "inerte", que podemos manipular os nós via Javascript antes de ativá-lo ao inserir no DOM principal.

Por não ser mais um trecho de texto, perdemos a função do Mustache e do Handlebar de facilmente mesclar dados e inclusive ter alguma lógica como condicionais e loops. Em vez disso precisamos manipular os nós via javascript, fazendo coisas como:

1
t.content.querySelector('img').src = 'logo.png';

Em vez de ter:

1
<imgsrc="{{minha-imagem}}"alt="great image">

Neste caso de templates eu diria que demos 2 passos pra trás e 1 para frente. Provavelmente dentro de um "HTML template" vamos precisar ter um Mustache para completar o processo? Admito que não acompanho a especificação mas pelo pouco que vi até agora não me parece que a especificação W3C de HTML template resolve o problema que bibliotecas como Mustache, Handlebars ou HTMLBars resolvem hoje.

E não estou nem mencionando sobre Binding. Pelo que entendi isso não está na especificação, mas implementado em projetos como o Google MDV que agora está integrado ao Data Binding e Event Mapping do Polymer como TemplateBinding.

O Problema de Reusar "Componentes"

Definindo "Web Components" como, um conjunto de HTML, CSS, Javascript que funciona em independência e isolamento, finalmente sobra o problema de "empacotar" esse conjunto. E agora entra a nova especificação de HTML Imports de Julho de 2014.

Na prática, um HTML Import é nada mais do que um arquivo HTML "normal" com links para outros arquivos como stylesheets, imagens, javascripts e outros assets. Novamente, não vou descrever todos os detalhes e para aprender mais leia o artigo Why imports?.

Atualmente, se precisamos usar algum conjunto desses, como um componente de Bootstrap, por exemplo, precisamos manualmente linkar para os stylesheets na ordem correta e fazer algo como:

123456789101112
<head><linkrel="stylesheet"href="bootstrap.css"><linkrel="stylesheet"href="fonts.css">
  ...</head><body>
  ...<scriptsrc="jquery.js"></script><scriptsrc="bootstrap.js"></script><scriptsrc="bootstrap-tooltip.js"></script><scriptsrc="bootstrap-dropdown.js"></script></body>

Com HTML Imports podemos fazer simplesmente:

123
<head><linkrel="import"href="bootstrap.html"></head>

O problema imediato de algo como Web Components é que qualquer pequena página pode ter rapidamente dezenas de Imports, cada import requerendo outros arquivos e potencialmente triplicando ou mais a quantidade de chamadas pela rede. Quando tivermos algo melhor como HTTP 2.0 ou outro processo de pipelining e multiplexing como com o protocolo SPDY talvez não tenhamos que nos preocupar com isso, mas com o HTTP 1.1 que temos hoje precisamos ainda pensar em como economizar ao máximo chamadas de rede para pedir assets.

O mundo Rails trouxe pela primeira vez uma implementação de um processo completo e automatizado para concatenar e minificar stylesheets, javascript e sprites com o Sprockets que Sam Stephenson - também criador do Prototype - iniciou em fevereiro de 2009 (obviamente os componentes que podem ser usados pelo Sprockets, como compressor, já existiam). Finalmente o Sprockets foi adicionado ao Rails 3.1 lançado em Agosto de 2011 como "Asset Pipeline".

Hoje em dia o Sprockets continua sendo uma das opções mais completas e outros frameworks correram para criar suas próprias versões, como o "connect-assets" para Node.js, diversas receitas para Grunt e Gulp) e opções para Grails, Cassette/ASP.NET MVC, Pipeline Django.

No mundo de Web Components foi imediatamente criado o projeto Vulcanize ou no caso do mundo Rails podemos adicionar o processo ao próprio Sprockets com o projeto Emcee, que foi o tema do meu post anterior. A idéia é pegar os HTML imports e concatená-los num único arquivo, incluindo tornar os links para stylesheets e javascripts externos como trechos inline num único HTML. Nem o Vulcanize e nem o Emcee atualmente minificam seus conteúdos, no entanto.

Note que imports é apenas uma parte do problema. Nem vamos entrar no problema de gerenciamento de versões (problema que projetos como Bower, NPM, Bundler no Ruby, PHP Composer, NuGet, Gradle, Pip, etc foram criados para resolver). O que acontece com componentes que dependem de versões específicas de outro componente? E bibliotecas internas como JQuery que um componente pode precisar? Ainda não sei o que acontece nesses casos.

Web Components é uma "Revolução"?

Tudo isso dito, vamos revisar:

  • Podemos criar conjuntos de tags isolados com Shadow DOM, com seus próprios estilos e comportamentos que não vazam e não automaticamente herdam estilos e comportamentos do DOM principal, a técnica é usar Shadow DOM (ou uma das formas antigas com Cleanslate, criação de elementos com Javascript, IFrame)
  • Podemos definir trechos inertes de HTML que podem ser instanciados via Javascript para dentro do DOM. Com projetos como TemplateBinding recuperamos algo como HTMLBars e podemos mesclar dados com o template. A técnica é usar HTML template e Polymer (ou uma das formas antigas com Mustache, Handlebars, HTMLBars).
  • Uma vez definido nosso "widget" ou "componente", podemos encapsulá-lo dentro de uma embalagem mais amigável usando Custom Elements (ou uma das formas antigas como plugins de JQuery fazem com Javascript para encapsular).
  • E uma vez montado o Widget/Componente podemos empacotar tudo num único HTML Import para podermos resusar facilmente dentro de outros HTML (em vez da forma antiga de declarar manualmente os arquivos de dependência)

Vocês devem ter notado que do ponto de vista de um desenvolvedor que apenas consome tais componentes/widgets, o processo em si é uma melhoria mas não é tão diferente quanto utilizar plugins de JQuery. De fato é uma passo adiante, oficializando o que antes era "gambiarra" em alguma coisa um pouco melhor (Custom Elements em vez de Javascript, Shadow DOM em vez de IFrame, HTML Template em vez de string em tag Script).

E aqui vem o maior desafio ao conjunto de tecnologias de Web Components: ele é definitivamente melhor. Só que não é disruptivo. Ao usuário final, o que ele "vê" e "interage" numa página web no navegador será exatamente idêntico. Significa que o usuário final tem muito pouco a se beneficiar da tecnologia. Portanto ele não é o público-alvo.

O público-alvo é o desenvolvedor front-end que, em vez de buscar um plugin JQuery - por exemplo - vai buscar um Web Component e a forma de utilizá-los não será muito diferente. Como ele não tem a motivação de melhorar muita coisa a seu público-alvo, ele tem muito pouco incentivo para mudar sua forma de trabalho.

O raciocínio é simples: quero colocar um Carrossel na minha página. Existem centenas, Jssor Slider, jCarousel, Slick - the last carousel you'll ever need. E para Web Components? Pelo menos no momento deste artigo só encontrei o Polymer-ui-carousel, que não chega aos pés dos antecessores. Qual você acha que o desenvolvedor front-end vai escolher?

Existem dois repositórios de componentes públicos (aliás, não entendi porque existem dois, um projeto como esse não ganha nada nascendo já fragmentado): o Component Kitchen com cerca de 276 componentes e o Custom Elements com 327 componentes. Como todo repositório inicial, a maioria deles não é de grande serventia. São mais demonstrações e provas de conceito. Sinceramente, alguém se dar ao trabalho para fazer um componente de Pokémon tem que ser só um tech-demo. É inútil. E você pode contar com coisas redundantes e/ou desnecessárias como botões de Facebook, gravatar, botão de Github, coisas que um AddThis já tem resolvido. Claro, não quero ser injusto e dizer que Web Components não tem utilidade só porque a primeira geração de componentes não é interessante. Essas coisas levam tempo para amadurecer, como qualquer tecnologia.

Para que a estratégia funcione ou a tecnologia em si é disruptiva - o que acabamos de ver que não é, é apenas evolutiva -, ou é necessário um pacote completo para ser candidato a "killer-app". Voltamos ao que disse antes sobre uma solução procurando um problema. Sem um verdadeiro killer-app-blockbuster é muito difícil conseguir tração e coesão de um ecossistema. No caso do Ruby isso foi o Rails. No caso do Go parece que é o Docker. No caso do Node foi o halo-effect do Google Chrome evoluindo o V8.

Para isso o Google criou o Polymer/Paper que define um conjunto coeso e visualmente integrado (via filosofia gráfica e interativa do Material Design que, assumindo que "pegue", também tem a vantagem de dar ao usuário final um "eye-candy" que justifique sua adoção). É uma proposição "tudo ou nada", embora você possa pegar pedaços dela, a intenção é fazer aplicações/sites usando inteiramente o Polymer.

O projeto Polymeré ambicioso e somente uma corporação como o Google poderia fazer algo assim tão rápido (dado que metade das especificações de tecnologia de Web Components como HTML Imports e HTML template são deste ano de 2014). Ao contrário do que deveria parecer, a arquitetura não é simples e com o pouco suporte de navegadores a única estratégia é criar Polyfills, implementações ("quasi"-completas) para tudo que navegadores "legados" mas que muita gente usa como IE abaixo de 10, Safari e Mobile Safari. Para isso serve o Polymer/Platform.

Arquitetura do Polymer

Só que já passamos do ponto de somente usar plugins JQuery, agora migramos para a era dos one-page-apps via Javascript que consome endpoints REST que retornam JSON. Estamos falando somente do ponto de vista de componentes, mas uma aplicação é maior do que isso. Para quem vem do mundo ASP.NET MVC, Rails, Django, falamos muito sobre o conceito "Web MVC" (Model-View-Controller) ou mais corretamente, MVC Model-2 da Sun, definido para J2EE.

Muitos nem sabem que usam outro modelo, o MVP (Model-View-Presenter) presente em ASP.NET (antigo), Window.Forms, GWT (Google Web Toolkit, lembram? Também do Google!). E, finalmente, também da Microsoft chegamos ao MVVM (Model View View Model), uma evolução de MVP com MVC2, mais conhecido pelos seus conceitos de Data Binding 2-way de elementos do DOM com models puxados via Javascript. Agora temos a categoria que vocês já devem ter conhecido com Knockout.js, Angular.js, Ember. Estamos falando de mais do que o jeito MVP de arrastar componentes a um canvas e adicionar eventos de callback, mas um framework completo que lida com Models, Views, Rotas.

O Yehuda Katz escreveu sobre integrar o Ember com Web Components em Maio e ele explicita muitos detalhes que vale a pena ler a respeito. Segundo esta thread no Google Groups, parece que o projeto Angular 2.0 deve também se integrar com Web Components e Polymer. Quando estes projetos e outros frameworks se unirem ao esforço Polymer provavelmente vamos ver o real valor dos Web Components.

Polymer é o projeto principal. Web Components é o conjunto de mecanismos, o meio para atingir esse objetivo. E é um problema clássico de ovo e galinha: os navegadores diferentes de Chrome precisam se equiparar e seguir a vontade do Google. Os polyfills, via Polymer/Platform e Mozilla X-Tag vão suprir o que falta (Mutation Observers, Shadow DOM, etc) como o JQuery fez no passado. Mas para os navegadores tracionarem nessa direção os desenvolvedores precisam entrar no barco, e para isso somente um pacote completo como Polymer/Paper e, se possível, aliado a frameworks como Ember e Angular podem fazer isso acontecer, e não pequenos componentes-demonstração.

A História se Repete

Já vimos essa história acontecer antes. Durante o Browser Wars muitos apenas vão se lembrar que a Microsoft conspirou ativamente para destruir a Netscape, culminando no processo que quase quebrou a Microsoft em 3 no ano 2000 e a consequência final que foi a sobra do amaldiçoado Internet Explorer 6 que, apesar de ter sido um excelente navegador em sua era, ele não deveria nunca ter durado mais de uma década em uso.

Muitos talvez não lembrem que isso também gerou muitas novas tecnologias, para listar algumas:

  • O Internet Explorer 3.0 foi o primeiro navegador a implementar o CSS 1.
  • O Internet Explorer 4.0 foi quem expôs o DOM e criou o DHTML, Dynamic HTML, com Dynamic Styling e manipulação de elementos do DOM via Javascript
  • O Internet Explorer 5.0 foi quem trouxe a semente do Ajax com o componente proprietário XMLHTTP e a técnica de buscar conteúdo de forma assíncrona com iframes usada no Outlook Web Access, dando origem ao XMLHttpRequest

O período negro pós-2000 da Microsoft culminou no fracasso do Windows Vista e consequente sobrevida à la The Walking Dead tanto do Windows XP quanto do IE 6. O Google pegou o bastão de onde a Microsoft largou. O Core Business do Google é o AdWords. Controlar as plataformas Web faz parte da estratégia e o navegador continua sendo importante, porque ele é o novo sistema operacional desta geração, seja desktop ou mobile. Esqueçam Windows vs OS X vs GNU/Linux.

Outra tecnologia Microsoft que foi esquecida foi a primeira verdadeira tentativa de componentizar a Web. Foi com HTML Components do fim de 1998. Nessa época ainda estávamos tentando dominar drag-and-drop de elementos com DHTML e começando a brincar com as possibilidades de fazer requisições sem precisar recarregar a página.

Se olhar esta página de APIs Legadas da Microsoft teremos:

  • Legacy DOM - substituída, claro, pelo DOM mais moderno
  • IE Architecture/Active X - substituído por Silverlight, Flash, ainda Applets e widgets
  • Browser Extensions - ainda temos extensions mas nenhum padrão
  • DHTML Behaviors e DHTML Data Binding - são os novos Web Components
  • Filters and Transitions - que até hoje temos browser-specific com modificadores como -moz ou -webkit, CSS 3
  • Vector Markup Language (VML) - que é o atual SVG e HTML 5 Canvas

Não estou querendo dizer que é tudo mérito da Microsoft. A intenção é apenas explicar - para quem começou a usar a Internet na era pós-Browser Wars e pós-Crash das Dot-coms que Web Components não surgiu do nada, ela é o próximo passo lógico da evolução dos browsers e arquitetura Web.

Para o próprio Google essa não é a primeira vez. A primeira vez foi com GWT (Google Web Toolkit), que nasceu em 2006. Esse foi o auge dos frameworks MVC back-end que facilitavam desenvolvimento de aplicações Web usando Ajax. Foi a era pós-J2EE onde surgiram Rails, Django e outros Rails/Django-like como CakePHP, Grails.

Depois veio a era back-end assíncrono, desenterrando o problema C10K de 1999 de Dan Kegel, use case de Web Sockets (chat, APIs) que começa com Scala, vai para Node.js, chega em GoLang, Elixir. Novamente, não veio do nada, foi o próximo passo evolutivo depois do próprio Erlang, Twisted, Tornado, Java NIO/Netty, etc.

Em paralelo o Google investiu no Chrome e para isso precisou investir em Javascript e tornar o V8 algo realmente usável. Milhares de homens-hora e milhões de dólares depois, temos uma engine realmente performática. Com isso o mundo Javascript cresceu exponencialmente. Uma tecnologia que já se imaginava dominada na década de 90 ganhou nova roupagem e uma segunda chance. Com isso a arquitetura MVC2 evoluiu para um híbrido, com frameworks MVVM no client-side.

Portanto é natural evoluir do mindset GWT para Angular.js e eventualmente para Web Components/Polymer. E é onde estamos agora. Note que estamos sempre circulando os conceitos de MVC-clássico, MVC Model-2, MVP e agora MVVM, todos patterns originados do lendário MVC de Trygve Reenskaug do Smalltalk-80. Lembrando que já experimentamos programação orientada a componentes antes: foi a década de 90, que imaginou uma revolução ao usar componentes reusáveis para tornar o processo de programação meramente um jogo de arrastar blocos. Isso ficou conhecido como RAD (Rapid Application Development), que deu origem a toolkits e IDEs. Foi o conceito que deu origem a PowerBuilder, Visual Basic, Delphi, Swing. E a evolução na direção de ferramentas CASE (Computer Aided Software Engineering). Achávamos que poderíamos criar diagramas (UML) e as ferramentas gerariam o código-fonte para nós. Já ouviu falar disso? Pois é, não deu muito certo. O Visual Studio de hoje ainda tem suporte a isso (yikes).

A diferença são as ondas da moda: na década de 90 ainda estávamos definindo o que era possível e, pelo bem ou pelo mal, o que a Microsoft inventou realmente foi revolucionário porque não havia precedente. A era pré-Bolha trouxe o MVC2 para o desenvolvimento Web com Web Objects e J2EE. O advento do Ajax e aplicações dinâmicas trouxe de GWT a Rails. E agora a era da Renascença do Javascript trouxe o MVVM e Web Components.

Não sei o que vem depois daqui, mas depois de organizar a informação histórica espero que mais alguém tenha insights do que vem pela frente. O que acham que Web Components realmente pode trazer que já não vimos com GWT e anteriores?

[Off-Topic] Alguém importante deixou a comunidade! E agora??

$
0
0

Esta semana um conhecido desenvolvedor da comunidade Node.js declarou estar deixando o barco. Foi TJ Holowaychuk, um dos mais prolíficos contribuidores dessa comunidade. Obviamente isso deve ter gerado alguma controvérsia e discussões e gente se desesperando.

Se você é um programador experiente, certamente não precisa de mim para ouvir isso. Mas se por acaso você ficou inseguro com as notícias recentes, talvez o que eu tenha a dizer lhes dê perspectiva.

Antes, quero compartilhar com vocês outros artigos que li poucos dias atrás:

  • My Next Chapter - eu achei que isso fosse gerar alguma discussão extra, mas é a declaração e Mike Perham, um dos mais conhecidos rubistas desta geração e criador do ubíquito e excepcional Sidekiq declarou não que está abandonando o projeto ou algo assim, mas que está trabalhando num novo produto e que ele não envolve Ruby.

  • Saying Goodbye To Python - neste caso foi o pythonista Ian Bicking, que declarou deixar o Python pelo Javascript, seguindo a onda atual. Importante entender que a bolha de Javascript atual não "requer" você "deixar" nada por ele. Novamente o caso em que você pode tranquilamente ser pythonista e usar javascript, não há conflito.

  • Why I Left the .Net Framework - um certo desenvolvedor chamado Jonathan Oliver resolveu também declarar porque está deixando sua tecnologia do dia-a-dia e aponta os pontos positivos e negativos das tecnologias Microsoft. Não é um troll, é até uma leitura bem interessante.

  • Java Again - quem é das primeiras gerações da comunidade Java não deve ter se esquecido de James Duncan Davidson, criador de nada menos do que o primeiro Tomcat e Ant. Ele deixou a comunidade Java, integrou a comunidade Ruby temporariamente, dedicou-se à fotografia (quem procurar por fotos das Rubyconf de 8 anos atrás vai ver as oficiais são todas dele). E agora declarou que está retornando ao Java.

  • Why Go Is Not Good - como o nome diz, é uma crítica de porque uma linguagem recém-lançada deveria ter sido melhor pensada para cobrir casos que outras linguagens já cobrem.

  • Rust vs Go - novamente, tem um certo apelo de "dor de cotovelo", no sentido de que Rust realmente parece ser uma tecnologia superior a Go em termos de design de linguagem e funcionalidades, e demonstra certa frustração de porque mesmo assim Go é mais popular.

  • Why Perl Didn't Win - é uma leitura obrigatória para observar circunstâncias de uma das linguagens mais populares desde o final da década de 80 até o final da década de 90, que caiu em esquecimento e desuso. Até mesmo o Swift, lançado pela Apple semanas atrás, já tem mais usuários ativos do que o Perl 6. Uma das conclusões? Qualquer coisa nova precisa almejar resolver os problemas do futuro, não os do passado.

Quem é das primeiras gerações da comunidade Ruby e Rails, em particular, vai se lembrar dos "traumas" que passamos:

  • Zed is Not Dead - de 2008, quando um dos nossos desenvolvedores mais prolíficos, Zed Shaw, criador do Mongrel e um dos primeiros a encarar o desafio de mensurar e otimizar a performance do Ruby declarou que estava deixando a comunidade e migrando para Python.

  • Bomba: Merb e Rails se fundem! - também em 2008 quando a equipe Merb estava em direção de colisão e destruição com o Core Rails e, felizmente (para alguns, infelizmente para alguns poucos - foi uma solução que deixou mortos e feridos), a solução foi engolir Merb para dentro do Rails 3. Em retrospectiva, vale ler o post "Learning from Rails’ failures" do Matt Aimonetti (que migrou pra Go também) e está entre os feridos da insurgência; e este outro "The Rails/Merb Merge In Retrospect" de Giles Bowkett (ainda rubista) que analisa os resultados com olhos bem críticos.

  • Twitter muda de Ruby para Java - de 2011 quando o Twitter declarou estar substituindo as partes da infraestrutura de mensagens que usava Ruby e migrando para uma solução proprietária em Scala. Apesar de o que a notícia original diz e o que as pessoas resolveram memorizar sejam diferentes, o fato é que foi uma boa dor de cabeça de Public Relations para nós. Felizmente isso já passou.

E esses links são apenas os que eu li e lembro de cabeça, existem dezenas de outros mais.

Para quem ainda é jovem ou inexperiente em comunidades de software, particularmente quem é novo na comunidade Node.js deve estar se perguntando "E agora? Se alguém importante como o TJ diz que está saindo, eu não deveria sair também?" E se você fizer sua pesquisa direito vai ver que esta não é a primeira vez. Em 2012 o criador do Node.js, Ryan Dahl declarou que continuaria acompanhando seu projeto mas não estaria mais envolvido no dia a dia de codificação. "Putz, o mundo acabou!"

Isto não é uma Má Notícia. Esta é uma Excelente Oportunidade! (Sério!)

Em 2006, logo quando eu estava iniciando minha carreira como ativista no mundo Ruby e Rails, eu já sabia o que estava por vir. Por sermos os novatos, imaturos, com tecnologia incompleta e muitas expectativas, naturalmente o caminho seria o mais difícil possível. Por isso escrevi o artigo Evolução pela Concorrência. Muitos imaginam que o melhor caminho do mundo seria onde ninguém questiona o que estou fazendo e apenas me deixam em paz, e acreditam nas minhas promessas que - obviamente - pretendo cumprir - um dia. (yeah, right ...)

Eu digo que não, qualquer promessa ou expectativa que valha a pena deve ser questionada, deve ser pressionada, deve ser escrutinada. Se essa promessa é tão fraca que não suporta críticas, ataques diretos e indiretos, sabotagens, então a promessa em si era fraca e não deveria merecer prosseguir. Quanto antes cair, melhor. Menos tempo estamos perdendo. Por isso eu sempre abraço ataques, pois eu espero estar pronto para contra-atacar em dobro ou morrer tentando. E eu não esperaria menos da comunidade Rails. Todos ainda acreditam que restrições são ruins, eu já disse antes que restrições são importantes: é o único lugar de onde surge inovação.

Qualquer um que precise utilizar dos velhos artifícios de falar mal dos outros, o famoso "eu não tenho vontade de melhorar, então vou prejudicar o outro para eu parecer maior" (escrevi sobre isso em 2007 também "Para eu ganhar, o outro precisa perder ..."), necessariamente se declara um fraco. Pare e relembre, artigos, palestras, entrevistas onde você ouviu alguém que você admira falando mal de outra comunidade. "Ah, Ruby, esse negócio de meninas. Porque nóiz homens usamos Javascript." Me faz rir e ter um pouco de dó, porque está claro para mim que será sempre um fraco.

Todas as declarações acima e similares - "Estou deixando Node". "Estou deixando .NET". "Estou deixando Ruby". "Estou deixando X" - eu honestamente acredito que seus autores não tenham tido nenhuma má intenção ou má fé, pelo menos não conscientemente. Porém eu tenho uma teoria. Todos que fazem declarações como essas querem validação de seus pares, ou pior, querem que seus pares o sigam - e isso também significa validação de sua posição. "Eu não gosto mais do meu brinquedo velho, mas também não quero que ninguém mais brinque com ele."É uma posição bem infantil.

Tomando como exemplo a comunidade Ruby, tivemos diversos nomes que meio que "deixaram" suas atividades principais na comunidade Ruby, mas não fecharam portas e nem agiram com infantilidade. Chad Fowler, está na Alemanha tocando a Wunderlist, focando em desenvolvimento Mobile e back-end e nunca mais ouvimos falando de Ruby. Ilya Grigorik teve sua startup adquirida pelo Google e eventualmente ele desapareceu também. Matt Aimonetti, depois do caso do Merb vs Rails, silenciosamente se retirou e agora está trabalhando com Go. Ryan Bates, um dos mais queridos da comunidade pelo seu trabalho incessante de 5 anos com o RailsCasts deixou de publicar faz meses e não declarou nada a respeito. David Chelimsky, mantenedor do RSpec, passou sua responsabilidade pra frente e se retirou sem alvoroço. José Valim, um dos principais responsáveis pelo Rails 3, hoje está com Elixir/Erlang e raramente ouvimos algo dele sobre Ruby.

"O.M.G! Quer dizer que tudo acabou!? Foi pelos ares!?"

Não, nesse meio tempo centenas de novos Rubistas surgiram e continuaram o trabalho. Exemplo imediato são os próprios Carlos Antônio e Rafael França, que meio que assumiram o manto do José Valim no Rails Core. Evan Phoenix assumiu o manto de Chad Fowler na RubyCentral. Avdi Grimm meio que assumiu o manto de Ryan Bates com seu excelente RubyTapas, e assim por diante.

Uma comunidade é formada por indivíduos. Indivíduos atuam no seu melhor quando eles agem para maximizar seu próprio benefício. Ao fazê-lo, o efeito colateral é que ele acaba naturalmente por influenciar e trazer mais para cima junto com ele. São sempre trocas voluntárias para mútuo benefício. Não existe quem age sem nenhum benefício para si próprio, mas há quem acredite que sim e são os que atingem seu "burn out" mais rápido, porque rapidamente a pergunta se torna:

"Por que eu me canso tanto de colaborar nessa comunidade, me estresso, e mesmo assim nem todos apreciam o que eu faço? Eu faço tudo por eles!"

Essa é a pergunta errada. E a pergunta errada, obviamente, leva à resposta errada. Alguns começam a acreditar que os outros devem alguma coisa a ele, já que ele dedicou tanto do seu tempo livre (especialmente no mundo open source) para "ajudar os outros". E "os outros" acreditam que não devem nada, já que ninguém pediu para eles fazerem esse esforço em primeiro lugar (e "os outros", na prática, estão certos).

Se você participa de uma comunidade, não o faz pelos outros, faz por si mesmo. Seja porque você entende que ajudar os outros faz parte da sua recompensa pessoal. Seja simplesmente porque isso te trás paz de espírito ou consciência limpa. Ou seja porque você é um bom estrategista e sabe que determinadas contribuições vão lhe abrir portas no futuro. Não importa o motivo, desde que exista uma recompensa que você não cobra obrigatoriamente dos outros. Cobrar respeito, cobrar educação, cobrar compaixão, nada disso faz sentido sem contrapartida: ninguém pediu para você fazer o que está fazendo, se está, entenda que é por você mesmo. É a definição de trabalho voluntário.

Aliás, para deixar bem claro: Trabalho Voluntário significa trabalho sem remuneração financeira e não sem benefícios ou altruísta. Se seu Trabalho é Financeiramente Remunerado, nesse caso a discussão é outra e o melhor conselho é de Don Draper:

Voltando ao assunto em questão, eu imagino que os nomes que mencionei acima que se retiraram parcialmente ou silenciosamente provavelmente entendem isso. Eles foram buscar satisfação pessoal em outro lugar. Eles não devem nada a ninguém e nem ninguém lhes deve nada.

Os que saem com declarações bombásticas estão, consciente ou inconscientemente, jogando na cara dos outros "você não me valorizou, agora perdeu sua chance, e eu sei que você vai sentir minha falta!" Não está escrito desta forma, mas é o que faz sentido, do contrário, porque jogar no ventilador e tornar isso uma controvérsia pública? Qualquer argumento por escrito é apenas parte da razão, e não "a" razão.

Você, Indivíduo

O outro lado da moeda é quem segue, admira, idolatra uma dessas pessoas que deixaram o lugar onde você está. Dependendo do seu nível de admiração, você provavelmente fica sem chão, atordoado, sem saber para onde correr. Das duas uma: ou você procura outro ídolo e começa o famoso "ele nem era tão bom assim" ou fica deprimido ou desesperado "não sei o que vai ser agora."

Meu conselho: "não tenha ídolos, tenha referências."

Pare de achar que você deve fazer alguma coisa pelos outros e, por consequência, pare de ficar jogando nos outros a responsabilidade de ajudar outros também. É isso que está acontecendo: você não entende seu propósito e acredita que os outros devem fazer o que você mesmo não faz. E pior, deixa os outros decidirem que caminho você deve tomar. Se você é tão inseguro assim, pare um instante e reflita o que você "é" primeiro.

Seu único propósito na vida é cuidar de si mesmo e produzir. E isso sem atrapalhar o caminho dos outros. Fazendo isso, o efeito natural é que colaborações expontâneas surgem, comunidades evoluem e todos saem ganhando. Uma comunidade onde todos cobram todos não cresce bem, cresce sem propósito.

Em particular sobre tecnologias, opiniões, propostas e promessas também lembre-se: você quer estar sob constante "ataque/restrições". Não há nada pior do que ser ignorado. Escrevi outro artigo, tradução de uma pessoa mais sábia do que eu, Kathy Sierra chamado Dilbert e a zona de mediocridade, onde eu cito:

Quão corajoso você é? Quão longe você iria (ou seu empregador) para evitar a Zona de Mediocridade? Até, ou, a menos que, você esteja disposto a arriscar por Ódio Passional, você pode nunca vir a sentir Amor. Scott Adams concorda. Em um post recente no blog do Dilbert, ele disse “se todos que forem expostos a um produto gostarem dele, o produto nunca será um sucesso … A razão de um produto que ‘todo mundo gosta’ falhará é porque ninguém o ‘ama’. A única coisa que prevê sucesso é paixão, mesmo que apenas 10% dos consumidores o tenham”.

E daí se alguém deixou sua comunidade? Por acaso sua comunidade é tão frágil que uma pancada - não importa o tamanho do impacto - vai desmoroná-la? Se você acredita que sua comunidade é somente resistente, você tem razão, depois de certo ponto, ela desmorona. Porém, se sua comunidade for resiliente, se ela é maleável e adaptável, ela vai sobreviver. É o que garante a sobrevivência das espécies: a Lei do Mais Adaptável (não do mais "forte"! Lembre-se: resistente vs resiliente, você quer ser o segundo).

Você é adaptável? Ou está somente procurando validação dos outros, deixando que eles decidam por você? Uma coisa eu digo com certeza: se um dia eu desistir do que eu faço, ninguém nunca vai saber por um comunicado por escrito, isso eu já havia determinado no dia em que comecei.

Aprendendo Ruby e Rails, Livros e Guias

$
0
0

Um dos mais conhecidos rubistas de nossa comunidade brasileira, Eustáquio Rangel acabou de lançar um bom ebook direcionado para quem quer começar com Rails. Conhecendo Rails. E por apenas USD 15, deixe-me dizer, é uma pechincha.

A intenção deste post é fazer um pequeno review deste livro e aproveitar para linkar mais material que vai te ajudar a ir adiante neste aprendizado.

Por acaso, o livro do Taq tem o mesmo perfil do Agile Web Development with Rails pois ele usa o desenvolvimento de um pequeno aplicativo de loja virtual como base. Obviamente, não será uma loja virtual completa e complexa para ser substituto de um Magento ou Spree Commerce mas serve para exercitar os principais conceitos do framework.

Uma coisa que gosto da linha do Taq é que ele se ateve ao stack básico do Rails. Por exemplo, todos os exemplos de código usam exclusivamente o Test/Unit do próprio Rails em vez de ir direto pra Rspec, incluindo funcionalidades como Fixtures em vez de ir pra FactoryGirl. Eu acredito que o melhor é usar o que vem já no Rails e depois evoluir pra RSpec, FactoryGirl ou Fabrication.

O livro começa explicando os conceitos mais copiados do Rails como "Don't Repeat Yourself" e o famoso "Convention over Configuration", que são as bases de um bom framework produtivo hoje em dia. Logo em seguida começa criando a estrutura da aplicação e indo para conceitos como Migrations, Asset Pipeline, Testes, ActiveSupport. Dali em diante ele expande sobre a aplicação apresentando funcionalidades como Rotas Restful, Views e Layouts, Associação de models do ActiveRecord. Finalmente, avança para conceitos um pouco mais complicados para quem está iniciando como Upload de Arquivos, Caching, Deploy. E no fim do livro ele lista outras coisas fora do framework que usamos nos projetos como Minitest, Guard, Capybara, FactoryGirl, Papertrail, e outros.

Para quem nunca viu o framework, o livro é excelente por apresentar as principais funcionalidades e dar exemplos dos aspectos essenciais.

Críticas

Não considerem minhas críticas como algo negativo ao livro. Enviei esta seção ao Taq para avaliação (ele provavelmente vai continuar evoluindo o livro), mas o que segue são minhas impressões iniciais.

A primeira é que o livro é baseado em Rails 4.0. Lembrem-se de que o Rails já está na 4.1. Leia o Release Notes para aprender sobre funcionalidades como Spring (em vez do Guard apresentado no livro), config/secrets.txt (ou mesmo dotenv-rails que não é falado no capítulo de Deploy). Mesmo da versão 4.0 senti falta de uma explicação sobre Turbolinks. E no capítulo de Caching ele explica sobre caches_page e caches_action, porém eles já não existem mais no Rails 4.1. O Taq menciona isso no livro mas precisa das gems actionpack-page_caching e actionpack-action_caching, mas isso não é mais recomendado. Em vez disso, o livro já menciona a alternativa que é o Russian Doll Caching ou mesmo primeiro ir para rack-cache e uso de etag/conditional get. Só isso já dá uma ordem de grandeza de performance e são simples de implementar.

Senti um pouco de falta de mais detalhes sobre ActiveRecord e Arel em particular. Muita gente que está iniciando não sabe que existem as Relations e como elas funcionam. Erros comuns como carregar tudo em memória em vez de usar ActiveRecord::Batches ou não usar a sintaxe do Arel e colocar tudo com strings. O ActiveRecord, por si só, daria outro livro inteiro de patterns, anti-patterns e truques. Mas mencionar esses aspectos já ajudaria.

O capítulo de Views e Layouts apresenta HAML. Não tenho nada contra o HAML, mas no conceito do livro de usar o stack padrão do Rails, talvez fosse mais importante manter o ERB para ficar coeso (e o resto do livro mescla HAML e partials com ERB) e deixar HAML e SLIM para os apêndices. Já o SASS é apresentado somente no final do livro, mas o SASS vem integrado por padrão no Rails e é uma das coisas mais importantes para produtividade front-end. É extremamente comum fazer qualquer aplicação Rails de front-end decente usando pacotes como Compass e Bourbon e frameworks de grid como Susy e Neat.

Em particular, o livro também tem uma seção sobre Bootstrap, mas eu dificilmente recomendaria como primeira opção. Ele se tornou famoso porque veio do Twitter mas é um conjunto de anti-patterns de front-end. Faça-se um favor e fique longe dele. Em vez disso vá direto ou pra algo bem experimental e ainda em evolução como o Polymer Paper ou para soluções mais tradicionais como o Compass Susy e Bourbon Neat que mencionei antes.

Quando entra no assunto de tarefas assíncronas, o Taq começa pelo Delayed Job - imagino porque não precisa instalar nada extra, já que ele usa o banco de dados para as filas. Porém, é mais do que normal usar diretamente Sidekiq (ou mesmo Resque, que ele substitui). Usar tabelas de banco como filas é um anti-pattern e por isso o Delayed já não é mais usado.

Sobre Deploy senti falta de mencionar assuntos de Cloud como o 12 Factors do Heroku, separar a configuração da aplicação em variáveis de ambiente com dotenv-rails. O Taq inclusive fala de Capistrano mas até porque as APIs dele sempre foram meio instáveis, ele resolveu fazer um próprio chamado Traq. Novamente, nada contra, foi o que levou a outros conhecidos como Vlad (não usado mais) ou Mina (ainda usado). Mas para um livro de iniciante eu tentaria manter o Capistrano como o básico porque muitos ainda usam e algo como Ansible como mais avançado, e mencionaria gigantes como Chef ou Puppet e opções como AWS Opsworks. Faltou também mencionar as opções mais populares hoje como DigitalOcean (por ser tão barato) e soluções como usar Dokku para ter um Heroku-like na DigitalOcean. Este é um assunto enorme, que daria um livro inteiro separado.

O Taq me explicou que o livro foi compilado a partir de material que ele vem usando em treinamentos faz alguns anos, por isso tem alguns aspectos que pode parecer "antigo". Exemplos disso são o Delayed Job que mencionei acima ou explicar sobre Paperclip para upload de arquivos quando hoje em dia a maioria usa diretamente Carrierwave (ou mesmo Dragonfly). Acredito que ele continue evoluindo o material, então continue acompanhando.

Além do Livro - Categoria Iniciante

Como disse antes, vou aproveitar o gancho deste review para adicionar mais material. Em particular veja o que a Casa do Código tem a oferecer, em particular:

  • Ruby on Rails - que foi escrito pelo grande Vini Baggio, hoje trabalhando na Medium.com. Ele tem uma estrutura semelhante ao livro do Taq com uma forma um pouco diferente no seu conteúdo. Acho que ambos se complementam em muitos aspectos para quem está iniciando.

  • TDD - Teste e Design no mundo real com Ruby - que foi escrito pelo Hugo Corbucci e Maurício Aniche. O livro do Taq demonstra códigos de testes diversas vezes durante o desenvolvimento do aplicativo mas é importante entender que testar é um "Processo". Uma das formas de implementar esse processo é por Test-Driven Development ou TDD e este livro vai ensinar como aplicar isso na prática, em Ruby.

  • Cucumber e RSpec - que foi escrito pelo Hugo Baraúna. Como disse antes, primeiro aprenda o básico de testes. Depois disso pule para RSpec para ver a diferença. Cucumber, em particular, não usamos mais tanto, mas os conceitos de Behavior-Driven Development (BDD) ainda são relevantes.

  • Ruby: Aprenda a programar na linguagem mais divertida - escrito pelo Lucas Souza. Muitos se perguntam se deve aprender Ruby ou Rails primeiro. Eu acho que se você está iniciando deve primeiro aprender o básico de Rails. Isso vai dar a motivação para logo em paralelo começar a explorar a linguagem Ruby em mais detalhes. Esse livro e o próprio Conhecendo Ruby são boas maneiras de começar.

Estes livros devem ser suficientes para que todos comecem tanto no framework Rails quanto na linguagem Ruby. Mas além disso existem os cursos online como da Alura onde eles oferecem 48 horas de curso de Rails que segue em parte o que o livro do Taq apresenta em texto. Depois disso recomendo ir para os cursos online da Code School, diferente da Alura me parece que o material deles é para quem já iniciou um pouco antes e ir do zero pode ser mais difícil.

Além do Livro - Categoria "Iniciante para Médio"

Além da Casa do Código, a editora The Pragmatic Bookshelf tem uma trilha de livros de Rails muito bons, em particular recomendo:

  • Learn Ruby The Hard Way - apesar de toda a controvérsia, é inegável que Zed Shaw é um excelente programador e também um ótimo escritor. Se você quiser escolher um único livro para iniciar em Ruby, eu recomendaria este. Ele é realmente para iniciantes, explica o básico, mas explica de forma sólida. Você pode ler a versão HTML online ou esperar a versão impressa que ainda não saiu.

  • The Ultimate Guide to Ruby Programming - é um livro muito fácil de entender para iniciantes. E se tem um educador que tem muita experiência ensinando Ruby, ele é realmente Satish Talim, do curso gratuito online RubyLearning.org. Está longe de ser o "ultimate" que declara em seu título. Mas antes de ingressar num curso como da Alura ou Code School, este material já se provou essencial para facilitar o começo do aprendizado. Eu diria que este ou o do Zed Shaw devem ser os primeiros antes de um curso online.

  • Confident Ruby - do grande Avdi Grimm e Sandi Metz, que publica os screencasts do Ruby Tapas. A maioria dos livros ensinando Ruby vai começar no básico, onde o mais diferente é quando se explica Metaprogramação. Mas a linguagem Ruby tem muito mais a oferecer que vai ter deixar muito surpreso e o Avdi destilou muito disso neste livro e nos seus screencasts. Você já precisa saber o básico de Ruby para ler este.

  • Exceptional Ruby - de novo, de Avdi Grimm, este livro complementa o anterior explicando um assunto negligenciado pela maioria dos livros de qualquer linguagem: os padrões e boas práticas de como lidar com exceções no seu código. Novamente, Avdi consegue surpreender quem achava que já conhecia a linguagem com coisas que você provavelmente nunca nem ouviu falar.

  • Eloquent Ruby - de Russ Olsen complementa os anteriores do Avdi Grimm e vai além dos livros básicos que explicam a sintaxe da linguagem Ruby. São livros que eu gosto porque não são apenas para iniciantes: muitos rubistas, que programam há anos, vão encontrar muitas novas técnicas que nem sabiam que existiam.

  • Practical Object-Oriented Design in Ruby: An Agile Primer - escrito pela Sandi Metz trás as principais boas práticas de como de fato organizar um código orientado a objetos, de fácil manutenção, em Ruby. Não basta jogar tudo dentro de uma classe e começar a herdar classes, isso não é OOP. Não basta jogar tudo dentro de módulos e fazer composição sem critério, isso não é OOP. Então leia este livro para se adequar ao que conhecemos com reais boas práticas.

  • Crafting Rails 4 Applications - por ninguém menos que José Valim, um dos grandes responsáveis pelo sucesso do Rails 3, neste livro explica mais sobre como o Rails funciona por dentro e como tirar proveito disso para criar aplicações modulares, indo de assuntos como template handlers, internacionalização, responders e muito mais. É um livro mais avançado.

  • Deploying Rails - como disse antes, o assunto Deploy daria um livro inteiro. Estava errado: daria mais de um livro. Este do Anthony Burns e Tom Copeland explica muita coisa importante para qualquer um que queira se tornar responsável por uma infraestrutura de produção de verdade, mas ainda não é completo. Eles entram nos assuntos de Vagrant, Puppet, Capistrano, Nagios, Ganglia. Mas ainda precisaria falar de Chef, Ansible, assuntos como load balancing, configuração de subnets, segurança e monitoramento, gerenciamento de logs com ferramentas como GreyLog e muito mais.

  • Rails Test Prescriptions - se tem um assunto que todo rubista já ouviu ad-nauseum é sobre testes. Significa que nós somos dos melhores para elaborar o assunto, sem sombra de dúvidas, e este livro do Noel Rappin trás mais da realidade de testes em muitos projetos Rails, explorando Rspec, Factory Girl, Rcov, e técnicas para garantir que seus testes não fiquem no seu caminho.

  • Metaprogramming Ruby 2: Program Like the Ruby Pros - se tem um assunto que realmente atrai outros programadores ao Ruby é metaprogramação. E mesmo para quem já usa Ruby no seu dia-a-dia, muitos de seus aspectos ainda são obscuros ou desconhecidos. Este livro do Paolo Perrotta deve ajudar a organizar seu conhecimento sobre este assunto que, uma vez entendido, torna-se trivial e parte importante das suas técnicas em projetos.

  • Ruby Under a Microscope: An Illustrated Guide to Ruby Internals - escrito por Pat Shaughnessy e eu diria que é o único livro realmente avançado desta lista e fora de qualquer categoria. O Pat foi literalmente bem a fundo, diretamente no código fonte do Ruby MRI e nos destilou um livro fácil de entender sobre como funcionam as menores engrenagens do motor do Ruby. Recomendo muito sua leitura se você já é um programador Ruby.

Conclusão

Muita gente gosta de ler livros técnicos, mas atenha-se a estes princípios:

  • livros demoram para ser escritos, revisados, publicados e distribuídos. Quando você comprar um livro, ele necessariamente estará um pouco defasado com o que você vai encontrar online, especialmente em projetos open source. O livro do Taq, por exemplo, usa Rails 4.0 mas já estamos no Rails 4.1. E isso é normal, só se lembre disso.

  • muitos desses livros tem conteúdo redundante, explicam as mesmas ferramentas mais de uma vez. Ignore a redundância se já conhece bem o assunto, claro, mas às vezes, ler sobre o mesmo assunto sobre a ótica de diferentes autores pode ajudar a dar mais clareza ao seu entendimento.

  • nunca tente ler um livro técnico intermediário ou avançado do começo ao fim, de capa a capa. No caso dos livros para iniciantes talvez isso seja o melhor, mas depois de ler dois ou três dessa forma, use os outros com livros de referência: pegue um capítulo mais à frente, depois volte um capítulo. A maioria não requer leitura numa única direção.

  • sempre acompanhe os autores, siga-os no Twitter, blogs, redes sociais. Seus livros sempre estão em atualização, novos livros podem estar sendo escritos. Livros, principalmente eBooks, são dinâmicos e como software também recebem atualizações que podem te ajudar e corrigir bugs.

  • livros não são caros. O do Taq, a USD 15, é uma verdadeira pechincha. O eBook do livro do José Valim custa USD 24 (aproximadamente R$ 57). Se for comprar todos os livros que mencionei neste artigo, significa um investimento que pode ser mais de R$ 600, se somar com cursos online, facilmente você vai investir R$ 1.000. Entenda: isso é absolutamente barato. Primeiro porque você não vai gastar tudo isso de uma só vez. Segundo porque investir R$ 1,000 em material (mais horas do seu tempo) para amanhã ter compensações que podem ser de R$ 1.500 até mais de R$ 5.000 por mês (se chegar no avançado, com experiência), mais do que compensa esse investimento.

Falando em investimento, lembre-se: seu conhecimento é sua responsabilidade! Nenhuma empresa ou instituição tem obrigações com sua atualização profissional. Se você não tiver interesse, ou achar que os outros é que deveriam investir em você, devo dizer que você está redondamente errado. Seu conhecimento, aprendizado e experiência são as únicas coisas que ninguém jamais pode tirar ou roubar de você. Cuide bem deles!

E além dos livros acima, quais outros vocês que já leram muito recomendam a quem está começando? Deixe suas recomendações e dicas na seção de comentários abaixo.

[Small Bites] Tirando Proveito de Threads em Ruby

$
0
0

Diferente dos meus longos posts TL;DR, quero experimentar um tamanho mais 'small bites'.

Vocês devem ter notado que em todo post do meu blog tem uma lista ao final organizando todos os links que eu espalho por todo o texto, assim você pode ir direto até lá se quiser se lembrar de um link, em vez de ter que reler o texto todo.

Para fazer isso eu implementei um simples before_save no meu model de Post onde eu vasculho o texto para buscar todos os links, desta forma:

12345678
html = self.excerpt_html.to_s + self.body_html.to_sreturn [] if html.empty?
doc = Nokogiri::HTML.parse(html)
links = doc.css('a').select { |link| link[:href] !~ /^#/ }
links = links.reduce([]) do |result, link|
  result << { :href     => link[:href],:title    => link.try(:children).try(:to_s).try(:strip),:internal => false }

Com isso tenho todos os links dentro da collection links, e agora vou de item a item, para puxar o link e buscar o título em seu conteúdo (que é o método retrieve_title no trecho abaixo):

123
links.each do |link|
  retrieve_title(link)end

Dependendo do post, se tiver muitos links (como o gigante recente de Web Components), ele pode demorar até quase 20 segundos!!

12
    user     system      total        real
0.310000   0.290000   0.600000 ( 19.968512)

O método retrieve_title que fiz, internamente chama outro método para puxar o link da internet e ler o título, usando Nokogiri:

12345678910111213
defparse_external_link(href)# require 'timeout' # precisa requerer isso antesbeginTimeout::timeout(3) {
      doc = Nokogiri::HTML(open(href,
        ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE,
        allow_redirections: :all))return doc.css('title').first.children.to_s.strip
    }rescuereturn""endend

E isso vai ser lento mesmo, porque o tempo de espera para fazer a conexão HTTP, esperar baixar os bits - que vai depender da velocidade da sua conexão -, para uma lista grande de links, pode demorar muitos segundos. E quanto mais links, mais vai demorar. No meu exemplo, no pior caso, se tiver 20 links e todos forem lentos, vai levar pelo menos 60 segundos pra terminar o processo (dado que eu coloquei um timeout de 3 segundos, no máximo, por link).

Outra forma é usar Thread. Mas aí a primeira coisa que você pode lembrar é:

"Mas eu sei que threads não funcionam em Ruby por causa do tal GIL - Global Interpreter Lock."

E isso é uma meia verdade. De fato, threads em Ruby não funcionam como em Java, por exemplo. Um único processo Ruby, só vai conseguir saturar um único Core do seu CPU. Mas internamente você pode executar tarefas concorrentemente em múltiplas threads se, e somente se, ela não bloquear. E no caso, I/O (chamada de rede, arquivo, sockets, etc) não bloqueia!

Sabendo disso, o trecho anterior eu posso escrever assim:

1234567
pool = []
links.each do |link|
  pool << Thread.new {
    retrieve_title(link)
  }end
pool.each(&:join)

Note que adiciono e inicio múltiplas threads e adiciono num array e depois dou join em todos eles, o que significa esperar até todos terminarem para prosseguir, mas neste ponto todos estão executando concorrentemente. E se fizer a mesma medição, com a mesma quantidade de links que antes estava dando mais de 19 segundos:

12
    user     system      total        real
0.200000   0.300000   0.500000 (  1.611597)

Apenas 1.6 segundo! Este trecho em particular ficou 12 vezes mais rápido com quase nenhum esforço!

Indo Além

Threads não são triviais, embora simples. Como em qualquer linguagem, devemos tomar cuidado para não escrever no mesmo recurso concorrentemente e cair em condições de corrida.

Existem outras formas de executar código em paralelo em Ruby. Uma delas é usar o bom e velho fork. E para abstrair threads e forks, você pode utilizar gems como o spawnling ou o mais maduro parallel.

Fork de processos tem a vantagem de ser "thread-safe", já que tudo vai rodar em processos isolados. Mas eles obviamente são muito mais pesados que threads. Somente a antiga versão 1.8.7 Phusion Enterprise Edition e agora a mais atual 2.1.2 tem o recurso de "copy-on-write", onde um fork não duplica a quantidade de memória.

Além de threads e processos, a terceira forma - mais na moda - é usar I/O assíncrono, com modelo de Actors. E para isso o melhor no mundo Ruby é o grande Celluloid, mas aí já é demais para este 'small bite'.

[Dica Rápida] Timeout no Heroku

$
0
0

Ano passado, quando um projeto de cliente entrou em produção, ter esquecido disso me custou várias horas de muita tensão. Graças à ajuda rápida e precisa da equipe de suporte e desenvolvimento do Heroku (thanks @ped) conseguimos contornar a situação.

O Heroku continua sendo minha recomendação a todos os meus clientes. A menos que você tenha uma situação presente muito particular (e lhes garanto, são casos raros), 99% dos casos cabem como uma luva no Heroku. Portanto, na dúvida, vá de Heroku.

Porém, o Heroku tem algumas peculiaridades que você precisa conhecer. Caso ainda não tenha visto, reveja meu artigo Enciclopédia do Heroku que publiquei em Abril de 2012.

Uma em particular merece atenção especial porque a maioria sempre esquece disso. O Router do Heroku evoluiu bastante desde o começo e também desde a controvérsia da RapGenius que estourou no começo de 2013. Mas o artigo não é sobre isso. Alguns já devem ter tentado navegar numa aplicação pesada que colocou no Heroku e receber uma página com um erro genérico roxa do próprio Heroku e não saber o que é. Ou, se você investiu pesado em marketing e começou a receber toneladas de acesso (dezenas ou centenas de requests por minuto), ver seus dynos patinando sem saber porque.

Então aqui vai a dica. Use a gem rack-timeout e configure um timeout baixo, igual ou menor que 15 segundos (que, convenhamos, se uma request demora 15 segundos pra ser processada é porque ela é extremamente mal feita. Culpe seu código antes de culpar o Rails, o Heroku ou qualquer outra coisa).

Para instalar é muito fácil. Adicione à sua Gemfile:

1
gem 'rack-timeout'

Rode bundle pra instalar e crie o arquivo config/initializers/rack_timeout.rb com o seguinte:

123
ifdefined?(Rack::Timeout)Rack::Timeout.timeout = Integer( ENV['RACK_TIMEOUT'] || 12 )end

Finalmente, configure sua aplicação no Heroku com o timeout que você quer, por exemplo:

1
heroku config:set RACK_TIMEOUT=10

E se você usa Unicorn, configure seu config/unicorn.rb com o seguinte:

123456789101112131415161718192021
# Based on https://gist.github.com/1401792

worker_processes 2

timeout 25

preload_app true

before_fork do |server, worker|
  if defined?(ActiveRecord::Base)
    ActiveRecord::Base.connection.disconnect!
    Rails.logger.info('Disconnected from ActiveRecord')
  end
end

after_fork do |server, worker|
  if defined?(ActiveRecord::Base)
    ActiveRecord::Base.establish_connection
    Rails.logger.info('Connected to ActiveRecord')
  end
end

Especial atenção à configuração de timeout. O timeout do Router do Heroku, por padrão, será sempre 30 segundos. Configure o timeout do Unicorn pra ser menor que 30 segundos (como no exemplo, 25 segundos), e configure o Rack Timeout pra ser menor ainda do que isso (no exemplo, 10 segundos).

Leia o README do Rack Timeout para mais detalhes, mas feito isso, se algum processamento levar mais do que 10 segundos para finalizar, ele vai estourar uma exception. E é isso que queremos, caso contrário o Router do Heroku vai cortar após os 30 segundos e não vai lhe dizer onde foi o problema, o gargalo que levou a dar um timeout acima dos 30 segundos.

Agora, você precisa de uma forma de ver o stacktrace gerado e para isso use uma opção simples como Exception Notification que você configura facilmente primeiro adicionando uma opção de envio de email à sua aplicação no Heroku como Sendgrid ou Mailgun, e então adiciona ao seu arquivo config/environments/production.rb algo como:

123456
config.middleware.use ExceptionNotification::Rack,:email => {:email_prefix => "[Exception - MyApp] ",:sender_address => %{"no-reply" <no-reply@myapp.com.br>},:exception_recipients => [ENV['EXCEPTION_NOTIFICATION_EMAIL']]
  }

Ou então adiciona algo mais parrudo como Honeybadger. O importante é você receber esse stacktrace. Com essa informação você pode otimizar sua aplicação. Talvez seja o caso de otimizar uma query muito lenta, talvez faltem índices nas suas tabelas (veja a gem Bullet), talvez seja uma questão de adicionar Caching, talvez você devesse mover um processo demorado como uma tarefa assíncrona via Sidekiq. Enfim, existem diversas opções para melhorar o tempo de uma requisição para que ela fique dentro do que eu considero como "bom" (abaixo de 1 segundo) ou "ótimo" (abaixo de 100ms).

E falando em otimização de requests, outra excelente opção ao Unicorn para colocar no Heroku é o Phusion Passenger que, com o novo garbage collector e a implementação de Out-of-Band Garbage Collector, pode diminuir dramaticamente o tempo das suas requests.

O importante deste artigo: você precisa de informação antes de saber como agir. O timeout default do Router do Heroku não vai lhe dizer, mas o Rack Timeout pode ser o que falta para descobrir seu gargalo, então configure o quanto antes.

[Small Bites] Entendendo conexões de Banco de Dados com ActiveRecord

$
0
0

Neste small bite, começo repetindo a mesma coisa que os seguintes posts do próprio Heroku já explicam:

Sugiro que vocês leiam os dois artigos acima com atenção, para aprender coisas como calcular quantidade de conexões que sua aplicação vai precisar, monitorar quantidade de conexões e muito mais. Em resumão, em todo projeto Rails, na dúvida, garanta que você tem o seguinte:

123456789101112
# crie o arquivo: config/initializers/database_connection.rbRails.application.config.after_initialize doActiveRecord::Base.connection_pool.disconnect!ActiveSupport.on_load(:active_record) do
    config = ActiveRecord::Base.configurations[Rails.env] ||Rails.application.config.database_configuration[Rails.env]
    config['reaping_frequency'] = ENV['DB_REAP_FREQ'] || 10# seconds
    config['pool']              = ENV['DB_POOL']      || ENV['MAX_THREADS'] || 5ActiveRecord::Base.establish_connection(config)endend

Se estiver usando Unicorn:

123456789101112131415161718192021222324252627
# crie arquivo: config/unicorn.rb
before_fork do |server, worker|# other settingsSignal.trap 'TERM'do
    puts 'Unicorn master intercepting TERM and sending myself QUIT instead'Process.kill 'QUIT', Process.pidenddefined?(ActiveRecord::Base) andActiveRecord::Base.connection.disconnect!endend

after_fork do |server, worker|# other settingsSignal.trap 'TERM'do
    puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to sent QUIT'endifdefined?(ActiveRecord::Base)
    config = ActiveRecord::Base.configurations[Rails.env] ||Rails.application.config.database_configuration[Rails.env]
    config['reaping_frequency'] = ENV['DB_REAP_FREQ'] || 10# seconds
    config['pool']            =   ENV['DB_POOL'] || 2ActiveRecord::Base.establish_connection(config)endend

Se estiver usando Sidekiq:

1234567891011
# crie arquivo: config/initializers/sidekiq.rbSidekiq.configure_server do |config|
  database_url = ENV['DATABASE_URL']ifdefined?(ActiveRecord::Base)
    config = ActiveRecord::Base.configurations[Rails.env] ||Rails.application.config.database_configuration[Rails.env]
    config['reaping_frequency'] = ENV['DB_REAP_FREQ'] || 10# seconds
    config['pool']            =   ENV['DB_POOL'] || 2ActiveRecord::Base.establish_connection(config)endend

Além do que tem nos artigos do Heroku (você já leu tudo, certo!?) vale entender alguns conceitos que muitos - principalmente iniciantes - podem achar estranhos.

Ruby suporta multithread e o framework web Rails (a partir da versão 4) vem por default ligado para ser thread-safe.

O que é um Connection Pool? A grosso modo, o conceito é que abrir e fechar conexões direto no banco de dados é uma operação "custosa" para se fazer o tempo todo, a cada query de cada requisição. Em vez disso, você deixa aberto um certo número num "pool" e recicla de lá. Em vez de "fechar" a conexão, devolve para o pool para que outra requisição possa reusar a mesma conexão. É um cache de conexões. Para quem vem do mundo Java, sabendo Hibernate, é o mesmo caso de se usar um C3P0, DBCP, BoneCP e outros.

Tecnicamente, um único processo Ruby, rodando com Unicorn, precisa de 1 única conexão ao banco. O Pool é por processo. Com um servidor como Puma, que suporta threads, então cada 1 processo Ruby pode precisar de mais de uma conexão de banco e aí precisamos de um pool para minimizar a quantidade de conexões abertas. Isso é importante porque quanto mais conexões abertas no servidor, pior - e usando serviços pagos como Heroku Posgresql, cada plano tem um número limite de conexões. O mesmo vale pra workers de Sidekiq, daí a configuração acima.

Quanto falamos em "throughput" web falamos de "quantidade de requisições por X" onde "X" é uma quantidade de tempo. Muitos ainda confundem "requisições por segundo" com "requisições simultâneas" e "usuários simultâneos". Usuários simultâneos fazem diversas requisições, mas elas não são todas simultâneas, cuidado com isso. Se uma requisição custa 300ms, então é possível fazer 3 requisições por segundo. Antes de cair numa fila, se temos 30 requisições por segundo, onde cada processo responde uma requisição a cada 300ms, precisamos uma capacidade teórica máxima de 10 processos. Obviamente, cada requisição tem tempos diferentes, mas isso é para dar uma idéia de ordem de grandeza.

10 processos trabalhando simultaneamente, significam pelo menos 10 conexões abertas no banco de dados. Na configuração do Unicorn, limitamos quantos "unicorn workers" podem existir. Cada um deles é um fork a partir do unicorn master. Por isso o código acima tem eventos de before_fork e after_fork, porque ao fazer um fork os recursos de I/O precisam ser reinicializados, arquivos abertos, sockets.

No caso de Puma, um mesmo processo pode executar requisições simultaneamente, concorrentemente, e cada thread precisa de sua própria conexão ao banco, daí voltamos ao pool de conexões. O Sidekiq também usa threads e precisa de um pool, novamente, daí o código acima configurando o tamanho do pool. Se estiver usando Puma, talvez seja necessário criar a seguinte configuração no arquivo config/initializers/database_connection.rb, em vez da que mostrei no começo:

123456789101112131415161718192021222324252627282930313233343536373839
modulePlatformmoduleDatabasedefconnect(size=35)
      config = Rails.application.config.database_configuration[Rails.env]
      config['reaping_frequency'] = ENV['DB_REAP_FREQ'] || 10# seconds
      config['pool']              = ENV['DB_POOL']      || sizeActiveRecord::Base.establish_connection(config)enddefdisconnectActiveRecord::Base.connection_pool.disconnect!enddefreconnect(size)
      disconnect
      connect(size)end

    module_function :disconnect, :connect, :reconnectendendRails.application.config.after_initialize doPlatform::Database.disconnectActiveSupport.on_load(:active_record) doifPuma.respond_to?(:cli_config)
      size = Puma.cli_config.options.fetch(:max_threads)Platform::Database.reconnect(size)elsePlatform::Database.connectendSidekiq.configure_server do |config|
      size = Sidekiq.options[:concurrency]Platform::Database.reconnect(size)endendend

Fonte: Setting ActiveRecord's connection pool size on Heroku with Puma or Sidekiq

No caso de uma aplicação Rails, a cada requisição o "correto" é abrir uma conexão e fechar ao terminar, e não deixar uma conexão aberta indefinidamente. No caso, pedir ao pool e devolver ao pool o quanto antes. Quem é de Java vai se lembrar que isso é o pattern de session-per-request ou a implementação do filtro OpenSessionInViewFilter do Hibernate. Demorou um pouco, mas o mundo Rails finalmente fez a mesma implementação como um Rack Middleware (que funciona como um Servlet Filter) chamado ConnectionManagement e cuja idéia o grande @tenderlove explica em seu post Connection Management in ActiveRecord.

Finalmente, se você está trabalhando numa aplicação que tem literalmente, dezenas de dynos, precisando de potencialmente centenas de conexões simultâneas (estamos falando de aplicações transacionais - que não serve só conteúdo estático em cache), talvez seja necessário ir um passo além - explicado no artigo do Heroku linkado acima - usando PgBouncer, que serve para criar uma connection pool no nível do Postgresql. Em vez de controlar pool de conexões na camada de aplicação, fazemos a aplicação pedir conexões normalmente ao banco, mas o PgBouncer intercepta isso e controla o pool geral com o Posgresql por baixo.

No Heroku, cada Dyno é configurado através de um buildpack, mas uma coisa que nem todos exploram é que é possível executar múltiplos buildpacks por dyno. Por exemplo, um buildpack de Ruby e de Node. Para isso existe o buildpack-multi que você configura assim:

1
heroku config:add BUILDPACK_URL=https://github.com/ddollar/heroku-buildpack-multi.git

Agora você pode declarar um arquivo .buildpack no seu projeto onde lista quais buildpacks quer executar:

123
# .buildpack
https://github.com/gregburek/heroku-buildpack-pgbouncer.git#v0.2.2
https://github.com/heroku/heroku-buildpack-ruby.git

E finalmente modifique o arquivo Procfile para que o Puma use o PgBouncer:

12
# Procfile
web: bin/start-pgbouncer-stunnel bundle exec puma -C config/puma.rb

Agora temos uma aplicação que rodando com Puma (poderia ser Unicorn na frente, leia a documentação do buildpack-pgbouncer, mas Puma em particular demanda mais conexões, por isso o exemplo com ele) na frente de um pool geral na frente do Postgresql. Cuidado: Puma suporta aplicações feitas pra serem thread-safe mas rodar qualquer aplicação sobre Puma não garante que suas requisições serão executadas concorrentemente. Porém, se estiver usando JRuby, Puma definitivamente é a melhor alternativa para aumentar a concorrência por processo.

Esse small bite não tem a intenção de ser um recurso completo sobre conexões de banco de dados, apenas arranhamos a superfície do que existe mas isso deve servir pra dar uma visão geral sobre alguns conceitos que não são apresentadas de maneira muito simples para quem está iniciando. Se tiverem mais assuntos complementares a estes, não deixem de comentar abaixo!

[Small Bite] Consumo de Memória de Browsers de Mac

$
0
0

Ontem vi um tweet do @fnando falando de Firefox. Particularmente fiquei curioso sobre ele porque faz muito tempo que eu só uso primariamente o Safari e para algumas coisas uso Chrome (coisas de Google, como Hangout, principalmente, mas sem nenhum motivo particular pra isso).

Tipicamente, tenho cerca de 40 abas abertas no Safari. Vou lendo, salvando (se for interessante, no Pocket, ou tweetando ou compartilhando em algum lugar), e fechando. Daí, navegando no Feedly diariamente, acabo abrindo mais e com isso fica essa média de 40 a 50 abas abertas todos os dias. É de fato um fardo que meu Mac precisa lidar diariamente.

Sei que existem algumas coisas que provavelmente só vão funcionar direito no Chrome (coisas experimentais como WebRTC que o Google vai empurrando). O Safari teoricamente deveria ser o que está mais pra trás em termos de funcionalidades, mas das 40 abas que abri iguais nos 3, todos renderizaram os conteúdos sem nenhum problema.

Do ponto de vista de navegação, as abas do Chrome continuam sendo as piores. Odeio o fato dele ir comprimindo a aba até ficar só o favicon e não ter por padrão uma lista das páginas abertas. O Safari e o Firefox tem abas muito mais úteis (e é uma das razões de porque eu abro muitas abas no Safari e não no Chrome). Uma curiosidade é que mudar de abas com shortcut (Cmd+]) é mais rápido no Firefox, em segundo no Safari e bem em terceiro no Chrome. Se eu deixar o shortcut apertado pra ele mudar de abas bem rápido, o Firefox mostra o conteúdo rapidamente. O Safari dá um ligeiro "flick", uma piscada em branco antes de dar refresh e o Chrome praticamente não mostra conteúdo algum, não dá tempo de dar refresh antes de mudar de aba de novo. Achei isso interessante, pessoalmente o Firefox pareceu visivelmente mais responsivo do que os outros.

Uma coisa que não testei é resistência a crash do Firefox. No caso do Safari e do Chrome, se uma página se comporta mal, ele vai fechar somente aquela aba sem quebrar os demais porque ambos moveram para o modelo de conteúdo separado em processos independentes. O Chrome é o mais isolado de todos, na minha contagem ele abriu nada menos do que 59 processos. O Safari não abre um processo por aba, ele é menos granulado, e abriu 28 processos - particularmente separando 6 processos só para Flash e QTKit (que são os candidatos a crash sempre). Já o Firefox continua no modelo de multi-threads e todas as abas abrem dentro do mesmo processo, por isso ele só tem 1 único processo e um outro separado para Flash.

Imagino que é por isso que o Firefox continua conseguindo ser mais responsivo para mudar de abas (porque não tem overhead de comunicação interprocesso) e também porque ele é consideravelmente mais econômico que os outros. Então vamos ao consumo de memória (lembrando, todos com as mesmas 40 abas):

  • Safari 7.0.5 (28 processos): 1.74 GB
  • Chrome 35.0 (59 processos): 1.70 GB
  • Firefox 30.0 (1 processo): 0.88 GB

Activity Monitor

Se quiserem ver em detalhes, além do screenshot acima (clique para versão maior), baixe também uma planilha Excel onde eu listei os processos, consumos e o cálculo total de cada um.

Ou seja, o Firefox consegue consumir 50% menos memória abrindo exatamente o mesmo conteúdo. Chrome e Safari ficam empatados. Um comportamento interessante do Firefox é que ele vai internamente tentando sempre economizar mais memória. Ao navegar por todas as abas, ele chega a mostrar consumo de mais de 900 MB, mas se deixar quieto por alguns instantes ele começa a decair até 800 MB ou um pouco menos.

Partindo disso minha conclusão é que vou experimentar o Firefox no lugar do Safari como meu navegador padrão. As perguntas que restam são:

  • Meu Mac tem uptime longo (por exemplo, desde meu último boot foram 19 dias já), será que ele não vai demonstrar leaks de memória com o tempo?
  • Se um site que abrir tiver um daqueles javascripts mal feitos ou Flash e der crash, ele vai conseguir isolar o problema ou vai derrubar o browser todo? E se derrubar, não lembro se ele vai reabrir com todas as abas (vou procurar extensions pra isso)
  • Ainda existe alguma incompatibilidade com os padrões que vão impedir a renderização correta de algum site que abriria normalmente no Safari ou Chrome? (acho que não)

Para quem é desenvolvedor front-end, lembrar que os 3 browsers tem renderizações ligeiramente diferentes. Eu notei em particular, o anti-aliasing dos tipos no Firefox parece mais "grosso". O Chrome e o Safari "parecem" mais próximos, provavelmente por ambos usarem WebKit por baixo (embora o Safari use diretamente renderização via Core Image e outros frameworks Cocoa), já o Gecko do Firefox pode realmente da resultados bem diferentes, especialmente no que diz respeito aos tipos. Veja as diferenças do mesmo trecho de Facebook nos 3 navegadores:

No Firefox:

Firefox

No Chrome:

Chrome

No Safari:

Safari

O que vocês acham? Quem usa Firefox hoje em dia, quais são as principais dicas de uso e plugins? Não deixem de comentar.


[Small Bites] Mantenha seu Mac Seguro e Protegido

$
0
0

Como sabemos, segurança é uma proposição de "tudo ou nada", não existe "meio protegido". Infelizmente, a única forma de ter certeza que seu dispositivo está 100% seguro é se ele estiver sempre offline e nunca se conectar a nenhuma rede, e que sua localização tenha segurança física (literalmente, numa jaula).

Ou seja, estamos sempre desprotegidos por padrão, parta desse princípio. O que podemos fazer é não facilitar o trabalho de quem quer invadir seus dados. Não deixe nada ao acaso, pois o máximo que vamos fazer agora é dificultar o trabalho dos outros.

Importante:

  • Este artigo parte do princípio que você está usando OS X Mavericks e que está constantemente baixando as atualizações de segurança.
  • Não falar muito de "redes sociais" e "SaaS", onde muito da sua privacidade já está comprometida, vamos falar de alguns aspectos mas tome cuidado com Engenharia Social, mais do que hackers remotos.
  • Não dá pra garantir que, depois de seguir todas as recomendações a seguir, seu Macbook está "garantidamente seguro", ele somente vai estar mais difícil de acessar, mas certamente um técnico mais motivado vai conseguir chegar onde ele quer.

A razão desse artigo é porque, por padrão, seu Macbook vem razoavelmente aberto, não oferecendo nenhuma dificuldade.

Para começar, mesmo se você tiver uma senha te protegendo, isso não quer dizer nada. Se eu tiver acesso físico à sua máquina:

  • posso reiniciar sua senha através do Recovery Boot. Portanto, a primeira coisa a fazer é pelo menos colocar a senha de EFI
  • posso fazer seu Macbook bootar através de outro OS X, com um HD externo ou USB key com um OS X bootável.
  • posso conectar seu Macbook a outro Macbook com um cabo USB/Firewire/Thunderbolt em Target Mode e ele vai aparecer como um HD externo no outro Mac.

Para dificultar isso, basta colocar uma senha no firmware EFI. Novamente, isso vai dificultar, mas eu posso quebrar o chip do firmware para desabilitar o bloqueio, assim:

Fique claro, isso não é um bloqueio permanente, apenas uma forma de dificultar. Se seu antagonista realmente estiver motivado, isso vai dar a ele acesso ao seu HD. O que fazer agora?

Vamos garantir que, mesmo que ele tenha acesso ao seu HD, ele não tenha acesso à sua partição. Para isso, desde o OS X Panther temos o File Vault para encriptar os dados do seu HD de forma transparente ao seu uso. Antigamente ele só conseguia encriptar seu diretório Home, mas o File Vault 2 oferece full HD encryption e você deve habilitá-lo se ainda não o fez. Quando fizer pela primeira vez ele vai ter mostra o recovery key, escreva à mão num papel e guarde num cofre! (sério!)

Significa que esse é o end-game? Estamos seguros? Não, existem formas de tentar quebrar a criptografia do File Vault como você pode ver nos seguintes artigos:

Habilite o FileVault 2

Lembre-se de uma coisa: o OS X é excepcional quando se fala em modo de hibernação. Você sabe que pode simplesmente fechar a tampa da tela, sem precisar desligar o Macbook e quando reabre ele volta exatamente onde estava. Então você coloca a senha do seu usuário e boom, de volta ao trabalho. Porém, se seu disco é encriptado, ele deveria também pedir a senha para abrir o volume encriptado, mas ele não pede!

Isso porque ele está salvo em memória! Significa que uma forma de quebrar a encriptação do seu File Vault é vasculhando a memória (RAM ou virtual memory), usando técnicas como DMA (Direct Memory Access) por Firewire - em particular essa vulnerabilidade foi consertada no OS X Lion 10.7.2. Recomendação: se estiver se movendo por locais inseguros, onde seu Mac pode ser interceptado, faça um shutdown completo!

Bom, isso deve adicionar um nível de dificuldade, pelo menos - e note como não basta somente a parte técnica: seu comportamento em lidar com seu equipamento é boa parte do seu procedimento de segurança.

Outra coisa que eu pessoalmente gosto de fazer apenas para adicionar uma pequena linha extra de defesa é criar um disco esparso encriptado com o Disk Utility. É a mesma coisa que seu volume já criptografado, mas dentro dele eu mantenho outro volume criptografado, com outra senha, para meus dados mais secretos. Faço a mesma coisa se preciso transportar alguma coisa num USB Key, por exemplo. Aprenda a usar discos esparsos criptografados. Digamos que você transporte alguma coisa num USB drive e ele se perca ou alguém roube, isso vai pelo menos adicionar uma camada extra que alguém iniciante não vai ter como abrir.

Encrypted Sparsebundle

E, obviamente, NÃO grave a senha no seu Keychain. Se gravar por acidente, abra a aplicação Keychain e apague a senha gravada.

Se seguiu os passos anteriores aproveite e cuide de outra coisa: desabilite o usuário Guest. Seu Macbook não foi feito para emprestar para ninguém - novamente, seu comportamento! Segurança significa que seu equipamento nunca deve sair do seu controle. O Guest User é uma funcionalidade do OS X Lion 10.7.2 que vem ligado por padrão. Tecnicamente, ele usa as permissões de usuário para manter os dados do seu usuário "invisíveis" a esse usuário convidado. Porém, basta uma vulnerabilidade que você não conhece no seu sistema operacional para que esse usuário tenha acesso de "root"! Por que correr o risco?? Desabilite o Guest User agora mesmo!

Disable Guest User

No System Preferences, existe um lugar onde você pode habilitar compartilhamento de recursos da sua máquina. Compartilhar arquivos, impressora, internet, etc. Espero que seja óbvio que você deve desabilitar todo e qualquer compartilhamento! Segurança e compartilhamento estão em espectros opostos.

Desabilite tudo em Sharing

Falando em System Preferences, em "Security & Privacy" garanta que esteja configurado para pedir senha sempre que seu Macbook acordar de hibernação e nunca desabilite a checagem de chaves de aplicação. Você deve, sempre que possível, só instalar aplicativos da App Store. E se fizer download, deve deixar o OS X checar se ele é de um desenvolvedor registrado - que pode ser rastreado! Nunca instale aplicativos desconhecidos! Nunca confie em ninguém, especialmente alguém remoto da internet! (Não preciso dizer o básico, obviamente, de nunca abrir nenhum anexo de nenhum email, de nenhuma forma e de nenhum site! Vamos assumir que nenhum dos leitores aqui é minha avó)

Habilite senhas sempre!

Clique em "Advanced" no fim da tela:

Habilite senhas

Não preciso dizer também para manter o Java e o Flash sempre atualizados, de preferência deixe configurado para atualizar automaticamente. A última coisa que você precisa é vulnerabilidades desse tipo. A configuração também fica no seu System Preferences.

A menos que precise muito também mantenha seu Bluetooth desligado!

Bluetooth Desligado

O ideal seria até seu Wifi estar desligado mas como não dá, pelo menos garanta que seu Firewall está ativo! Mas como só isso eu acho pouco, recomendo instalar também o aplicativo Little Snitch 3. Ele é bem chato: toda vez que qualquer coisa tentar enviar qualquer coisa ou quando qualquer coisa tentar enviar pacotes pra você, ele vai te notificar.

Essa nem é a melhor opção pois ele só vai conseguir filtrar coisas da camada de aplicação do seu TCP, mas novamente, é apenas mais uma barreira. Você precisa se disciplicar a não simplesmente aceitar tudo, mas parar pra ver o que é e experimentar recusar tudo por padrão. Se algo importante que você queria quebrar, basta fazer de novo.

Little Snitch 3

Pense que alguém pode estar vendo seu Mac, seus arquivos, tudo via algum aplicativo online que tem vulnerabilidade ou um cavalo de tróia que você não está vendo. Pelo menos vamos tentar interceptar a comunicação. E os melhores não vão ser pegos nem pelo Little Snitch, e aí você precisa de algo mais parrudo, no nível do roteador, pra pegar. Mas esse é o melhor custo-benefício para o caso onde você só tem seu Macbook e precisa conectá-lo a redes estranhas o tempo todo.

Aliás, em redes estranhas, idealmente você tem um servidor remoto de confiança para abrir uma VPN e tunelar todo seu tráfego para lá. Você pode experimentar qualquer um dos que existem como BTGuard, IPVanish, TorGuard, PrivatVPN e outros, escolha um fora da jurisdição do seu país e sem leis de cooperação, de preferência.

Para simplesmente não ter seu tráfego snifado, pelo menos use o TorBrowser. E falando em web, vamos rapidamente só colocar um outro ponto em questão: até aqui estamos falando de acesso físico ao seu HD e ao seu Macbook, mas não se esqueça que seus dados já estão comprometidos de uma forma ou outra através das dezenas de serviços que você precisa usar diariamente como Dropbox, Github, Evernote, Pocket, Facebook, Instagram, Google.

Para começar, tenha senhas seguras. Não preciso dizer o óbvio:

NÃO USE A MESMA SENHA EM TUDO!!

É uma grande estupidez! Use um gerenciador de senhas como o 1Password ou outros e gere senhas minimamente fortes e bem longas:

Strong Password

Sendo sincero, eu também usava a mesma senha em muitos serviços, mas com o tempo vim substituindo a grande maioria. E somente nos que não tem importância ainda está senha fraca. Em todos os relevantes, que inclui tudo do Google, Dropbox, Github, Twitter, Amazon e muito mais, além da senha forte também está habilitado autenticação em 2 etapas. Hoje está bastante conveniente porque existe 1Password para iOS e Android, além de extensions para todos os navegadores e, com isso, você nunca vai precisar digitar sua senha. E para a autenticação em 2 etapas também tem aplicativos pra iOS e Android como o Authy.

Me preocupa um pouco a implementação deles. Significa que pelo menos 1 senha está em memória, no clipboard, para podermos colar no campo de senha em algum momento. Pelo menos no caso do Mac, sabemos que desde o OS X Lion a memória virtual é criptografada por padrão. Mesmo assim, em algum lugar, em algum momento, existe uma senha aberta que "pode" ser interceptada. Mas ainda é muito melhor do que usar a mesma senha fraca em todos os lugares.

Por outro lado, significa que basta roubar o cofre das suas senhas do 1Password E saber sua "Master Password" para ter acesso a basicamente tudo! E aí voltamos ao ponto inicial: garanta que as chances disso acontecer sejam mínimas! Se alguém roubar seu Macbook agora, e ele não estiver no mínimo com o que expliquei até aqui, qualquer um poderá extrair todas as suas senhas!

E falando em roubar máquinas, habilite agora mesmo o serviço de Back to my Mac:

Back to My Mac

O procedimento é o seguinte: se seu Macbook desaparecer ou for roubado, a primeira coisa que você precisa fazer é arranjar uma conexão com a internet e abrir seu navegador no iCloud e imediatamente enviar sinal para destruir os dados do seu notebook remotamente, se por alguma razão, o perpetrador tiver sucesso em colocar sua conta online! Além disso você deve acessar todas as suas contas de todos os seus serviços online e imeditamente trocar todas as suas senhas, sem exceção!!

Para garantir, use um segundo serviço de redundância, o Prey Project que serve não só para Mac como Windows, Linux.

Aliás, garanta que seus smartphones estejam sempre configurados para pedir senha e coloque a opção de apagar tudo caso erre sua senha mais de 10 vezes! Sempre tenha uma forma de destruir seus dados. E habilite também o Find my iPhone e, no caso de Android, habilite o Google Android Device Manager e configure em todos os seus dispositivos. A função é a mesma em ambas as plataformas: você precisa ter uma forma de destruir seus dados remotamente. Como seus smartphones estarão sempre online, do momento em que for roubado, você terá uma janela muito pequena para apagar tudo, não perca essa chance! Se o perpetrador for esperto, ele vai desligar o dispositivo tão logo o roube, torça para que isso não aconteça!

Finalmente, backup! Felizmente o Mac OS X tem o recurso de Time Machine desde o OS X Leopard. A recomendação é simples: compre um HD externo, de preferência com suporte a USB 3 ou Thunderbolt (ou minimamente um Firewire 800, se seu notebook for antigo). Crie uma rotina: sempre que chegar em casa, conecte seu HD externo e deixe o Time Machine fazer seu trabalho, desconecte e coloque num cofre na sua casa (sério!).

Desta forma, se seu Macbook for roubado, com tudo que disse até aqui:

  • o perpetrador vai ter trabalho para acessar seus dados
  • se por acaso conseguir e sua conta for logada e ficar online, o Back to my Mac e o Prey Project vão enviar uma ordem remota de auto-destruição

E se você tiver um backup protegido, na sua casa, você pode imediatamente comprar um novo Macbook e não perder tempo para voltar à ativa (afinal, tempo é dinheiro!)

Isso é o que eu faço na minha rotina. O que mais vocês costumam fazer para manter as coisas pelo menos um pouco mais difíceis de invadir?

[Small Bites] Vagrant: Virtualbox ou VMWare?

$
0
0

Se você ainda não usa Vagrant como ambiente de desenvolvimento e testes, vá já instalar o seu!

Em seguida, garanta que você está usando NFS para a máquina virtual acessar seus arquivos no seu HD de verdade na maior velocidade possível.

Finalmente, a dúvida que você pode ter é: usar Virtualbox, que é open source e gratuito ou comprar o VMWare Fusion Provider a caros USD 79 e mais a licença do VMWare Fusion pra Mac que vai te custar outros USD 59.99, para um total de USD 138.99 !!??

O problema é que você pode decidir que é caro demais e que o Virtualbox é suficiente, mas aí sempre que sentir algo lento vai ficar pensando "será que vale a pena pagar os quase USD 140?"

A resposta TL;DR é simples: NÃO, fique no Virtualbox. O VMWare pode até ser mesmo um pouco melhor, e certamente se você quer usar Windows e ter uma boa integração entre desktops gráficos e tudo mais, acho que vale o custo. Mas para a maioria de nós, desenvolvedores, o custo certamente não compensa, não pare de se sentir com dor na consciência e aprecie o Virtualbox.

Como testes bem não-científicos, eu criei duas máquinas Vagrant usando o box 'hashicorp/precise64', com NFS habilitado e nada mais de customização.

Copiando arquivos, peguei um projeto Rails médio e o código-fonte do Rails e copiei do meu HD local, compartilhado via NFS, pro HD interno da máquina virtual. Respectivamente, no VMWare Fusion tive os tempos de 3 segundos e 6 segundos; já no Virtualbox tive os tempos de 4 segundos e 5.5 segundos.

Quando eu digo não-científico, entenda que ao mesmo tempo meu Dropbox está sincronizando, meus emails estão aparecendo, diversas abas em browsers devem estar atualizando algum conteúdo, e diversas outras coisas estão interferindo nesses tempos. Baseado nisso, pra mim foi empate.

Em seguida, tentei instalar o RVM com Rails:

1
time curl -sSL https://get.rvm.io | bash -s stable --rails

No VMWare Fusion, terminou em 15 minutos. No Virtualbox levou 10 minutos. Obviamente, o gargalo aqui não é performance da máquina virtual, mas sim o tempo de internet para download do Ruby, das Gems, etc. Mas coloquei esses tempos mais para demonstrar o ponto que muitos dos tempos do seu dia-a-dia dependem da qualidade da sua conexão de internet mais do que só performance bruta de hardware.

Finalmente, quando tempo para um mero comando "rails new", criando um novo projeto? Lembrando que ao final ele vai executar "bundle install" e, logo, será afetado por tempo de internet. No caso do VMware, levou 1 minuto e 1.2 segundos. No caso do Virtualbox, levou 1 minuto e 1.4 segundos. Novamente, empate.

Portanto, não, você não vai ter uma vantagem "milagrosa" só por pagar USD 140 e instalar o VMWare. Para sua máquina local, de desenvolvimento, melhor ficar no Virtualbox.

Quero testar eu mesmo!

Se não acreditou e tem USD 140 para investir, mãos à obra. Digamos que você já tem uma máquina virtual em Virtualbox, que montou manualmente (sem scripts de provisionamento), e quer migrar pro VMWare, como fazer?

Eu escrevi um pequeno Gist faz algum tempo, mas chegou a hora de colocar num post mesmo pra ficar mais fácil encontrar. Segue a transcrição:

  • exporte seus boxes do Virtualbox para arquivos em formato OVA
  • execute vagrant destroy para matar seus boxes em Virtualbox
  • desinstale o Virtualbox usando o script de uninstaller que vem no DMG de instalação (passo opcional)
  • faça download do VMWare Fusion (depois de comprar a licença)
  • compre a licença do VMWare Fusion Provider para Vagrant
  • execute vagrant plugin install vagrant-vmware-fusion para instalar o plugin do novo provider
  • execute vagrant plugin license vagrant-vmware-fusion license.lic para instalar a licença que comprou
  • do VMWare, importe os arquivos OVA (provavelmente opcional, eu não tentei abrir o OVA direto)
  • execute vagrant up a partir de onde seu Vagrantfile está. Isso vai criar um novo box novinho a partir da sua configuração. Se não desinstalar o Virtualbox, force o provider: vagrant up --provider=vmware_fusion ou vagrant up --provider=virtualbox
  • agora abra o VMWare, abra as configurações do novo box que acabou de ser criado pelo Vagrant, remova o harddrive
  • depois de remover, adicione um novo dispositivo de harddrive e selecione "from existing disk" e então aponte para o box importado (da OVA) e selecione o disco formato "vmdk". Ele vai recomendar copiar para a nova máquina, faça isso.
  • se o box for Linux, inicie a máquina a partir do VMWare usando o login 'vagrant' e senha 'vagrant'
  • de dentro, execute sudo /opt/[VBoxGuestAdditions ...]/uninstall.sh
  • do lado de fora, execute vagrant reload para reiniciar a máquina virtual
  • do VMWare vá para o menu de "Machine" e instale o vmware tools. Ele vai fazer download do ISO. Se seu box Linux não montar automaticamente, encontro o arquivo "linux.iso" dentro da aplicação do VMWare application, abra e copie para a pasta compartilhada que foi montada como "/vagrant".
  • instale o VMWare tools
  • finalmente, vagrant reload, e é só isso!

Agora você mesmo pode rodar seus testes, não fique muito decepcionado se os tempos não forem tão diferentes. Mas se por acaso alguém souber de alguma situação específica onde o VMWare for ordens de grandeza superior ao Virtualbox, não deixe de comentar abaixo!

[Off-Topic] Meu Primeiro "Livro"

$
0
0

Em 2007 escrevi meu primeiro livro "publicado", sobre Ruby on Rails. Em 2006, comecei este blog. Mas essas não foram minhas primeiras experiências escrevendo.

Se acompanha meu blog viu que ontem publiquei um artigo sobre Segurança, onde falo sobre a importância do Backup. Imagine que minha rotina de backup vem de longa data. Eu já fazia backup quando tudo que eu tinha eram caixas de disquetes. E a cada nova geração de mídias eu transferia de uma para outra. Foi assim de disquetes para discos de zip drive, depois para CDs, daí para DVDs e finalmente para meu Drobo, como publiquei em 2009 e parte dele para Dropbox.

De vez em quando dou uma fuçada nesse backup e acabei de esbarrar num "livro" que escrevi quando era estudante do 3o semestre de Ciências da Computação na USP, em Maio de 1996! Aliás, o backup é datado de Maio de 1996, provavelmente eu escrevi isso antes!

Trecho

Fonte: The Road Ahead - Bill Gates

Obviamente eu nunca escrevi esse livro para ser publicado, eu escrevi simplesmente porque eu sempre gostei de fazer pesquisa e de escrever, para mim mesmo. O motivo de porque gosto de escrever tem um momento muito específico: o filme Indiana Jones e a Última Cruzada, de 1989.

Eu provavelmente tinha acabado de fazer um curso de datilografia (acho que foi em 1988, não tenho mais certeza). Tinha uma enciclopédia, e o filme tinha o diário do pai do Indiana. A "idéia" de um livro que contém toda sua pesquisa da vida se tornou uma "imagem" que me acompanha até hoje. E pior: eu acho que não gostava da idéia de um dia esquecer tudo que aprendi, e queria conseguir registrar o que eu sabia, num "único" lugar, para garantir que estaria acessível se um dia eu quisesse lembrar (como hoje!).

Indiana Jones

E desde então eu quis "escrever", como uma forma de destilar tudo que eu sabia sobre um assunto num único lugar (lembrem-se, isso foi muito antes da noção de Wikipedia ou ter qualquer informação acessível a qualquer momento como temos hoje!) E ainda é um dos motivos de porque eu escrevo: mesmo se ninguém lesse, eu escreveria pra mim mesmo, como faço faz mais de 2 décadas.

Isso dito, boa parte desse material é um exercício de digitação. Para os meninos novos, vou explicar que antes de consultarmos tudo pela Web, existia uma mídia analógica quase extinta chamada "papel" :-) E antes de ser possível simplesmente dar "copy and paste" de textos, antigamente não havia essas fontes e éramos obrigados a datilografar ou digitar, transcrever do meio analógico para o digital. Tecnologias como OCR ainda não eram difundidas e nem todo mundo tinha um scanner (e os que existiam hoje seriam considerados de baixíssima resolução e baixíssima qualidade), portanto, tinha que gostar muito de transcrever e, por sinal, era um dos meus hobbies favoritos desde quando ganhei minha primeira máquina de datilografia.

Então, para a posteridade, segue a versão em PDF, capítulo a capítulo, caso tenham curiosidade de saber o que um estudante de 1996 sabia.

Se tiver que escolher, você pode pular os capítulos II, IV, V, X. O VII é engraçado para ver o que era um Windows em 1996. O capítulo VIII é para lembrar que nessa época a migração de 16-bits para 32-bits era uma dor de cabeça (nada parecido com a facilidade que foi ir de 32 para 64-bits). O capítulo IX é para quem usava Mac nos anos 90, isso foi antes da era pós-RISC de hoje. Os mais curiosos provavelmente são a introdução e os dois últimos capítulos, que contém mais opiniões pessoais sobre o pouco que eu entendia de internet nessa época (a primeira vez que naveguei na Web foi em 1994!)

O que acharam? Não deixem de comentar :-)

Backup

[Small Bites] Vagrant + Ubuntu 14.04 + Chef Solo

$
0
0

Este post é dedicado a quem utilizar Mac OS X (ou mesmo Windows) como sistema de desenvolvimento. Para quem usa uma distro Linux, adapte para usar o plugin de LXC do Vagrant.

A versão TL;DR é muito simples. Baixe e instale o VirtualBox e o Vagrant. Assumindo que está no OS X (já tem Ruby 2.0.0 pré-instalado), faça o seguinte do Terminal:

12345678910111213
sudo gem install berkshelf
vagrant plugin install vagrant-berkshelf
vagrant plugin install vagrant-omnibus

mkdir ~/Vagrant
cd ~/Vagrant
git clone https://github.com/akitaonrails/vagrant-railsbox.git railsbox
cd railsbox

export VAGRANT_SYNCED_FOLDER=~/Sites

berks install
vagrant up --provision

Note que o Vagrantfile vai buscar a variável de ambiente VAGRANT_SYNCED_FOLDER, não esqueça de colocar no seu .zshrc ou .bashrc apontando para o diretório onde você costuma clonar seus projetos. Ele será montado, via NFS, dentro do box Vagrant no diretório /vagrant.

Pronto, isso deve ser suficiente. Ao final você terá um ambiente de desenvolvimento com os seguintes componentes principais:

  • RVM (receita 'user_install', onde você mesmo deve instalar os rubies que precisar manualmente)
  • Oh-My-Zsh (isso não seria necessário, mas ZSH é tão bom que é melhor já ter pré-instalado)
  • MySQL
  • Postgresql
  • MongoDB
  • Redis 2
  • Elasticsearch
  • Node.js, Java 1.7, Git, Imagemagick

Acesse seu novo box com vagrant ssh, instale seu primeiro Ruby com rvm install ruby-2.1.2 e pronto!

Alguns Conceitos de Vagrant e Chef

Meu projetinho vagrant-railsbox por si só é estruturado como uma receita Chef. Ele tem um metadata.rb que funciona mais ou menos como uma "gemspec", se fosse uma Rubygem.

Para gerenciar as dependências, uso o Berkshelf, que funciona como se fosse um Bundler. Ao rodar berks install ele vai usar o arquivo Berksfile.lock (novamente, similar ao "Gemfile.lock" dos seus projetos Ruby). O arquivo Berksfile tem as definições de versão ou fonte, e no caso desta receita, puxa as dependências do metadata.rb. Leia mais sobre como usar Berkshelf com Vagrant neste post.

O arquivo Vagrantfile tem as configurações da receita. Na teoria eu deveria colocar as configurações que você encontra no bloco config.vm.provision :chef_solo no diretório attributes, que toda receita Chef tem, mas neste caso, como é muito específico ao Vagrant, deixei lá mesmo.

Note que estou usando um IP interno fixo com config.vm.network :private_network, ip: "192.168.50.4" em vez de usar a configuração com DHCP que seria , type: 'dhcp', porque acho que no VMWare Fusion (que eu uso) estava dando problema. Tente usar DHCP e veja se no seu caso funciona, senão mantenha fixo.

Como é máquina de desenvolvimento, a senha do usuário 'root' do MySQL é simplesmente 'root'. E a senha do usuário 'postgres' é simplesmente 'postgres', além de estar tudo como 'trust' no arquivo pg_hba.conf. Obviamente, estas configurações não devem ser mantidas assim se for subir em produção. Redis, Mongo e Elasticsearch, está tudo na configuração padrão e tudo sem proteção.

Para quem nunca usou Chef, o conceito é simples:

  • procure por receitas no Chef Supermarket
  • adicione no seu metadata.rb como depends 'git'
  • adicione no seu recipes/default.rb como include_recipe 'git' ou o que a documentação da receita mandar
  • configure o node['git'] no attributes/default.rb (ou, neste exemplo, no Vagrantfile), conforme a documentação

A receita é onde fica os comandos para instalar e configurar o que você precisa. Atributos são os valores customizáveis que variam de instalação para instalação. No diretório files costuma ficar templates ERB para arquivos de configuração, do tipo que você editaria em /etc. Em libraries ficam classes Ruby que organizam lógicas mais complexas que você quer estruturar para reusar.

Resources e Providers são conceitos mais complicados de explicar, e como a idéia deste post não é detalhar Chef, vamos apenas resumir dizendo que resources definem o estado de um sistema. Por exemplo, num cookbook de NGINX teríamos o pacote de instalação, o serviço e o arquivo de configuração. Providers são as ações que levam o sistema ao estado definido, como instalar o pacote propriamente dito, editar o arquivo de configuração e configurar o serviço. Se quiser saber mais sobre o assunto, leia este post e este outro.

A grande vantagem é você poder modificar este cookbook e incrementalmente instalar coisas novas no seu box com o comando vagrant provision. E também poder simplesmente recomeçar do zero, destruindo seu box com vagrant destroy e reiniciando com vagrant up --provision e chegar na mesma configuração final. É sempre bom pode começar do zero sem dores de cabeça.

Sobre montar seu próprio cookbook, a parte mais complicada é buscar os cookbooks que já existem, entender como eles funcionam, e isso requer ler as receitas, ler a documentação, entender dependências como ver que o oh-my-zsh depende o data_bag do cookbook 'user', por exemplo. Antes de sair montando tudo do zero, procure no supermarket e, obviamente, no Google, para buscar direto no Github.

Alguém tem mais dicas para melhorar este cookbook? Não deixe de comentar aqui ou mesmo mandar um Pull Request pra mim!

[Small Bites] IDEs e Editores, como escolher?

$
0
0

Todo ano, em toda lista de discussão, algum iniciante sempre vai perguntar: "Que IDE devo usar?" E isso vai gerar sempre todo tipo de flame war.

RubyMine

O TL;DR para este post é o seguinte:

  • Se quiser 100% open source e old school: Vim com Oh-My-Zsh ou YADR.
  • Se quiser 100% open source e hipster: Atom.io, que é o editor feito em Javascript pelo Github.
  • Se quiser o melhor moderno, mas comercial: Sublime Text. Não é barato, a USD 70, mas garanto que vale cada centavo, especialmente aliado ao Package Control
  • Se quiser o melhor old school, mas comercial: Textmate, está estagnado há anos desde que se tornou o favorito dos Railers na era 2006-2009, mas a versão 1.5.x (não a 2.0) é muito boa, e eu pessoalmente ainda uso para várias coisas ainda hoje.
  • Se quiser uma IDE de verdade, com ferramentas mais avançadas para refactoring e debugging, definitivamente use RubyMine. Custa USD 99 e vale cada centavo, ou se você mantém projetos open source, pode requisitar uma licença gratuita
  • Se for somente um montador de front-end, uma opção para Mac que parece interessante é o Coda 2, disponível na App Store.

Aliás, para entender uma diferença crucial de filosofias entre Vim e Atom/Sublime/Textmate, leia este ótimo artigo "Why Atom Can’t Replace Vim". Vim, assim como Emacs, tem uma filosofia própria.

Qual escolher?

Emacs, assim como Vim, é uma boa opção também, mas como não sou especialista em ELisp, vou deixar passar. Mas pra quem se interessa em se aprofundar em hacking old school, vai fundo! Aliás, o miner Andrew me indicou o pacote Prelude, feito pelo Bozhidar Batsov, o mesmo do Rubocop, ruby-style-guide, etc. Outros que não listei como Dreamweaver, obviamente é o extremo oposto: não use.

Textmate é somente para pessoas como eu, que pegaram Rails entre 2005 e 2009. É difícil largar ele mesmo com novas opções. Se você nunca usou, não vai sentir falta. O Sublime Text veio pra substituí-lo e faz tudo que o Textmate faz, com a vantagem que tem opções pra Windows e Linux. O Atom.io é a mesma coisa que o Sublime, mas um pouco mais lento, por outro lado é grátis, então é uma escolha de custo-benefício. E eu vou dizer que minha sensação é que é mais lento se considerar que estou acostumado com Vim. Se nunca usou Vim ou mesmo Sublime/Textmate, talvez não note.

Textmate Classic

O RubyMine é da excelente família de IDEs da JetBrains, que desde os anos 90 se manteve como uma das melhores IDEs Java com o IntelliJ, que sempre teve o melhor conjunto de auxílios para refatoramento. Depois da decaída dos fabricantes de IDEs, como Borland, a JetBrains foi quem se manteve firme e forte, implementando qualidade. Eles evoluíram e, se você for desenvolvedor .NET é quase obrigatório instalar o ReSharper para vitaminar o magro Visual Studio. Se você é desenvolvedor Python, vai gostar muito do PyCharm.

O RubyMine faz tudo que eu considero importante como editor (que é o que vamos listar abaixo) e mais, então vou deixar para um outro post exclusivamente sobre RubyMine. Aguardem!

Voltando ao assunto, um bom editor de textos precisa de poucas coisas pra funcionar decentemente:

Esqueça o Vim-mode onde você "acha" que vai se tornar um programador mais rápido porque sabe deletar 10 linhas pra baixo fazendo a combinação d10j em vez de selecionar as linhas com o mouse e apagar ou selecionar usando shift+setas e apagar. A maioria dos desenvolvedores não escrever uma média maior que 50 linhas de código por dia durante um ano. Tem dias que digita 1000, tem dias que digita 0. Se vai ficar se preocupando se digitou 10 caracteres a mais, ou a menos, faça alguma coisa sobre os dias que ficou procrastinando com Dota 2 ou YouTube. Quantidade de keystrokes, pra granda maioria dos desenvolvedores, é uma desculpa para tentar mostrar que entende mais do que acha que sabe.

Produtividade é uma questão de FOCO. Faça uma coisa de cada vez, prioridade no que está fazendo. Se está programando, desligue as notificações do sistema operacional, deixe seus comunicadores em "Away" ou "Busy" e elimine interrupções. Veja Facebook, YouTube e jogue Dota no fim do dia. Só assim você ganha produtividade, não economizando shortcuts de editor de texto. Por mais que você acredite no oposto preste atenção: você não é bom em multitasking, ninguém é. Uma coisa de cada vez, começo até o fim, é o único jeito de ser ágil.

Portanto, sim, eu gosto de usar o Vim-mode, mas não 100% do tempo. Eu prefiro usar MacVim porque se eu quiser, posso selecionar coisas com o mouse também e não estou sendo "menos produtivo" por causa disso. O Vim-mode é importante porque quando estou no Vim de Terminal, via SSH num servidor remoto, obviamente não posso usar o mouse. E esse é outro motivo de porque todo mundo tem que saber pelo menos o básico de Vim: para configurar servidores remotos, se necessário (normalmente não deveria ser, pra isso servem deployments automatizados, mas isso é assunto pra outro post).

Outra coisa importante é selecionar não só caracteres, palavras e linhas mas também colunas verticais. O Vim tem o bom e velho Ctrl-V (:help CTRL-V). Sublime Text tem Column Selection e Atom tem que instalar um pacote como o Sublime Style Column Selection. Mas nem Sublime e nem Atom ainda são melhores que Textmate e Vim nesse departamento. Mas pelo menos todos eles tem o recurso: qualquer editor de texto que não permite selecionar colunas verticais de texto é obsoleto e não presta pra desenvolver. Nada supera o Ctrl-V do Vim, mas o do Atom e Sublime Text são funcionais o suficiente. O Sublime uma coisa extra que é melhor: edição em múltiplas partes do texto, basta selecionar uma variável, usar Command-D para selecionar as mesmas ocorrências e, quando for editar, ele vai editar em múltiplos lugares. É como um Find e Replace "in-place".

Sublime Text Column Selection

Falando em Find e Replace, obviamente a coisa mais importante é suportar Regular Expressions. No Vim é o comando "%s/blabla/foofoo/g". Nos outros editores tem um ícone ".*" que muda de Find de texto para Find usando Regex. Textmate tinha isso e os outros também funciona razoavelmente bem. Extremamente importante!

Atom Find com Regex

Customização de temas e code highlighting corretos são importantes, já que você vai passar o dia todo olhando pra código, é bom que ele seja agradável. Os dois melhores temas, de longe, são os Solarized Dark e Light (eu pessoalmente prefiro o Dark). Esse é tema "cientificamente" produzido, a paleta de cores com o melhor balanço de contraste e cor para desenvolvedores. Na dúvida, instale Solarized Dark. Todos os editores listados tem esse tema.

Em particular, meu Textmate usa o tema "Mac Classic", é o melhor tema para screencasts e slides para projetor (em projetor sempre use letras escuras em fundo branco!) Falando nisso, lembre-se que LCD emite luz na sua cara. Branco é luz total. Tema branco é garantia de cansar sua vista muito mais rápido. Por isso algo como o Solarized Dark, para quem fica codificando o dia todo, é sempre o mais recomendado.

Sublime Text Theme

Todo bom editor precisa ter um índice de arquivos e uma maneira "fuzzy" de encontrar. O Textmate foi quem imortalizou o hoje ubíquito "Command-T". O pacote YADR para Vim trás o excelente similar, CtrlP. O Sublime e Atom, ambos tem um similar ativado com a combinação de teclas "Command-T". Isso é essencial para navegar rapidamente pelo seu projeto. Um "Project Pane", com a versão visual em árvore do seu diretório de projetos não é útil para navegar rapidamente, mas sim para encontrar coisas que você não lembra o nome mas tem uma idéia de onde fica na estrutura de sub-diretórios. Todo bom editor tem um Project Pane, o Vim tem o plugin NerdTree.

Atom Command TSublime Text Command TVim CtrlP

Finalmente, existem os "Snippets", trechos de código que funcionam como template. Novamente, todos os editores tem pacotes de snippets para cada linguagem. Foi outra coisa que o Textmate tornou famoso, com seus "bundles" e agora todo mundo copiou. Não precisamos de muita coisa, apenas o suficiente para coisas como digitar "def", apertar "tab" e poder digitar o nome do método e o editor automaticamente identar e colocar o "end" pra fechar. Não fique muito viciado nisso, eles são úteis mas não devem ser utilizados para trechos grandes demais, senão seu código vira um grude de copy e paste. Para boilerplates, temos os diversos generators de frameworks como Rails e Yeoman para Javascript. Para HTML temos Slim e HAML para "economizar" simplificar burocracia de tags. No Sublime Text e Atom você pode usar o Package Control de cada um para procurar e instalar os bundles pra suas linguagens favoritas. O YADR já trás diversos plugins como o Vim Rails que criaram a fama do lendário Tim Pope.

Sublime Text Snippets

Todos suportam "tabs" para abrir múltiplos arquivos. Mas se você é um desenvolvedor sério, provavelmente trabalha com Split Screen ou Multiple Panes, que no Sublime são diversas combinações como Command-Alt-Shift-2 para split horizontal ou o Command-K e seta-pra-baixo no Atom, ou simplesmente ":sp" no Vim (Vim rulez!). É a única feature única que Textmate nunca suportou. É absolutamente essencial para que em um pane fique seu código e no outro pane fique o teste desse código! Lembre-se, TDD ou Test-After, não importa, faça testes! Ou no caso de Front-End, HTML de um lado e CSS do outro. E assim por diante. Neste aspecto, o do Vim e do Atom empatam porque eu posso ficar fazendo splits de cada pane invidualmente em qualquer direçao. O do Sublime Text é funcional mas ele tem layouts pré-definidos e não dá pra splitar além, o que eu não gosto.

Atom SplitSublime Grid LayoutVim Split

Outras coisas que facilitam incluem funcionalidades como "Code Folding" para esconder blocos de código, como um método. Textmate tornou isso prático e os outros copiaram o recurso. É útil, mas cuidado para não virar uma "muleta" para arquivos que, na verdade, já deveriam ter sido refatorados em arquivos menores. Ou então métodos gigantes, que já deveriam ter sido refatorados em métodos menores.

Atom Code Folding

Praticamente tudo isso também existe nos editores de IDEs como Eclipse ou NetBeans. Mesmo XCode tem boa parte disso. O pior de todos é o editor do Visual Studio (que verdade seja dita, vem evoluindo até que bem nos últimos anos, e fica melhor se adicionar o ReSharper) e outros editores simples de texto de Windows como UltraEdit ou Notepad++. Em Windows, se possível, use Sublime Text ou Atom, ou mesmo gVIM mas aí não vai ter YADR e outras ferramentas de linha de comando, como explico nas seções abaixo.

Finalmente, outra parte extremamente importante de todos esses editores: eles precisam ser rápidos. O suficiente para eu chamar da linha de comando (o Textmate tem o comando "mate .", o Sublime Text tem o "subl .", o Atom tem o "atom ." e o MacVim, obviamente "mvim") e eles abrirem quase instantaneamente. Uma IDE pesada como Eclipse Kepler (com plugins de Spring, etc) abre - no meu Macbook Pro com SSD - em mais de 17 segundos!! O Atom, que eu considero o mais lento, abre em menos de 3 segundos. Todos os outros abrem em 1 segundo ou menos. Faz muita diferença em como eu vou trabalhar.

Cada um dos editores tem dezenas de outras funcionalidades que vão te surpreender, então não deixe de ler a documentação de cada um deles. Em particular, no caso do Vim, você pode ler o README que normalmente cada bundle tem (procure a partir do diretório ".vim/bundle"). No caso do Sublime Text você tem o Unofficial Documentation. O Atom é a documentação do próprio site. Aliás, note que tem como converter bundles de Textmate para Atom.

Pesquisa em Múltiplos Arquivos: Grep, Ack, Ag?

O maior ponto fraco do Textmate é seu Find em múltiplos arquivos que, se esbarrar num log gigante, vai travar tudo. Substitua para usar o Ag. Em Mac, use Homebrew para instalar o the_silver_searcher. Agora você precisa instalar o AckMate no Textmate e substituir pelo Ag:

12
rm ~/Library/Application Support/TextMate/PlugIns/AckMate.tmplugin/Contents/Resources/ackmate_ack
ln -s /usr/local/bin/ag "~/Library/Application Support/TextMate/PlugIns/AckMate.tmplugin/Contents/Resources/ackmate_ack

Para quem nunca ouviu falar disso, vamos resumir: todo mundo conhece o bom e velho Grep para fazer pesquisas usando regular expressions. Depois dele surgiu o Ack, como uma opção mais eficiente e veloz. E depois dele veio o Ag, como uma opção ainda melhor. O artigo "The Silver Searcher: Better than Ack" explica um pouco disso, mas resumindo:

1234567891011121314
% du -sh
250M    .

% time grep -r -i SOLR ~/cloudkick/reach | wc -l
     617
11.06s user 0.81s system 96% cpu 12.261 total

% time ack -i SOLR ~/cloudkick/reach | wc -l
     488
2.87s user 0.78s system 97% cpu 3.750 total

% time ag -i SOLR ~/cloudkick/reach | wc -l
     573
1.00s user 0.51s system 95% cpu 1.587 total

11 segundos no Grep. Quase 3 segundos no Ack. 1 segundo no Ag. Na dúvida, escolha sempre Ag!

Windows, porque não usar

Para quem é de Windows, existe um port to the silver searcher. E aqui vem um ponto importante: não use Windows se não for necessário, como máquina de desenvolvimento de qualquer coisa que não seja Java ou .Net. Sim, PHP uma parte funciona. Python, Perl, uma parte funciona. Até Ruby, uma parte funciona. E sempre vai ser assim: uma parte, nunca 100%.

.NET é óbvio que funciona porque foi feito para Windows. Apesar de existir uma máquina virtual CLR, uma parte significativa são chamadas a subsistemas de baixo nível do sistema operacional usando pontes como PInvoke (Platform Invocation Services, para permitir código gerenciado chamar código não-gerenciado ou não-seguro). No caso de Java, a filosofia era 100% Pure Java, com o tempo surgiram adaptações usando JNI (Java Native Interface, essencialmente algo como PInvoke no .NET), mas no caso de Java preferencialmente tudo é feito para rodar dentro da JVM. Mesmo scripts de linha de comando são sempre chamadas java -jar xxx.jar por dentro.

Perl, PHP, Ruby, Python, e outros interpretadores que nasceram no ambiente Unix dependem de APIs POSIX por baixo. Ditribuições GNU/Linux e BSD/Darwin (OS X) implementam essa família de padrões e seguem a filosofia UNIX. O Windows, obviamente, não é UNIX e muito menos POSIX. Existe, porém, como ter o sub-sistema POSIX sobre o Windows. É isso que são os projetos Cygwin e Windows Services for UNIX. Apesar do grande esforço desses projetos em tentar prover as mesmas APIs POSIX, existem hoje diferenças nos ambientes Linux e Darwin que eles não cobrem, e por isso muita coisa ainda vai quebrar. É um trabalho homérico tentar fazer o Windows ficar compatível com um ambiente UNIX inteiro.

Por isso, a melhor forma de desenvolver com plataformas que dependem de UNIX é usar máquinas virtuais como VirtualBox, com a ajuda do bom e velho Vagrant, como falei no post anterior.

"Mas eu desenvolvo PHP e Python no Windows sem problemas!"

É verdade, mas você nunca vai poder usar tudo dessas plataformas, sempre vai precisar existir gambiarras pra fazer uma ferramenta que é simples no UNIX funcionar no Windows. Veja o PHP Composer Installer, precisa trazer embutido o Git, Msys, Cygwin e tudo mais. Como no caso particular do PHP, uma parcela considerável de todos os desenvolvedores usam Windows, então projetos de Installers como esse ainda funcionam razoavelmente, mas é uma considerável redundância de esforços. Sempre vai ter conflitos de versões mais novas com installers velhos e toda a velha dor de cabeça de sempre. Como instala num Linux? Simples, um comando:

1
curl -sS https://getcomposer.org/installer | php

Vamos instalar o PIP do Python no Windows? Não é necessariamente trivial, como esta thread no StackOverflow indica. E depois você precisa lidar com o Virtualenv no Windows. No Ubuntu?

12
sudo apt-get install python-pip
sudo apt-get install python-virtualenv

'nuff said.

Atalhos, Shortcuts, Cheat sheets

Se você está acostumado a um conjunto de keybindings, se adaptar a outro é uma dor de cabeça mesmo. Uma coisa que muitos tentam fazer é adaptar o editor às keybindings que estava acostumado, tipo tentar simular combinações do Textmate no Sublime. Recomendação: não faça isso. Você precisa lembrar de meia dúzia de combinações principais, o resto é secundário e via menu você relembra.

Para ajudar, aqui vão alguns cheatsheets que podem ajudar (principalmente se você está tentando ainda se adaptar a Vim):

Por que Ruby (ou Python, ou Perl, etc) não precisam de IDE?

"O que é uma IDE?" Tecnicamente "IDE" significa Integrated Development Environment. Significa um editor de textos, automatização de compilação e debugging.

No mundo Ruby não há preocupação sobre compilação porque salvo os raros casos onde você está trabalhando com uma extensão em C, não há "compilação". No mundo Rails, em particular, temos preocupação de deployment. Pra maioria de nós, significa um mero git push heroku master e boom.

Debugging é outra tarefa que não nos preocupa muito, ou pelo menos não deveria. Se precisarmos muito, basta adicionar a gem pry-rails ao seu projeto e colocar a linha binding.pry onde quer debugar. O servidor web vai parar nessa linha no seu console e você pode debugar de lá. Mas como você deveria estar desenvolvendo orientado a testes (Test-First/TDD ou Test-After, não importa, apenas teste!), debugging perde importância. Front-end precisa de debugging visual e todo navegador decente (Safari, Chrome e Firefox) tem excelente debuggers e web inspectors.

Terminal oriented development

Isso nos deixa somente com um aspecto importante: o editor de textos! Por isso que no mundo Rails não falamos em "IDE", e sim em editores de texto. Mas quem vem de uma IDE como Eclipse ou NetBeans para Java, ou mesmo XCode para Objective-C sempre pensa em uma e apenas uma coisa: "auto-complete" e ficam pasmos que no mundo Ruby ou não usamos ou o auto complete é bem simples.

Para entender isso precisamos de perspectiva. Vamos pensar em coleções. Em Ruby, temos Array e Hash. Em Java precisamos escolher entre: Vector, HashTable, List, ArrayList, LinkedList, Queue, ArrayDeque, PriorityQueue, Deque, BlockingQueue, Set, HashSet, LinkedHashSet, TreeSet, HashMap, TreeMap, SortedSet, NavigableSet, Map, LinkedHashMap, NavigableMap. Pelo menos 21 classes (e eu acho que não listei todas!) E se incluirmos o Apache Commons, temos mais: ArrayStack, FastArrayList, BinaryHeap, BoundedFifoBuffer, UnboundedFifoBuffer, BeanMap, DoubleOrderedMap, FastHashMap, MultiHashMap, ReferenceMap, FastTreeMap, ArrayEnumeration, ArrayIterator, BagUtils, BufferUtils, CollectionUtils, CursorableLinkedList, etc (essa é só metade da lista!)

Eclipse auto-complete

Isso deve dar uma perspectiva de porque não precisamos de "auto-complete". Use ferramentas como o Dash para ter acesso à documentação (e que no caso do Vim, tem integração do tipo selecionar a palavra-chave no seu código, digitar o comando ":Dash" e ele vai abrir diretamente a documentação no Dash! Muito prático). Se não tem Mac e usa uma distro Linux ou até mesmo Windows (!!), talvez o Zeal seja a melhor opção para documentação offline.

Dash

E o mundo iOS/OS X com framework Cocoa não é muito diferente. Bem menos opções do que em Java, mas ainda muito mais do que Ruby.

No caso de Objective-C ou o novo Swift, o XCode continua sendo um IDE competente. Ele ainda tem crashes bizarros e é um pouco pesado mas ter acesso a ferramentas como Interface Builder, Instruments, Simulator, etc faz parte do workflow de desenvolvimento de aplicações Desktop ou Mobile. No caso de Windows, fazer aplicações para desktop também exige um Visual Studio. Fazer Swing com Java sem alguns bons plugins e debugging também é complicado, então realmente use Eclipse ou NetBeans.

Xcode

Aliás, um Eclipse ou NetBeans demoram porque literalmente rodam sobre uma "máquina virtual" (que é leve, claro), que é a JVM. Nesse conceito, não é um grande salto rodar suas outras ferramentas de desenvolvimento de outra máquina virtual (mais pesada, sim) que é um Linux dentro de um Virtualbox. Ou se sua máquina de desenvolvimento já é Linux, rodar Vagrant com LXC.

O RubyMine assim como outras IDEs, foge da minha opinião deste post de usar a combinação "Bom Editor" + "Terminal" + "Vagrant" como fluxo de trabalho para Web. Mas se quiser muito tentar uma IDE para Ruby, esta é obviamente a melhor opção. Em particular, diferente do Eclipse, ele é consideravelmente mais rápido e responsivo. Ele quase empata com o Atom.io em tempo de abertura, levando perto de 4 segundos. O Atom leva perto de 3 segundos e o Eclipse leva mais de 17 segundos. Quase entra na categoria de editores de texto que você pode abrir rápido. Por isso mesmo é uma boa opção.

RubyMine

E aí, quais dicas legais vocês tem para cada um dos editores mostrados? Não deixem de colocar nos comentários!

Viewing all 481 articles
Browse latest View live