Resultado da tentativa de aprender Rust

Antes de começar esse texto propriamente dito, preciso comentar que conversando na comunidade de Rust no Telegram, recebi o link de um material de Rust muito bom do Elias (@eamaral), que é o novo livro, gostei muito mais desse que do anterior, e me pareceu muito melhor para quem não está migrando de C++ ou não tem um conhecimento prévio de muitos conceitos. Também gostaria de agradecer a “aula” que foi dada pelo mesmo sobre alguns conceitos, mesmo quando eu até estava tentando evitar a conversa, embora que isso já aconteceu comigo em outras comunidades de novas linguagens, tendo pessoas que realmente gostam de compartilhar o seu conhecimento sobre uma coisa nova.

Infelizmente essa primeira tentativa não terminou como eu gostaria, muito por querer desenvolver alguns projetos, onde ainda não conseguiria ter uma boa produtividade em Rust. Nos meus testes feitos, consegui fazer exemplos simples e entender a teoria de muitos conceitos, porém suas aplicações não se mostraram muito simples na prática. Porém acredito que o maior problema é a falta de experiência com a forma de programar e pensar de Rust.

Porém nem tudo foi em vão, o uso do enum e pattern matching, principalmente no tratamento de erros foi uma coisa que já usei fora do Rust, em outra linguagem de programação que desejo falar num texto futuro.

Então embora não tenha conseguido aprender um bom nível de Rust desta vez, aprendê-lo ainda não foi descartado, principalmente pelos que ele traz de interessante, como identificar muitos problemas em tempo de compilação, que embora já exista nas linguagens de programação funcional, é a primeira vez que vejo ser aplicado tão fortemente numa linguagem de outro paradigma.

Anúncios

Em busca de um material sobre Rust

No texto anterior contei o motivo da escolha de aprender Rust, neste texto vou falar sobre os materiais que encontrei.

A primeira vez que ouvi falar da linguagem foi em 2014 durante o FISL 15, na palestra “Servo: O web engine paralelo” do Bruno de Oliveira Abinader (infelizmente parece que a gravação não está mais no servidor). Inicialmente gostei do servo, porém não chegou a me interessar a ponto de correr atrás, tanto do servo, quanto do Rust. Mas de alguma forma, que não me lembro agora, acabei tento contato novamente com a linguagem.

Quando decidi começar a aprender, veio a primeira dificuldade de todas, encontrar um bom material. Achei alguns que poderiam ser bons, porém voltado principalmente para quem programa em C++, comentando principalmente as diferenças, porém não é o meu caso. Também não queria algo para quem esta começando a programar agora, ou só uma breve apresentação da linguagem, o ideal seria algo para quem só está migrando de linguagem, como talvez o tutorial do Python, explicando de forma direta e incremental as instruções e particularidades do Rust para qualquer um que tenha conhecimento de lógica de programação, independente da linguagem, que infelizmente não achei muito facilmente.

Antes de começar a estudar de fato, encontrei o Rust on the Rocks! do Dalmo Veras Neto, e a melhor parte é por ser em português, porém ele parou de postar os textos por falta de tempo, inclusive nem chegou a estrear o canal no YouTube.

Já que teria que ser em inglês mesmo, parti para o The Rust Programming Language, que encontrei na documentação oficial. Inicialmente não gostei muito da ordem dos tópicos, como comentar vários conceitos antes de me apresentar os tipos primitivos da linguagem, então fiquei um pouco perdido em algumas partes dos exemplos que eu só veria mais adiante.

Desta forma estou adotando a estratégia de simplesmente não me importar se não entender muito bem algo, tentar avançar o máximo que puder, para depois rever os conceitos com mais calma e uma base mair da linguagem. Aprendendo mesmo o que cada coisa significa, conceitos e elementos da sintaxe, num segundo estudo.

Ainda não terminei de lê-lo, porém me parece que será um bom guia de referência no futuro. Mas como material de estudo único, talvez falte um pouco a forma Rust de resolver os problemas, para evitar de só trocar a linguagem, mas não a mentalidade de resolver o problema. Então ainda estou em busca de um material, atualizado de preferência, com exemplo de um projeto para eu entender como me adaptar a linguagem.

Acho importante essa parte de se adaptar a linguagem, uma vez que mesmo que não vá mais utilizá-la, aprenderei conceitos que podem ser uteis em outras linguagem. Também entender como a tecnologia funciona, para não tentar usá-la de forma incorreta e gerando vários problemas por causa disso. Infelizmente essa é a parte mais difícil.

