sábado, 26 de novembro de 2016

DevOps - MySQL no Docker

Terceiro artigo da série DevOps, continuação do livro Docker que pode ser acessado através do site Academia.edu.

Entre todas as linguagens que um desenvolvedor possa utilizar, pelo menos um banco de dados é comum a todas elas: MySQL. Utilize PHP, C, Java, Python (talvez não .NET que o pessoal é meio paranoico com Microsoft), ou qualquer outra linguagem o banco de testes será um MySQL.


Então neste artigo veremos como utilizar o MySQL com o Docker (essa mesma técnica pode ser aplicada para o MariaDB ou Postgres - respeitando obviamente a porta deste último). São apenas 3 passos a realizar:

1º) Baixar imagem oficial:
$ docker pull mysql
2º) Rodar o contêiner:
$ docker run --name mybanco -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 -d mysql
3º) Chamar o administrativo do banco:
$ docker exec -it mybanco mysql -p
Obviamente que não iremos parar por aqui pois não teria a menor graça. Vamos acessar o banco através de um programa Java, ainda com o administrativo aberto crie uma base de dados com o seguinte comando:
> create database teste;
> use teste;
> show tables;
Agora precisamos de um editor para o Java, para meus testes sempre utilizo o BlueJ e o Conector JDBC do MySQL deve ser disponibilizado, para proceder isso:

  1. Baixar o conector JDBC do MySQL no driver oficial ou através desse link.
  2. Acessar no menu principal "Tools | Preferences".
  3. Ir para a pasta "Libraries".
  4. Pressionar o botão "Add" e localizar o conector baixado.
Uma vez adicionado sair e entrar novamente no BlueJ para ativar a biblioteca. Agora é só criar o programa para testar a conexão (através do botão "New Class..."):
import java.sql.*;
import java.text.SimpleDateFormat;

public class Conexao {
    
    private Connection con;

    public static void main(String [] args) {
        new Conexao().executar();
    }
    
    public void executar() {
        try {
            criar();
            selecionar();
        } catch (ClassNotFoundException e) {
            System.out.println(e.getMessage());
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }

    }
    private void conexao() throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");
        con = DriverManager.getConnection(
         "jdbc:mysql://localhost:3306/teste", "root", "root");
    }
         
    private void criar() throws ClassNotFoundException, SQLException {
        conexao();
        // Criar a tabela
        Statement stm = con.createStatement();
        stm.executeUpdate(
            "CREATE TABLE funcionario (" +
            " matricula INT NOT NULL, " +
            " nome VARCHAR(50)," +
            " PRIMARY KEY (matricula))");  
        stm.close();

        // Adicionar 100 funcionarios
        PreparedStatement pstm = con.prepareStatement(
            "INSERT INTO funcionario (matricula, nome) VALUES (?, ?)");
        int tot = 0;
        for (int i = 0; i < 100; i++) {
            pstm.setInt(1, i);
            pstm.setString(2, "Funcionário " + i);
            tot += pstm.executeUpdate();
        }
        System.out.println("Inseridos : " + tot);
        pstm.close();
        con.close();
    }

    private void selecionar() throws ClassNotFoundException, SQLException {
        SimpleDateFormat fdt = new SimpleDateFormat("hh:mm:ss:SSSS");
        conexao();
        // Varrer todos os dados
        Statement stm = con.createStatement();
        ResultSet res = stm.executeQuery(
            "SELECT nome, matricula FROM funcionario");
        int x = 0;
        String nome = null;
        int matricula;
        System.out.println("Tempo Inicial: " + fdt.format(new java.util.Date()));
        while (res.next()) {
            nome = res.getString(1);
            matricula = res.getInt(2);
            x += 1;
        }
        System.out.println("Tempo Final: " + fdt.format(new java.util.Date()));
        System.out.println("O último que li foi " + nome);
        System.out.println("Total de " + x);
    }
}
Na primeira parte deste programa será criada uma tabela na base teste e populada com 100 registros de funcionário, na segunda parte é realizada uma consulta para verificar a existência dos registros e o tempo de performance de leitura.

Assista o vídeo para tirar quaisquer dúvida de como proceder:


Pronto o MySQL está pronto para seus testes, uma boa vantagem é que podemos criar várias instâncias (contêineres) do banco para múltiplos testes ou mesmo destruir sem deixar rastro de quaisquer dados.

Obrigado e até a próxima
Fernando Anselmo

sábado, 19 de novembro de 2016

DevOps - MongoDB no Docker

Segundo artigo da série DevOps, continuação do livro Docker que pode ser acessado através do site Academia.edu.

Essa postagem garanto que será um tanto diferente, agora estou unindo som, imagem e texto. Isso mesmo, todos os comandos aqui estão reproduzidos em um vídeo no meu canal do YouTube assim pretendo colocar uma nova dimensão a este blog.

Dando continuidade a nossa série com o DevOps iremos ver como instalar e utilizar o banco de dados MongoDB. Qual a vantagem? Melhor organização, utilizando contêineres podemos facilmente ligar o servidor (ou desligá-lo), criar e remover múltiplas instâncias do banco para projetos diferentes, testar novidades sem atrapalhar o ambiente.
Não se surpreenda para instalar o MongoDB, imagem oficial, através do Docker é necessário um único comando:
$ docker pull mongo
Agora precisamos subir um contêiner:
$ docker run --name some-mongo -p 27017:27017 -d mongo
Onde "some-mongo" é o nome do contêiner criado. Podemos testá-lo através de um navegador através do endereço:
http://localhost:27017
Ou podemos executar o Administrador do MongoDB:
$ docker exec -it some-mongo mongo admin
No administrador podemos executar alguns comandos, por exemplo, verificar os bancos criados:
> show dbs
Utilizar determinado banco:
> use local
Mostrar as coleções existentes deste banco:
> show collections
Para sair do administrador:
> exit
Verificar o estado atual dos contêineres:
$ docker ps -a
Podemos parar o contêiner criado:
$ docker stop some-mongo
Ou iniciá-lo com o comando:
$ docker start some-mongo
Para remover um contêiner executamos:
$ docker rm some-mongo
Agora já temos o MongoDB instalado, em breve iremos utilizá-lo para nossos futuros testes. Confira o vídeo que completa este artigo:


Obrigado e até a próxima
Fernando Anselmo

quarta-feira, 16 de novembro de 2016

DevOps - MSSQL Server no Docker (em Linux)

Primeiro artigo da série DevOps, continuação do livro Docker que pode ser acessado através do site Academia.edu.

Essa será a primeira de uma série de publicações para a montagem de ambientes utilizando o Docker com o Ubuntu 16.10. E, pode pensar que enlouqueci, mas não, vamos realmente instalar o Banco de dados Microsoft SQL Server no Linux e ainda por cima através do Docker.
O primeiro passo é baixar a imagem oficial:
$ sudo docker pull microsoft/mssql-server-linux
O segundo e último passo é executar a imagem para criar um contêiner com o seguinte comando:
$ docker run –e 'ACCEPT_EULA=Y' –e 'SA_PASSWORD=<YourStrong!Passw0rd>' -p 1433:1433 -d microsoft/mssql-server-linux
Não estou brincando o banco já foi instalado e está respondendo na porta 1433. Podemos verificar que a imagem está realmente rodando com o comando:
$ docker ps -a
Podemos utilizar qualquer linguagem para testá-lo porém prefiro instalar um "Administrador" para isso, vamos então proceder mais alguns passos.

1. Entrar em modo super usuário:
$ sudo su
2. Importar do repositório público as chaves GPG:
# curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
3. Registrar o repositório Microsoft (não se preocupe com 16.04 para o Ubuntu 16.10):
# curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list > /etc/apt/sources.list.d/msprod.list
4. Sair do modo super usuário:
# exit
5. Atualizar o sistema:
$ sudo apt update
6. Instalar o aplicativo e suas dependências:
$ sudo apt install odbcinst-utf16 odbcinst1debian2-utf16 unixodbc-utf16 msodbcsql mssql-tools

Testar o ambiente

Mais uma vez já poderiamos ter terminado mas aí não teria graça. Vamos testar o ambiente, digitar o seguinte comando para entrar no MSSQL-Tools:
$ sqlcmd -S localhost -U SA -P '<YourStrong!Passw0rd>'
Como resposta obtemos "1>", significa que estamos na linha de comando do MSSQL-Tools, cada comando SQL que digitarmos é necessário terminá-lo com ";" e digitar "GO" na linha de baixo, por exemplo, ver os bancos existentes com o comando:
SELECT name FROM sys.databases;
Pressionar "ENTER" e será mostrado "2>" digitar:
GO
Pressionar "ENTER". Provavelmente nada sera mostrado, pois é um banco limpo de tudo. Vamos criar uma base de dados e uma tabela, siga a sequencia, pressionando "ENTER" em cada linha:
CREATE DATABASE testedb;
GO
USE testedb;
GO
CREATE TABLE funcionario(matricula INT NOT NULL, nome NVARCHAR(50), salario NUMERIC(10,2), PRIMARY KEY(matricula));
GO
INSERT INTO funcionario VALUES (1, 'Fernando', 1200.00);
INSERT INTO funcionario VALUES (2, 'Maria', 1400.20);
INSERT INTO funcionario VALUES (3, 'Manoel', 1100.00);
INSERT INTO funcionario VALUES (4, 'Pedro', 1230.25);
GO
Podemos ver os dados através do comando:
SELECT * FROM funcionario;
GO
Sair do MSSQL-Tools com o seguinte comando:
quit
Digitar:
$ docker ps -a
Parar o servidor com o comando:
$ docker stop [CONTAINER ID]
Tentar acessar novamente o MSSQL-Tools e observar que dessa vez será mostrado um erro informando que não existe o banco ativo. Ativar o servidor novamente com o comando:
$ docker start [CONTAINER ID]
Acessar e verificar que a base testedb está integra e com os dados que foram inseridos corretamente.

