Autor: Luiz Ricardo (Página 7 de 16)

Desafios na carreira de um desenvolvedor

business

Programador, Analista, Desenvolvedor, Engenheiro de Software. Não importa qual o título adotado. Você escreve código? Então é mais um que caiu nessa “cilada”! 😉

Brincadeiras à parte, a área de desenvolvimento de software é uma das mais comentadas, desejadas, amadas e até odiadas da atualidade. Sendo sua história relativamente recente, ainda há muita confusão sobre a identidade do profissional de TI.

Isso se reflete na dificuldade de muitos, senão todos, profissionais ao tomar decisões sobre carreira. O que devem estudar? Vale a pena saber a linguagem X? Em que se especializar?

Todos já ouviram o mantra de que em TI “é necessário estar sempre se atualizando”. Esta é mais uma frase pronta que, de tantas vezes repetida, já perdeu completamente o significado e o impacto em nossas mentes.

Quero agora levá-lo a uma breve reflexão sobre o seu desenvolvimento como profissional e tentar responder de forma geral às indagações acima.

Sim, TI é complicada

Brooks escreveu na edição especial do livro The Mythical Man-Month, lançada em 1995, que ele já não conseguia mais acompanhar o avanço em todas as áreas da Engenharia de Software como antigamente. Quem dirá hoje!

A situação piorou muito. A cada ano aumenta a gama de conhecimento, plataformas, linguagens, frameworks e ferramentas. Os formandos que vão trabalhar com software precisam sair da faculdade dominando conceitos que foram formulados ao longo de anos, décadas e até séculos. É como se cada turma saísse da faculdade sabendo menos que a anterior, já que existem sempre novidades e o gap de informação aumenta.

Essa gigantesca gama de informações faz com que muitos fiquem ansiosos sobre a infinidade de tecnologias a serem aprendidas. E as empresas parecem procurar super programadores que parecem já ter nascido sabendo tudo.

Algumas vezes já fiquei bastante ansioso por conhecer tão pouco e ver cada dia novas tecnologias sendo lançadas. Parecia nunca ter fim!

Não se desespere

Apesar do cenário acima, precisamos compreender que leva tempo para se aprender bem qualquer profissão. Alguns dizem que leva uma média de 10 anos para alguém ser realmente bom no que faz. E pesquisas indicam que passamos a gostar mais do que fazemos proporcionalmente ao tempo que nos dedicamos aquela atividade.

Além disso, não se deixe levar por aquelas milhares de siglas que você não entende, por exemplo quando você olha aquelas vagas de emprego que pedem centenas de conhecimentos que você nem tem ideia do que são. Isto é algo possível de se conhecer com o tempo.

Não estou dizendo que é fácil. É preciso se esforçar bastante, mas o segredo é ter calma, paciência e persistência. Então você poderá planejar seu avanço profissional dentro de suas capacidades e estudar rotineiramente sem desistir ou desanimar.

Ninguém nasce sabendo

Você não precisa saber de tudo para atuar numa certa área. Aliás, faculdade ou curso algum vai ensinar o que é realmente preciso para encarar um trabalho desafiador ou mesmo empreender em seu próprio negócio.

Basta aprender o necessário para cada fase de sua carreira. Para quem está começando em TI, o importante é conhecer bem os fundamentos da computação, orientação a objetos e pelo menos uma linguagem de programação. Depois disso, é importante intercalar ciclos de estudo e trabalho prático para começar o amadurecimento profissional.

Em minha experiência é importante pensar iterativamente, isto é, em ciclos. Você pode traçar uma meta de aprender profundamente sobre uma tecnologia por ano ou a cada 6 meses, dependendo do seu ritmo. Aí você pode gastar o primeiro mês estudando livros e apostilas, o segundo implementando um protótipo simples, o terceiro estudando um pouco mais a fundo, o quarto tentando criar um projeto mais sério, o quinto lendo material mais difícil sobre o assunto e assim por diante.

Especialistas

Persistindo nos estudos, muitos profissionais acabam se especializando num subconjunto de conhecimentos de uma das áreas de TI. Tornam-se especialistas.

Isso fica bem visível ao analisar alguns eventos de TI. É possível observar diferentes nichos de tecnologias, com palestras e cursos voltados para cada subcultura de TI, cada uma com um público bem específico.

É bom especializar-se em algo. Trabalhar e estudar diferentes aspectos de alguma tecnologia por alguns anos é um grande investimento, pois você passa a ser distinto dentro desse segmento.

Porém, a especialização tem lados positivo e negativo.

Especialistas e especialistas

Como mencionei, há algumas pessoas que são especializadas porque se aplicaram consideravelmente em conhecer determinado assunto.

Por outro lados, outras são “especialistas” porque não se aplicaram em conhecer nada além daquilo que já usam no dia-a-dia.

Enquanto os especialistas de verdade estão dentro da média na maioria dos assuntos e dominam sua especialidade, há os falsos especialistas que não se interessam por nada que não é necessário para eles.

Respeitando a individualidade

Devo fazer uma consideração aqui. Precisamos entender que nem todas as pessoas que trabalham em TI são aficionadas por programação ou questões técnicas.

Conheço bons profissionais, organizados e produtivos, mas que não chegam perto de serem bons programadores. Nem todos os “especialistas” e bons profissionais são necessariamente bons programadores. A Engenharia de Software possui muitas disciplinas que envolvem outras áreas.

Não devemos cair no grande erro de muitos educadores no decorrer da história, o qual tem impactado nossa geração inteira. Estou falando da padronização do que é considerado “inteligência” ignorando as singularidades de cada indivíduo. Isso nada mais é do que dar vantagem a um perfil específico em detrimento dos demais.

Muitas empresas e muitos profissionais ignoram isso e inconscientemente geram incalculáveis prejuízos para si mesmas. Aliás, os profissionais que coordenam processos seletivos deveriam ser os melhores da empresa, porque nada como um excelente profissional para identificar as potencialidades dos entrevistados. Porém, o que geralmente ocorre é que essa tarefa fica relegada a profissionais, no mínimo, medíocres. E o resultado são contratações, no mínimo, medíocres.

Enfim, se você não é um programador, ainda pode aplicar todas as dicas que tentou passar aqui em sua área de conhecimento.

Generalistas

Outro perfil profissional é do generalista, isto é, aquele que estuda diferentes áreas, não ficando muito tempo em apenas uma coisa.

Por muito tempo ouvi críticas a esse tipo de profissional. Você já ouviu algo como “saber pouco de tudo é não saber nada de nada”?

Pois bem. Há até um certo fundo de verdade nisso. Se um profissional troca frequentemente de trabalho, mas não se aprofunda em nada, seu destino será exatamente esse: não saberá “nada de nada”.

Por outro lado, veja a tendência do mercado mudar fortemente nos últimos anos. Antes todos queriam espacialistas. Hoje, os profissionais mais valorizados são os que possuem uma visão abrangente da Engenharia de Software, mas conhecendo o que fazem profundamente.

No entanto, colocarei esses profissionais numa nova categoria…

Generalistas especialistas

Que diacho é um generalista especialista?

Após alguns anos de mercado, analisando vagas em grandes e pequenas empresas, notei uma tendência no perfil mais desejado por boas empresas.

É mais ou menos assim. O profissional deve:

  1. Ter pelo menos 5 ou 7 anos de experiência
  2. Dominar pelo menos 2 tecnologias
  3. Ter conhecimentos intermediários em várias tecnologias
  4. Conhecer o básico de todos os conceitos importantes da Ciência da Computação e Engenharia de Software

Obviamente esses valores e as estatísticas são uma média arbitrária da minha cabeça, mas serve bem para ilustrar meu ponto aqui. Vou traduzir isso em alguns princípios e estou certo que será útil para você.

1. Experiência

Os anos de experiência na verdade não são tão importantes em si mesmos. A questão toda está na maturidade do profissional.

As empresas e os próprios desenvolvedores querem alguém que agregue à equipe e não que seja um atraso. É uma realidade cruel para os novatos, mas a verdade é que hoje não importa muito se você é um gênio em matemática ou em programação. Os desafios mais comuns da Engenharia de Software estão em outras áreas, principalmente nas relações humanas. E, convenhamos, poucos recém-formados são habilidosos em trabalhar com pessoas.

Além disso, não importa se você sabe uma linguagem de programação de cabo a rabo. Resolver problemas complexos da via real exige uma carga de conhecimentos em diferentes áreas.

2. Especialização

Para entregar software no prazo e com qualidade, além de corrigir os problemas mais difíceis, o profissional deve dominar a tecnologia com que trabalha.

Porém, conhecer uma única tecnologia não é mais suficiente.

A grande maioria dos sistemas desenvolvidos hoje são web. De início, podemos dividir esses sistemas em back end e front end. Se você é da área, deve saber que em geral as tecnologias de um e de outro são completamente diferentes. Por isso, é comum hoje um bom profissional que domina .NET ou Java também dominar Javascript, HTML e CSS.

Note que não estou falando em conhecer um pouco de cada tecnologia, mas sim em ser altamente proficiente em várias delas.

3. Generalização

Com a grande variedade de tecnologias disponíveis, o profissional que conhece pelo menos em nível introdutório o funcionamento básico de cada uma, além dos conceitos que dão suporte a essas ferramentas, terá muito mais capacidade de escolher a solução mais correta e adequada para os diferentes desafios.

Isso parece contradizer o tópico anterior, mas não é bem assim. Se você domina pelo menos uns dois paradigmas de programação e tem bons fundamentos técnicos, provavelmente se dará bem com qualquer novidade. Este é o ponto: um generalista é muito mais adaptável a novos desafios.

As antigas guerras de “Ruby vs PHP”, “Python vs Perl”, “C++ vs Java” simplesmente acabaram, exceto para alguns que faltam em maturidade.

Hoje os bons profissionais sabem que não é preciso escolher uma linguagem definitiva. Você poderia usar todas ao mesmo tempo, se quiser. Aliás, em determinadas situações você deve usar um conjunto delas no mesmo projeto.

4. Visão abrangente

Primeiro, desenvolver software não é apenas digitar código. Tenha em mente que para programar bem você deve sim conhecer os fundamentos da Ciência da Computação.

Não vou menosprezar quem aprendeu por conta. Alguns conseguem. Mas não pense que nesta área você será um bom profissional sabendo apenas digitar comandos numa linguagem qualquer.

Estruturas de Dados, Sistemas Operacionais, Geometria, Cálculo, Estatística. Tenha certeza que, cedo ou tarde, disciplinas que lhe faltam poderão ser um empecilho para uma atividade de mais alto nível, a não ser que você queira fazer sistemas de cadastros e relatórios pelo resto da vida.

Segundo, desenvolver não é apenas programar bem. Se você tem alguma experiência em projetos, já deve saber que a programação em si é apenas uma parte de uma grande cadeia de comunicação, motivação, acordos, burocracia, egos e muito mais. Saber lidar com tudo isso é o que realmente irá levá-lo a algo maior.

O perfil do profissional ideal

Escutamos repetidas vezes que as empresas procuram o profissional com experiências nas tecnologias X, Y ou Z. Pode até ser verdade em muitos casos. Porém, quem já trabalha em TI há mais tempo sabe que bons profissionais, com bons fundamentos teóricos, podem aprender qualquer linguagem ou tecnologia.

Outra habilidade importante é a de realmente produzir coisas úteis. Pode parecer estranho, mas muitos profissionais com boa formação e conhecimento abrangente têm dificuldade em implementar ferramentas e sistemas que tenham algum valor para os clientes. Pode ser porque eles deem excessiva importância a minúcias técnicas ou não consigam entender o que o cliente realmente quer, mas seja qual for o motivo por detrás disso, o código que eles produzem é bom só para eles mesmos.

Já o profissional ideal é aquele que consegue compreender os usuários do sistema e implementar, tecnicamente da melhor forma, exatamente aquilo que o usuário precisa.

Por último, mas não menos importante, vou citar as habilidades interpessoais. Inclua no pacote boa capacidade de comunicação e uma personalidade agradável para então ter um profissional realmente “perfeito”.

É claro que na maioria das vezes essas questões de comunicação e relacionamentos são extremamente subjetivas. Elas acabam ficando de enfeite nas descrições de vagas e grande parte dos entrevistadores não dão importância a isso. Mas não se engane! A personalidade é um fator chave para o sucesso e fracasso de toda uma equipe.

Qual seria a personalidade ideal? Aquela que faz as pessoas se sentirem bem ao trabalhar com você. Um profissional que deixa o ambiente da empresa ruim gera um prejuízo incalculável. Porém, se os membros de uma equipe encontram em um profissional alguém com quem realmente desejam trabalhar, este profissional deveria ser mantido na empresa a todo custo.

Como chegar lá

Todo esse papo pode deixar você com um grande peso nas costas. Mas, como já disse, deixe a ansiedade para trás.

Se você é da geração Y ou, pior, da geração Z, mude sua disposição e saiba que todas as coisas boas levam tempo para serem construídas e tem um custo associado.

Primeiro, se você acha que sabe tudo, conscientize-se de que então não sabe nada.

Segundo, Aprenda conceitos e fundamentos sólidos. Não tente seguir todas as ondas e modinhas tecnológicas. Por exemplo, aprenda muito bem orientação a objetos antes de dizer que sabe C++, Java, Scala, Go. Aprenda o que é programação funcional antes de dizer que sabe Javascript. Aprenda sobre redes e protocolos antes de dizer que sabe desenvolver um sistema web.

Crie um planejamento de estudos. Quais são as coisas mais importantes e prioritárias para se aprender na sua área?

Estude frequentemente, não muito intensamente. Se você quer aprender bem Java, por exemplo, pode estudar para obter a certificação. Você vai precisar ler mais de 800 páginas. Faça um plano de estudos de 6 meses a 1 ano, dependendo do seu ritmo. Pode parecer muito, mas lembre-se que tudo leva tempo.