Começo a aprender Rust

Começo a aprender Rust

Neste final de semana comecei a estudar a linguagem de programação Rust. E para registrar o meu estudo, pretendo escrever alguns textos aqui, começando pelo motivo de ter escolhido esta linguagem, mas depois comentar o que estou achando e dificuldades que estou encontrando.

O principal motivo para eu escolher esta linguagem está ligando as principais linguagens que utilizo, sendo que existia um caso onde elas não atendiam. Para entender a necessidade vou listá-las.

De forma geral utilizo shell script (bash para ser mais específico) quando tenho que fazer automações, ou se já existe algum programa pronto, simplificar o seu uso. Sendo seu maior exemplo o Commit Rules, que permite executar comandos para validar o commit, onde leio o arquivo de configuração, executo alguns comandos e manipulo a saída e exit status dos mesmos.

Quando preciso desenvolver algo mais elaborado, opto pelo Python, que por ser uma linguagem bem geral e de rápido desenvolvimento, facilita bastante o meu trabalho, sendo desde programas em linha de comando, até aplicações web. Vou deixar aqui de exemplo o Deduplicated, que foi desenvolvido como uma biblioteca, tendo tanto uma interface por linha de comando, quanto web.

Porém Python não é uma linguagem que tem foco em performance, especialmente na versão 3. Este foi um dos principais motivos de algumas pessoas da comunidade Python ficarem de olho no Go, o que talvez seria o meu caminho, se tivesse tido necessidade de performance. Também cheguei a pesquisar sobre o Genie, porém por ser recente e a pouca documentação, fizeram eu a deixá-la de lado, até por nem ela, nem Vala terem tido um grande sucesso.

Tenho algum conhecimento de C, porém é mais teórico que prático, não tendo tanta confiança para escrever um software seguro nesta linguagem. Também já tentei estudar mais sobre algumas ferramentas, como Make e Autoconf, porém não encontrei bons materiais para o meu estudo.

Neste ponto encontrei Rust, que pode ser visto como uma alternativa ao C, porém verifica o acesso seguro a memória em tempo de compilação, aumentando minha confiança em escrever um software seguro. Ele também um tem gerenciador de pacotes, que pelos meus testes funcionou muito bem e sem espalhar vários arquivos pelo sistema inteiro, podendo ser excluídos ao apagar um único diretório.

Rust tem outras qualidades, porém esses dois pontos suprem minhas “dificuldades” do C. Se encaixando como uma opção de linguagem quando preciso de desempenho (tenho controle semelhante ao C, e sem garbage collector como outras linguagens), porém ainda é uma linguagem nova com recursos bem interessantes em suas expressões (comandos).

No próximo texto comentarei mais sobre materiais e primeiras impressões.

Deploy do MX Reverse no Heroku