Obrigado e até a próxima
Fernando Anselmo

sexta-feira, 23 de setembro de 2016

Aprendizado - Instalar o Scratch no Ubuntu

Scratch é um ambiente criado pelo MIT para ensinar Lógica de Programação através de uma estrutura visual de blocos. Sua instalação no Ubuntu requer alguns comandos via terminal que pode ser um pouco complicado para o usuário iniciante mas nada que assuste tanto a ponto de desistir.


A primeira ação a fazer é visitar o site oficial e realizar um download de dois programas, Adobe AIR  e Scratch 2.0 Offline Editor. A partir da versão 2.0 o MIT disponibilizou uma página aonde o Scratch roda online, porém algumas vezes desejamos tê-lo no computador de modo offline.
Para instalar o Adobe AIR (necessário para instalar e rodar o Scratch) seguiremos alguns passos básicos:

1. Abra o terminal com Ctrl+Alt+T.

2. Instalar as bibliotecas i386, que são requeridas para o Adobe AIR.
$ sudo apt-get install libxt6:i386 libnspr4-0d:i386 libgtk2.0-0:i386 libstdc++6:i386 libnss3-1d:i386 libxml2:i386 libxslt1.1:i386 libcanberra-gtk-module:i386 gtk2-engines-murrine:i386
3. Instalar o pacote libgnome-keyring.
$ sudo apt-get install libgnome-keyring0:i386
4. Criar links simbólicos para o gnome-keyring de modo que o Adobe Air possa vê-lo.
$ sudo ln -s /usr/lib/x86_64-linux-gnu/libgnome-keyring.so.0 /usr/lib/libgnome-keyring.so.0
$ sudo ln -s /usr/lib/x86_64-linux-gnu/libgnome-keyring.so.0.2.0 /usr/lib/libgnome-keyring.so.0.2.0
5. Dar permissão para executar o arquivo do Adobe AIR:
$ sudo chmod +x AdobeAIRInstaller.bin
6. Executar o arquivo:
$ sudo ./AdobeAIRInstaller.bin
7. Uma tela gráfica será mostrada para o aceite da licença e continuação do processo de instação. Uma vez concluído, entrar no Nautilus através do SuperUsuário:
$ sudo nautilus
8. Acessar a pasta das aplicações: /usr/share/applications

9. Localizar o aplicativo: Adobe AIR Application Installer

10. Clicar neste e chamar o arquivo baixado do Scratch.

Pronto, agora é só aceitar as licenças necessárias e instalar corretamente o Scratch.

Obrigado e até a próxima
Fernando Anselmo

domingo, 11 de setembro de 2016

DIY - Cardboard a custo R$ 0,00

Estava tranquilamente passeando em um Shopping de Brasília e resolvi entrar na loja da Samsung para ver algumas novidades tecnológicas. O vendedor me mostrou o Óculos VR e tomei um verdadeiro choque ao constatar o preço. Fiquei pensando sobre o projeto orignal chamado CardBoard, da Google.
Para quem não conhece a palavra "Cardboard" pode ser traduzida para "Papelão", isso mesmo é um óculos para imersão 3D totalmente feito com papelão e o custo deveria beirar a ZERO. Só que existem 2 custos na sua confecção: as lentes e os imãs. Porém ao ver o seguinte vídeo:


Fiquei pensando se não seria possível criá-lo realmente a custo ZERO. Os imãs poderia tirar de uma caixa de som velha. então meu maior problema realmente seriam as lentes, não sentia muita confiança nesse negócio de cortar uma garrafa PET mas corri atrás. Meu primeiro teste saiu assim:


Cometi 2 erros nessa lente, primeiro tentei colar com cola super-rápida (tipo Superbond) resultado que a lente ficou completamente embaçada - Tentei arrematar com cola quente. Segundo que deixei bolhas de ar. Mas como era apenas para teste até que funcionou bem, a lente original funciona como uma lente de aumento.


Agora já sabia o que fazer para construir as lentes. Esse outro vídeo pode lhe ajudar com algumas dicas bem importantes.


Acabei usando apenas cola quente para selar as lentes, 2 recomendações: primeiro uma pequena camada interna de cola e arremata com uma externa, segundo deixe um pequeno vão e coloque a água por último. De resto, foi apenas questão da trabalheira de cortar o papelão, pintar (pintar? resolvi pintar de preto para melhorar a imersão 3D), montar, baixar o aplicativo para cardboard e testar. Segue o óculos 3D a custo ZERO.


Funcionou muito bem, com 2 detalhes (sempre os malditos): as lentes devem ser manuseadas com o máximo de cuidado e os imãs deve ser pelo menos um superimã.

2 dicas finais (estou pensando em mudar o título dessa postagem):


Obrigado e até a próxima
Fernando Anselmo

terça-feira, 9 de agosto de 2016

Linguagem de Programação - O faz o Java ser forte?

Tem mais de 10 anos que programo e ministro aulas com a linguagem Java e certa vez ouvi a seguinte pergunta:
O que faz Java ser tão forte no mercado?
Acho que esse é o motivo principal por ministrar aulas, começamos a pensar em algo que sozinho nunca pensaríamos. Realmente, o que tem Java de tão importante assim? Se olharmos a lista do TIOBE a linguagem aparece na liderança com 19,01%, artigos como o JavaWorld mostram que 90% das empresas da revista Fortune 500 usam Java, Rankings de sites como DZone e InfoWorld colocam a linguagem em 1º Lugar na preferência de seus usuários. Será que são esses dados que fazem Java ser forte?
Penso que não isso é uma mera consequência e não o motivo. Vamos dar uma olhada na história de Java para entendermos seu sucesso. Foi lançada em março de 1995 (a versão 1.0 tem a data de janeiro de 1996) e foi algo jamais visto, foram milhares de downloads em um único dia, porém para que servia? Para muita gente era uma forma de programar para Web (nessa data a Internet ainda estava engatinhando). O slogan principal era: "Escreva uma vez e rode em qualquer lugar". Falando francamente a linguagem só atingiu a maturidade em 1998 com a chegada da versão 1.2, até lá era confusa e sem um objetivo definido. Com a Swing a linguagem teve um objetivo construção de aplicativos desktop. Em 2002 veio a versão 1.4 divisora de mundos com os três ambientes conhecidos até hoje JSE, JEE e JME.

Um dia, estava lendo a Exame Informática que tinha uma comparação entre Java e .NET (recém lançada da Microsoft e principal concorrente de Java na época) e chamaram dois especialistas para mostrar os benefícios de cada uma. Achei engraçado que metade do artigo de .NET dissertava sobre "os malefícios de Java" ao invés dos benefícios de se usar essa outra linguagem. Só que um dos malefícios era basicamente o seguinte:
O problema de Java foi a pressa para preencher buracos, o pensamento era: precisamos rodar na Web damos uns tapas no ASP e criamos a JSP, precisamos rodar no desktop criamos a Swing e para acessar banco de dados mudamos a ODBC e criamos a JDBC.
Neste dia entendi um dos fatores para o sucesso de Java, a capacidade em se adaptar rapidamente para qualquer ambiente.

Vejamos um outro detalhe. Quantos amigos conhece que possui um celular com o sistema operacional Java. Esse tipo de celular foi um grande fracasso, mas por adaptação Java entrou nesse mundo dos celulares graças ao Android (que possui por base o sistema Linux mas a linguagem de seus aplicativos é Java). JSF por muito tempo perdeu o espaço para diversos outros Frameworks como Struts, Seam e Spring. Qual a IDE Oficial de Java? Se respondeu Eclipse saiba que é da IBM e foi um pedaço cedido para a comunidade do VisualAge for Java que não alcançou o sucesso desejado (na época os desenvolvedores adoravam o JBuilder - Antiga Borland). A IDE oficial de Java é o NetBeans que nunca atingiu a preferência dos desenvolvedores. De mesma forma o Servidor de Aplicação Glassfish é substituido pelo JBoss (RedHat). O TomCat só foi usado em larga escala quando entrou como parte do Projeto Jakarta da Apache.

E se reparar em toda a história do Java quem fez sucesso foram terceiros que criavam adaptações bem sucedidas porém usando a linguagem Java. Podemos concluir que o segundo fator para o sucesso de Java está em uma comunidade forte para criar/adaptar aplicativos, ferramentas e sistemas que os usuários usem.

Resultado, Java criou um muro de proteção com esses dois pilares (sua capacidade rápida de adaptação e uma comunidade forte) que dificilmente (não acredito que seja impossível) outra linguagem sera capaz de superar. Por esse motivo a linguagem tornou-se um sucesso.

Obrigado e até a próxima
Fernando Anselmo

sábado, 21 de maio de 2016

Software Livre - Em substituição ao Software Pago

Contei a história do meu TCC na Pós em Gestão Empresarial Avançada no meu Blog de Leitura, escrever algo assim nunca é fácil e sempre sobram ideias que gostaria de ver publicadas mas que não cabem no contexto do TCC. Uma dessas ideias foi uma tirinha do blog "Vida de Programador" sobre o Software Livre:


E essa tirinha me fez realizar um levantamento de preços para dotar uma Empresa de Pequeno Porte com os aplicativos necessários ao mínimo de controle de sua gestão. Deve-se considerar que essas empresas são mais sensíveis em relação ao preço e uma redução do custo na obtenção das licenças pode ser considerado um fator estratégico valioso. O valor de investimento para produtos de informática é muito baixa em relação a outras áreas, entretanto soluções como CRM, ERP e Identidade Visual não deveriam ficar restritas as grandes empresas ou, vistas como soluções caras e que não compensam seu investimento.

Utilizando Software Proprietário

Segue uma relação do custo de aplicativos proprietários de uso comum (todas as consultas de preços dos aplicativos proprietários foram realizadas no dia 8 de Março de 2015 através dos sites oficiais).