Conclusões

Você pode estar ansioso por alguma pressão externa. Então espero que este artigo tenha lhe acalmado.

Por outro lado, se você fica ansioso porque quer progredir muito rápido, tenha cuidado para não se decepcionar.

Se você acha que sabe muito mais do que pessoas mais velhas e mais experientes, talvez achando que a empresa não te reconhece, também tome cuidado. Faça entrevistas em empresas melhores para tirar a prova disso, pode ser uma lição de humildade.

Alguns programadores acham que são melhores que os chefes porque estes não conhecem tanto sobre uma certa linguagem ou certas novidades. Sim, em alguns casos pode ser verdade, mas na maioria das vezes falta maturidade em compreender os desafios diários que ele precisará enfrentar.

É o mesmo caso de tantos jovens que acham fácil programar e tentam empreender, só para depois perceber que não conseguem clientes o suficiente ou não dão conta das demandas técnicas e da gestão do negócio.

A experiência mostra que os inexperientes acham que tudo é fácil. A maturidade de um proporcional vem sempre acompanhada de sua capacidade de enxergar os desafios que ele precisa enfrentar e as consequências de suas decisões.

Enfim, não tenha pressa, estude sempre e aproveite todas as oportunidades que tiver para aprender e se relacionar com outros profissionais mais experientes.

Problemas de compatibilidade de versões no Java: especificando a versão do JDK para compilação

Uma das preocupações ao compilarmos aplicações e bibliotecas em Java é que a versão usada para compilação seja compatível com a versão onde o código será executado.

Por exemplo, você pode ter o Java 7 instalado em seu computador de desenvolvimento. Se você gerar um jar e tentar executar no computador de um cliente com o Java 6 pode ocorrer um erro!

Compilação em modo de compatibilidade

A primeira solução para problemas com versões diferentes é configurar o compilador para compilar em modo de compatibilidade.

Mas há um problema: isso não garante que o código executá. A cada versão do Java, classes ganham novos métodos e novas classes são adicionadas. A compilação em modo compatibilidade irá suceder sem erros, mas ao executar as classes em versões anteriores do Java, ocorrerão erros de tempo de execução por falta dos métodos e classes que não existem nas APIs nativas naquela versão.

Um exemplo simples é o construtor da classe BigDecimal que recebe um inteiro. Ele foi adicionado no Java 5, mas um código que use esse construtor é compilado sem problemas em compatibilidade para Java 1.4. Obviamente, ao executar esse código num JRE 1.4 ocorrerá um erro fatal.

Especificando um JDK alternativo

Então temos a segunda solução, que nos traz garantia de funcionamento: compilar o código com a mesma versão do ambiente do cliente.

Isso não significa, entretanto, que precisamos excluir todas as demais versões do Java de nosso ambiente de desenvolvimento, muito menos que só poderemos trabalhar com uma única versão em todos os projetos.

É possível especificar uma versão alternativa do Java para cada projeto, seja no Eclipse, Ant ou Maven.

Para ver como instalar o JDK 7, consulte o artigo Instalando e Configurando o Java Development Kit 7 para Desenvolvimento.

Especificando a versão e o JDK no Maven

No pom.xml podemos configurar o maven-compiler-plugin da seguinte forma:

  • <source>: especifica a versão do Java em que está escrito o código-fonte.
  • <target>: especifica para qual versão do Java o compilador deve compilar o código.
  • <executable>: especifica qual compilador (javac) será usado.

Exemplo:

<!-- CONFIGURAR VERSÃO DO JAVA PARA 1.7 -->
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
                <source>1.7</source>
                <target>1.7</target>
                <executable>C:\Program Files\Java\jdk1.7.0_45\bin\javac</executable>
            </configuration>
        </plugin>
    </plugins>
</build>

Veja a documentação aqui.

Configuração única para um grupo de projetos usando herança

Não é necessário ter a configuração acima em cada novo projeto. Você pode criar um parent pom e usar a herança para reaproveitar essa configuração em todos os seus projetos.

Veja como especificar o pai de um projeto:

<parent>
    <groupId>org.minhaempresa</groupId>
    <artifactId>meu-pom-principal</artifactId>
    <version>1.0.0</version>
</parent>

Configuração única para todos os ambientes

Um problema que pode ocorrer é que cada desenvolvedor tem uma instalação do Java em local diferente. Se houver um servidor de integração contínua, o problema é o mesmo. Como especificar o Java sem ter que ajustar o caminho em cada máquina?

Para resolver isso, podemos criar um perfil (profile) diretamente na configuração do Maven. Um perfil nada mais é que um conjunto de configurações que você pode ativar e desativar quando quiser. Se essa configuração for feita em cada instalação do Maven e o perfil for ativado por padrão, podemos especificar a versão do Java em cada local sem maiores dificuldades.

Primeiro, edite o seu arquivo settings.xml que fica na sua pasta de usuário ou então no diretório conf da instalação do Maven e adicione um perfil com uma propriedade especificando onde está o Java.

Exemplo:

<profiles>
    <profile>
        <id>compiler</id>
        <properties>
            <JDK7>C:\Program Files\Java\jdk1.7.0_45</JDK7>
            <JDK4>C:\Program Files\Java\jdk1.4</JDK4>
        </properties>
    </profile>
</profiles>

No código acima, definimos duas propriedades JDK7 e JDK4. Note que você pode definir quantas propriedades quiser.

Agora devemos ativar o perfil para todos os projetos que usem essa instalação do Maven, editando novamente o settings.xml e adicionando o seguinte trecho:

<activeProfiles>
    <activeProfile>compiler</activeProfile>
</activeProfiles>

Então, em seu projeto ou parent pom, use a propriedade definida assim:

<executable>${JDK7}/bin/javac</executable>

Definindo o JDK num projeto do Eclipse

Ao abrir o Eclipse, ele virá configurado com mesmo o JDK usado para executá-lo, ou seja, o que estiver configurado como padrão em seu computador. Todavia, você pode incluir na configuração do Eclipse quantas versões quiser, tanto do JDK (compilação) quanto do JRE (execução).

Incluindo uma instalação do Java no Eclipse

Primeiro, acesse o menu Window > Preferences... e vá até a configuração Java > Installed JREs.

01

Clique em Add....

02

Selecione a opção Standard VM e clique em Next >.

03

Preencha o campo JRE home digitando o diretório de instalação do Java que você quer adicionar. Ou clique em Directory... para procurar a pasta. O Eclipse irá preencher as demais informações para você.

04

Clique em Finish e a nova instalação será adicionada à lista.

05

Clique em OK.

Configurando o projeto para usar uma versão específica do Java

Clique com o botão direito em um projeto e acesse a opção Properties. Clique no item Java Build Path e vá até a aba Libraries.

06

Selecione o Java atualmente em uso e clique no botão Edit....

07

Selecione o item Alternate JRE, selecione a JRE ou JDK que você quer usar e clique em Finish.

08

Verifique se o Java mudou e clique em OK para concluir a configuração.

Talvez o Eclipse emita um aviso de que será necessário recompilar o projeto. Isso é normal, apenas confirme.

Note que para projetos que usam o plugin do Maven para o Eclipse (M2E), você não precisa fazer isso manualmente. Apenas adicione o JDK ao Eclipse, como descrito acima, e configure seu pom.xml. O plugin selecionará o Java mais adequado para o projeto automaticamente.

Especificando o JDK num build Ant

Caso você faça a compilação e empacotamento de seus projetos com scripts Ant, é possível especificar a versão de compilação para a task <javac> de uma forma muito simples. Basta definir o atributo executable, por exemplo:

<javac srcdir="" 
    destdir=""
    executable="path-to-java14-home/bin/javac" 
    fork="true"
    taskname="javac1.4" />

Considerações finais

Especificar uma versão do Java é uma boa prática para evitar problemas inesperados durante a entrega de um software. Procure compilar e testar seus programas usando a mesma versão do ambiente onde eles serão executados.

Este artigo descreve várias formas de atingir isso, para você ter um ambiente de desenvolvimento “saudável”.

Por este e outros motivos, recomendo o uso do Maven para novos projetos, já que ele evita a repetição do processo de configuração do ambiente para cada novo desenvolvedor ou servidor.

Para maiores detalhes sobre o Maven, consulte o artigo: Instalando, configurando e usando o Maven para gerenciar suas dependências e seus projetos Java.

Instalando, configurando e usando o Maven para gerenciar suas dependências e seus projetos Java

Este artigo é uma introdução ao Maven, uma ferramenta de gerenciamento de dependências e ciclo de vida de um projeto em Java.

Para usar o Maven, você precisa ter o JDK instalado. Você também pode integrá-lo à sua IDE. Para saber como instalar o JDK e o Eclipse, consulte os seguintes artigos:

O que é o Maven?

O Maven é uma ferramenta de gerenciamento de dependências e do ciclo de vida de projetos de software no sentido técnico. Isso inclui:

  • Facilitar a compilação do código, o empacotamento (JAR, WAR, EAR, …), a execução de testes unitários, etc.
  • Unificar e automatizar o processo de geração do sistema. Nada mais de uma coleção de passos e scripts a serem executados manualmente.
  • Centralizar informações organizadas do projeto, incluindo suas dependências, resultados de testes, documentação, etc.
  • Reforçar boas práticas de desenvolvimento, tais como: separação de classes de teste das classes do sistema, uso de convenções de nomes e diretórios, etc.
  • Ajuda no controle das versões geradas (releases) dos seus projetos.

Conceitos importantes

Artefato (artifact)

Um artefato é geralmente um arquivo JAR que fica no repositório do Maven, mas pode ser de outro tipo.

Cada artefato é identificado através dos seguintes elementos:

  • Grupo: é como o endereço do site ao contrário, como br.com.starcode, org.apache, com.google, com.ibm, etc.
  • Identificador único de artefato: geralmente é o nome do projeto. Ele deve ser único por grupo.
  • Número de versão: a versão do projeto, como 1.4.2 ou 3.0. Se houver o sufixo -SNAPSHOT (0.0.1-SNAPSHOT, por exemplo) significa que o projeto está em desenvolvimento e o pacote pode ser alterado.
  • Tipo do projeto: jar, war, ear, pom (projeto de configuração).
  • Classificador: identificação opcional para diferenciar variações da mesma versão. Por exemplo, se o programa é compilado para diferentes versões do Java podemos usar os classificadores jdk4 e jdk6. Se há variações específicas para Sistemas Operacionais, podemos ter os classificadores linux e windows.

Repositório local

É um diretório em seu PC onde os artefatos são armazenados após baixados de um repositório remoto na internet ou na intranet. Você também pode instalar os artefatos dos seus projetos nesse repositório executando o install do Maven. Continue lendo para entender o que é isso.

O repositório possui uma estrutura padrão onde o Maven consegue encontrar os artefatos através da identificação do mesmo.

Repositório remoto

Consiste numa aplicação que disponibiliza artefatos do Maven. Pode se um repositório público na Internet, onde criadores de bibliotecas e frameworks disponibilizam seus artefatos, ou pode ser um repositório privado da empresa, disponível na intranet.

Existe um repositório central que já vem configurando no Maven, mas algumas empresas criam seus próprios repositórios. Inclusive você pode criar o seu instalando o Artifactory ou Nexus num servidor.

Quando adicionamos esses repositórios remotos em nossa instalação do Maven, ele é capaz de localizar e baixar automaticamente as dependências através da identificação do artefato.

Arquivo POM

O arquivo pom (pom.xml) é a configuração principal do Maven e estará presente em todo projeto. Nele você declara a identificação do seu projeto (que após gerado será também um artefato Maven), as dependências, repositórios adicionais, etc.

Há um arquivo pom por projeto, mas ele pode herdar configurações de um parent pom, isto é, como se houvesse um projeto "pai".

Ciclo de vida padrão do Maven

O Maven possui um ciclo de vida padrão. Cada passo do ciclo de vida é chamado de Goal e possui plugins específicos. Os mais importantes são:

  • validate: valida o projeto e se as informações necessárias para os próximos passos estão disponíveis, como as dependências por exemplo.
  • compile: compila o código-fonte.
  • test: executa os testes unitários (JUnit, por exemplo).
  • package: empacota o código compilado em um JAR, WAR, etc.
  • integration-test: executa os testes de integração.
  • install: adiciona o pacote gerado ao repositório local, assim outros projetos na mesma máquina podem usar essa dependência.
  • deploy: copia o pacote final para o repositório remoto, disponibilizando-o para outros desenvolvedores e outros projetos.

Os itens acima, nessa ordem, são passos comuns para geração de uma versão de qualquer sistema, não é mesmo?

No Maven, você pode configurar detalhadamente cada um desses passos e até incluir novos. Por exemplo, alguns frameworks que geram código-fonte usam um goal generate-sources para fazer isso.

Além disso, não é necessário executar todos os passos sempre. Você pode escolher qual deseja executar num determinado momento, mas o Maven sempre executará todos os passos anteriores.

Por exemplo, enquanto você está desenvolvendo um módulo, a cada alteração pode executar o passo test para executar a validação, compilação e então os testes unitários. Então você só precisa executar os passos posteriores quando tiver concluído o trabalho.

Para maiores informações sobre o ciclo de vida, consulte a documentação.

Estrutura padrão de um projeto Maven

A estrutura padrão do projeto inclui boas práticas (como separar as classes de teste das classes do sistema) e facilita aos novos desenvolvedores encontrar o que eles querem, já que todos os projetos seguirão uma estrutura semelhante.