No texto anterior, comentei sobre minhas escolhas para montar um site para verificar o DNS reverso (https://eduardoklosowski.wordpress.com/2014/12/08/mx-reverse-e-escolhas-de-frameworks/). Agora comentarei sobre a hospedagem do mesmo no Heroku.

Primeiro fiz a aplicação funcionar localmente, que bastava juntar a página escrita no AngularJS para ficar disponível no WSGI. Não é uma boa prática servir arquivos estáticos pelo WSGI, porém é fica mais simples para o desenvolvimento ter apenas um servidor HTTP e é desta forma que o Heroku trabalha. Para isto reutilizei o virtualenv do Python que havia criado para fazer o desenvolvimento, com a biblioteca do DNS e o Gunicorn (servidor WSGI) já instalado, adicionei o pacote static3 e alterei no código.

Com tudo devidamente testado no Gunicorn, criei o arquivo requirements.txt que é um padrão de projetos Python para dizer as dependências, no meu caso eram todos os pacotes instalados via pip, então foi só executar pip freeze > requirements.txt, porém o mesmo pode ser editado para remover alguma coisa ou ajustes de verão dos pacotes sem problemas.

Bastava ainda dizer como iniciar a aplicação, já que o Gunicorn tem vários parâmetros e é necessário informar onde está a função WSGI dentro do código Python. No Heroku esses parâmetros ficam dentro de um arquivo chamado Procfile, que consiste em um nome mais a linha de comando, podendo ter vários processos em diferentes linhas, no meu caso fiz apenas web: gunicorn wsgi:application --access-logfile - --error-logfile -. É possível utilizar esse arquivo localmente como o Heroku faz utilizando um programa escrito em Ruby chamado Foreman, porém optei pela versão escrita em Python chamada Honcho, com ele devidamente instalado bastou um honcho start e minha aplicação estava funcionando localmente já na forma necessária para subir no Heroku.

Criei uma conta, sem mistérios. Como o Heroku trabalha com o deploy baseado em Git, é necessário cadastrar uma Chave SSH, da mesma forma que ocorre no GitHub e outros serviços que utilizam o protocolo do SSH. Como já tenho a minha chave, não precisei criar uma nova, porém quem precisar pode utilizar o comando ssh-keygen no GNU/Linux. Copiei o conteúdo do arquivo id_rsa.pub e adicionei em SSH Keys dentro do Manage Account.

Próximo passo é criar o aplicativo, que pode ser feito dentro de Personal Apps, clicando no ícone de mais. Incrivelmente esse cadastro é bem simples, o nome do aplicativo, que caso não seja especificado será gerado automaticamente e em qual região você deseja que o seu aplicativo fique rodando.

Agora a parte mais importante, enviar seu código para o servidor. Existe a opção tradicional via Git ou via Dropbox (em beta neste momento). Na opção via Dropbox, basta copiar seu código para o diretório criado, ir no Heroku e mandar ele buscar a nova versão. Como eu tenho experiência com o Git, já tinha meu código nele, achei muito mais simples adicionar um repositório remoto e fazer o push. Vendo as configurações do aplicativo, achei a URL em Settings (git@heroku.com:mxreverse.git), adicionei no repositório (git add remote heroku git@heroku.com:mxreverse.git) e enviei o código (git push heroku master).

Depois desses simples passos já tinha a minha aplicação rodando em https://mxreverse.herokuapp.com/. Obviamente por ser uma aplicação simples, sem banco de dados, não precisei fazer uma série de configurações, bem como o uso da ferramenta de linha de comando do Heroku.

Uma das vantagens do Heroku sobre outras soluções como OpenShift é a possibilidade de criar vários aplicativos de graça, uma ótima opção para quem esta desenvolvendo e quer deixar sua aplicação rodando ou um demo, depois se a quantidade de acessos crescer, você pode escalar sua aplicação lá mesmo ou mudá-la para outro lugar. Porém já ter sua aplicação disponível na internet logo no início pode motivá-lo a continuar o desenvolvimento ou trazer mais pessoas para o projeto, já que ela não terá o trabalho de fazer o deploy para ver seu projeto e a facilidade para apresentar a outras pessoas.

Estrutura interna do Git – Parte 2

Não exatamente uma sequencia, porém ainda ficaram alguns pontos que eu acho muito interessante do Git que levarei em conta quando precisar desenvolver algo.

Além dos comandos normalmente utilizados, que para quem utiliza o bash completion possui autocompletamento, existem vários comandos “ocultos”, porém documentados. O comando git cat-file do texto anterior é um exemplo. Isso ocorre pela forma que os comandos do Git foram feitos, existe um conjunto de comandos básicos para executar pequenas tarefas, assim como a filosofia UNIX (uma única coisa, porém bem feita). Ou seja, comandos para adicionar arquivos na estrutura do Git, recuperá-los, calcular diferenças, aplicá-las, lidar com braches e outros.

No capítulo 9 do Pro Git temos um exemplo melhor desses comandos, e até como fazer um commit sem utilizar o git commit. Isso mostra que até mesmos comandos internos são implementados utilizando outros comandos, dividindo o problema em partes menores.

Agora imagina que você está desenvolvendo um sistema que utiliza alguma parte do Git, como o GitHub para visualizar o código, ou o OpenShift para receber o código e fazer deploy da aplicação. Como existem várias operações você não precisa desenvolver algo para ler a estrutura do Git, pode simplesmente reutilizar esses comandos, ou seja, a API já está pronta, basta adaptá-la para a sua linguagem.

Porém não precisamos ir muito longe para tirarmos proveito disso. No meu texto Verificador de estilo de código no VIM, comentei sobre os verificadores de estilo e podemos utilizá-las em conjunto com o Git. Imagine que seu projeto tem um estilo que todo o código deve ser seguido, porém as vezes alguém acaba deixando passar um espaço a mais, troca espaço por tab. No Git podemos fazer a validação do código é permitir o commit apenas caso ele esteja de acordo com o estilo.

Para fazer essa verificação precisamos utilizar outro recurso chamado de Hook, que são scripts executados em determinados momentos (consulte o capítulo 7.3 do Pro Git). Inicialmente fiz a verificação apenas local para lembrar caso tenha alguma coisa fora do padrão, mas ainda possível forçar o commit se assim for desejado. Como os projetos tinham vários arquivos fora do estilo, queria verificar apenas os alertas referentes as minhas mudanças, até por questão de performance, se eu não alterei o arquivo não preciso ser lembrado que ele tem algum erro, deixando a saída até menos poluída e posso verificar todos os arquivos caso esteja atrás de erros.

Primeira coisa, preciso saber quais os arquivos que foram alterados no commit, para tanto utilizei o comando git diff –raw –cached, uma informação um pouco mais bruta dos arquivos selecionados com git add. Porém eu posso ter executado o git add e alterar o arquivo novamente antes de fazer o commit, então não posso simplesmente fazer a validação do código do arquivo no diretório, para isso utilizei a hash do git diff para pegar o arquivo que será commitado com git show e fazer a validação em cima dele.

Quem quiser ver como tudo ficou, tenho esse código no meu GitHub (https://github.com/eduardoklosowski/codelint), está escrito em Python, porém tenho que trabalhar melhor a documentação e ter decidido fazer tudo em inglês não ajudou, porém assim que estudar melhor as formas de documentação e opções que tenho para compartilhá-la irei fazer isso, mas se alguém for usar e tiver alguma dúvida deixe nos comentários, até ficarei feliz em saber que alguém está utilizando (testando). Report de bugs, melhorias no código ou funcionalidades novas são bem vindas. Pode ser utilizado com outras ferramentas de controle de versão, só não tenho conhecimento e necessidade para isso agora, mas pode ser facilmente desenvolvido já que o Git foi feito a parte também.

Depois de criar os arquivos de configuração em ~/.config/codelint, preparo tudo para o commit e executo git codelint, isso iniciará os validadores. Um detalhe que todos os comandos no PATH que começam com git-, exemplo git-codelint podem ser executados como comandos do git dessa forma e com autocompletamento.

Agora só falta colocar no Hook executado antes do commit, o pre-commit, seu conteúdo é simples.

#!/usr/bin/env bash
git-codelint

Caso queira verificar os arquivos antes de commitar posso executar git codelint e quando der o git commit será verificado, se tiver algum erro o commit será interrompido para correção, ou posso forçar com git commit -n.

Estrutura interna do Git

Existem diversos tutoriais e guias sobre como utilizar o Git e seu funcionamento, como por exemplo o Try Git e o Pro Git. Todos esses materiais auxiliam nos primeiros passos com a ferramenta, porém quando se começa a trabalhar com recursos mais avançados, principalmente branches e merge/rebase as coisas tentem a ficarem mais confusas para quem está iniciando.

Eu particularmente li o livro Pro Git, aprendi muito sobre o funcionamento e seus recursos. Como faz algum tempo quase um ano que fiz esta leitura, irei fazer um resumo para relembrar e compartilhar com vocês sobre a parte interna do Git, que foi o mais importante, no meu caso, para aprender ou imaginar como os demais recursos funcionam. Como exemplo irei utilizar um código publicado do meu Git Hub (https://github.com/eduardoklosowski/webprint), assim todos podem visualizar os mesmos resultados.

Talvez o mais importante a se entender é que o Git possui um sistema para armazenar objetos, que na verdade é tudo o que está na sua estrutura interna, como arquivos, diretórios e commits, podendo ser acessados por uma hash SHA1. Um exemplo prático, na data de publicação deste texto, o último commit deste repositório era o “cb584a1992fef3c286c5b36d2aba1c66bfe9b3a2”, o que significa que existe um commit que pode ser acessado com essa hash dentro da estrutura do Git, podendo ser visualizado com o comando git cat-file -p cb584a1992fef3c286c5b36d2aba1c66bfe9b3a2:

tree 73e7173b7f13853343b3bbad766f2b54852e8995
parent ff12eb157275a886feb9a039819cfc067e7292d5
author Eduardo Klosowski 1406755582 -0300
committer Eduardo Klosowski 1406755582 -0300

Correção da exclusão da imagem

Além das informações de quem fez as modificações, quem fez o commit, suas respectivas datas e mensagem, temos duas informações importantes. A primeira é o “parent”, seu valor é o hash do commit anterior, que pode ser verificado com um git log, é possível seguir esse valor dos commits até primeiro, que não fará referência a outro justamente por ser o primeiro. Se em algum comento tiver uma ramificação no histórico dos commits, o ponto de união apresentará mais de um parent, justamente para mostrar essa união.

A segunda informação importante e o “tree” que é um objeto de diretório, assim como existe na maioria dos sistemas de arquivos, é possível considerar essa estrutura interna do Git como um sistema de arquivos, porém específica para controle de versão, existem outros tipos de objetos além de arquivos e diretórios, mas não quem é o domo, data de criação e modificação por exemplo, isso torna as vezes mais rápido colocar um arquivo na estrutura do Git que no sistema de arquivos do HD por exemplo. Utilizando o mesmo comando para visualizar o objeto do diretório (git cat-file -p 73e7173b7f13853343b3bbad766f2b54852e8995) temos:

100644 blob 7821b4a1a8bc6e6d29368e25bb1d2a4b42f3754e .gitignore
100644 blob bcca729f3ce131d32dbe9af737e8d9ed049fe25d LICENSE
100644 blob d45ebab4a0fb6137cd519a6448cb4313a8e0ba2a README.md
100755 blob 3f3fdf92237f708dd3494b63b7fce452d406d870 manage.py
040000 tree f6e01702b079c29f3798ed54349c2218e4131fc3 webprint

Essas informações, pela ordem das colunas são: permissões do objeto (os últimos 3 dígitos são a mesmas permissões do EXT4 por exemplo), o tipo de objeto (lembrando que tree é outro diretório e blob são arquivos), o hash do objeto referenciado e finalmente seu nome.

Os arquivos também podemos acessar pelo hash, no caso git cat-file -p bcca729f3ce131d32dbe9af737e8d9ed049fe25d teremos conteúdo do arquivo “LICENSE” desse commit específico. Quem já trabalhou com ponteiros e estruturas em C já deve ter entendido como o Git funciona internamente, já que é a mesma lógica, de ter referências (ponteiros) para outros objetos (estruturas).

Sendo um pouco atento você poderá notar que o Git não gravou a diferença entre os commits em sua estrutura em nenhum momento, o motivo é simples, ele não faz isso. Toda vez que precisar a diferença os objetos são acessados e calculados na hora, pode ser um pouco mais lento que simplesmente ter o resultado já armazenados, porém se você tiver vários commits entre os objetos que for comparar é mais simples ter os dois e calcular a diferença que juntar todas as diferenças de cada commit.

Outro ponto importante é que cada commit tem referência para todos os arquivos que estão no projeto naquele momento, assim como um “snapshot”, então mesmo que algum arquivo ou diretório não tenham sofrido mudanças, eles estarão em ambos os commits, porém como não houve mudanças, os dois commits (ou mais) podem apontar para os mesmos objetos da estrutura, assim já otimizando o espaço e evitando objetos duplicados.

Agora se você tiver um arquivo com centenas de linhas e alterar apenas uma, você terá uma cópia completa do arquivo com apenas essa uma linha alterada dentro da estrutura do Git, a princípio parece desperdício de espaço, porém mesmo esse arquivo exista dentro da estrutura do Git, não quer dizer que ele existirá no sistema de arquivos, quando existem vários objetos semelhantes, o Git junta esses objetos em um “pack”, um único arquivo para esses vários objetos, sendo elegido um para estar na integra dentro do pack e os demais apenas as diferenças.

Então é verdade que o Git guarda diferenças de arquivos, porém no sistema de arquivos e não em sua estrutura de objetos, assim não tendo o problema de arquivos quase duplicados. Outro ponto importante que não é necessariamente a primeira ou última versão do arquivo que estará na integra no pacote, podendo ser uma versão intermediária que gerarias diferenças menores, reduzindo ainda mais o tamanho do pack no sistema de arquivos.

Então para calcular a diferença de dois arquivos com vários commits de modificação, na pior das hipóteses terá que ler dois arquivos do pack, aplicar duas diferenças e calcular as diferenças entre eles, em vez de somar as diferenças de cada commit, ganhando assim mais desempenho.

Sobre os branches, nada mais são que referências aos commits, ou seja, guardam o hash de algum commit, que podem ser visualizados dentro do diretório “.git” do projeto com o comando cat .git/refs/heads/master por exemplo.

Todos os processos que alteram o histórico do Git, como rebase e cherry-pick são alterações nessas referências, porém se os commits forem alterados, serão gerados novos commits com outros hashs, os antigos não deixam de existir de imediato, apenas não tem mais nenhuma referência apontando direta ou indiretamente para eles, por isso não aparecem mais, porém ainda estão na estrutura do Git e podem ser acessados pelos seus hash, a menos que tenham sido removidos automaticamente pelo Git depois de algum tempo ou com o comando git prune.

Esse é um assunto extenso, e só é possível se dominar com o uso do Git, porém entender isso me ajudou e ajuda muito quando preciso fazer algo no Git. Recomendo a leitura do Pro Git para todos, já que ele vai do básico ao avançado, é gratuito e está em português, além de mostrar muito mais exemplos como esse descrito aqui.

Docker

Uma das novidades da versão 3.8 do kernel Linux é o superte ao LXC (Linux Containers), apesar de ser possível utilizar esse recurso diretamente, existem algumas alternativas que facilitam seu uso como o Docker.

Os Linux Containers nada mais são que uma evolução do chroot, que antigamente era muito utilizado para rodar o bind de forma isolada do sistema por questões de segurança (procedimento na wiki do Debian). O chroot simplesmente troca o root do sistema para aquela aplicação de forma que todos os caminhos absolutos comecem de um determinado diretório e não seja possível acessar os arquivos que não estiverem de baixo do mesmo. Está técnica também é conhecida por enjaulamento (chroot jail).

Apesar do isolamento na parte de sistema de arquivos pelo chroot, nem tudo do processo fica isolado, como a pilha de rede, que por exemplo ainda é compartilhada. O Linux Container veio para melhor isso e o Docker para facilitar seu uso.

Primeira coisa para se entender do Docker é que ele só funciona no kernel Linux para executar containers Linux, apesar de existir versão no site oficial para Windows e Mac, por trás é utilizado uma VM com o Linux para executá-los. A segunda que diferente de máquinas virtuais, que recriam todo o ambiente de um computador para executar o sistema operacional, ele reutiliza o kernel em execução, então a versão do kernel dentro do container será a mesma do sistema hospedeiro, então se tiver que carregar algum módulo do kernel para alguma aplicação específica, deve ser feito no hospedeiro.

Agora para entender como a mágica é feita basta voltar no gerenciador de boot. Um dos parâmetros do Linux é o root=, onde é dito para o kernel que ponto dele deve utilizar como root para o sistema assim que for iniciá-lo. No Docker é como se criássemos um processo que voltaria neste ponto e diria que o root= é outro, apenas para um grupo de processo, porém sem iniciar um novo kernel, mas com seus próprio espaço de sistema de arquivos, pila de rede, controle de processos, CPU e alocação de memória, fazendo-o parecer muito com uma VM, se não fosse pela questão do kernel ter que ser o mesmo.

Uma vez na máquina hospedeira será possível listar todos os processos dos containers com um simples ps aux, já que tudo está sobre o mesmo kenel, porém dentro do container não é possível acessar o hospedeiro diretamente devido ao isolamento feito pelo kernel, bem como outros containers.

Agora mais específico para o Docker. Ele trabalha com grupos de imagens e diferenças entre elas, você tem uma imagem básica do sistema, que pode ser o que você quiser como CentOS, Debian ou até apenas um simples BusyBox, que é possível devido ao fraco acoplamento dos programas com o kernel (sendo possível um kernel Debian e imagem CentOS), e várias pilhas de imagens até chegar ao sistema de arquivos do seu container. O funcionamento desse sistema de arquivos é devido ao Aufs, que é um sistema de arquivos voltado a mudanças, ou seja, só serão gravadas as mudanças efetuadas, assim como num repositório Git (que é um dos requisitos no Debian pelo menos). Você tem a imagem do sistema operacional básico, uma camada aonde você instalou o SSH, outra o Apache e na última sua aplicação, qualquer mudança será feita na camada da sua aplicação, porém para acessar os arquivos binários do apache, como ele não está na camada a aplicação, vai descendo até chegar nos arquivos, para acessar o bash, por exemplo terá que ir até a camada do sistema base. Se ainda ficou um pouco confuso basta lembrar dos snapshots das VMs, aonde você pode voltar para um momento específico do sistema de arquivos e normalmente só é gravado no HD a diferença do último snapshot.

Agora para começar a parte mais prática, tendo o Docker instalado conforme a documentação, precisamos de uma imagem base, por exemplo a do CentOS, que pode ser baixada do repositório oficial do Docker com o seguinte comando docker pull centos. Para iniciá-la um container com esta imagem basta executar docker run -t -i centos /bin/bash. E assim que o bash for fechado, este container parará de executar.

Para subir um WordPress por exemplo, podemos utilizar os containers das aplicações já prontas, primeiro um container com o MySQL:
docker run --name blog-db -e MYSQL_ROOT_PASSWORD=senhanovadoroot -d mysql

E depois o WordPress:
docker run --name blog-wp --link blog-db:mysql -d wordpress

Vale notar que caso você não tenha as imagens, a mesma será baixada automaticamente do repositório oficial do Docker e que executar o banco em um container diferente permite simplesmente trocar o containder do WordPress para atualizar e manter o mesmo banco, assim como escalar para várias instâncias do WordPress conectando no mesmo banco.

O Docker também tem uma vantagem para quem faz aplicações, você pode pegá-la e gerar um container, com o sistema que mais desejar, assim como as versões específicas das bibliotecas, e sempre rodará sem problema em qualquer distribuição, atualizada ou não. Há algum tempo no meu GitHub, fiz um exemplo/tutorial de como criar um container e executar uma aplicação WSGI dentro do Docker (https://github.com/eduardoklosowski/Exemplo-Docker-para-WSGI). Para visualizar melhor as camadas do sistema de arquivos basta olhar o arquivo Dockerfile, cada comando presente no arquivo gera uma camada, e caso tenha algum erro nesse processo não é necessário executar novamente os comandos que não tiveram erro, apenas os demais.

Deixo o vídeo do Allisson Azevedo (https://www.youtube.com/watch?v=vb2k8jOlHkA) para quer quiser saber mais ou ter outra explicação para comparar, além de aconselhar a leitura da documentação oficial.

Verificador de estilo de código no VIM

Exemplo pep8

Como mencionado no texto anterior sobre o VIM, existem algumas ferramentas para análise de sintaxe e estilo de código. A principal vantagem dessas ferramentas é a possibilidade de validar o código independente da IDE, uma vez que nem todos gostam e se acostuma com as mesmas ferramentas, o maior exemplo é a “flame war” VIM e Emacs, mesmo assim é possível ter um nível de padrão no código.

As ferramentas e alertas variam conforme a linguagem desejada, porém basta uma pesquisa para encontrá-las. Para Python temos o pep8 e o Pylint, o primeiro faz a verificação segundo as regras da PEP8, o segundo vai além e mostrar variáveis que não são utilizadas, algumas boas práticas, erro nos imports e assim por diante.

Para JavaScript temos o JSLint e o JSHint, ambos efetuam a mesma tarefa, porém possuem diferenças de configuração e o estilo do código correto também será levemente diferente, basta ver o que melhor se adapta a situação.

Integrar esses verificadores no VIM exige que primeiro tenhamos eles instalados e funcionando corretamente no sistema. O pep8 instalei via pip (pip install pep8), caso o faça dentro de um virtualenv não se esqueça que o executável deve estar no PATH para que seja encontrado. O JSLint foi instalado com o Node.js. Para utilizá-los basta chamar o executável, pep8 ou jslint, e o nome do arquivo, agora é possível configurar dentro do VIM.

Como já mencionado no texto anterior, simplesmente configurei o validador como se fosse o compilador, o que pode ser feito com o parâmetro “makeprg”, porém para que os erros aparecem integrados ao VIM é necessário informar como ele deve interpretar a saída dos programas com o parâmetro “errorformat” (digite :help errorformat dentro do vim para mais informações).

Minha configuração ficou:

autocmd Filetype python set makeprg=pep8\ %
autocmd Filetype python set errorformat=%f:%l:%c:\ %t%n\ %m
autocmd Filetype javascript set makeprg=jslint\ %
autocmd Filetype javascript set errorformat=%-P%f,
                                           \%E%>\ #%n\ %m,%Z%.%#Line\ %l\\,\ Pos\ %c,
                                           \%-G%f\ is\ OK.,%-Q

Para validar o código basta salvar o código, e executar :make. Porém se você quiser pode criar um atalho para essa tarefa, no meu caso coloquei no F4:

map <F4> :w<CR>:cw<CR>

Lembrando que esses comandos devem ficar dentro do .vimrc no seu home.

Editor de Texto: VIM

Atualmente estou usando o VIM como meu editor padrão, o principal motivo e buscar um editor livre, porém tem algumas vantagens interessantes que notei nesse processo e estou compartilhando com vocês.

Primeiro todas as versões de GNU/Linux e possivelmente UNIX sempre possuem alguma versão do VIM ou VI instalado por padrão, então mesmo que você não esteja no seu computador, terá o editor ao qual está acostumado, provavelmente sem os plugins, porém melhor que pegar um editor totalmente diferente.

Não existe a necessidade de um ambiente gráfico para poder utilizar o mesmo, então é possível utilizar ele completamente apenas no terminal, mesmo conectado via SSH não precisa redirecionar o X, o que somado a primeira vantagem torna as coisas muito interessantes pelo menos para mim. As vezes, preciso desenvolver ou testar algo direto no servidor que não tem interface gráfica. Porém existindo a interface ainda podemos utilizar o gVim que adiciona mais algumas facilidades na interface gráfica.

Totalmente extensível por plugins, como ele possui esse recurso e não é um editor novo, provavelmente já existe um syntax highlight para os formatos que você precisa e talvez até funcionalidades para auxiliar em algumas tarefas, basta dar uma pesquisada no site oficial.

É possível adaptar algumas coisas, por exemplo trabalho com linguagens interpretadas como Python e JavaScript, então não tenho erros de compilação. Como existem alguns verificadores de sintaxes (como pep8 para o Python e JSLint para o JavaScript), substitui o comando make dessas linguagens por seus respectivos verificadores, configurei a saída de erros e com uma simples tecla verifico se o meu código apresenta algum erro ou não conformidade com as boas práticas de código integrado na tela do código. Tenho a intenção montar um tutorial sobre isso mais para frente.

Para Python temos o Jedi, o melhor autocompletar que eu já vi para a linguagem, completamente diferente do padrão do Sublime que por exemplo apenas lista palavras já utilizadas, podendo enganar as vezes.

Obviamente o VIM não é amigável logo de cara, muitos tiveram o trauma de reiniciar o computador na primeira vez que abriram ele sem saber como fechar. Porém com o tempo você acaba pegando o costume dos atalhos que mais utiliza e nem se importa com os demais. Utilizando os menus do gVim temos o comando para fazer as tarefas direto no VIM e é possível decorar conforme a frequência de visualização dos mesmos. Também existe o Cream, que torna o VIM mais parecido com os demais editores de texto, vale a pena dar uma olhada, caso esse seja o seu desejo para um editor.

Todo mundo que utiliza o VIM sempre tem o problema de como configurar o .vimrc, porém como ele é totalmente customizável só com o uso você conseguirá deixá-lo da forma que desejar, porém para ajudar os iniciantes temos o Vim Bootstrap, basta selecionar as linguagens que deseja e mandar gerar o .vimrc.

A curva de aprendizagem pode ser grande, porém muitas pessoas conseguiram superá-la e não querem mais largá-lo, vele a pena dar uma estudada, o comando vimtutor pode ensiná-lo. Esse conhecimento pode salvá-lo, principalmente quando tiver que editar algum arquivo dentro de um access-point com Linux.

Editor Web: Brackets

Bracket

É muito difícil encontrar um programador que não saiba HTML, CSS e JavaScript, hoje esse trio é suportado em praticamente todos os dispositivos que possuem conexão com a internet. Porém além de saber utilizá-los, algo que auxilia e muito na hora de codificar é uma boa IDE. Também são interessantes as IDEs que são escritas com as próprias linguagens, que tende a integrar melhor com a forma de desenvolver daquela linguagem.

O Brackets é uma IDE para HTML, CSS e JavaScript (suporta outros formatos com plugins) escrita em HTML, CSS e JavaScript, como descrito no próprio programa: “Made with ♥ and JavaScript”. Essa IDE é um projeto open source da Adobe com código no GitHub e disponível para GNU/Linux, Mac e Windows, possuindo recursos muito interessante para o desenvolvimento web. Para os designs existe o “Live Preview”, que mostra no Google Chrome como o seu site está em tempo real (infelizmente ainda não é compatível com os demais navegadores), ou como demonstrado neste vídeo do YouTube (https://www.youtube.com/watch?v=xAP8CSMEwZ8) a montagem de um layout a partir de um arquivo “psd”, graças a integração com as outras ferramentas encontradas nos produtos da Adobe.

Porém os desenvolvedores também ganham ótimas ferramentas, além de poder debugar a própria IDE com as ferramentas de debug do Webkit. Existem extensões para as mais diversas funcionalidades, desde validados de código com as boas práticas, até integração com o Git mostrando linhas modificadas em arquivos, documentação na própria IDE e suporte a outros formatos de arquivos. Também existe extensões para mudar o tema, ToDo List, mostrar alguns sites como o Building Firefox OS e Can I use….

Com versões sendo lançadas mais ou menos no espaço de um mês, está sempre atualizado e vem adicionando recursos novos a cada versão, tanto que existem vídeos no site apenas para demonstrar as novidades. Se você tem algum contato com desenvolvimento web, ou interesses nesta área, vale muito a pena dar uma conferida nesta IDE.