Iniciamos com a licença do sistema operacional Windows 8.1 versão PRO é de R$ 610,00 (em muitos casos este custo vem embutido na compra do computador). O custo do pacote MS-Office 365 versão Personal é de R$ 169,00 por mês (consulta realizada na Microsoft Store), e em conjunto, obtemos um software de CRM, tal como o Microsoft Dynamics, é de R$ 212,20 por mês.

Um ERP, que é um pacote de Gestão que abrange aplicativos como Controle Financeiro, Controle de Estoque e Integração Bancária, o ContaAzul (um dos mais baratos do mercado) é de R$ 99,00 por mês (versão Pequeno). Para produção de cartazes e imagens que podem ser disponibilizadas em propaganda na Internet, a empresa deve contar com um editor gráfico de imagens tal como o Adobe Photoshop, no qual para empresas deve ser realizada uma consulta com o produtor, porém tomaremos como base o plano para Pessoa Física que adquire o produto como parte do plano Criative Cloud por R$ 44,00 por mês (no site oficial da Adobe).

O próximo da lista é um pacote para auxiliar na criação de documentos tais como revistas eletrônicas, panfletos e todo o material de marketing para a divulgação da empresa, o aplicativo inDesign da Adobe é encontrado no mesmo preço do Photoshop. Ou seja, chegamos a uma conta final de softwares no valor de R$ 399,20 mensais, excluindo o sistema operacional, que a empresa deve desembolsar para ter a sua disposição este conjunto para um único computador.

Mesmo resultado com Software Livre

Uma lista equivalente pode ser criada exclusivamente com Software Livre, de custo zero, incluindo a disponibilização do código-fonte para a realização de qualquer customização necessárias:

  • LibreOffice ou OpenOffice é uma suíte de escritório livre compatível com as principais suítes de escritório do mercado. Destinada tanto à utilização pessoal quanto profissional. Oferece uma completa solução de pacote de escritório, contém um editor de documentos, editor de planilhas eletrônicas, gerente de apresentação, programa para desenho, banco de dados simplificado para a criação de pequenos aplicativos ou mesmo mala direta de clientes e um editor de equações para trabalho matemático.
  • Zurmo CRM é uma aplicação fácil de personalizar e que pode ser adaptada para qualquer tipo de negócio. Criada com uma metodologia orientada a testes para a construção de todas as partes do aplicativo. Isto significa que é possível criar e manter um sistema de CRM com a garantia de que as futuras atualizações não vão causar inconvenientes na instalação atual.
  • OpenERP Brasil como solução de ERP que é uma iniciativa para traduzir e adaptar os módulos nativos do OpenERP11 para atender às leis e regulamentações exigidas no Brasil, tendo como maiores desafios as necessidades fiscais, financeiras e contábeis.
  • Gimp como solução de manipulação de imagens é apontado como um dos melhores substitutos ao Photoshop, este aplicativo reúne uma série de recursos ideais para aplicações comerciais e profissionais.
  • Scribus é um aplicativo para Desktop Publishing, ou seja, uma ferramenta de diagramação para editoração de panfletos, revistas e todo o material de distribuição visual da empresa.

O dinheiro investido nas licenças dos Softwares Proprietários seria melhor utilizado em investimentos nas outras áreas da empresa. Foi relacionado um simples conjunto de aplicativos que podem ser usados independente do ambiente operacional escolhido, seja este Windows, MacOS ou Linux. Desta forma a mudança para o Software Livre pode ser realizada de forma gradual sem a necessidade de mudanças radicais. Como destaca Serrano, Guerreiro & Caldeira (2004), “observa-se uma dificuldade de adaptação dos usuários de outras plataformas”.

Essa foi uma das partes do trabalho que não saíram na versão final, mas que gostaria de publicar como forma de iluminar os Empresários a entenderem a real vantagem na adoção do Software Livre. Não é questão de utopia, de amor ou qualquer dessas coisas apaixonantes dos livros, mas uma mera questão de custo. E que para muitas empresas pode significar sobrevivência.

Obrigado e até a próxima
Fernando Anselmo

sábado, 14 de maio de 2016

Projeto - Teste de Rorschach em Java

O Teste de Rorschach ficou famoso em duas ocasiões, primeira quando estreou o filme "Watchmen" e todos ficaram curiosos com o estranho personagem, a segunda quando foi aplicado a Suzane von Richthofen como forma de tentar entender sua personalidade.


É um teste simples e ao mesmo tempo muito complexo, consiste na apresentação de um cartão "manchado com tinta" (por esse motivo também é chamado de "Teste do Borrão de Tinta") e perguntar a pessoa o que ela está vendo. A partir das respostas (essa é a parte complexa) traçar a personalidade do entrevistado.

O que mais me diverte nesse teste, como programador, é ver que a imagem formada segue um padrão, a tinta é colocada em um lado do cartão e esse é dobrado ao ser aberto é que se forma o desenho. É como se metade do cartão fosse visto através de um espelho.

Então me perguntei se seria possível criar um programa para reproduzir os desenhos em Java? Um programa com o pacote Swing (parte gráfica da linguagem) usa o método paint(Graphics) para criar imagens (criei um RefCard que pode ser baixado aqui sobre esse assunto). Então é possível utilizá-lo para recriar o padrão desse desenho.

Primeiro detalhe é que a imagem deve possuir um tamanho fixo, pensando em uma imagem de 640 px por 335 px, temos que lembrar de alguns detalhes importantes:
  • Pensemos que o papel será dobrado para obter a imagem completa, sendo assim devemos pintar apenas metade da largura da área total (320 px) e reproduzir o mesmo desenho na outra metade em forma espelhada.
  • Deve ocorrer uma maior concentração de pontos da imagem do centro para as bordas.
  • Fica mais destacado o desenho se as cores são variações de preto e vermelho.
A lógica é simples, criar imagens ovais (bolinhas) com altura entre 5 px e 295 px (para não chegarmos ao topo), largura entre 1 px e 30 px e altura entre 1 px e 20 px. Para a posição a esquerda deve existir uma maior concentração de pontos no meio da figura, para isso vamos trabalhar com 5 áreas distintas, a primeira permitir que 150 bolinhas sejam geradas na área total, diminuir 50 px de margem esquerda e desenhar mais 150 bolinhas, e assim vai até chegar na última área de 50 px.

Para cada conjunto de 150 bolinha geradas serão 145 no padrão preto (isso é, com RGB variando entre [0,0,0] preto escuro e [109,109,109] cinza escuro) e outras 5 no padrão vermelho (isso é, com RGB variando entre [255,0,0] preto escuro e [255,109,109] cinza escuro).

O pulo do gato para formar a figura completa e duplicar cada uma das bolinhas geradas no seu correspondente a esquerda imitando um espelho. Imaginemos que uma bolinha foi gerada na posição a esquerda de 10 px (está bem perto do canto esquerdo) com largura de 10 px, ela deve parar no canto direito da imagem. Para isso vamos usar uma fórmula simples, [Tamanho Total] menos a [Posição a Esquerda] menos a [Largura].

Veja 4 imagens geradas pelo programa:





Adicionei dois detalhes ao programa que é um botão para mudar a imagem e outro para permitir salvá-la em arquivo formato PNG. Use esse programa para gerar suas imagens, mudar os padrões de geração aumentando ou diminuindo os valores e principalmente para melhorar seus conhecimentos na prática da linguagem Java.

Baixe o programa completo em: Rorschach

Obrigado e até a próxima
Fernando Anselmo

domingo, 8 de maio de 2016

Sistema Operacional - Adaptações com o Ubuntu 16.04

Muitos usuários esperavam ansiosamente por essa nova versão do Ubuntu, principalmente com a promessa da adição dos pacotes Snappy e a chegada da "Convergência", ambas novidades entraram no sistema de forma muito discreta e teremos que esperar pela versão 16.10 para uma mudança mais efetiva. Porém o que realmente mudou? Resolvi criar uma lista com as principais atualizações que tive que realizar na minha máquina como desenvolvedor de aplicativos.

1. Eclipse

Misteriosamente o Eclipse começou a apresentar um comportamento estranho, ao criar um projeto a tela fica travada, ao criar um pacote, uma classe tudo ficava travado. A solução para este problema envolve uma mudança ocorrida no uso da SWT utilizada para a construção visual do Eclipse. Para corrigir mudar a chamada do Eclipse (no seu arquivo .desktop):
Exec=env SWT_GTK3=0 eclipse

2. Adeus ao Braseiro e Emphaty

Esses programas cairam fora da distribuição original, o primeiro utilizado para gravar CD/DVD e segundo um comunicador de mensagens instantâneas. Acredito que com o uso e aumento da capacidade dos Pen Drivers e do "Armazenamento na Nuvem" poucas pessoas utilizavam o Braseiro e o Skype e Whats derrubou o Emphaty a muito tempo. Se utilizava esses programas basta reinstalar com os comandos (não é necessário importar nenhum repositório):
$ sudo apt install braseiro
$ sudo apt install empathy 

3. Falando de Repositórios

Os repositórios padrões do Ubuntu ganharam muitos programas que antes era necessário um repositório externo, GIT, Musescore, e muitos outros agora são instalados diretamente. Para gerenciar esses pacotes recomendo que instale o PPA Manager com os seguintes comandos (esse precisa de repositório):
$ sudo add-apt-repository ppa:webupd8team/y-ppa-manager
$ sudo apt update
$ sudo apt install y-ppa-manager
Só isso? Exatamente, só isso. A maior diferença que senti com o novo Ubuntu foi em termos de performance que ficou muito mais rápido em relação a versão anterior. Comecei o artigo falando de duas mudanças que os desenvolvedores aguardavam ansiosos e quero encerrar este com duas mudanças que afetou a comunidade.

1. Loja de Aplicativos

A loja agora se chama "Ubuntu Software", muito mais rápida que a antiga "Central de Programas", nela agora é possível atualizar um único determinado aplicativo, porém ainda está passando por acertos, por exemplo, até a data de lançamento não era possível obter aplicativos de terceiros "não confiáveis" isso já foi corrigido (mas gerou um determinado estresse).