Veja a seguir os principais diretórios utilizados:

  • src/main/java: aqui fica o código-fonte do sistema ou biblioteca.
  • src/main/resources: arquivos auxiliares do sistema, como .properties, XMLs e configurações.
  • src/main/webapp: se for uma aplicação web, os arquivos JSP, HTML, JavaScript CSS vão aqui, incuindo o web.xml.
  • src/test/java: as classes com seus testes unitários ficam aqui e são executadas automaticamente com JUnit e TestNG. Outros frameworks podem exigir configuração adicional.
  • src/test/resources: arquivos auxiliares usados nos testes. Você pode ter properties e configurações alternativas, por exemplo.
  • pom.xml: é o arquivo que concentra as informações do seu projeto.
  • target: é o diretório onde fica tudo que é gerado, isto é, onde vão parar os arquivos compilados, JARs, WARs, JavaDoc, etc.

Para ver mais detalhes sobre a estrutura de diretórios do Maven, consulte a documentação.

Usando o Maven em projetos já existentes

Você pode ter ficado desapontado com a estrutura anterior, pois estava pensando em usar o Maven em um projeto que já começou, mas não quer ou não pode mudar a estrutura de pastas atuais.

Saiba que o Maven é flexível e permite alterar toda a estrutura padrão.

Por exemplo, é comum usar a pasta src para os fontes, ao invés de src/main/java. Para ajustar isso, basta adicionar uma tag <sourceDirectory> dentro da tag <build>, assim:

<project>
    ...
    <build>
        <sourceDirectory>src</sourceDirectory>
        ...
    </build>
    ...
</project>

Não vou ir fundo nessa questão, mas se o leitor tiver um projeto em condições semelhantes, sugiro uma leitura mais completa da documentação, começando com Using Maven When You Can’t Use the Conventions.

É claro que nem tudo é tão simples. Muitos projetos usam estruturas tão diferentes que se exige a refatoração desta estrutura.

Benefícios do Maven

A adoção do Maven no desenvolvimento traz de imediato os seguintes benefícios:

Centralização das informações

O Maven centraliza as informações dos projetos no arquivo pom.

Sendo assim, não é preciso configurar várias ferramentas, build scripts, servidores e IDEs durante o desenvolvimento. O Maven segue o conceito DRY (Don’t Repeat Yourself).

Além disso, o Maven também disponibiliza formas de analisar o projeto. Por exemplo, o goal dependency:analyze exibe as dependências declaradas que não estão sendo usadas e as usadas via terceiros, mas não declaradas no pom.

Padronização do ambiente de desenvolvimento

Através da especificação do projeto, incluindo suas características e dependências, o Maven constrói a estrutura necessária do projeto, baixando automaticamente as versões corretas das dependências (JARs, por exemplo) de um repositório central ou de um repositório privado (contendo sistemas da empresa).

Você não precisa entrar no site de cada biblioteca e framework usado e então fazer manualmente o download e adicionar os jars no seu classpath.

Dessa forma, cada desenvolvedor consegue configurar rapidamente um ambiente para desenvolvimento com a garantia de que esse ambiente é igual ao dos outros desenvolvedores.

Gerenciamento de dependências

Como já mencionei, o Maven faz o download automático de dependências para o projeto e os adiciona ao classpath do seu projeto.

Cada dependência pode ter também as suas próprias dependências. Elas são chamadas dependências transitivas. O Maven resolve essa árvore de dependências e traz tudo o que você precisa.

Em alguns casos, podem haver problemas de conflitos, no caso da árvore de dependências incluir versões diferentes de um mesmo artefato. O Maven vem com mecanismos para resolver isso.

Facilidade de compreensão do projeto

Ao usar a convenção de diretórios sugerida pelo Maven os desenvolvedores terão mais facilidade em compreender a estrutura do projeto, afinal todos os projetos seguirão uma estrutura básica de diretórios, como vimos anteriormente.

Automação

O Maven gerencia o ciclo de vida da aplicação. Após configurar um projeto, você será capaz de executar comandos que vão desde a compilação até a geração de documentação (Javadoc) e um site padrão contendo informações sobre o projeto.

Uma vez feita a configuração necessária, o projeto pode ser baixado e compilado sem nenhum esforço. Novas versões podem ser geradas em servidores de Integração Contínua e testadas automaticamente sempre que necessário.

Um alerta

Embora os tópicos anteriores tenham enumerado diversas vantagens do uso do Maven, este não é uma "bala de prata", ou seja, uma solução mágica para o projeto.

Dependendo da complexidade do projeto, pode ser bem complicado criar uma configuração adequada para ao Maven.

Além disso, o Maven não irá livrá-lo de problemas como:

Incompatibilidade de dependências

O projeto depende dos frameworks A e B. O framework A depende a versão 1.0 da biblioteca C. O framework B depende da versão 2.0 da biblioteca C.

O Maven não vai resolver sozinho isso, mas facilita muito a resolução do problema já que podemos usar as informações do mecanismo de resolução de dependências para identificar os conflitos.

Algumas tecnologias simplesmente não vão funcionar bem com o Maven

Alguns autores de frameworks ou arquiteturas inventam o seu próprio jeito de trabalhar. Isso significa que para usar o Maven é necessário alguma adaptação, o que nem sempre é trivial.

No entanto, é possível escrever plugins para o Maven que façam o trabalho para você. Geralmente a comunidade de cada framework, se não os próprios autores, já terão resolvido esse problema. Embora existam casos em que essas soluções acrescentem novas limitações.

Ódio do Maven

A verdade é que existe muita gente que odeia o Maven por ter vivido experiências ruins com ele, principalmente no início. Infelizmente, não sei se este artigo terá o poder de curá-lo de traumas passados ao tentar usar o Maven sem a devida orientação. 😉

No entanto, não deixe que isso influencie você neste momento. Mesmo que não pretenda usar o Maven em seus projetos, vale a pena conhecê-lo. Você pode ser obrigado a usá-lo na empresa ou mesmo num projeto opensource de que vai participar.

Se você não gosta do Maven, tenha duas coisas em mente:

  1. Existem várias alternativas, desde scripts Ant até outras ferramentas de resolução de dependências mais avançadas como o Graddle.
  2. Embora algumas pessoas atinjam um excelente nível de produtividade sem o Maven, se considerarmos um contexto mais amplo, como um projeto que com mais de meia dúzia de desenvolvedores, alguns deles novatos, o Maven pode trazer mais vantagens que desvantagens se bem configurado por um desenvolvedor experiente.

Instalando o Maven

Acesse a página do Maven e clique no item Download do menu.

A página disponibiliza diferentes versões para diferentes ambientes. Baixe o arquivo da última versão de acordo com seu sistema operacional. Destaquei na imagem a versão zip para Windows que usarei neste exemplo:

01

A versão mais atual do Maven na data de criação deste tutorial é 3.2.1. O pacote baixado é nomeado apache-maven-3.2.1-bin.zip. Veja o arquivo aberto no 7-Zip:

02

Descompacte o conteúdo para a pasta c:\starcode\.

03

Configura o resultado na imagem a seguir:

04

Configurando o Maven

O Maven é configurado através do arquivo settings.xml que fica no diretório c:\starcode\apache-maven-3.2.1\conf.

Abra o arquivo usando um editor avançado, como o Notepad++. Você vai ver que existem diversos blocos de XML comentados com possíveis configurações e explicações sobre elas.

Em um ambiente simples você não vai precisar mexer em muita coisa. Porém, vamos ver alguns pontos mais importantes.

Proxy

É muito comum precisarmos autenticar o acesso à internet em um Proxy quando estamos no trabalho. Procure a tag <proxy>, a qual deve estar comentada no arquivo de configuração. O trecho é o seguinte:

<proxy>
    <id>optional</id>
    <active>true</active>
    <protocol>http</protocol>
    <username>proxyuser</username>
    <password>proxypass</password>
    <host>proxy.host.net</host>
    <port>80</port>
    <nonProxyHosts>local.net|some.host.com</nonProxyHosts>
</proxy>

Se você tem um proxy na sua rede, mova o bloco acima para fora do comentário, então substitua os parâmetros de acordo com seu ambiente. Mantenha a tag <proxy> dentro de <proxies>.

Veja abaixo um exemplo de uso:

<proxies>
    <proxy>
        <id>proxy</id>
        <active>true</active>
        <protocol>http</protocol>
        <host>proxy.intranet.empresa.com</host>
        <port>8080</port>
        <nonProxyHosts>localhost,127.*,192.*</nonProxyHosts>
    </proxy>
</proxies>

Local do repositório

O Maven utiliza um diretório local para baixar os artefatos da internet. O diretório padrão fica dentro pasta do usuário, na pasta .m2. Um exemplo no Windows é c:\users\luiz\.m2\repository.

Entretanto, tenho o hábito de mudar esse diretório para junto de meus arquivos de desenvolvimento. Para isso, basta editar o settings.xml, movendo a tag <localRepository> para fora do comentário e adicionando o caminho, por exemplo:

<localRepository>c:\starcode\apache-maven-3.2.1\repo</localRepository>

Não se esqueça de criar o diretório especificado caso o mesmo não exista.

Configurando as variáveis de ambiente

Para usar o Maven em linha de comando você deve adicionar o caminho para os executáveis ao PATH do ambiente. No Windows, pressione Ctrl+Break para abrir a tela de informações do do sistema.

05-configurar-maven

Clique na opção Configurações avançadas do sistema, à esquerda da janela.

06-configurar-maven

Na aba Avançado da tela de Propriedades do Sistema, clique em Variáveis de Ambiente....

07-configurar-maven

Você pode adicionar a variável de ambiente apenas para o usuário atual ou globalmente para todo o sistema. Faça o que for melhor para o seu caso. Alguns ambientes corporativos impedem o acesso à configuração de sistema por questões de segurança, então você terá que configurar apenas seu usuário.

Clique em Novo... e crie a variável M2_HOME com o valor apontando para o diretório base do Maven. No nosso exemplo o valor é c:\starcode\apache-maven-3.2.1.

08-configurar-maven

Clique em OK para criar a variável.

09-configurar-maven

Agora vamos incluir o diretório com os executáveis do Maven ao PATH. Localize a entrada, selecione-a e clique em Editar....

10-configurar-maven

Adicione ao final um ponto e vírgula e o caminho para a pasta bin do Maven (;%M2_HOME%\bin), assim:

11-configurar-maven

Clique em OK para confirmar a edição e OK novamente para confirmar as alterações nas variáveis do sistema.

Vamos então testar a instalação. Abra o CMD (linha de comando) e digite mvn -version. Você deve ver algo como na figura abaixo:

12-configurar-maven

Se ocorreu algum problema, verifique se você tem o Java instalado e configurado corretamente, incluindo as variáveis de ambiente JAVA_HOME e PATH incluindo o Java. Caso tenha dúvidas, acesse o artigo citado no início sobre a instalação do JDK.

Usando o Maven

Usando a instalação do Maven no Eclipse

Para integrar o Maven e Eclipse eu aconselho o plugin M2E. Note que o M2E é um plugin do Eclipse que faz integração com o Maven.

Existe também o Maven Eclipse Plugin, aquele onde se digita eclipse:eclipse para gerar um projeto para o Eclipse. Este é um plugin do Maven que simplesmente gera os arquivos de configuração necessários para a IDE. Não confunda os dois.

A distribuição Eclipse for JEE Developers já vem com o plugin M2E e uma instalação interna do Maven. Veja como instalar e usar o Eclipse acessando o artigo citado no início.

Se você tem uma versão diferente do Eclipse, use o menu Help > Eclipse Marketplace..., pesquise por M2E e instale o plugin.

Com o plugin instalado e o Eclipse aberto, acesse o menu Window > Preferences... e vá até a opção Maven > Installations.

01-maven-eclipse

Veja que já existe uma instalação "embarcada", mas com uma versão desatualizada. Vamos adicionar o nosso Maven.

Clique em Add... e selecione a pasta com a nossa instalação, no caso: c:\starcode\apache-maven-3.2.1.

02-maven-eclipse

Note que ele já encontrou nosso arquivo de configuração.

Vá até o menu User Settings. Há um warning lá dizendo que a configuração do usuário não existe. Você pode criar um outro settings.xml na pasta indicada ou simplesmente use um artifício (que eu sempre uso), que é definir o mesmo arquivo da configuração global.

03-maven-eclipse

Caso não tenha entendido, o Maven possui um arquivo de configuração global que afeta diretamente a instalação e fica na pasta conf. Entretanto, cada usuário do sistema pode ter um arquivo próprio e sobrescrever as configurações globais que ele desejar. No entanto, se você é o único usuário do computador, não é necessário ter os dois arquivos.

Criando um projeto Maven simples no Eclipse

Com o Maven configurado, vamos criar um novo projeto no Eclipse. Acesse o menu File > New > Maven Project. Selecione a opção Create a simple project (skip archetype selection) e clique clique em Next >.

01-projeto-simples

Vamos preencher a identificação do projeto, que nada mais é do que a identificação de um artefato.

02-projeto-simples

O Group Id para o exemplo será br.com.starcode e o Artifact Id será teste-maven-01. A versão e o tipo de artefato (Packaging) já devem estar preenchidos, então simplesmente deixe como está. O nome e a descrição são opcionais.

Clique em Finish para ver o projeto criado.

Note que ele ainda não está definido com as configurações de um projeto Java, então clique com o botão direito sobre o projeto, acesse o menu Maven > Update Project....

03-projeto-simples

Clique em OK para atualizar o projeto com as configurações do Maven e agora temos a estrutura característica.

04-projeto-simples

Adicionando manualmente uma dependência

Agora vou ilustrar como podemos adicionar algumas dependências ao projeto. Acesse o site mvnrepository.com, que contém um índice das dependências disponíveis no repositório do Maven. Pesquise por commons-lang.

05-projeto-simples

Selecione o item Apache Commons Lang, como indicado na imagem abaixo:

06-projeto-simples

Clique sobre a última versão (3.3.2 na data em que escrevo o artigo).

07-projeto-simples

Selecione e copie a identificação do artefato, conforme a imagem abaixo:

08-projeto-simples