2. gEdit

Considerado um substituto do "Bloco de Notas" do Windows, ganhou uma função mais nobre como editor simplificado de programas. Agora é possível inclusive abrir um "Mapa de Visão Geral" (uma visão na lateral direita com a estrutura do código), numerar as linhas ou adicionar (na seção de plugins) uma console para o Python. Essa nova função também não agradou a comunidade, mas acredito que tudo se uma mera questão de adaptação.

As pessoas não estão acostumadas em sair de suas "zonas de conforto", porém é facilmente percebido que é interesse da Canonical realizar mudanças muito mais profundas nas novas versões que virão. E agora é aguardar pelo Yakkety Yak (Ubuntu 16.10 a ser lançado em Outubro deste ano), só uma dica "Yakkety" é um Slang que significa algo como "Falar Demasiadamente"... Então essa versão pode ser traduzida para "O Iaque Falador".

Obrigado e até a próxima
Fernando Anselmo
 

sábado, 30 de abril de 2016

Mobile - Ubuntu Phone ou Android

Certa vez um aluno me perguntou: Qual a diferença entre o Ubuntu Phone e o Android, visto que os dois são uma distribuição Linux para celular? Acho que o detalhe mais precioso em ser professor está exatamente aí, nas questões que normalmente não pensamos e que devemos ter a resposta na ponta da língua (ou usar a velha desculpa, irei pesquisar e lhe darei a resposta).

Mas neste caso a resposta foi simples, simples como uma tese de doutorado, creio que a maior diferença seja que o Ubuntu Phone nasceu como um Sistema Operacional nativo para Linux a partir do Debian enquanto que o Android foi adaptado para ser um Linux. Calma e antes que os defensores do Android queiram minha cabeça explico.

Android nasceu para ser colocado em um Celular em uma época que as pessoas não conheciam a palavra "Convergência". Sua base de construção foi o Kernel do Linux com algumas modificações para se adaptar ao dispositivo móvel, simplificando o Android é uma máquina virtual Java (denominada Dalvik) sobre um Linux, possui suporte para o desenvolvimento de aplicações nesta linguagem através de um conjunto com bibliotecas e serviços. Basta ver qualquer imagem de sua estrutura:


Ubuntu Phone é bem diferente, primeiro que ele nasceu no Desktop, a primeira versão era chamada de Ubuntu Touch e servia para se utilizar com telas sensíveis ao toque, que começavam a aparecerem em muitos Notebooks. A segunda tentativa foi colocar esse sistema no telefone, porém era restrito ao Nexus, e ainda assim muitas vezes travava, consumia muita bateria, não aparecia a som e muitos outros problemas. A terceira foi em 2014 quando surgiu o BQ Aquaris E4.5 Ubuntu Edition, só vendido em 2015 e restrito a Europa.


Paro a história por aqui, que pode facilmente ser lida na Wikipedia, e retorno ao sistema em si. A ideia central da Canonical é criar um sistema que permita a "Convergência", e o que é isso? Pense em todo o hardware que existe a sua disposição: desktop, notebook, tablet, celular, relógio, televisão, carro, e por essa linha vamos. Agora vamos pensar no lado do desenvolvedor ou mesmo de um usuário. Um aplicativo que roda no Desktop provavelmente também roda no Notebook pelo simples motivo do sistema operacional de ambos serem o mesmo. Se o tablet possuir o mesmo sistema então é bem provável que o mesmo aplicativo também rode, se o celular possuir o mesmo sistema, e por aí vai em uma Convergência entre Hardware e Software. Ou seja, seria o melhor dos mundos para qualquer desenvolvedor ou usuário.

É essa a loucura que todos os Sistemas Operacionais perseguem atualmente e podemos dizer que o Ubuntu está na frente, o sistema em desktop está se adaptando para um novo modelo de pacotes (denominado Snappy) e já roda em celulares e tablets com razoável estabilidade e sucesso.

O Android permanece preso ao mundo móvel, não que isso seja uma falha ou um problema, é apenas uma característica de um sistema que nasceu para dispositivos móveis enquanto que o Ubuntu Phone foi definido como um sistema para realizar a Convergência.

Obrigado e até a próxima
Fernando Anselmo

sábado, 26 de março de 2016

Apresentação - Controle via Celular seus Slides Livremente

Criar apresentações profissionais não é fácil, conheço muitos bons palestrantes que criam fantásticas palestras só que ficam preso ao computador pois devem passar os slides. O que pretendo ensinar aqui é uma dica de ouro para qualquer pessoa que deseje impressionar na hora de apresentar suas palestras.

Porém tudo o que for mostrado aqui só serve para o Mundo Livre, isto é, o software de apresentação dos slides deve ser o Impress do LibreOffice (não serve PowerPoint) o celular deve ser Android (não serve iPhone) e a aplicação é obtida gratuitamente.


No Impress é necessário realizar 2 configurações:

  1. No menu superior acessar a opção "Tools | Options", no lado esquerdo acessar "LibreOffice Impress" e "General". Marcar as opções "Enable remote control" e "Enable Presenter Console".
  2. No menu superior acessar a opção "Tools | Options", no lado esquerdo acessar "LibreOffice" e "Advanced". Marcar a opção "Enable experimental features".

Sair e entrar novamente no Impress para as alterações fazerem efeito.

Agora vamos colocar o aplicativo no celular. Acessar a Play Store e instalar o aplicativo Libre Office Impress Remote. Existem duas formas de realizar a conexão: Via Bluetooth (ideal para quando não existe rede WiFi) ou via WiFi (o celular e o computador devem estar na mesma rede).


Acessar o aplicativo através do celular e selecionar a aba "WIFI", automaticamente o computador será reconhecido e basta clicar nele. A primeira vez será informado um PIN de conexão, no Impress acessar no menu superior a opção "Slide Show | Impress Remote", o celular que está tentando realizar a conexão será mostrado, clicar nele e informar o número do PIN de conexão.

Tudo pronto, no celular aparecerá os slides, as anotações e inclusive se existir um Relógio (Android Wear) conectado ao celular é possível passar os slides através deste. O programa permite saltar slides, utilizar ponteiro laser, pausar ou parar sua apresentação, ou seja, agora está com toda a liberdade para andar na sala e ter o controle total de seus slides.

Obrigado e até a próxima
Fernando Anselmo

domingo, 13 de março de 2016

Web - Retorno a Simplicidade com JSP e MongoDB

A anos programo com Java, principalmente com JSP, e o único detalhe que percebo é que as pessoas deixaram de ser simples. Por exemplo, muitos reclamam que no aviso de emprego é exigida muita coisa do profissional solicitado. Porém o único culpado disso é o próprio profissional (ou talvez o Arquiteto). Me pergunto se realmente essa complexidade toda é realmente necessária.
Atualmente para criar qualquer sistema Web é necessário conhecimento (vou citar apenas Java para não me estender muito) de: Linguagem Java, HTML 5, CSS 3, Bootstrap, JQuery, JSON, JSF ou Struts 2 ou Spring ou os três, Symphony, Hibernate, JDBC, vários Design Patterns Java e J2EE, JBoss ou outro Application Server e Banco de Dados. Porém o que o profissional não entende é que do lado do cliente muito pouca coisa mudou. Então do ponto de vista dele "porque tenho que pagar mais para receber a mesma coisa"? ou seja, o salário de um programador com essa gama de conhecimento não mudou para o tempo que só precisava de JSP, HTML, TomCat e Banco.

Toda essa mudança foi criada buscando facilitar a "modificação" do sistema, porém o que ninguém percebeu é que estávamos complicando muito o desenvolvimento, acabamos por tornar os sistemas muito mais difíceis de gerar e dar manutenção com suas 6 ou 7 camadas. Quando acontece um erro o profissional não tem a menor noção nem por onde começar.

Resolvi criar um pequeno sistema para incluir dados em um banco NoSQL e percebi que o mínimo necessário de requisitos seria:
  • Conhecimento de Java Básico.
  • Conhecimento de HTML 5 (CSS 3 e Bootstrap apenas se desejar melhorar o visual).
  • Conhecimento de JSP e JSTL.
  • Uso de 2 padrões de projeto J2EE (TO e DAO).
  • Uso do TomCat (qual a finalidade de um Application Server se não desejo usar EJB?).
  • Conhecimento das funções do Conector do Banco de Dados.

Preparação do Ambiente

Referência: Entenda como funciona a conexão MongoDB e Java através dessa apostila.
Básico: Java instalado, MongoDB instalado, Eclipse instalado e Servidor Web TomCat instalado.
Básico 2: Configure o TomCat no Eclipse

Abra o Eclipse e crie um projeto Dynamic Web Project e na pasta WEB-INF\lib insira as seguintes bibliotecas:
Vamos começar pela configuração do site, na pasta WEB-INF crie um arquivo chamado "web.xml" e insira a seguinte codificação:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>Escola</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>
Este arquivo contém as informações básicas para o Servidor Web na hora de tratar as páginas, somente foram colocadas duas informações: 1. Nome do Sistema e 2. Quem será a página inicial.

Camada Visual

Todas as páginas JSP devem ser criadas abaixo da pasta WebContent. Como não desejo popular de códigos a index.jsp (página inicial) colocaremos apenas a seguinte codificação para chamar a página de cadastro dos alunos:
<h1>Escola de Alunos</h1>
<ul>
 <li><a href="IEaluno.jsp">Cadastro de Alunos</a>
 <li><a href="IEprofessor.jsp">Cadastro de Professores</a>
</ul> 
Apenas uma chamada HTML, note que já deixei a chamada ao cadastro de Professores, este será seu exercício como forma de implementá-lo para verificar se realmente aprendeu algo.  O resultado de sua execução será este:

A página de cadastro de alunos (IEaluno.jsp) está dividida em duas partes conforme o código a seguir:
<!DOCTYPE html>
<html>

<%@page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<head>
<%
  response.setHeader("Cache-Control", "no-cache");
  response.setHeader("Cache-Control", "no-store");
  response.setHeader("Pragma", "no-cache");
  response.setDateHeader("Expires", 0);
%>
</head>

<body>
  <form action="ICaluno.jsp">
    Nome: <input name="nome"><br /> 
    Nota: <input name="nota"><br /><br />
    <input type="submit" />
  </form>
  <h2>Alunos</h2>
  <jsp:useBean id="alunoDAO" scope="page" class="dao.AlunoDAO" />
  <table>
    <tr>
      <th>Nome</th>
      <th>Nota</th>
    </tr>
    <c:forEach var="al" items="${alunoDAO.obter}">
      <tr>
        <td>${al.nome}</td>
        <td>${al.nota}</td>
      </tr>
    </c:forEach>
  </table>
</body>
</html>
A primeira parte é o formulário que chamará a próxima página para enviar os dados e proceder a inclusão e a segunda parte é uma listagem de todos os alunos que estão no banco.  O resultado de sua execução será este:

A próxima página (ICaluno.jsp) envia as informações ao TO e a DAO e realiza o procedimento de inclusão.
<!DOCTYPE html>
<html>

<%@page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<body>
  <jsp:useBean id="aluno" scope="page" class="to.Aluno" />
  <jsp:setProperty name="aluno" property="nome" value="${param.nome}" />
  <jsp:setProperty name="aluno" property="nota" value="${param.nota}" />

  <jsp:useBean id="alunoDAO" scope="page" class="dao.AlunoDAO" />
  <jsp:setProperty name="alunoDAO" property="aluno" value="${aluno}" />
  <SCRIPT>
    alert("" + <jsp:getProperty name="alunoDAO" property="inserir" />
        + " aluno inserido com sucesso.");
    history.go(-1)
  </SCRIPT>
</body>
Com os dados do formulário preenchemos um objeto TO e esse objeto é enviado para a DAO proceder a inclusão. O resultado de sua execução será este:

Camada de Negócios

Todos os arquivos .java devem ser criados abaixo da pasta src (que se encontra dentro de Java Resources), crie nesta 2 pacotes dao e to. O padrão TO (Transfer Object) é muito simples, é uma classe que representa um registro do arquivo, já o DAO (Data Access Object) é o que faz toda a implementação e conversação com o Banco de Dados. Normalmente os arquitetos complicam a vida adicionando mais 4 padrões: BO (Bussiness Object), VO (Value Object), DTO (Data Transfer Object) e POJO (Plain Old Java Object). Não pretendo discutir o uso ou o valor de cada um deles deixarei isso para os arquitetos, pois como disse aqui busco a simplicidade.

No pacote TO crie a classe Aluno.java com a seguinte codificação:
package to;

public class Aluno {

  private String nome;
  private int nota;
  
  public Aluno() {
  }
  public Aluno(String nome, int nota) {
    setNome(nome);
    setNota(nota);
  }
  
  public String getNome() {
    return nome;
  }
  public void setNome(String nome) {
    this.nome = nome;
  }
  public int getNota() {
    return nota;
  }
  public void setNota(int nota) {
    this.nota = nota;
  }
}
Observe que não existe nada demais aqui, uma classe Java normal com métodos GET/SET. Mantive 2 construtores apenas para respeitar o padrão Bean. Agora vamos para a camada DAO, Crie uma ENUM (TipoColecao) com a seguinte codificação:
package dao;

public enum TipoColecao {
  ALUNO, PROFESSOR;
}
Entenderemos a existência dessa classe na próxima classe criada que será herdada por qualquer outra classe deste pacote e por esse motivo ela é abstrata:
package dao;

import com.mongodb.MongoClient;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoCollection;
import org.bson.Document;

public abstract class DAO {

  protected MongoCollection col;
  private MongoDatabase db;
  private MongoClient mongo;
  
  protected boolean conectar() {
    try {
      mongo = new MongoClient("localhost", 27017);
      db = mongo.getDatabase("escola");
    } catch (Exception e) {
      return false;
    }
    return true;
  }
  
  protected void setColecao(TipoColecao tpCol) {
    switch (tpCol) {
    case ALUNO:
      col = db.getCollection("aluno");
      break;
    case PROFESSOR:
      col = db.getCollection("professor");
      break;
    }
  }
  
  protected boolean desconectar() {
    try {
      mongo.close();
    } catch (Exception e) {
      return false;
    }
    return true;
  }
}
Esta classe contempla os três métodos que toda DAO deve realizar: conexão com o banco, ajuste da tabela (que no MongoDB é chamada de Coleção) correta através do tipo definido na Enum criada e desconexão com o banco. A classe de implementação para Aluno (AlunoDAO.java) possui a seguinte codificação:
package dao;

import java.util.ArrayList;
import java.util.List;
import com.mongodb.client.MongoCursor;
import org.bson.Document;

import to.Aluno;

public class AlunoDAO extends DAO {

  private Aluno aluno;

  public Aluno getAluno() {
    return aluno;
  }

  public void setAluno(Aluno aluno) {
    this.aluno = aluno;
  }

  public int getInserir() {
    if (conectar()) {
      setColecao(TipoColecao.ALUNO);
      Document doc = new Document("nome", aluno.getNome())
        .append("nota", aluno.getNota());
      col.insertOne(doc);
      desconectar();
      return 1;      
    }
    return 0;
  }

  public List getObter() {
    List lista = new ArrayList();
    if (conectar()) {
      setColecao(TipoColecao.ALUNO);
      MongoCursor cursor = col.find().iterator();
      Document doc;
      while (cursor.hasNext()) {
        doc = cursor.next();
        Aluno al = new Aluno(doc.getString("nome"), doc.getInteger("nota").intValue());
        lista.add(al);
      }
      cursor.close();
      desconectar();  
    }
    return lista;
  }
}
Basicamente, é criado um objeto da TO referente a Aluno com a implementação do seus métodos padrão GET/SET e mais dois métodos (observe que ambos são do padrão GET - isso é obrigatório para a chamada padrão da JSP) o primeiro realiza a inclusão do registro no banco e o segundo a busca de uma lista de objetos TO contendo os alunos já cadastrados.

Tudo pronto, agora basta iniciar o TomCat e obter o resultado. Como teste realize a parte dedicada a Professor e note como é fácil trabalhar com JSP e o MongoDB em uma Aplicação Web multi camadas sem ter que complicar muito.

Obrigado e até a próxima
Fernando Anselmo

domingo, 6 de março de 2016

Arduino - Olá Mundo

A Internet das Coisas, ou IoT como é conhecida, surgiu graças ao baixo preço das placas programadas. Atualmente com menos de R$ 50,00 é possível comprar uma (algo impensável a alguns anos atrás) e o preço vem caindo. Duas placas são as mais famosas Raspberry (que está mais para um computador) e Arduino.


O Arduino é uma placa microcontroladora baseada na ATmega328 e por seu baixo preço é ideal para realizar experimentos de eletrônica e ótima para os iniciantes. O que pretendo mostrar em alguns artigos é como integrar projetos IoT, porém devemos entender algumas coisas básicas antes, ou seja, preciso realizar um Olá Mundo.

A ligação Arduino/Computador é feita através de um cabo USB, mas antes é necessário instalar um aplicativo feito em Java para criar e enviar os programas para a placa. No Ubuntu isso é feito da seguinte forma:

1. Devemos adicionar o repositório
$ sudo apt-add-repository ppa:ubuntu-desktop/ubuntu-make 
$ sudo apt-get update
2. Instalar o programa
$ sudo apt-get install ubuntu-make
$ sudo umake ide arduino 
Agora já podemos criar um projeto para testar. O primeiro passo é montar o circuito que vamos trabalhar. Os materiais necessários são:
  • Arduino Uno R3
  • Placa protoboard
  • Dois fios de cobre
  • Resistor de 220 amp. (+/- 5% - Vermelho, Vermelho, Marrom)
  • LED (633 nm)
Para a montagem basta seguir o seguinte esquema:


Dica, a perna mais curta do Led é na mesma coluna do resistor que é ligado na D13 (Digital 13) e a mais longa na linha da conexão GND do Arduino. O segundo passo é criar o programa. Acesse o aplicativo Arduino no dash e digite a seguinte codificação:
/* 
Testar LED
*/
void setup(){
  pinMode(13, OUTPUT); // Configurar a porta D13.
}
void loop(){
  digitalWrite(13, HIGH); // Ligar a saída D13
  delay(1000);            // Esperar um segundo
  digitalWrite(13, LOW);  // Desligar a saída D13
  delay(1000);            // Esperar um segundo
}
O método void setup() só será chamado uma única vez e será utilizado para configurar a porta de saída. O método void loop() é executado indefinidamente, uma porta GND de alimentação está ligada ao resistor que por sua vez ligada ao LED e este a saída D13. Imagine isso como um interruptor de luz, uma vez desligado a energia deixa de fluir.

O último passo é enviar o programa para a placa. Conecte-a ao computador através do cabo USB, agora acesse o programa novamente e no menu principal selecione "Tools | Board" verifique se a placa correta está marcada. Ainda no menu principal selecione "Tools | Serial Port" verifique se a porta correta está marcada (no meu caso foi a /dev/ttyACM0).

Agora é só clicar no segundo ícone (Update) e o programa será transferido para a placa (dica: os leds da placa TX/RX acenderão e apagarão). Uma vez que o programa entrar em ação você verá o LED acender, esperar 1 segundo, apagar, esperar 1 segundo e repetir isso indefinidamente.

Basicamente é assim que sempre trabalhamos com o Arduino com a criação de projetos físicos e lógicos. E essa é a ideia maravilhosa desse novo mundo IoT.

Obrigado e até a próxima
Fernando Anselmo

domingo, 21 de fevereiro de 2016