Agora volte ao Eclipse e clique duas vezes sobre o arquivo pom.xml para editá-lo. Provavelmente o editor foi aberto no aba Overview (veja abaixo do editor) com diversos campos e informações sobre o projeto.

Clique na aba pom.xml para mostrar o código fonte.

09-projeto-simples

Adicione a tag <dependencies> logo abaixo da tag <description> e cole o conteúdo do site dentro dela.

Dica: Pressione CTRL+A para selecionar todo o conteúdo do arquivo e depois CTRL+I para indentar (tabular) o arquivo.

10-projeto-simples

O conteúdo do pom.xml deve ser o seguinte:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>br.com.starcode</groupId>
    <artifactId>teste-maven-01</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Teste Maven 01</name>
    <description>Um teste de projeto simples com o maven</description>
    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.3.2</version>
        </dependency>
    </dependencies>
</project>

Salve o arquivo. O plugin M2E irá identificar a alteração, baixar automaticamente a dependência do repositório central para o seu repositório local e adicioná-la ao classpath do projeto.

Confira a entrada Maven Dependencies na imagem a seguir:

11-projeto-simples

Pronto! Agora você já pode usar qualquer classe da biblioteca Apache Commons Lang. 😉

Fiz uma classe de exemplo (File > New > Other..., selecione Class), com o seguinte conteúdo:

package br.com.starcode.testemaven01;

import org.apache.commons.lang3.StringUtils;

public class ClasseDeTeste {

    public static void main(String[] args) {

        System.out.println(StringUtils.capitalize("luiz"));

    }

}

Executei o método main clicando com o botão direito sobre a classe, menu Run As > Java Application. Veja o resultado:

12-projeto-simples

Executando os passos (goals) do Maven

Vamos supor que estamos construindo uma nova biblioteca. Precisaremos testá-la (test), empacotá-la (package) num jar e distribuí-la (deploy) para o uso de terceiros, não é mesmo? O Maven nos ajuda grandemente com esses passos naturais do ciclo de vida de um projeto.

Vamos usar nosso projeto de exemplo e criar uma classe utilitária chamada SuperUtil:

package br.com.starcode.testemaven01;

import org.apache.commons.lang3.StringEscapeUtils;

public class SuperUtil {

    /**
     * Possibilita exibir um texto contendo HTML no navegador sem ataques XSS.
     * @param html Entrada do usuário (pode ter HTML, mas não deve ser renderizado, somente exibido)
     * @return Texto sem posíveis tags HTML
     */
    public static String escapeHTML(String html) {
        return StringEscapeUtils.escapeHtml4(html);
    }

}

Veja no Eclipse:

01-executando-com-maven

Vamos ainda criar um teste unitário para nossa classe, as primeiro temos que adicionar a dependência do JUnit ao nosso projeto. Para isso vá até o site mvnrepository.com e pesquise por junit. Vá até a última versão, copie o trecho do XML e adicione na seção de dependências do seu pom.xml.

Adicione também a tag <scope>test</scope> à esta dependência, para informar ao Maven que ela somente será usada no teste. Sim, o Maven é “esperto” e não incluirá, por exemplo, o JUnit na pasta WEB-INF/lib de uma aplicação web.

Veja como ficou o pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>br.com.starcode</groupId>
    <artifactId>teste-maven-01</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Teste Maven 01</name>
    <description>Um teste de projeto simples com o maven</description>
    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.3.2</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

Ao salvar o arquivo o Maven deve baixar o JUnit automaticamente.

Agora crie a classe de teste SuperUtilTest em src/test/java:

package br.com.starcode.testemaven01;

import org.junit.Assert;
import org.junit.Test;

public class SuperUtilTest {

    @Test
    public void escapeHTMLTest() {

        String escapedHtml = SuperUtil.escapeHTML("<script>alert(1);</script>");
        String expected = "&lt;script&gt;alert(1);&lt;/script&gt;"; 
        Assert.assertEquals(expected, escapedHtml);

    }

}

Caso queira executar o teste já, clique com o botão direito sobre a classe e acesse o menu Run As > JUnit Test:

02-executando-com-maven

Confira o resultado:

03-executando-com-maven

Sucesso! 😀

Imagine agora que tenhamos criado diversas classes e métodos. Temos uma versão beta de nossa biblioteca.

Vamos testar o projeto usando o Maven. Clique no projeto com o botão direito e na opção Run As > Maven test:

04-executando-com-maven

Na primeira execução o Maven vai baixar diversos plugins e dependências internas para a execução do projeto. Aguarde um pouco e confira o resultado de todos os testes do projeto:

05-executando-com-maven

Ok, agora vamos gerar um JAR do projeto. Clique no projeto com o botão direito e na opção Run As > Maven build.... Isso é necessário porque não é uma opção pronta para o passo package. Vá até o campo Goals e digite package.

06-executando-com-maven

Clique em Run e aguarde.

07-executando-com-maven

Se você observar o log no Console notará que os testes foram executados. Lembra que eu disse que os passos anteriores sempre são executados? Espero que agora tenha entendido melhor.

Note a última linha antes das palavras BUILD SUCCESS. Ali está o caminho do Jar gerado. Ele foi gerado dentro da pasta target do projeto.

Selecione a pasta target e Pressione F5 para atualizá-la. Abra-a clicando na seta à esquerda e confira:

08-executando-com-maven

Vamos agora executar o install, isto é, instalar o jar no repositório local. Clique no projeto com o botão direito e na opção Run As > Maven install. Aguarde um pouco e veja o resultado:

09-executando-com-maven

As duas últimas linhas antes da mensagem de sucesso demonstram os locais onde o Jar e o seu arquivo POM foram instalados:

[INFO] Installing D:\starcode\workspaces\workspace_demo\teste-maven-01\target\teste-maven-01-0.0.1-SNAPSHOT.jar to c:\starcode\apache-maven-3.2.1\repo\br\com\starcode\teste-maven-01\0.0.1-SNAPSHOT\teste-maven-01-0.0.1-SNAPSHOT.jar

[INFO] Installing D:\starcode\workspaces\workspace_demo\teste-maven-01\pom.xml to c:\starcode\apache-maven-3.2.1\repo\br\com\starcode\teste-maven-01\0.0.1-SNAPSHOT\teste-maven-01-0.0.1-SNAPSHOT.pom

Vamos abrir o diretório do repositório local e dar uma olhadinha:

10-executando-com-maven

Agora você pode usar este artefato em outros projetos na sua máquina local, adicionando a seguinte dependência:

<dependency>
    <groupId>br.com.starcode</groupId>
    <artifactId>teste-maven-01</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

Qualquer projeto com essa dependência vai usar o nosso jar gerado e, automaticamente, incluir também o jar do Apache Commons Lang que definimos em nosso projeto.

Analisando as dependências

Vamos aprender a analisar as dependências de um projeto.

Abra novamente o seu arquivo pom.xml e vá até a aba Dependency Hierarchy. Você deve estar vendo isso:

01-maven-dependencies

Abaixo, mais um exemplo de dependências extraído da minha biblioteca T-Rex:

maven-dependency-hierarchy

Usando o Maven em linha de comando

Tudo o que fizemos anteriormente através da IDE pode ser feito via linha de comando. É importante entender isso porque quando o projeto for compilado em um servidor de Integração Contínua, por exemplo, ele não contará com as facilidades do plugin que usamos.

Irei ilustrar a seguir a execução do goal install via linha de comando.

O primeiro passo é abrir o CMD e ir até o diretório do projeto. Então basta digitar o comando maven install.

11-executando-com-maven

Configura o resultado da execução:

13-executando-com-maven

Pronto!

Explicando: nós adicionamos o Maven ao path do sistema, lembra? maven é o nome do executável do Maven e install é o goal que você deseja executar. Também há usar o executável mvn, que é apenas um atalho para evitar digitar mais caracteres.

Da mesma forma, poderíamos executar mvn test ou mvn package como fizemos nos tópicos acima via menu do Eclipse para ativar os respectivos Goals.

Um goal muito importante ainda não mencionado é o clean, que serve para limpar todos os arquivos gerados da pasta target. Ele é muito importante para limpar eventual “sujeira” de gerações anteriores.

Quando estiver tendo problemas estranhos ou for gerar uma versão "oficial", sempre use comandos comandos como mvn clean install ou mvn clean deploy para garantir uma geração "limpa".

Note que você pode especificar vários goals simultaneamente para o Maven executar. Nos exemplos acima, o Maven vai primeiro limpar o projeto e depois executar o install ou o deploy.

Passando parâmetros para o Maven

Há ainda situações onde precisamos ajustar a execução do Maven através de parâmetros.

Por exemplo, em certas ocasiões queremos gerar um jar ou war para testes, porém o build do Maven falha porque um teste unitário terminou em erro.

Para resolver essa situação sem excluir o teste unitário, é possível configurar o Maven para “pular” os testes com o seguinte comando:

mvn -DskipTests clean install

14-executando-com-maven

Configura o resultado da execução:

15-executando-com-maven

O mesmo resultado pode ser obtido no Eclipse clicando com o botão direito sobre o projeto e indo no menu Run As > Maven build..., digitando clean install no campo Goals e selecionando a opção Skip Tests.

Distribuindo seu projeto

Os próximos passos incluiriam disponibilizar o jar para outros desenvolvedores através do goal deploy. Em um deploy, o Maven envia seu jar para um Repositório Remoto. Entretanto, isso exige várias configurações adicionais e as devidas permissões.

Disponibilizar seu projeto no repositório central do Maven exige que seu projeto seja opensource e que você solicite as permissões necessárias. Caso você queira fazer isso, siga os passos disponíveis neste link.

Já dentro de uma empresa geralmente se configura um servidor para conter um repositório com os artefatos da empresa. Existem aplicações gratuitas que podem ser usadas para isso, como o Artifactory ou o Nexus.

As configurações necessárias para o deploy num repositório remoto estão fora do escopo deste artigo, mas existem várias referências disponíveis na web.

Leitura adicional

Usar o Maven para desenvolver projetos pessoais é relativamente fácil e este artigo cobre o necessário para isso. Entretanto, não deixe de estudar o material oficial e, aos poucos, ir entendendo os mecanismos do Maven para usá-lo em projetos maiores:

Considerações finais

Usar o Maven pode ser confuso a princípio, mas traz diversos benefícios.

Em curto prazo ele ajuda você a gerenciar as dependências e organizar seus projetos.

Em médio prazo você poderá ter um controle muito bom de versões e releases, além de um padrão maduro para seus projetos.

Em longo prazo o Maven possibilitará a Integração Contínua de seus projetos. Será necessário um esforço considerável, mas seus projetos serão compilados e testados automaticamente. Com uma quantidade de testes adequada para garantir que as funcionalidades existentes continuam funcionando e as novas vão funcionar, você pode ter versões sendo geradas todos os dias ou a cada commit!

Nesse ponto, cruzamos com conceitos de TDD, Agile e outros. Mas é exatamente este o motivo pelo qual ferramentas de automação como o Maven são importantes.

Espero que o leitor tenha compreendido seu funcionamento básico e possa evoluir daqui em diante para um melhor aproveitamento da automação em benefício da qualidade e da agilidade.

Instalando e configurando o Eclipse Kepler no linux Ubuntu

Continuando a série de artigos sobre configuração de um ambiente de desenvolvimento no linux Ubuntu em uma máquina virtual, chegou a hora do Eclipse.

Você deve ter o JDK instalado no seu Ubuntu. Os passos de instalação do Ubuntu e do Java estão em seus respectivos artigos:

Baixando o Eclipse

Acesse a página de download do Eclipse a partir do seu Ubuntu. Vamos fazer o download da versão Eclipse IDE for Java EE Developers, que já vem com um conjunto maior de plugins do que a versão Standard.

Meu Ubuntu é de 64 bits, portanto vou selecionar a opção Linux 64 Bit, conforme indicado na imagem:

install-eclipse-01

Na próxima tela, clique na seta verde para iniciar o download.

install-eclipse-02

Salve o arquivo no local desejado e aguarde o término do download.

install-eclipse-03

Instalando o Eclipse

Ainda no navegador, clique sobre o nome do arquivo para abri-lo, conforme a imagem abaixo. Ou simplesmente abra o gerenciador de arquivos e navegue até o diretório onde baixou o arquivo e abra-o com um duplo clique. O arquivo deve ter sido baixado no diretório ~/Downloads, que é a pasta padrão de downloads do usuário.

install-eclipse-04

Agora, o arquivo deve estar aberto no Archive Manager, conforme a imagem:

install-eclipse-05

Selecione a pasta eclipse que aparece na listagem do programa e clique no botão Extract da barra de ferramentas.

A caixa de diálogo de extração aparecerá. Navegue até um diretório de sua preferência para descompactar o Eclipse. Se estiver em dúvida ou tiver problemas de permissão, use o diretório Home (~), como na imagem.

install-eclipse-06

Clique no botão Extract para confirmar a extração.

Após a conclusão, o Archive Manager mostratá um diálogo. Clique em Show the Files para abrir o diretório Home. Acesse a pasta eclipse com um clique duplo.

install-eclipse-07

Você deve estar vendo os arquivos do Eclipse, incluindo o executável dele.

Ao invés de abri-lo, vamos criar um atalho para facilitar nas demais utilizações. Clique com o botão direito sobre o executável e selecione a opção Make Link.

install-eclipse-08

Um atalho deve ter sido criado como na imagem abaixo:

install-eclipse-09

Com o atalho selecionado, pressione CTRL+X para recortá-lo.

Minimize todas as janelas, clique com o botão direito no fundo da sua Área de Trabalho e selecione a opção Paste.

install-eclipse-10

Pronto!

Configurando o Eclipse

Antes de iniciar o Eclipse, vamos ajustar alguns parâmetro de memória para melhorar o desempenho geral de nossa IDE.