Desktop Publishing - Seu Currículo com LaTeX e xMind

Concordo que criar um currículo não é uma tarefa das mais fáceis. Primeiro que isso não se aprende na escola, segundo que existem milhares de modelos disponíveis, terceiro que existem milhares de regras de conduta para um currículo e quarto que ele deve refletir muito bem o profissional que você é e qual imagem deseja passar. Anote a primeira regra: Um currículo é a sua foto. E por esse motivo, um currículo não deve ter foto (a menos que essa seja solicitada).


Não pretendo falar aqui sobre dar dicas como criar seu currículo (ainda mais porque já fiz isso nessa postagem), o que pretendo aqui é lhe dar um Modelo Pronto para que possa criar seu currículo sem erros ou perda de tempo. Esteja consciente que para isso vamos utilizar duas ferramentas: o LaTeX e o xMind.

Porque não o MS-Office ou OpenOffice? Porque a função principal do LaTeX é a geração de documentos profissionais, e quer algo mais profissional que seu currículo? Esse currículo vale para 90% dos profissionais de quaisquer áreas. Esses 10% que sobra é que este currículo não serve se deseja um cargo que envolva Criatividade, o objetivo aqui é ser muito "sóbrio" e sem muita "criação". Entenda essa diferença com esse modelo de uma Profissional em Marketing.


Este é um currículo tremendamente criativo, não poderia copiá-lo? Não, ser criativo no currículo é ser único então se esta é sua área crie seu currículo e não copie. Outro detalhe, não quero que pense que ser "sóbrio" é ser sem graça, existem toques de criatividade que são permitidos, usaremos o programa xMind para nos auxiliar na criação de alguns Mapas Mentais.

Vamos a primeira parte, baixe os seguintes arquivos necessários para nossa montagem:
Coloquei meu currículo aqui apenas para servir de exemplo e possa ver como ficará o resultado final.

Segunda parte é com o programa xMind é usado para a criação de dois Mapas Mentais, o primeiro é o tradicional no qual colocará todas as tecnologias que conhece por área não parta de um modelo pronto escolha o Mapa que melhor reflete suas características e a disposição entre elas. O segundo é uma linha do tempo, no qual usará a template disponível para criar um resumo de seu histórico profissional durante os anos. Gere duas imagens (uma para cada Mapa) e guarde-as.

A terceira parte é com o LaTeX, para isso é necessário colocar na mesma pasta os dois arquivos disponibilizados e as duas imagens geradas no passo anterior. Agora vamos começar realmente a construir nosso currículo. Pense que um currículo deve responder 3 perguntas:

  1. Quem sou?
  2. O que conheço?
  3. O que fiz com o que conheço?

Para colocar realmente a mão na massa, abra o Modelo do Currículo no seu editor de LaTeX e procure por:
\thispagestyle{empty} % Esta página não possui cabeçalho
\name{ZEZINHO DA ZEZA\\[10pt]}
\address{{\bf Cidade} -- Bairro \\
  Tel. (61) 9999.9999 \\  Tel.Contato (61) 9999.9999}      
Troque para seu nome e seus dados. Esqueça esse negócio de colocar Nº RG ou CPF, Carteira Profissional, Carteira de Habilitação ou outra informação irrelevante, tipo Casado, Pai/Mãe de 2 lindos filhos, Heterossexual, Não Homofóbico, Evangélico... Confesso que já vi as coisas mais bizarras.

Em seu Resumo Profissional fale "quem é você?" a pior coisa que pode fazer aqui é errar o português então MUITA ATENÇÃO neste detalhe. Segunda pior coisa é falar coisa que não deve (quer ser engraçado arrume um emprego de comediante) ou algo que não condiz com seu cargo. Terceira pior coisa é fazer o leitor se perder por divagar demais.

As próximas seções são relativas a seus conhecimentos, em Habilidades, deixei formatado no modelo a forma como ficaria se fosse apenas texto, porém se criou um Mapa Mental com as tecnologias que conhece é hora de usá-lo. Troque esta seção para:
\section{HABILIDADES}
\vspace{120pt}
\includegraphics[width=0.4\textwidth,natwidth=550,natheight=300]{tecnologias.jpg}
Esses 120pt de espaço vertical dependerá de muitos fatores, entre eles o tamanho do seu mapa, então ajuste até se encaixar corretamente.

Em Certificações e Títulos, Educação e Idiomas não é para colocar TODOS seus diplomas mas os mais importantes em cada área. Esqueça aquele curso de Panquecas que fez no final de semana ou a participação nas aulas de Yoga, básico em algum idioma é proibido (por exemplo, sei o básico de Esperanto mas não me arrisco a sequer tentar falar isso) e em Educação coloque Ensino Fundamental apenas se não possui o Ensino Médio, e se possui Graduação comece a partir dai. Coisas óbvias é que ninguém quer saber se foi Campeão no Torneio de Palitinhos da Escola ou se conseguiu capturar todos os Pokemóns no jogo... já disse, vi as coisas mais bizarras.

As próximas duas seções são as mais importantes pois provam todas as anteriores. Ou seja, tudo tem que casar. O principal detalhe de um currículo é sua COERÊNCIA, não adianta colocar que fez um curso de PHP se a vida toda trabalhou com Java. Por exemplo, fiz um curso de 4 meses de Desenho Web, isso mesmo, muito tempo e dinheiro investido, porém abra meu currículo e verá que não tem absolutamente nada indicando isso. Por que? Não é meu foco. Fiz este curso pois desejava me aperfeiçoar na correta criação visual de um sistema e não porque almejo ter o cargo de Desenhista Web em uma empresa.

Acima do Histórico Profissional usaremos a segunda imagem respectiva a Linha do Tempo. Para tanto adicione o seguinte comando:
\section{HISTÓRICO PROFISSIONAL} % Da mais nova para mais antiga
\vspace{8pt}
\includegraphics[width=0.4\textwidth,natwidth=550,natheight=300]{experiencia.jpg}

% Mais Recente
A ideia é permitir o leitor uma visão rápida sobre da vida profissional. Outro detalhe aqui tenho mais de 25 anos de experiência, porém restringi meu currículo a 2004 para frente. Por que? A tecnologia mudou e não adianta ter um currículo com milhares de páginas com coisas antigas. No Linkedin mantenho toda minha carreira profissional e para a existência da última seção Maiores Informações e onde o leitor pode achar mais detalhes sobre seu trabalho. Nada de perder o foco, mantenho dois blogs de Música e de Literatura e ambos não estão no meu currículo.

Se profissional é ter foco e coerência naquilo que se deseja para sua carreira. Vejo bons profissionais não conseguirem uma simples entrevista por terem um péssimo currículo: mal escrito, mal formatado e mal feito. Use esse modelo e não perca mais nenhuma chance.

Obrigado e até a próxima
Fernando Anselmo

domingo, 14 de fevereiro de 2016

REST - YO com MEAN

Acredito que nesse último ano você não tenha vivido em uma caverna e já deve ter ouvido falar de MEAN, isso é uma abreviatura para MongoDB + ExpressJS + AngularJS + NodeJS. Todas aquelas tecnologias que temos discutido aqui neste blog e que estão concentradas na página Novas Tecnologias. A mudança ocorrida no último ano foi usar o gerador Yeoman para criar a estrutura e os artefatos necessários para usar tudo isso sem precisar gastar horas (preciosas).

Para integrar todas essas tecnologias precisamos modificar o gerado que utilizamos até o momento, nos dois artigos que postei sobre o Yo (YO facilitando a vida Angular e Criação de Rotas com o YO), que podem ser utilizados como base para nosso projeto.

Abra uma janela de terminal e instale o gerador através do NPM com o seguinte comando:
sudo npm -g install generator-angular-fullstack
Esse gerador possui, basicamente, os mesmos comandos do generator-angular visto anteriormente, recomendo que acesse sua página oficial. Na estrutura do projeto gerado existe um diferencial que serão criadas duas camadas do projeto divididas na pasta client e na server. Do que já vimos, está tudo concentrado na pasta client, então a novidade fica a cargo dessa nova pasta server.

Para gerar o projeto, vamos seguir os mesmos passos já vistos para o outro gerador. No terminal digite os seguintes comandos:
mkdir coffeshop2
cd coffeshop2
yo angular-fullstack:app coffeshop2
Agora basta seguir o passo a passo do gerador e ir responder suas perguntas escolhendo as tecnologias com que se deseja trabalhar, observe que podemos configurar muitas coisas como o banco que pode ser o MongoDB ou SQL (MySQL ou MariaDB). Segue aqui meu roteiro, para que possamos deixar as tecnologias de modo similar:

# Client

? What would you like to write scripts with? Babel
? What would you like to write markup with? HTML
? What would you like to write stylesheets with? CSS
? What Angular router would you like to use? ngRoute
? Would you like to include Bootstrap? Yes
? Would you like to include UI Bootstrap? Yes

# Server

? What would you like to use for data modeling? Mongoose (MongoDB)
? Would you scaffold out an authentication boilerplate? Yes
? Would you like to include additional oAuth strategies? No
? Would you like to use socket.io? Yes

# Project

? Would you like to use Gulp or Grunt? Grunt
? What would you like to write tests with? Jasmine

Ao término da geração, inicie o servidor do banco MongoDB, em seguida digite o comando para executar o projeto:
grunt serve
E a seguinte janela será mostrada:
Já disse uma vez que odeio ser repetitivo, toda a estrutura contida em client é a mesma vista nos artigos anteriores. Deixarei aqui um pequeno exercício, modifique-a deixando este projeto no exato ponto em que paramos. Porém como não desejo causar qualquer confusão, façamos algo mais simples: gere o projeto conforme indicado, baixe o projeto do link abaixo e sobreponha os arquivos originais.


Já procedi todas as mudanças necessárias para a primeira página e a tradução dos arquivos. É possível assinar a lista de usuários bem como proceder a administração do sistema (email: admin@example.com; senha: admin). O resultado final será este:
Atenção: Este projeto não rodará sozinho pois foram retiradas as pastas node_modules e client/bower_components. Deste modo é necessário gerar o projeto, sobrepor os arquivos e iniciar o banco MongoDB. Em breve vamos dar prosseguimento e criar a página para cadastrar os locais para se achar um bom café.

Obrigado e até a próxima
Fernando Anselmo


terça-feira, 9 de fevereiro de 2016

Desktop Publishing - Cartão de Páscoa com o LaTeX

Se na sua vida nunca fez um trabalho de faculdade então provavelmente para você a palavra LaTeX deve está associada com borracha (ou talvez fez mas usou o Word, OpenOffice ou outro). Pois bem, LaTeX é um sistema de criação de documentos de alta qualidade tipográfica, por esse mesmo motivo é utilizado em faculdades para realização de trabalhos ligados a Pós graduação, Mestrado e Doutorado.


É também utilizado para produção de artigos técnicos ou científicos, porém é possível utilizá-lo para qualquer tipo de publicação. É exatamente isso que pretendo mostrar aqui. Devemos entender que LaTeX não é um editor, é apenas e definição das macros para o programa de diagramação de textos (assim como HTML5 ou XML).

No Ubuntu, escolhi como editor o Kile por ser muito visual, possuir auto complete do código e bem fácil de aprender. Não se preocupe pois existe versão para todos os ambientes (e isso inclui Windows, Mac e BSD).

Para instalar no Ubuntu, execute o seguinte comando em uma janela de terminal:
sudo apt-get install kile
Pronto como a Páscoa está chegando vamos criar um Cartão de Páscoa. Chame o kile e crie um novo projeto. Para nosso exemplo, use uma template vazia. Na página em branco digite a seguinte codificação:
\documentclass[a4paper,10pt]{article}

\usepackage[utf8]{inputenc}
\usepackage{gcard} % chama o pacote para criar o cartão
\usepackage{calligra} % adiciona a fonte calligra
\usepackage[T1]{fontenc} 
\usepackage{graphicx} % adiciona o pacote para a imagem
\usepackage{color} % adiciona a cor para a fonte

\begin{document}
  \begin{frontcover}
    \begin{center}
      \includegraphics[width=0.8\textwidth,natwidth=610,natheight=642]{pascoa.jpg}
      \newline
      \newline
      {\LARGE \color{red} % muda a cor da fonte
      {\calligra Que eu possa continuar a ter uma amizade tão especial quanto a sua...}}
    \end{center}
  \end{frontcover}

  \begin{insideleft}
  \end{insideleft}

  \begin{insideright}
    \section*{Que a alegria}
    da Páscoa invada o seu coração e o daqueles a quem ama, 
    irradiando luz para iluminar e fazer brilhar o mundo em que vivemos, 
    enchendo-o de AMOR, SAÚDE e PAZ. \\
    {\LARGE \color{red}\\ % muda a cor da fonte
    {\calligra Feliz Páscoa!}}
  \end{insideright}
\end{document}
Calma que não existe nada do outro mundo aqui, apenas a sintaxe pode ser desconhecida, mas aos poucos iremos compreender como é simples. O primeiro comando define o tipo de documento que estamos escrevendo. Os comandos usepackage informam ao LaTex quais são os pacotes necessários. Tudo inicia realmente no begin{document} no qual são criadas três partes: frontcover, insideleft e insideright. Na primeira é exibida uma imagem e um texto em fonte Calligra. A segunda está vazia. A terceira uma mensagem.

Agora precisamos de mais os seguintes passos. Salve este arquivo com a extensão .tex, na barra de botões clique no botão LaTeX para gerar o arquivo .dvi e no botão DVItoPDF para gerar o arquivo .pdf. E o resultado, ao abrir o arquivo PDF, será este:


E agora basta imprimir em um papel de qualidade e entregá-lo aos seus amigos e familiares. Uma observação é necessária, na mesma pasta que salvar seu arquivo insira uma imagem para seu cartão (que no código usamos pascoa.jpg) e o arquivo (extensão mf) contendo a fonte Calligra (pode ser baixado aqui).

O LaTex pode ser utilizado para dar uma qualidade profissional tanto para seus trabalhos escolares como para outras atividades de diagramação. Então aproveite e conheça o que esse poderoso sistema pode fazer por você.

Obrigado e até a próxima
Fernando Anselmo

domingo, 31 de janeiro de 2016

REST - Criação de Rotas com o YO

Vamos dar continuidade ao nosso projeto com o Yo (ou Yeoman se prefere) com o Angular.js iniciado na postagem anterior. Quando nosso projeto foi criado com o Yo a estrutura criada foi utilizando as rotas do Angular (arquivo angular-route.js). Existem programadores que preferem trabalhar sem seu uso para facilitar, porém isso atrapalha muito a estrutura do projeto, exigindo um uso excessivo da tag ng-controller e a perda da visão do projeto.


Uma estrutura de rotas facilita a navegação entre as visões, sabemos exatamente qual controlador pertence a qual visão e para onde vai seu link de acesso. Lembre-se que segundo a metodologia REST esse controle é fortemente necessário.

Antes de criarmos uma nova rota, existe um detalhe que me incomoda no Bootstrap: seus ícones. Me desculpe quem gosta, pessoalmente acho-os feios e prefiro utilizar os do Font Awesome.

Para adicionar este pacote ao nosso projeto, acesse o site, baixe o pacote, descompacte e nele encontramos duas pastas essenciais. Na pasta \css copie o arquivo font-awesome.css e coloque na pasta \app\styles do projeto. Copie a pasta \fonts (inteira) para a pasta \app (resultando em \app\fonts). Edite o arquivo index.html na pasta \app e na tag head adicione a seguinte linha.
<link href="styles/font-awesome.css" rel="stylesheet"></link>
Pronto, agora já podemos utilizar esta biblioteca com 605 ícones a nossa disposição e de fácil pesquisa no site.

Agora podemos retornar as rotas. Vamos implementar uma página que mostrará os locais aonde podemos encontrar um bom Café. Não pretendo ainda usar o banco de dados, então os dados ficarão armazenados em memória.

Não pense no Yo apenas como um gerador da estrutura de projetos, uma de suas melhores vantagens é a geração de artefatos para o projeto. Obviamente isto dependerá do gerador utilizado. No caso do gerador do Angular temos a nossa disposição a geração de vários artefatos que incluem: constantes, controladores, decoradores, diretivas, padrão factory, filtros, provedores, rotas, serviços, valores, visões e alguns outros que veremos no decorrer dessas postagens.

Vamos iniciar pelo gerador de rota (route). Na janela de comandos, interrompa o servidor Grunt e digite o seguinte comando:
 yo angular:route contato
Serão realizadas as seguintes ações:
  • Criação do controlador contato.js em \app\scripts\controllers
  • Criação da classe de teste contato.js em \test\spec\controllers
  • Criação da visao contato.html em \app\views
  • Modificação do arquivo app.js com a adição da nova rota 
Ou seja, está tudo pronto para trabalharmos o código das páginas em si, sem termos de nos preocupar com a estruturação do projeto devido a criação de um novo artefato e sua implementação na rota. Reinicie o servidor Grunt e vamos realizar a chamada desta rota no menu principal do sistema. Edite novamente o arquivo index.html na pasta \app e modifique o link descrito em Contact para o seguinte:
<li><a ng-href="#/contato">Contatos</a></li>
Agora temos acesso a página criada a partir do menu.

Modifique o controlador de contato para a seguinte codificação:
'use strict';

/**
 * @ngdoc function
 * @name coffeshopApp.controller:ContatoCtrl
 * @description
 * # ContatoCtrl
 * Controller of the coffeshopApp
 */
angular.module('coffeshopApp')
  .controller('ContatoCtrl', function ($scope) {
    $scope.contatos = [
      {nome: 'Belini Pães e Gastronomia', endereco: 'SCLS 113, Bloco D, Loja 35', telefone: '(61) 3345-0777'},
      {nome: 'Casa de Biscoitos Mineiros', endereco: 'SCLS, Bloco A -21', telefone: '(61) 3242-2922'},
      {nome: 'Café Daniel Briand', endereco: 'SCLN 104 Loja 26', telefone: '(61) 3326-1135'}
    ];

     $scope.adicionarContato = function () {
      $scope.contatos.push({nome: $scope.contato.nome,
             endereco: $scope.contato.endereco,
             telefone: $scope.contato.telefone});
      $scope.contato.nome = $scope.contato.endereco = $scope.contato.telefone = '';
     };
   });
Criamos o JSon que responderá a página com alguns contatos e criamos um método para adicionar um novo contato. Para melhor explicar vou dividir a codificação da visão em 3 partes.

Primeira Parte - Superior da Tela
<div class="container">
  <div class="row">
    <div class="col-md-12 col-xs-12">
      <div class="panel panel-info">
        <div class="panel-heading">
          <div class="panel-title">
            <div class="row">
              <div class="col-md-12">
                <h5><span class="fa fa-coffee"></span> Locais para Tomar um Café</h5>
              </div>
            </div>
          </div>
        </div>
Acredito que o único problema aqui seja essa complexidade de tags div. Uma simples regra para o Projeto Web Responsivo é quanto ao uso das tags table, tr e td que são trocadas por estrutura de divisões. O Bootstrap provê classes muito bem definidas para que possamos realizar essa troca, e é basicamente isso que estamos estruturando.
Segunda Parte - Dados da Tela
        <div class="panel-body">
          <div class="row" ng-repeat="contato in contatos">
            <div class="col-md-4 col-xs-12">
              <strong>{{contato.nome}}</strong>

              <small>
                <span class="fa fa-home" style="opacity:0.5"></span> {{contato.endereco}}
                <br />
                <span class="fa fa-phone" style="opacity:0.5"></span> {{contato.telefone}}
              </small>
            </div>
          </div>
        </div>