Primeiro, abra o explorador de arquivos e vá até o diretório onde extraiu os arquivos do Eclipse. No nosso caso é ~/eclipse.

install-eclipse-15

Clique com o botão direito sobre o arquivo eclipse.ini e abra com um editor de texto. Você verá o arquivo com o conteúdo a seguir:

install-eclipse-16

Vamos aumentar um pouco os parâmetros de memória:

install-eclipse-17

O conteúdo do arquivo ficou assim:

-startup
plugins/org.eclipse.equinox.launcher_1.3.0.v20130327-1440.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.1.200.v20140116-2212
-product
org.eclipse.epp.package.jee.product
--launcher.defaultAction
openFile
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
256m
--launcher.defaultAction
openFile
--launcher.appendVmargs
-vmargs
-Dosgi.requiredJavaVersion=1.6
-XX:MaxPermSize=256m
-Xms512m
-Xmx1G

Feche o editor e não esqueça de salvar o arquivo.

Executando o Eclipse

Clique duas vezes sobre o ícone que criamos na área de trabalho. A splash screen irá aparecer.

install-eclipse-11

Aguarde e logo você será saudado pelo Workspace Launcher para selecionar o Workspace de trabalho.

install-eclipse-12

Clique em OK para criar um novo Workspace no diretório indicado. Aguarde mais um pouco para ver a tela de boas-vindas.

install-eclipse-13

Clique no link Workbench para fechar a tela de abertura e ir à perspectiva de desenvolvimento.

install-eclipse-14

Agora é só usar!

Usando o Eclipse

Caso não esteja acostumado com o Eclipse, não deixe de ler o artigo Instalando, Configurando e Usando o Eclipse Kepler.

Embora o tutorial seja para instalação no Windows, na segunda parte você encontra detalhes sobre como realizar configurações básicas, criar um projeto, executar e depurar um programa, além de informações sobre os componentes principais do Eclipse.

Considerações finais

Com Java e o Eclipse instalados no linux, você já tem um ambiente para iniciar o desenvolvimento de aplicações.

Pretendo em artigos futuros usar este ambiente para ilustrar o desenvolvimento de aplicações Big Data com Hadoop.

Instalando e configurando o JDK 7 no linux Ubuntu

Neste pequeno tutorial você aprenderá a instalar o Java Development Kit 7 no linux Ubuntu. O JDK consiste no conjunto de ferramentas para desenvolvimento em Java.

Caso você não tenha acompanhado, publiquei recentemente em um tutorial sobre como instalar o Ubuntu numa máquina virtual. Esta é uma espécie de continuação da série de artigos que visa a configuração de um ambiente de desenvolvimento no Linux. Com esse ambiente, poderemos brincar livremente bom Big Data. Não perca este e os próximos capítulos! 😉

Instalando o JDK 7

Antes de mais nada vamos verificar se, por acaso, já não temos o JDK instalado. Abra o terminal e digite:

javac

install-jdk-02

Note a mensagem de que o programa não foi encontrado. O próprio Ubuntu nos dá uma dica do comando de instalação. Vamos aceitar a sugestão e instalar o pacote openjdk_7-jdk. Digite o comando:

sudo apt-get install openjdk-7-jdk

O terminal irá solicitar a senha. Digite-a.

install-jdk-03

Depois ele vai pedir a confirmação da operação.

install-jdk-04

Pressione Y para aceitar e aguarde o download e a instalação do pacote.

install-jdk-05

Vamos digitar novamente o comando javac para verificar a instalação.

install-jdk-06

Pronto!

Onde está o Java?

Vamos agora conferir onde o Java foi realmente instalado. Para isso, no terminal, digite o comando abaixo para navegar até o diretório onde geralmente ficam as instalações do Java:

cd /usr/lib/jvm

Agora vamos listar os arquivos no diretório com o comando ls:

install-jdk-08

Em nosso exemplo temos duas entradas: java-1.7.0-openjdk-amd64 e java-7-openjdk-amd64.

Ué!? Mas não instalamos apenas uma versão do Java? Sim! Note que cada entrada tem uma cor diferente. O azul mais claro do primerio item indica que ele é um link simbólico (symbolic link), isto é, um simples um atalho. Vamos confirmar com o comando abaixo:

ln -li

install-jdk-09

Notou a seta que demonstra o link apontando para a pasta original?

Enfim, o Java foi instalado no diretório /usr/lib/jvm/java-7-openjdk-amd64, como podemos ver na imagem a seguir:

install-jdk-10

Algumas configurações adicionais

Embora o Java já funcione apenas com a instalação realizada, vamos configurar as variáveis de ambiente para o caso de algum programa procurar o JAVA_HOME.

Vamos novamente verificar se, por acaso, esta variável já existe usando o comando abaixo:

echo $JAVA_HOME

install-jdk-07

Nada. Então vamos defini-la em nossa sessão com o seguinte comando:

JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64

Em seguida, vamos exportar a variável para os demais programas com o comando export:

export JAVA_HOME

Somente como observação, poderíamos ter feito os dois passos anteriores em apenas um comando da seguinte forma:

export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64

Agora vamos testar se a variável está correta:

echo $JAVA_HOME

install-jdk-11

Tudo certo até agora!

O problema é que o comando export não salva a variável de forma permanente, ou seja, se reiniciarmos o computador (ou máquina virtual), perderemos seu valor. A fim de persisti-la e disponibilizá-la para todos os usuários, vamos criar um script que faz a exportação da variável durante a inicialização do ambiente e a torna disponível para todos os usuários do sistema.

Isso é feito com um Shell script no diretório /etc/profile.d. Todos os scripts neste diretório são executados na inicialização.

Primeiro, vamos até o diretório mencionado:

cd /etc/profile.d

install-jdk-12

Para não complicar muito, vamos usar o editor nano para criar um arquivo com permissão de administrador, então execute o seguinte comando:

sudo nano export_vars.sh

No editor, digite a linha abaixo:

export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64

install-jdk-13

Em seguida, pressione CTRL+X para sair do programa (Exit). Ele vai perguntar se você quer salvar o conteúdo. Pressione Y e depois Enter.

Pronto de novo!

O arquivo export_vars.sh foi criado com sucesso. Podemos conferir o conteúdo com o comando cat, da seguinte forma:

cat export_vars.sh

install-jdk-14

Para mais detalhes sobre variáveis de ambiente veja a documentação do Ubuntu.

Considerações finais

Este tutorial tem a intenção de prepará-lo para tópicos mais avançados.

Entretanto, procurei ser detalhado nos comandos utilizados também para que o leitor possa se ambientar no ambiente linux, ao invés de apenas digitar comandos “às cegas” sem compreender o que está fazendo.

O que é Big Data – e por que você deveria estar desesperadamente interessado nisso

Word Cloud "Big Data"

Estima-se que 2,5 quintilhões de bytes de dados são criados todos os dias, criados em sua maioria por usuários na web de forma desestruturada. em diferentes meios (texto, áudio, vídeo, etc.) e fontes (Facebook, Twitter, Youtube, etc.).

O potencial desses dados é gigantesco, mas os bancos de dados relacionais não são capazes de lidar com algo dessa natureza. Qual a solução?

A história dos dados

A forma como os dados são gerados, processados e armazenados mudou drasticamente ao longo das últimas décadas e mesmo em relação aos últimos anos.

Os primeiros cientistas da computação preocupavam-se em criar estruturas de dados otimizadas para armazenar a maior quantidade de informação, da forma mais eficiente possível. Os bancos de dados relacionais ajudaram bastante nessa tarefa.

Porém, o volume de dados que existe no mundo hoje simplesmente não cabe mais nesse modelo. Com a ascensão da Internet disponível, virtualmente, a todo mundo e com a popularização dos sistemas web, incluindo as Redes Sociais, temos hoje um número inimaginável de informação, que aumenta a cada dia.

Agora pare e imagine o potencial desses dados se devidamente analisados. As pesquisas de mercado tradicionais consideram uma população de algumas centenas ou, no máximo, milhares de pessoas para testar alguma tendência.

E se conseguíssemos analisar os dados comportamentais de milhões ou até bilhões de pessoas? A chance de identificar tendências em grupos mais específicos aumentaria enormemente.

O grande problema é que esse volume monstruoso de dados está distribuído em inúmeros locais e em geral não é estruturado para transportarmos tudo para tabelas.

Pense no Twitter. Milhares de pessoas ao redor do mundo postando comentários, críticas, reclamações em forma de um texto com no máximo 140 caracteres. Se pudéssemos analisar sobre o que as pessoas estão mais comentando hoje e se estão falando bem ou mal, teríamos uma enorme vantagem competitiva, não é mesmo? Poderíamos responder “em tempo real” aos consumidores de acordo com o que eles estão querendo.

Texto, som, vídeo, imagem. Há um enorme potencial em tudo isso em busca de uma informação relevante.

O que é Big Data?

Big Data é um termo cunhado por Budhani em 2008 para descrever qualquer conjunto de dados que seja inviável de manipular por uma ferramenta tradicional em um tempo razoável.

Obviamente isso é um tanto vago, mas já existem algumas definições mais específicas.

Os V’s do Big Data

Ao contrário do que o termo pode levar-nos a pensar, Big Data não é apenas sobre o volume de dados. Em tese, um SGBDR tradicional pode tratar quantidades imensas de dados. Big Data envolve outras características relacionadas com velocidade e variedade.

Procurando definir o que é Big Data, alguns pesquisadores chegaram a um conceito de múltiplos atributos. Isso ficou conhecido como os 3 V’s do Big Data: Volume, Velocidade e Variedade.

Entretanto, o amadurecimento da tecnologia deu origem a uma definição mais completa, com 5 V’s: Volume, Velocidade, Variedade, Valor e Veracidade

Confira na imagem abaixo:

Volume

Big Data envolve uma quantidade de dados que começa na casa dos terabytes e chaga até os petabytes. Note que enquanto escrevo esta informação já pode estar desatualizada!

Velocidade

As informações precisam ser transmitidas, processadas e retornadas em tempo hábil para o negócio. Pense na busca do Google, ela precisa “ler a internet” em alguns milissegundos. Ou você usaria o Google se cada pesquisa levasse horas ou dias?

Variedade

Ao contrário dos sistemas de informação mais tradicionais, Big Data gira em torno de uma grande variedade de dados não estruturados e não normalizados.

Muitas informações podem ser obtidas através de processamento de vídeos do youtube, tweets, arquivos de log e páginas de blog.

Eu sei que você já deve estar cansado de eu usar o Google como exemplo, mas farei novamente. Já viu a legenda automática do YouTube? Houve um bom avanço nos algoritmos de análise de áudio, não é? Já pensou em como o Google ordena os resultados da pesquisa, priorizando o conteúdo mais adequado para os termos inputados?

Trabalhar com SEO nada mais é do que tentar influenciar os algoritmos de Big Data do Google!

Valor

Com o amadurecimento das soluções de Big Data, notou-se que as três características já apresentadas não eram razão suficientes para a utilização desta tecnologia.

É necessário que as informações extraídas da massa de dados proporcionem um benefício tangível.

Por exemplo, se uma empresa consegue identificar através de análises estatísticas certas tendências dos consumidores, ela poderá obter uma grande vantagem em relação aos seus concorrentes.

Veracidade

Desde que alguns institutos passaram a usar dados de redes sociais para verificar tendências, surgiu uma nova versão de ataque digital que procura manipular os resultados.

Vou dar um exemplo. Ouvi recentemente que foram criados bots (robôs) para gerar milhares de tweets e postagens na Internet sobre certo candidato a cargo político. O objetivo é fazer parecer que o candidato tem popularidade, sendo “o candidato mais comentado na internet”.

Uma preocupação que tem faltado nas implementações de Big Data é justamente verificar se os dados são oriundos de fontes confiáveis e se os mesmos são autênticos.

Não vou aprofundar-me nesse assunto, mas continuando com o exemplo, uma boa implementação de contagem de tweets poderia eliminar as mensagens repetidas ou muito parecidas. Isso porque spammers são capaz de gerar frases aleatórias com variações de palavras. Portanto a mesma técnica que filtros de spam utilizam deveria ser aplicada nesse caso.

Por quê Big Data?

Até aqui você já deve ter compreendido alguns conceitos básicos sobre Big Data. Porém, ao mesmo tempo, pode estar se perguntando essa tecnologia não teria seu uso limitado a empresas altamente técnicas como o Google.

Em teoria, sobre tudo o que se pode fazer estatística pode se beneficiar de Big Data.

Vejamos agora algumas aplicações reais de grandes e pequenas empresas.

Vendas

O Walmart, por exemplo, adotou Big Data desde muito cedo. Os dados de dez diferentes sites foram consolidados num cluster Hadoop, migrados a partir de bases Oracle e outras fontes de dados.

Além de diminuir o tempo das buscas o Walmart é capaz de verificar se um amigo seu lhe enviou informações sobre um determinado produto em uma rede social e então lhe mandar um e-mail com uma promoção daquele produto.

Ele também pode lhe indicar produtos de acordo com o perfil dos seus amigos no Facebook, de modo que você possa dar um presente adequado.

Telecom

Algumas empresas de Telecom usam Big Data para traçar perfis dos consumidores, unindo padrões de ligação, envio de mensagem e participação em redes sociais. Eles conseguem então descobrir quais consumidores estão mais propensos a trocar de operadora.

Esportes

No campo dos esportes, há várias iniciativas de monitoramento dos atletas. Isso permitirá a análise do desempenho de um time e de cada indivíduo, possibilitará encontrar tendências, prever resultados e até criar jogos mais reais com as características dos times verdadeiros.

Saúde

Na saúde, os pesquisadores poderão prever com mais precisão problemas de saúde baseando-se em históricos hospitalares.