Mostramos os dados que estão armazenados no JSon com a tag do Angular ng-repeat.

Terceira Parte - Formulário da Tela
        <div class="panel-footer">
          <form style="padding: 0 10px 10px 5px" name="frmContato">
            <div class="input-group">
              <span class="input-group-addon"><i class="fa fa-male fa-fw"></i></span>
              <input class="form-control" type="text" ng-model="contato.nome" placeholder="Nome" />
            </div>
            <div class="input-group" style="padding-top:5px;">
              <span class="input-group-addon"><i class="fa fa-home fa-fw"></i></span>
              <input class="form-control col-xs-12" type="text" ng-model="contato.endereco" placeholder="Endereço" />
            </div>
            <div class="input-group col-lg-6" style="padding-top:5px;">
              <span class="input-group-addon"><i class="fa fa-phone fa-fw"></i></span>
              <input class="form-control" type="text" ng-model="contato.telefone" placeholder="Telefone" />
            </div>
            <div style="text-align:right;padding-top:10px;">
              <button class="btn btn-success" ng-click="adicionarContato()">Adicionar Contato</button>
            </div>
          </form>
        </div>
      </div>
    </div>
  </div>
</div>
Na parte final criamos um formulário para adicionarmos um novo contato, através da chamada a função adicionarContato(). Como as tags input possuem o parâmetro ng-model o Angular poderá reconhecer os campos digitados e passá-los através do $scope.

E nossa tela está conforme a seguinte figura:


E já podemos visualizar e adicionar alguns contatos. Pronto, simples assim.

Obrigado e até a próxima
Fernando Anselmo

sábado, 23 de janeiro de 2016

REST - YO facilitando a vida Angular

O que mais gosto na tecnologia é como as coisas mudam rápido. Se dissesse a 10 anos que o JavaScript causaria uma revolução nas páginas Web, provavelmente seria taxado de louco. Atualmente estamos vendo não apenas a aceitação dessa linguagem, mas o seu completo domínio.

Obviamente seus filhos é que estão ganhando o mercado. O Angular.js da Google é sem dúvida a "menina loirinha e dos olhos azuis" desses filhos. Angular é prático, rápido, fácil de usar e com uma infinidade de recursos - publiquei uma série de artigos em 2013 sobre este framework. Porém nesse ambiente um único detalhe deixa a desejar: a montagem de um projeto consistente que permita crescer. Essa parte está completamente amarrada a capacidade e conhecimento do arquiteto.

Para resolver este problema, encontramos o Yo. Um framework com a função de manter a arquitetura de seu projeto voltada as boas práticas do mercado, e assim podemos nos preocupar somente com a codificação.


Criar uma aplicação Angular com o Yo é muito fácil e arquiteturalmente falando muito prática, já seguindo as regras de um bom modelo MVC. Vamos montar uma aplicação como forma de entendermos como funciona.

Instalação

Este tutorial está criado para o Ubuntu (meu sistema), mas acredito que facilmente poderá ser adaptado para qualquer sistema.
$ sudo npm install -g yo generator-angular generator-karma grunt-cli bower
Instalamos através do npm o yo, o Gerador do Angular, arquivos necessários para acessarmos o servidor Grunt e o gerenciador de dependências Bower. A diretiva -g indica que serão instalados de forma global para que não necessitemos mais instalá-los (esse passo só será realizado esta vez). Importante: Instale o Git.

Criar a Aplicação

Uma vez que todos os aplicativos estão instalados podemos criar uma aplicação.
$ mkdir coffeshop
$ cd coffeshop
$ yo angular:app coffeshop
Criamos uma pasta para abrigarmos o projeto. Acessamos esta pasta. Criamos os arquivos necessários para a aplicação - Responda "N" para a troca do Grunt pelo Gulp e para o uso do Sass.

Por fim iniciamos o servidor Grunt com o seguinte comando:
$ grunt server
E a seguinte página inicial será mostrada:


O servidor Grunt é excelente, permite o hot deploy de sua aplicação, isto é, ao realizar mudanças a página é dinamicamente reprocessada sem a necessidade de reiniciar o servidor. Pronto, já foi criado toda a estrutura necessário para se começar a trabalhar com o Angular, Bootstrap e Karma - este último é um framework de testes unitários que verifica os erros de suas páginas. Para executar os testes com o Karma é necessário baixar os pacotes localmente, para isso digite Ctrl+C para interromper o servidor e instale os pacotes com o comando:
$ npm install karma jasmine-core phantomjs phantomjs-prebuild
Execute o teste com o seguinte comando:
$ grunt test
Poderíamos parar por aqui, mas quero iniciar um pequeno aplicativo, inicie novamente o servidor do Grunt. Sou louco por café, para se ter uma ideia do quanto comprei uma dessas máquinas italianas para preparar um bom Cappuccino e todas suas variações.

Para o primeiro passo, baixe as imagens necessárias (no link abaixo) e descompacte-as na pasta \app\images da aplicação.

Baixar as images

Segundo passo, modifique o arquivo main.js que se encontra na pasta \app\scripts\controller para a seguinte codificação:
'use strict';

/**
 * @ngdoc function
 * @name coffeshopApp.controller:MainCtrl
 * @description
 * # MainCtrl
 * Controller of the coffeshopApp
 */
angular.module('coffeshopApp')
  .controller('MainCtrl', function ($scope) {
    $scope.coffes = [
      {nome:"Affogato", imagem:"cafe01", descr:"Sorvete de baunilha com um pouco de expresso"},
      {nome:"Americano", imagem:"cafe02", descr:"Expresso diluído com água quente"},
      {nome:"Black coffe", imagem:"cafe03", descr:"Café sem a adição de leite"},
      {nome:"Cafe au Lait", imagem:"cafe04", descr:"Partes iguais de café e leite"},
      {nome:"Cafe Breva", imagem:"cafe05", descr:"Expresso servido com meio a meio"},
      {nome:"Cafe Latte", imagem:"cafe06", descr:"Curto expresso com leite quente e, um pouco de espuma de leite"},
      {nome:"Cappuccino", imagem:"cafe07", descr:"Curto expresso com a combinação de leite quente e fervido. Cappuccino possui uma larga espuma de leite com um café com leite"},
      {nome:"Double", imagem:"cafe08", descr:"Duas partes de expresso usados como um drink expresso"},
      {nome:"Dry Cappuccino", imagem:"cafe09", descr:"Cappuccino feito com um pouco de expuma de leite"},
      {nome:"Expresso", imagem:"cafe10", descr:"Leite quente é forçado por um fino cano com café para produzir uma forte bebida"},
      {nome:"Expresso con Panna", imagem:"cafe11", descr:"Uma porção de expresso com um pouco de espuma de creme"},
      {nome:"Expresso Macchiato", imagem:"cafe12", descr:"Uma porção de expresso com um pouco de espuma de leite"},
      {nome:"Flat White", imagem:"cafe13", descr:"Expresso com leite vaporizado derramado de um jarro quente com um pouco de expresso"},
      {nome:"Flavoured Coffee", imagem:"cafe14", descr:"Blend de café com xaropes de especiarias de diferentes sabores"},
      {nome:"Frappe", imagem:"cafe15", descr:"Expresso ou Blend de café instantâneo com açucar, água, leite e gelo"},
      {nome:"Iced Coffe", imagem:"cafe16", descr:"Café servido com gelo"},
      {nome:"Indian Filter Coffe", imagem:"cafe17", descr:"Café e chicória produzem um doce café que é servido com leite"},
      {nome:"Kopi Tubruk", imagem:"cafe18", descr:"Um fino café feito com grãos de café fervido e açúcar sólido"},
      {nome:"Long Black", imagem:"cafe19", descr:"Um blend de água quente e expresso"},
      {nome:"Lungo", imagem:"cafe20", descr:"Água quente é passada duas vezes sobre o pó de café para produzir uma forte bebida"},
      {nome:"Melya", imagem:"cafe21", descr:"Blend de cafe com uma colher de cacau e mel"},
      {nome:"Mocha", imagem:"cafe22", descr:"Um cappuccino com a adição de xarope de chocolate"}
    ];
  });
Agora temos uma resposta JSON chamado coffes com todos os 22 tipos de café mais conhecidos do mercado, suas descrições e qual foto corresponde a cada café. E na página principal (arquivo main.html na pasta \app\views) mostramos todos esses tipos, modificando seu código para:
<style type="text/css">
.marketing {
  text-align: center;
  margin: 10px 0 10px 0;
}
.marketing p {
  font-size: 14px;
  margin: 10px 10px 10px 10px;
}
</style>
<div class="jumbotron">
  <h2>Tipos de Cafés Disponíveis</h2>
  <div class="container">
    <div ng-repeat="coffe in coffes">
      <div class="row marketing" ng-show="{{$index%3 == 0}}"></div>
      <div class="col-md-4 col-sm-4 col-xs-12 marketing">
        <img ng-src="images/{{coffe.imagem}}.png" alt="Cafe" class="img-circle">
        <h2>{{coffe.nome}}</h2>
        <p class="marketing">{{coffe.descr}}</p>
        <a href="#/" class="btn btn-default">Detalhes...</a>
      </div>
    </div>
  </div>
</div>
E agora a janela principal possui a seguinte aparência:


E apenas para deixarmos as coisas bem arrumadas. Na classe de teste da janela principal (main.js em /test/spec/controllers/main.js) modifique a seguinte função:
  it('should attach a list of awesomeThings to the scope', function () {
    expect(MainCtrl.awesomeThings.length).toBe(3);
  });
Para:
  it('should attach a list of coffes to the scope', function () {
    expect(scope.coffes.length).toBe(22);
  });
Em breve iremos adicionar mais alguns detalhes para aprendermos como o Yo pode auxiliar na criação dos artefatos necessários e organização de seus projetos, por enquanto recomendo que estude como o projeto está distribuído.

Obrigado e até a próxima
Fernando Anselmo