Hoje já existem estudos sobre a coleta de informações de respiração e batimentos cardíacos de bebês nascidos prematuros e o uso de Big Data para identificar padrões de infecção. Isso possibilitará identificar antecipadamente quando um bebê realmente está com infecção antes dos sintomas mais visíveis aparecerem e, consequentemente, aplicar um tratamento mais efetivo.

Trânsito

No Japão, um aplicativo baseado em Big Data está ajudando a melhorar trânsito de uma cidade ao coletar informações de 12 mil táxis e vários sensores.

O serviço consegue analisar 360 milhões de informações sobre o trânsito instantaneamente para retornar a melhor rota naquele horário para o motorista. Com bancos de dados relacionais, o processamento levava vários minutos.

O que realmente é Big Data?

Parafraseando um outro artigo, “no fundo, no fundo, Big Data não se trata de dados nem de tamanho”. Também não se trata de novidades tecnológicas ou descobertas científicas.

Big Data é uma nova forma de ver o mundo, de usar estatísticas e de tomar decisões de negócio.

Uma metáfora seria como a descoberta do microscópio. Uma vez que se consegue enxergar as coisas numa escala completamente diferente de antes, novas descobertas inevitavelmente irão surgir.

A análise criteriosa de um grande volumes de dados é uma tendência que vai continuar e logo se expandirá para mais e mais esferas da vida humana.

Big Data é apenas mais uma modinha?

Algumas pessoas acham que Big Data é apenas mais uma moda tecnológica.

Como toda moda, existe um ciclo onde a princípio todos estão falando sobre aquilo e tem uma expectativa muito alta, depois começam a perceber que o investimento não está trazendo todos os benefícios imaginados, alguns desistem e outros persistem e começam a usar a tecnologia de forma mais adequada e ao final atingem um grau mais real de aproveitamento.

gartner_hype_cycle

Certamente os termos e as tecnologias podem mudar, mas é verdade também que a ideia principal está aí para ficar.

Big Data não é a mesma coisa que Data Warehouse ou Business Intelligence?

Quem conhece um pouco sobre Data Warehouse ou Business Intelligence pode ter encontrado muitos pontos em comum com o que foi apresentado sobre Big Data. Muitos, inclusive argumento que é a mesma coisa. Será?

Por um lado, podemos dizer que a ideia principal é a mesma, a saber, processar um grande volume de dados para ajudar em decisões de negócios e detectar padrões.

Por outro lado, as tecnologias de BI e DW são mais conservadores no que diz respeito às técnicas, tecnologias e estruturas de dados. O foco delas é processar e consolidar os dados estruturados das empresas em uma base de dados somente-leitura separada dos bancos de dados principais dos sistemas a fim de obter estatísticas relevantes.

Já Big Data tem por objetivo unir fontes heterogêneas, privadas e públicas, geralmente em bases NoSQL ou mesmo em arquivos, com dados modificáveis. Big Data também é usado diretamente “em produção”, provendo informações diretamente para os usuários. Os fundamentos também são diferentes, pois Big Data lida especialmente para processamento distribuído, como veremos em breve num artigo sobre MapReduce.

Quais são as tecnologias relacionadas com Big Data?

Não entrarei em detalhes, pois pretendo escrever outros artigos sobre essas tecnologias. Vou simplesmente citar as mais comuns que envolvem o ecossistema do Hadoop, de longe a solução Big Data mais conhecida e também usada como base para outras soluções comerciais.

Hadoop

É uma implementação opensource do framework MapReduce. O Hadoop é um projeto mantido pelo grupo Apache.

Ele é capaz de coordenar tarefas executadas processamento distribuído e paralelo de grandes conjuntos de dados em qualquer quantidade de nós de um cluster.

O Hadoop é implementado em Java, sendo executado numa JVM. Você pode escrever um programa para executar no Hadoop usando a API disponibilizada em jars ou no Maven, inclusive usando sua IDE predileta.

No entanto, Java não é o limite. O Hadoop nada mais é do que uma base de uma pilha de tecnologias, incluindo linguagens de mais alto nível para fins específicos.

HDFS

O Hadoop Distributed File System é um sistema de arquivos distribuído de alta velocidade usado no Hadoop.

YARN

Trata-se de um framework para agendamento de tarefas e gerenciamento do cluster.

HBase

Um banco de dados NoSQL com suporte a dados estruturadas e tabelas grandes.

Hive

O Hive é um tipo de linguagem SQL (HiveQL, para ser mais exato) próprio para realizar consultas em grandes quantidades de dados distribuídos.

Mahout

Este é um projeto que procura unir Inteligência Artificial com Big Data, falando especificamente de Aprendizado de Máquina.

Pig

Pig é uma linguagem de programação de alto nível que facilita na criação de tarefas e análise de dados distribuídos, com execução em paralelo.

Bem, eu sei que você pode ser especialista em “programação porca”, mas não é disso que se trata o Pig. Tá… todo mundo aqui no Brasil já fez essa piada, mas não pude perder a oportunidade! 😉

ZooKeeper

Para manter todos os bichos do Hadoop em suas jaulas é necessário alguém para administrar tudo.

O ZooKeeper é um serviço centralizado para manter a configuração, dar nomes, prover sincronização e agrupamento de serviços.

Mas quem vai operar tudo isso?

Big Data trouxe também um novo tipo de profissional ao palco: o Cientista de Dados.

Uma breve pesquisa sobre esse termo vai trazer muitos resultados, demonstrando que é uma carreira em alta no momento.

Os cientistas de dados devem unir diversas habilidades:

  1. Ser bom em estatística e matemática para analisar corretamente os dados;
  2. Dominar as bases da Ciência da Computação para implementar devidamente as soluções, que geralmente incluem algum tipo de programação e entendimento da arquitetura distribuída; e
  3. Conhecer o negócio da empresa para gerar benefícios tangíveis com os resultados do seu trabalho.

Considerações finais

Sendo uma moda ou não, as empresas estão investindo pesadamente e obtendo resultados concretos com Big Data. Quanto antes uma empresa obtiver os benefícios em potencial de uma solução Big Data, mais ela terá chances de aumentar sua participação no mercado.

Os profissionais que mais cedo dominarem essa tecnologia também terão mais chances de destacar-se nesse nicho de mercado.

Como em toda mudança, os que chegarem por último terão que se contentar com as sobras.

A maior consideração quanto a isso é não entrar no frenesi de implementar Big Data por um fim em si mesmo, nem criar expectativas irreais sobre as tecnologias.

Torna-se necessário então compreender o cenário atual para avaliar cautelosamente o caminho adequado para um investimento em Big Data.

Além disso, voltando ao exemplo do microscópio, a nova visão de mundo proporcionada pela análise de enormes massas de dados deve ser suplementar e não substituta da visão da realidade dos negócios e da realidade humana.

Apache POI: adicionando segurança em arquivos Excel

poi-original
A biblioteca Apache POI possibilita a leitura e gravação de documentos do Microsoft Office via código Java.

Por esses dias, fiz uma pesquisa sobre como essa biblioteca viabiliza (ou não) trabalharmos com arquivos protegidos do Excel.

Níveis de segurança do Office

Documentos do Excel podem ter diferentes níveis de proteção, a saber:

  • Proteção contra alteração: permite abrir o documento em modo somente-leitura, mas não deixa o usuário alterá-lo sem antes digitar a senha.
  • Proteção contra alteração de um trecho do documento: protege planilhas e células específicas com senha.
  • Proteção contra leitura: não permite abrir o documento sem a senha.

Todos esses modos podem ser usados ao mesmo tempo, inclusive com senhas diferentes.

Se o arquivo tiver proteção contra leitura, o Excel irá solicitar a senha antes de abrir o mesmo. Se houver proteção contra alteração ele irá solicitar a senha para desbloqueio da edição ou permitir acesso somente-leitura ao documento. Se planilhas ou células estiverem protegidas contra alteração, então o usuário deve acessar a função “Desproteger” no Excel e digitar a senha de desbloqueio para cada trecho.

As proteções contra alteração são simples travas no editor, pois o arquivo em si permanece aberto e não há restrições de alteração via programação ou com o uso de editores de terceiros. Podemos dizer que este mecanismo oferece um baixíssimo grau de segurança, que impedirá apenas o usuário mais leigo de efetivamente modificar o documento.

Por outro lado, a proteção contra leitura oferece um grau de segurança maior, pois o documento como um todo é criptografado. Isso significa que nenhum programa ou editor conseguirá sequer ler o documento sem antes descriptografar os bytes do arquivo com a senha original.

Versões dos documentos do Office

Quem acompanha o Office há algum tempo deve ter notado que, a partir da versão 2007, os documentos ganharam novas extensões, com o sufixo x. Por exemplo, doc passou a ser docx, xls mudou para xlsx e assim por diante.

Mas não foi apenas a extensão que mudou. O conteúdo foi completamente reformulado. O formato mais antigo era do tipo binário, enquanto os novos são baseados em XML.

As vantagens do formato XML são inúmeras, a começar pela capacidade de qualquer ferramenta que trabalha com XML conseguir processar o documento ou pelo menos parte dele.

No que se refere à biblioteca Apache POI, isso também nos afeta diretamente, pois há APIs diferentes para trabalhar com os diferentes formatos de documentos.

Como veremos adiante, nem todos os formatos suportam todos os tipos de segurança.

Capacidades do POI

A conclusão dos meus testes foi a seguinte:

Tipo de documento Operação Proteção contra alteração do documento Proteção contra alteração de uma planilha Proteção contra Leitura (criptografia)
XLS
Leitura OK
Criação N/D* OK N/D
XLSX
Leitura OK
Criação N/D OK OK

Na leitura de um arquivo XLS ou XLSX, as proteções contra alteração são ignoradas, então não há o que testar.
N/D = Não disponível, isto é, não há suporte na API.
* Existe um método para proteger o documento, mas ele não surte efeito (bug).

Como pode ser visto, para documentos no formato legado XLS o POI suporta apenas a leitura de arquivos criptografados. Na criação, ele apenas consegue proteger parte do documento contra alteração.

Já para o formato mais novo XLSX, o POI consegue ler e criar arquivos criptografados. Entretanto, na criação do documento, não há um método para proteger o documento todo contra alteração.

Alguns fóruns sugerem uma possibilidade de contornar a falta do recurso de proteger o documento como um todo contra alteração. Para isso, basta criar um arquivo Excel com tal proteção e usá-lo como template para geração de um novo.

Implementação

Criptografia em arquivos XLS

O POI suporta apenas ler arquivos criptografados neste formato, isto é, que estão protegidos contra leitura.

O segredo é a classe Biff8EncryptionKey. Basta definir a senha através do método estático setCurrentUserPassword e depois ler o arquivo normalmente.

Exemplo:

try {
    Biff8EncryptionKey.setCurrentUserPassword(password);
    new HSSFWorkbook(input);
} finally {
    Biff8EncryptionKey.setCurrentUserPassword(null);
}

É bom não esquecer de remover a senha ao final para não atrapalhar futuras leituras.

Mesmo sendo um método estático, não deve haver problemas de concorrências, pois a documentação afirma que a senha é armazenada usando ThreadLocal.

Criptografia em arquivos XLSX

O POI implementa tanto a leitura quanto a criação de documentos criptografados neste formato.

Veja minha implementação para a leitura:

public class XlsxDecryptor {

    public static XSSFWorkbook decrypt(InputStream input, String password)
            throws IOException {

        POIFSFileSystem filesystem = new POIFSFileSystem(input);
        EncryptionInfo info = new EncryptionInfo(filesystem);
        Decryptor d = Decryptor.getInstance(info);

        try {
            if (!d.verifyPassword(password)) {
                throw new RuntimeException("Unable to process: document is encrypted");
            }

            InputStream dataStream = d.getDataStream(filesystem);
            return new XSSFWorkbook(dataStream);
        } catch (GeneralSecurityException ex) {
            throw new RuntimeException("Unable to process encrypted document",
                ex);
        }

    }

    private XlsxDecryptor() {
    }

}

E para criação:

public class XlsxEncryptor {

    public static void encrypt(InputStream input, OutputStream output, 
            String password) throws IOException {

        try {
            POIFSFileSystem fs = new POIFSFileSystem();
            EncryptionInfo info = new EncryptionInfo(fs, EncryptionMode.agile);

            Encryptor enc = info.getEncryptor();
            enc.confirmPassword(password);

            OPCPackage opc = OPCPackage.open(input);
            OutputStream os = enc.getDataStream(fs);
            opc.save(os);
            opc.close();

            fs.writeFilesystem(output);
            output.close();
        } catch (GeneralSecurityException e) {
            throw new RuntimeException(e);
        } catch (InvalidFormatException e) {
            throw new RuntimeException(e);
        }

    }

}

Proteção de partes de um documento

O POI implementa a proteção de uma planilha de um documento Excel e a proteção de células. Testei apenas a proteção de planilhas.

A implementação é muito simples, basta usar o método protectSheet. Veja o exemplo para o formato XLSX:

XSSFSheet sheet = workbook.createSheet();
sheet.protectSheet("54321");

E agora o equivalente para o formato XLS:

HSSFSheet sheet = workbook.createSheet();
sheet.protectSheet("54321");

Testes e exemplo

Antes de encerrar o artigo, vou acrescentar aqui dois dos testes unitários que implementei de forma que possam servir como exemplo de uso do POI e do meu projeto.

O primeiro cria um novo arquivo XLSX cripgrafado e em seguida lê o mesmo arquivo verificando se o valor foi gravado corretamente:

@Test
public void createXLSXOpenAndModifyProtected() throws IOException {
    System.out.println("createXLSXOpenAndModifyProtected");

    //creates sheet
    XSSFWorkbook workbook = new XSSFWorkbook();
    XSSFSheet sheet = workbook.createSheet();
    sheet.protectSheet("54321");

    XSSFRow row = sheet.createRow(0);
    XSSFCell cell = row.createCell(0);
    cell.setCellValue("Gravado");

    //saves sheet
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    workbook.write(bos);
    bos.close();
    ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());

    new File("target/.output-file/xlsx").mkdirs();
    WorksheetEncryptor.encrypt(
        bis, 
        new FileOutputStream("target/.output-file/xlsx/OpenAndModifyProtected.xlsx"), 
        DocumentType.XML, 
        "54321");
    bis.close();

    //read again and check
    XSSFWorkbook workbook2 = (XSSFWorkbook) WorksheetDecryptor.decrypt(
        new FileInputStream("target/.output-file/xlsx/OpenProtected.xlsx"),
        DocumentType.XML, 
        "54321");
    Assert.assertEquals("Gravado", workbook2.getSheetAt(0).getRow(0).getCell(0).getStringCellValue());
}

Em seguida, o segundo lê um arquivo XLS criptografado e verifica o valor da célula:

@Test
public void testOpenAndModifyProtectedXLS() throws IOException {
    System.out.println("### testOpenAndModifyProtectedXLS");
    HSSFWorkbook workbook = (HSSFWorkbook) WorksheetDecryptor.decrypt(
        getClass().getResourceAsStream("xls/OpenAndModifyProtected.xls"),
        DocumentType.LEGACY, 
        "12345");
    String conteudoCelula = workbook.getSheetAt(0).getRow(0).getCell(0)
        .getStringCellValue();
    Assert.assertEquals("Teste criptografia", conteudoCelula);
}

Código-fonte

Todo o código, inclusive os testes, está disponível em um projeto no meu GitHub.

Com o Maven você será capaz de executá-lo sem nenhuma configuração adicional. Basta clonar o repositório.

Instalando e configurando o Ubuntu linux numa máquina virtual

virtualbox-ubuntu

Neste tutorial, vamos instalar o Ubuntu, uma das distribuições linux mais populares da atualidade, numa máquina virtual.

Você poderá usar isso para várias finalidades. Aqui no blog, em breve, usaremos em artigos sobre Hadoop e Big Data.

Virtualização

Para quem não está acostumado com virtualização, uma máquina virtual (Virtual Machine, em Inglês) é um ambiente que simula um computador, com sistema operacional próprio, mas que você pode executar dentro do seu sistema atual.

Isso significa que você pode executar um sistema operacional linux dentro do seu Windows e vice-versa. Eu mesmo uso primariamente o Windows 7, mas tenho imagens com XP e diversas distribuições linux.

O sistema operacional principal da máquina é chamado de hospedeiro (host). Os sistemas operacionais usados dentro de máquinas virtuais no sistema hospedeiro são chamadas de sistemas convidados (guests).

Essa técnica tornou-se viável num passado não tão distante quando o hardware atingiu um bom nível de eficiência, inclusive hoje com tecnologia que torna a virtualização quase tão eficiente como um sistema tradicional.

A virtualização traz vários benefícios. O principal é possibilitar a criação da tão famigerada computação em nuvem (cloud computing). Além disso, as empresas que dependem de infraestrutura de TI tanto para desenvolvimento quanto para produção podem usufruir de maior facilidade para a criação de novos ambientes e servidores virtuais, além de flexibilidade para o gerenciamento. Desenvolvedores ou mesmo usuários domésticos como eu podem ter vários servidores com diferentes tecnologias em seu notebook pessoal, inicializados apenas de acordo com a demanda.

Existem ainda sites que disponibilizam ambientes com diversas tecnologias prontos para os administradores usarem em servidores. Um deles é o TurnKey Linux. Baixando imagens de discos virtuais relativamente pequenas, você tem um sistema pronto para uso e somente com o que é necessário para executar a tecnologia escolhida. Enfim, você pode ter um servidor pronto em uma máquina virtual em apenas alguns minutos.

VirtualBox ou VMWare Player?

Os programas gratuitos de virtualização para usuários domésticos mais conhecidos são o VirtualBox da Oracle e o VMWare Player. Ambos são bons produtos, maduros e em constante evolução. Mas com funcionalidades específicas um pouco diferentes, além de vantagens e desvantagens.

Como sou usuário de ambos posso dizer que na prática não há um ganhador absoluto. Depende do uso que fizermos deles. O VMWare, por exemplo, permite copiar e copiar um arquivo do sistema hospedeiro para o convidado e vice-versa. O VirtualBox, por sua vez, traz várias funcionalidades que o VMWare só disponibiliza na versão paga.

Para quem faz questão de uma solução mais completa e possui condições de arcar com as despesas, o melhor seria adquirir uma versão paga do VMWare. Já o usuário doméstico que está começando se dará muito bem com qualquer versão gratuita.

Aqui usaremos o VirtualBox. Mas se alguém optar pelo concorrente não encontrará tanta dificuldade em atingir o mesmo objetivo.

Funcionalidades interessantes do VirtualBox

Existem algumas funcionalidades bem legais quando usamos uma máquina virtual. Irei descrever algumas nas próximas linhas que estão disponíveis no VirtualBox.

Por exemplo, você pode pausar uma máquina virtual a qualquer momento através do menu Máquina > Pausar.

Também é possível salvar snapshots da máquina através do menu Máquina > Criar Snapshot. Sabe o que significa isso? Ao criar um snapshot, você tira uma “fotografia” ou “instantâneo” do sistema naquele momento. Então pode “pintar e bordar”, realizar testes, instalação de programas ou até vírus. Quando cansar da brincadeira, basta restaurar o snapshot e o sistema (disco e memória) voltarão ao estado salvo como se nada tivesse acontecido.

Caso em algum momento você deixe a máquina virtual em tela cheia ou o cursor do mouse seja capturado por ela de forma que você não consiga sair, não se desespere. A tela usada para liberar o mouse e também para algumas teclas de atalho é o CTRL da direita do seu teclado. Este é o padrão e você pode mudá-lo. Essa tecla especial é chamada tecla do hospedeiro, isto é, que permite acessar comandos no sistema hospedeiro. Por exemplo, CTRL+F alterna a máquina virtual entre modo de tela cheia e janela.

Outra funcionalidade interessante, embora deva ser usada com cuidado, é o modo Seamless. Com ele, os programas abertos no sistema dentro da máquina virtual “misturam-se” com a área de trabalho do sistema hospedeiro, dando a impressão de haver apenas um sistema operacional. Veja o seguinte exemplo de um terminal aberto no Ubuntu e exibido em seamless mode:

seamless-mode

Configuração de Hardware

Máquinas mais novas, como o Intel i7, possuem suporte em nível de hardware para virtualização. Entretanto, até algum tempo atrás essas capacidades eram desativadas por padrão. Isso chegava a impedir a virtualização de sistemas operacionais convidados de 64 bits.

Leia o manual da sua placa mãe e do seu processador e verifique se eles possuem suporte nativo para virtualização. Procure por algo como VT-x (Intel) ou AMD-V. Veja um exemplo da BIOS para um processador AMD:

5x3YW

E aqui outro exemplo para um processador Intel:

bios_enablt_vtx1

Lembre-se, sem o suporte nativo, você não será capaz de instalar um sistema operacional de 64 bits como convidado no VirtualBox. Entretanto, se não estou enganado, o VMWare consegue emular via software a virtualização de sistemas 64 bits, mas de qualquer forma o desempenho será sofrível.

Instalando o VirtualBox e as extensões

Acesse a página de downloads e baixe a versão correspondente ao seu sistema operacional.

dowload-virtualbox

Baixe também as extensões para o sistema convidado.

dowload-virtualbox-extension

As extensões trarão várias facilidades, tais como: redimensionamento automático da tela, melhor integração do mouse, compartilhamento de pastas automático entre o sistema hospedeiro e o convidado, uso da USB dentro da máquina virtual e muito mais.

Execute o primeiro arquivo baixado para instalar o VirtualBox. Em geral você não precisa alterar nenhuma configuração, então simplesmente avance até o final da instalação

virtualbox-install

Confirme ainda a instalação de todos os drivers, que serão usados para integrar seus dispositivos como mouse, teclado e rede com a máquina virtual.

Após concluir, execute também o outro arquivo para instalar as extensões do convidado (Guest Additions). O nome deve ser algo como Oracle_VM_VirtualBox_Extension_Pack-4.3.12-93733.vbox-extpack. O programa VirtualBox será aberto. Aceite o contrato para concluir a instalação.

Dando tudo certo, não se esqueça que o atalho adicionado no Menu Iniciar é “Oracle Virtual Box”.

virtualbox-open

Criando uma máquina virtual

Na tela principal do VirtualBox, clique no botão Novo.

virtualbox-main

Na tela de criação, digite “Ubuntu 14”. Note que os demais campos serão preenchidos automaticamente.

configure-vm-01

Clique em Próximo e selecione a quantidade de memória para seu novo ambiente. Aqui vou deixar com 2 Gigabytes (2048 Megabytes), mas uma dica é não ultrapassar 50% da memória total do seu computador.

configure-vm-02

Clique em Próximo. Nesta tela, você poderá criar um novo disco rígido virtual. Um HD virtual é simplesmente um arquivo grande que ficará no seu sistema de arquivos, o qual funcionará como se fosse um HD para o sistema da máquina virtual. A não ser que tenha outros planos, deixe marcada a opção para criar um disco novo.

configure-vm-03

Clique em Criar. Na próxima tela, você poderá escolher o formato do arquivo desse novo disco. Vamos deixar o formato nativo do VirtualBox, o VDI.

configure-vm-04

Clique em Próximo. Nesta tela você pode escolher entre duas opções:

  1. Dinamicamente alocado: nesta opção, o arquivo do disco virtual vai aumentando de tamanho somente quando novos arquivos forem gravados. Isso significa que se você criar um disco de 30 Gigabytes, mas a instalação do SO e os demais arquivos ocuparem apenas 2 Gigabytes, então o arquivo terá apenas 2 Gigabytes. O disco vai aumentando de tamanho na medida do uso até alcançar o limite de 30 Gigabytes.
  2. Tamanho fixo: nesta opção, um disco virtual de 30 Gigabytes vai ocupar todo esse tamanho no seu disco verdadeiro.

Já que economizar espaço nunca é demais, vamos deixar a primeira opção selecionada.

configure-vm-05

Clique em Próximo. Agora vamos selecionar o nome do arquivo e o tamanho do disco virtual.

configure-vm-06

Caso tenha mais de uma partição ou HD no seu computador, você pode mudar o local do arquivo do disco virtual. Em algumas situações já criei máquinas virtuais no meu HD externo. Porém, para este tutorial, vamos apenas deixar tudo como está, pois o padrão é suficiente.

Finalmente, clique em Criar.

Agora você tem um computador virtual para brincar!

virtualbox-virtualmachine-created

Instalando o Ubuntu

Antes de mais nada, acesse a página de downloads da versão desktop do Ubuntu e baixe a versão adequada para o seu computador. Neste tutorial, fiz o download da versão 64 bits, cujo nome do arquivo baixado é ubuntu-14.04-desktop-amd64.iso e possui 964 Megabytes.

ubuntu-download

Com a imagem do disco de instalação do nosso novo sistema operacional, podemos então iniciar a máquina virtual e a instalação.

Na tela principal, selecione a VM (máquina virtual) criada e clique em Iniciar.

Antes da inicialização da VM, o VirtualBox vai saudá-lo com uma tela solicitando o disco de boot. Isso ocorre porque ele verificou que o disco virtual está vazio.

Clique no botão à direita do campo e selecione o arquivo do Ubuntu anteriormente baixado.

vm-boot-disk-select

Clique em Iniciar e aguarde a inicialização da instalação do Ubuntu.

ubuntu-install-01

Você pode selecionar sua língua materna ou deixar em Inglês. Eu prefiro o Inglês porque em TI as traduções acabam por confundir mais que ajudar. Clique em Install Ubuntu ou Instalar Ubuntu, dependendo da sua escolha.

A próxima tela irá informar se o Ubuntu vai executar bem na máquina onde está sendo instalada. Além disso, há opções para já instalar as últimas atualizações e alguns softwares de terceiros. Selecione todas as opções e clique em Continue.

ubuntu-install-02

Agora há opções para formatar ou particionar o disco antes da instalação. Como temos um disco virtual dedicado, simplesmente selecione a primeira opção para formatá-lo e executar uma instalação limpa.

ubuntu-install-03

Clique em Install Now.

Na verdade, a instalação não vai começar ainda. Isso deve ter sido uma grande falha de design. A próxima tela contém a seleção da sua localidade. Digite o nome da capital do seu estado. Coloquei “Sao Paulo”.

ubuntu-install-04

Clique em Continue.

Na próxima tela você pode selecionar o tipo do seu teclado. Teste-o para ver se está ok e clique novamente em Continue.

ubuntu-install-05

Finalmente, digite seus dados de usuário, incluindo a senha, e clique em Continue para iniciar a instalação de verdade.

ubuntu-install-06

Aguarde o processo de instalação.

ubuntu-install-07

Ao final, uma caixa de diálogo vai aparecer informando que o sistema deve ser reiniciado. Clique em Restart Now.

Nota 1: enquanto fazia este tutorial, o Ubuntu travou e não reiniciou corretamente. Então, fui até o menu Máquina > Reinicializar para forçar um reset.

Nota 2: a instalação do Ubuntu ejetou automaticamente o disco de instalação virtual do Ubuntu. Se estiver instalando outro sistema operacional que não faça isso, use o menu Dispositivos > Dispositivos de CD/DVD > Remover disco do drive virtual para não iniciar a instalação do sistema novamente por engano.

Pronto, o sistema está instalado e pronto para uso.

ubuntu-installed

Melhorando a integração entre sistema hospedeiro e convidado

Note que a janela do ubuntu ficou bem pequena, quase inutilizável. Vamos resolver isso!

Lembra que instalamos as “extensões do convidado” (Guest Additions) no VirtualBox? Elas facilitarão o uso da máquina virtual de várias formas, mas falta a parte da instalação no sistema convidado. Isso ocorre para que o VirtualBox consiga “conversar” com o SO que está na máquina virtual.

Para fazer isso, devemos seguir as instruções da documentação do VirtualBox que nos dá alguns comandos.

Vamos abrir o terminal de comandos clicando no primeiro botão à esquerda (equivalente ao “Iniciar” do Windows) e pesquisando na caixa de busca por “terminal”.

search-terminal

Se nada mudou no VirtualBox ou no linux desde que escrevi este tutorial, as instruções do Guest Additions para o Ubuntu consistem nos seguintes comandos:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install dkms

Nota: um usuário comentou que não conseguiu executar o último comando com sucesso, tendo substituído por sudo apt-get install virtualbox-guest-dkms. Isso pode ser necessário se estiverem sendo usadas diferentes configurações ou outras versões do Ubuntu ou ainda outras distribuições linux.

O comando sudo que prefixa os demais não está na documentação, mas é necessário se você não está executando o terminal com privilégios de superusuário (administrador).

O primeiro comando é apt-get update. Ele irá atualizar o índice de pacotes do Ubuntu. Dessa forma ele saberá as últimas versões de todos os seus componentes e programas. Após digitar o comando, o sistema irá solicitar a senha do usuário e então executar a ação.

guest-additions-01

O próximo comando é apt-get upgrade. Ele vai efetivamente instalar todas as atualizações do sistema. Após entrar o comando, o Ubuntu vai solicitar algumas confirmações. Pressione Y (yes) para confirmar a atualização e aguarde.

guest-additions-02

Após a atualização do sistema, executaremos o último comando: apt-get install dkms. Este comando vai instalar o pacote dkms, que possibilita a módulos do kernel serem atualizados independentemente. O Guest Additions precisa disso porque ele é um módulo do Kernel e é atualizado com frequência, caso contrário seria necessário recompilar o Kernel do linux a cada atualização.

guest-additions-03

O comando vai pedir a confirmação da instalação. Pressione Y quando necessário.

Neste momento já cumprimos todos os pré-requisitos para a instalação do Guest Additions. Então vamos à instalação em si.

Acesse o menu Dispositivos > Inserir imagem de CD dos Adicionais para Convidado....

guest-additions-04

Ao acionar o menu, uma imagem de CD do VirtualBox será montada no sistema do Ubuntu e a execução automática (auto run) ocorrerá. Uma mensagem de confirmação será exibida.

guest-additions-05

Clique em Run. A senha será novamente solicitada. Digite-a e aguarde o final da instalação.

guest-additions-06

Finalmente, vamos reiniciar o sistema para ativar o módulo que acabamos de instalar. Clique no botão do sistema no canto superior direito do Ubuntu e selecione a opção Shut Down....

guest-additions-07

Na tela que vai abrir, clique no botão da esquerda para reiniciar.

Após a reinicialização, você poderá, entre outras coisas, redimensionar a janela do VirtualBox como quiser e o Ubuntu irá se ajustar a esse tamanho. Legal, né? Esta é a opção Visualizar > Redimensionar Tela Automaticamente que estava desabilitada anteriormente, mas agora veio ativada por padrão.

Palavras finais

Virtualização é um conceito importantíssimo no mundo de hoje. Desenvolvedores de software não precisam ser especialistas em virtualização, mas devem ter bons conceitos sobre como isso funciona e devem saber usar todos os benefícios a seu favor.

Criar máquinas virtuais não é difícil, basta ter uma base sobre o assunto e saber usar as ferramenta já existentes, que estão cada vez mais intuitivas e poderosas.

Os benefícios da criação de máquinas virtuais são inúmeros, a começar por podermos usufruir de uma variedade de ambientes dentro de um único computador.

Em futuros artigos, pretendo trazer tutoriais envolvendo Hadoop, inclusive com a criação de um cluster, cada um em uma máquina virtual, para processamento Big Data.

Dissecando o padrão de projetos Singleton

singleton O padrão de projetos Singleton consiste em uma forma de garantirmos que teremos uma única instância de uma determinada classe no programa atual.

Por exemplo, em um programa Java para desktop podemos criar um Singleton da classe que gerencia a conexão com o banco de dados.

Este é um dos design patterns mais simples que existem, mas ele possui algumas nuances importantes de se entender do ponto de vista de implementação.

Implementação inicial em Java

Para garantirmos uma única instância de uma classe, a abordagem mais comum é criar um método estático que retorne sempre o mesmo objeto. Exemplo:

public class Singlegon {
    private static Singleton instance = new Singleton();
    public static Singleton getInstance() {
        return instance;
    }
    private Singleton() { }
}

O atributo estático instance armazena o objeto criado para retornar a cada chamada de getInstance().

O trecho private Singleton() { }; é um construtor privado, garantindo que nenhuma outra classe poderá criar inadvertidamente uma instância desta.

Postergando a criação do objeto

Tudo ok, mas nem sempre queremos criar o objeto no modo agressivo (eager), isto é, instanciá-lo logo que a classe é carregada. Em muitas situações, é desejável postergar a criação do objeto até a primeira chamada. Exemplo:

public class Singlegon {
    private static Singleton instance;
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

No código acima, o primeiro acesso ao método getInstance() irá disparar a criação do objeto, que será então retornada nas demais chamadas.

Problemas de sincronizção

O problema do código acima é que se houver mais de uma chamada concorrente no primeiro acesso ao método getInstance() ele pode criar duas instâncias de Teste. Duas threads poderiam entrar dentro do if, certo?

A solução mais básica para isso é sincronizar o método:

public static synchronized Singleton getInstance() {
    if (instance == null) {
        instance = new Singleton();
    }
    return instance;
}

O problema desta abordagem é que todas as chamadas estarão sujeitas a bloqueios, deixando a execução geral do programa mais lenta. Imagine um método assim num servidor de aplicação com vários usuários acessando o sistema! É terrível.

Uma solução melhor seria um bloco synchronized dentro do if, assim:

public static Singleton getInstance() {
    if (instance == null) {
        synchronized (Singleton.class) {
            instance = new Singleton();
        }
    }
    return instance;
}

Isso resolve o problema da sincronização em todos os acessos, mas é uma solução “ingênua”, pois na verdade voltamos ao problema inicial. Como o if não está sincronizado, duas threads diferentes podem entrar no bloco de criação ao mesmo tempo e, mesmo com a sincronização, elas retornarão instâncias diferentes quando instance == null.

Então, a solução mais “pura” para o singleton pattern seria acrescentar uma verificação dupla, assim:

public static Singleton getInstance() {
    if (instance == null) {
        synchronized (Singleton.class) {
            if (instance == null) {
                instance = new Singleton();
            }
        }
    }
    return instance;
}

Com esta última abordagem garantimos que não haverá perda de desempenho por causa de sincronização desnecessária do método inteiro.

Além disso, garantimos uma única instância de Teste, pois mesmo que duas chamadas concorrentes entrem dentro do primeiro if, temos uma nova verificação sincronizada.

No pior caso, se houver duas ou mais chamadas concorrentes no primeiro acesso a getInstance (quando INSTANCE ainda é null), apenas estas primeiras chamadas serão sincronizadas, sendo que após a primeira atribuição de INSTANCE, nenhuma chamada posterior será sincronizada.

Além do Singleton: padrão Registry

Alguns argumentam que o padrão Singleton está depreciado e deve ser abandonado. De certa forma eu concordo, pois em ambientes onde múltiplas threads e múltiplas aplicações executam concorrentemente, ter apenas um objeto quase nunca é desejável.

O padrão de projeto Registry permite armazenarmos uma coleção de objetos, cada um contendo um identificador ou um escopo específicos. É como se limitássemos o escopo do Singleton de “um objeto por programa” para “um objeto por qualquer escopo que quisermos“.

A implementação varia muito, mas podemos encontrar exemplos claros desse padrão em:

  • Threadlocal, que permite armazenar valores para uma thread, ou seja, um Singleton para cada uma.
  • HttpSession, que retorna sempre o mesmo objeto para cada usuário do sistema web, ou seja, um Singleton por usuário.
  • Frameworks de Injeção de Dependências como Spring ou CDI, os quais gerenciam a criação de objetos em diferentes escopos e permitem inclusive usar o padrão Singleton declarativamente.

Não entrarei em detalhes sobre o Registry neste artigo.

Indicações de Leitura

Uma leitura mais completa sobre o assunto está no Head First Design Patterns (Use a Cabeça! Padrões de Projeto). Embora tendo suas falhas, este é um livro muito bom para quem ainda está começando a entender Padrões de Projetos.

Outros detalhes interessantes sobre Singleton, como variações de implementação, podem ser encontrados na Wikipédia (em Inglês).

Uma breve definição do padrão Registry pode se encontra no catálogo de padrões do Martin Fowler.

Is TDD dead?

Test Driven Development is a very popular software development methodology focused (guest what?) on tests.

However, despite of being well known, there’s some criticism on this methodology from prominent professionals and thinkers.

A few days ago, there was a very interesting talk about this issue between Martin Martin Fowler (that elaborated the Dependency Injection definition), Kent Beck (creator of TDD and JUnit framework), and David Heinemeier Hansson (creator of Ruby on Rails).

Let’s review some highlights from that talk in the next topics. But let’s start with a brief review of TDD…

How TDD works

Different from the “traditional” development life-cycle composed by Specification, Implementation and Test, TDD begins testing the interfaces of the system.

At first, all tests will fail. The developer’s goal is to make they succeed. In theory it guarantee the focus on what really should be done and provides a concrete measure of progress.

In general, TDD adopts Unit Tests. Both are different things, but closely related.

Unit Tests

Each Unit Test tests only one function or method of the system. Often they are automated.

It seems too simple, but implies that the routine under test can’t depend on other routines, otherwise the test is subjected to third part failures.

This way, in order to test routines that naturally depend on other classes and methods, resources like databases and files, and other stuff, developers need to create simulations of these elements so the routine works without them during the test.

This is the mock idea, i.e., something that mimics the original dependencies.

For instance, a method that would normally return a value from database could be replaced by a method that returns a fixed value for a particular test. Each language, framework, and tool should provide proper ways for doing that. This is also a manner to assess the quality of these tools!

Benefits of TDD

Writing tests in advance brings various advantages:

  • Helps in the understanding of the requirements, since you have to understand them and also what the system should do in order to write down tests.
  • Provides a clear goal in the development, that is, to make all tests to pass.
  • Increases the visibility of what is or not ready, since the tests are generally more reliable indicators of progress than something “implemented, but not tested”.
  • The automation enables Continuous Integration with some level of guarantee the system won’t break, since all unit tests can be executed over and over as regression tests.

Disadvantages

As a general rule, everything has its advantages and also its negative points. We always have to take care with “evangelists” that will make some technology or methodology looks like it hasn’t problems or has zero impact.

This also applies to TDD. Let’s see some of its reservations:

Increases the effort

It’s necessary to spend much more time creating tests and mocks, not to mention the Continuous Integration infrastructure. Of course it can be considered as an investment in quality instead of a penalty, but in practice not everyone can afford the overhead.

Increases the complexity

The architecture becomes more complex since Dependency Injection and other decoupling techniques are abundantly used everywhere.

Changes in requirements are much more costly, since you need to rewrite the code of the system itself plus all the tests and mocks involved.

If the engineer don’t know well what he’s doing, the system will end with tons of kludges.

Intrusiveness in the main code

In some situations, you’ll have to code in a specific way in order the code can be tested later. The application architecture is then affected by outside unnatural factors.

In short, the design is influenced by tests, what is not desirable since is one more thing to be considered and to grab the architect’s attention.

Testing everything is almost impossible

Many technologies are hard to test independently or even in integration tests.

Think about user interfaces, for example. How many technologies allow us to run it in a decoupled way? There’s tools like Selenium for web apps, but they also brings tons of other limitations and dependencies.

Is TDD dead?

We just saw every benefit comes at a cost. This is the main point about TDD being dead. Is the cost of testing everything and creating mocks for every dependency worthy? Let’s look at some comments about the aforementioned talk.

David Hansson starts arguing that lots of people can’t do TDD because of the nature of their work. He talks about the need of numerous mocks and how it makes coding more difficult.

Kent Beck continues and tell us about situations where the team couldn’t refactor their code because the tests were so coupled to the implementation, with two or three levels of mocks, that any modification affected countless of them. He also asserted TDD fits better certain scenarios, for instance, when requirements are clear enough so you can write them in form of tests directly. On the other hand, there are situations when the developer finds out little by little what he actually should do. This is recurrent in framework development and algorithms for analyzing non-structured data.

Fowler argues the major benefit of TDD is a self-testing code. But this could be achieved in other ways. He also talks about those who say “you aren’t doing unit tests right” because of some dependencies during the test. According to him, the “purity” of the definition is not so important, but the test should work and be useful. Furthermore, there’s alternative definitions of Unit Test.

Conclusions

It’s important to comprehend TDD is not the silver bullet of software development. It brings various potential challenges and problems, mainly if there’s not enough experienced people in the team.

Tests are essential, but for each project we could have different kinds of tests, whose cost-benefit should be evaluated for each individual case.

Tests shouldn’t be the goal in itself, even in TDD. Their true goal is guarantee we’re delivering what the client really needs.

Time and effort invested in tests also should be pondered. It affects directly the quality, but the quality has its price. Who will pay for it?

About unit testing, we shouldn’t pursue only purity. The important is the test tests, that is, it works for that situation.

Finally, a general rule could be: use TDD moderately.


Here is the link of the Hangout with those great guys:

Is TDD dead?

Página 7 de 16

Creative Commons O blog State of the Art de Luiz Ricardo é licenciado sob uma Licença Creative Commons. Copie, compartihe e modifique, apenas cite a fonte.