Você REALMENTE acha que vai aprender assim?
Uma lição importante aprendida com o Grails Brasil foi como não aprender alguma coisa. A foto do Baudrillard ai ao lado não é acidental.
Há alguns anos atrás li um pequeno livro de Baudrillard chamado “A Ilusão Vital” que chega a uma conclusão fascinante: se você quiser privar um indivíduo de informação, afogue-o nela. E há uma razão epistemológica para isto.
Só conseguimos prestar atenção e absorver conhecimento de uma fonte por vez. Sendo assim, caso você ofereça dezenas de fontes a alguém que deseje aprender (mais especificamente se iniciar em) um assunto, esta levará muito mais tempo para aprender (se aprender) do que alguém que possua uma fonte única.
E o problema é que hoje temos fontes demais: blogs, vídeos, fórums, artigos, revistas e… livros. Sendo assim, num ato de talvez pura arrogância resolvi escrever este post no qual apresento um guia expondo como procedo quando quero me iniciar em algum assunto, seja ele desenvolvimento de sistemas, filosofia, matemática ou qualquer outra coisa.
Iniciando: o livro
A iniciação sempre se dá de forma acidental. Eu topo com algum post, artigo,vídeo ou até uma conversa solta e tomo conhecimento da existência daquele assunto. Se o assunto de fato me interessar, é hora de buscar um bom livro sobre aquele tema.
Yeap: a minha fonte primária sempre é um livro. Neste momento, ignoro todos os blogs, agregadores e fórums que possam existir sobre o assunto. Meu objetivo é encontrar um livro que me sirva de base. Busco aquele com o qual me sinta mais a vontade (normalmente é um processo puramente instintivo) e leio-o de cabo a rabo. Mesmo que seja um livro horrível, pelo menos já vou estar mínimamente preparado para que eu possa me aprofundar no assunto.
Livros são bons porque normalmente apresentam a espinha dorsal do aprendizado.O autor gastou um bom tempo planejando como guiar seu leitor. Lembre-se: quando você está aprendendo algo, simplesmente não sabe qual caminho seguir. Resumindo: não seja arrogante.
Caso você opte por aprender apenas por blogs, artigos e fórums, difícilmente vai acertar de cara qual o melhor caminho de aprendizado.
Pondo em prática: Internet começa a te ajudar
Livros de programação possuem uma vantagem: são interativos. Normalmente o autor expõe alguns exemplos que podemos tentar por conta própria para ver se funcionam mesmo. Use e abuse destes exemplos e, de preferência, procure criar alguma coisa baseando-se no que o autor te expõe. Experimente!
Se ficar com dúvidas em relação a algum assunto que o livro não deixe claro, busque na Internet algo a respeito. Com certeza encontrará alguma coisa. Outra fonte bacana são os fórums, aonde seus participantes farão o possível para sanar suas dúvidas. Mas logo em seguida retorne ao seu livro.
Lembre-se: fórums servem para resolver dúvidas pontuais e conhecer novas pessoas, mas não para se aprofundar. Tenha isto em mente o tempo inteiro. Já posts tratam sempre de apenas detalhes. O mesmo pode ser dito a respeito de artigos.
Se aprofundando: escreva
Após confirmar seu gosto pelo assunto a melhor forma de se aprofundar é ler ainda mais e, principalmente, escrever a respeito. Escreva suas descobertas e espere por comentários. É fascinante ver o que as pessoas pensam do que você está expondo. E ainda mais fascinante aprender com seus leitores. Diversas vezes meus leitores apontaram erros em meus textos que me ajudaram DEMAIS no meu aprendizado.
E aqui entra o postulado Kiconiano: você só conhece de fato aquilo que consegue descrever com palavras. Sendo assim, nada melhor para confirmar o seu aprendizado do que escrever a respeito.
Cursos
Um curso pode proporcionar ganhos iguais ou até superiores aos que obtemos com um livro (há uma razão pela qual não existem apenas autores, mas também professores). Isto porque você vai estar durante o período do curso 100% (ao menos em teoria) dedicado a prestar atenção em seu instrutor. Além disto, também estará absorvendo a experiência de alguém que já passou por aquele caminho. Outra razão é que cursos costumam oferecer apostilas e textos básicos que ajudam o estudante a se aprofundar. Resumindo: une o melhor dos dois mundos: a leitura e o conhecimento prático.
Podendo fazer algum curso de qualidade não pense duas vezes. Pule dentro!
Como não aprender: evitando apenas a prática
Você não vai aprender apenas por fórums, posts e videos. Sem um guia inicial que ofereça o mínimo de aprofundamento não há como aprender de fato. Respostas em um fórum ou um blog podem causar a ilusão de aprendizado em quem está começando, mas na esmagadora maioria das vezes, a dúvida que te fez buscar um fórum é alimentada pela falta de algum conhecimento básico que muito provavelmente esta a apenas algumas páginas adiante no livro que você deveria estar lendo.
Valorize a tecnologia e não apenas a prática
Observo muita gente que tenta aprender apenas vendo exemplos de código na Internet. Ei! Como você pode ter certeza de estar compreendendo aquele código se não possui a base para tal? É hora de deixar a arrogância de lado e valorizar a base do aprendizado: teoria. Acredite: pegar um sistema pronto e ver como funciona sem conhecer de fato a tecnologia não estará lhe ajudando, mas sim alimentando sua desistência daquele assunto.
Nestas horas devemos pensar no significado da palavra tecnologia. Vem da junção de duas palavras gregas: techné (técnica) e logos (conhecimento baseado na razão). Conhecendo apenas a técnica você falhará miserávelmente na primeira situação que fugir da sua experiência. Já conhecendo a razão (logos) por trás da sua prática, saberá o porquê do seu fazer e, principalmente, a razão pela qual algo não saiu como o esperado.
Resumindo: evite ser uma máquina e passe a agir como ser humano.
Perguntas frequentes
Como escolher o meu livro e saber se presta?
Procure o site oficial da tecnologia e veja se indicam algum livro. Já é um bom começo. Busque opiniões também em fórums ou com pessoas que possuam experiência confirmada no assunto. Caso seja uma tecnologia recente e não exista material publicado, comece pela própria documentação do projeto que, normalmente, é a mais completa possível a respeito do assunto.
Quando devo usar um fórum então?
Quando precisar de apoio para dúvidas específicas, quiser conhecer mais pessoas que lidem com o assunto ou se aprofundar no assunto ajudando os inexperientes, mas NUNCA como fonte primária de informação.
E blogs? Quando devo usar?
Para conhecer visões diferentes sobre um mesmo assunto ou resolver uma dúvida específica. Talvez até mesmo como um possível contato com o autor do blog.
E vídeos? Quando?
Vídeos são ótimos quando desejamos ver a coisa na prática. Talvez seja o que chega mais próximo de um curso, porém possui a desvantagem de que você não pode interromper o narrador durante sua execução. Tenha isto em mente. E, assim como fórums, não devem jamais ser usados como fonte primária de informação. Sempre os use em conjunto com alguma outra fonte de instrução como um livro ou mesmo série de artigos a respeito.
Como usar a Internet para buscar maiores informações?
Tenho um post neste blog exatamente sobre este assunto. Clique aqui.
Eu não tenho paciência para ler. E ai?
Você tem certeza disto? Já reparou que sempre se pega lendo uma seção específica em jornais ou revistas? Use esta sua impaciência como um sinal de que talvez você não se interesse de fato pelo assunto. Normalmente sentimos prazer em ler a respeito dos assuntos que nos atraiam. Pense nisto.
Concluindo
Este é o caminho que sigo quando pretendo me iniciar em algum assunto de meu interesse. Trata-se apenas da minha experiência e de modo algum deve ser entendido como regra geral. Porém, se lhe servir de apoio, ótmo! Sinal de que meu tempo não foi perdido ao escrever este post.
O mais importante deste post na realidade é sua mensagem final: evite ser uma máquina: valorize a tecnologia e não apenas a técnica para não se tornar apenas “mais um” ok?
E aqui recoloco a pergunta: e você? Quando vai se iniciar em um assunto, como procede?
Integrando o NUnit ao VB.net Express Edition 2008 (e ao C# ED também)
Então finalmente aconteceu: precisei aprender .net direito para um projeto. No caso, o requisito do cliente foi o de que tudo deveria ser desenvolvido em VB.net. Sendo assim, busquei material para aprender DIREITO esta linguagem (recomendo o livro “Pro VB 2008 and the .NET 3.5 Platform” de Andrew Troelsen (que fala MUITA merda sobre Java, mas a parte sobre .net é fantástica)).
Pois bem: minha maior dificuldade inicial foi trabalhar com algum framework de testes unitários (sou viciado e considero fundamental para que eu possa progredir no aprendizado da linguagem). Como terei de usar o Visual Basic 2008 Express Edition, tive de me virar por conta própria (o Visual Studio pago já oferece suporte integrado a frameworks de testes unitários pelo qu epude ver). Há duas opções de procedimento a serem adotadas. Antes de tratá-las individualmente, acho importante tratar do que é comum a ambas.
1. Baixe a última versão do NUnit em http://www.nunit.org e a instale em seu PC
2. Na sua solução, adicione um novo projeto que conterá todos os seus testes unitários. Adicione duas referências a este projeto: nunit.framework na aba “.NET” e o outro projeto que faz parte da sua solução na aba “Projects”
3. Escreva seus testes unitários. A documentação oficial do JUnit é excelente.
Agora às duas alternativas: a do preguiçoso que trabalha mais e a que te permite depurar seus testes unitários
Alternativa do preguiçoso
É simples: no menu “Tools” do VB.net Express Edition selecione a opção “External Tools…”. Você adicionará uma ferramenta à mais para a sua IDE. Simplesmente preencha o formulário tal como na imagem abaixo:
Command deverá possuir o caminho completo até o executável nunit.exe em seu PC.
E Arguments deverá possuir o texto exatamente como digitei. Assim, o programa nunit.exe será executado na versão compilada do seu projeto que contém os testes unitários e, quando quiser ver se tudo está ok, basta ir ao menu “Tools” e clicar sobre a opção NUnit. Mas lembre-se de que ao clicar nesta opção do menu, o projeto que contém seus testes unitários deverá estar selecionado. Caso contrário, o NUnit irá lhe dizer que não encontrou teste algum em seu assembly.
O legal desta abordagem é que pode ser aplicada a qualquer projeto sem que você precise adicionar qualquer configuração adicional. O problema é que não te permite depurar seus testes unitários.
Alternativa detalhada por projeto
A primeira alternativa é ótima se você não precisa depurar seu código fonte. Mas as coisas começam a ficar feias caso seja necessário depurar testes unitários, pois não será possível, pois o VB.net Express Edition não permite anexar processos ao depurador, ao contrário da versão paga. Porém não o permite apenas se estiver trabalhando pela IDE…
Para poder depurar os seus testes unitários, siga o passo a passo abaixo:
1. Se o VB.net Express Edition estiver aberto, feche-o.
2. Abra com um editor de texto qualquer o seu arquivo de projeto (tem a terminação .vbproj) que contém os seus testes unitários. Neste documento que está no formato XML, busque pela primeira tag chamada PropertyGroup e no final desta adicione as linhas abaixo:
<StartAction>Program</StartAction> <StartProgram>C:\Program Files\NUnit 2.5.5\bin\net-2.0\nunit.exe</StartProgram>
A segunda linha contém o caminho completo até a sua instalação do NUnit. Seu arquivo deverá estar similar ao trecho abaixo:
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{17E79D88-1181-45CB-AA60-388976791BA5}</ProjectGuid>
bla bla bla
E finalmente, no final desta tag o código abaixo:
<strong> <StartAction>Program</StartAction>
<StartProgram>C:\Program Files\NUnit 2.5.5\bin\net-2.0\nunit.exe</StartProgram></strong>
E é isto: quando for executar seu projeto pela IDE, automáticamente o NUnit será aberto e você poderá depurar seus testes quando forem executados.
E o mesmo procedimento pode ser adotado ao C# Express Edition. A diferença é apenas o arquivo a ser aberto, que terá, se não me engano, a extensão csproject.
PS: e o que estou achando do VB.net 2008 e .net em Geral? É muito legal! :)
Grails: do Groovy à Web – Quinta e última parte publicada na Java Magazine 79
Acaba de sair a edição digital (o que quer dizer que a versão impressa já deve estar a caminho) da revista Java Magazine n. 79, que contém a quinta e última parte da minha série “Grails: do Groovy á Web”.
Desta vez o assunto é a camada de visualização: dei foco ao detalhamento da tecnologia GSP (Groovy Server Pages). Serão expostas todas as similaridades com o JSP, incluindo melhores e piores práticas do seu uso. Acredite: conhecer BEM GSP vale muito à pena.
Também veremos o uso de templates, criação de tags customizadas, gerenciamento de layouts com SiteMesh e aplicação de Ajax com Grails, abrangendo assim a esmagadora maioria dos temas (em detalhes) que você precisa conhecer para criar uma camada de visualização de alto nível usando Grails.
Foi um prazer imenso escrever esta série de artigos, e pelo que pude observar, incentivou muita gente a aprender este framework maravilhoso que é o Grails. Sendo assim, agradeço a todos aqueles que me incentivaram com críticas, sugestões e elogios na produção desta série (principalmente o Eduardo Spinola).
Aproveito também o post para lhes convidar a ler o meu próximo artigo a ser publicado na Java Magazine, no qual tratarei do uso do padrão de injeção de dependências com o Spring 3.
Aguardo ansiosamente pelo feedback de vocês.
Até lá!
Primeiros passos NoSQL com MongoDB: manipulando documentos
Continuando meu post anterior sobre o assunto, é hora de colocarmos a teoria em prática. Meu objetivo agora é expor o básico sobre o funcionamento e operação do MongoDB para que, em seguida, possamos aplicar este SGBD a alguma linguagem de programação (muito provávelmente usarei o Groovy, que cai como uma luva).
Instalando o Servidor
De todos os SGBDs não relacionais que experimentei, aquele com qual tive mais facilidade para trabalhar foi o MongoDB por duas razões: ele é realmente simples e a documentação é excelente. A facilidade do sistema se apresenta no primeiro contato que temos com a criatura: instalando-o.
Simples e rápido: baixe a versão que se adequa ao seu sistema operacional neste link. Descompacte-o em um diretório de sua escolha e o bicho está quase pronto para ser usado.
Para iniciar o servidor, você deverá executar o programa mongod, presente no diretório $MONGODB/bin (entenda $MONGODB como sendo o diretório aonde você descompactou a sua distribuição do programa). Você será saudado por uma nada simpática mensagem de erro na qual encontrará um texto similar ao abaixo:
Thu Apr 15 21:32:54 Assertion: 10296:dbpath (/data/db/) does not exist
Isto ocorre porque por default o MongoDB armazena seus bancos de dados no diretório /data/db (C:\data\db se estiver usando Windows). A solução é simples: ou você cria este diretório ou inicia o processo mongod com o parâmetro -dbpath como no exemplo abaixo:
$mongodb/bin/mongod -dbpath=/home/kicolobo/mongodb
Neste caso, estou instruindo o servidor a buscar pelos arquivos de banco de dados dentro do diretório /home/kicolobo/mongodb
Nota: é importante mencionar que se eu inicio o MongoDB usando a abreviação ~ para o meu diretório home (por exemplo: ~/mongodb) o processo mongod não identifica o diretório, retornando aquela mesma entediante mensagem de erro (ao menos no Mac OS X).
Observação importante: caso você esteja usando uma versão de 32 bits do MongoDB, esta possuirá o tamanho dos bancos de dados limitados a no máximo 2 Gb.
Conectando-se
O cliente nativo do MongoDB é o programa mongo, localizado no diretório $MONGODB/bin. Com o servidor em execução, caso você inicie este aplicativo automáticamente já estará logado no servidor default, que é o local usando a porta 27017. Não é necessário prover um usuário (posso falar mais sobre gerenciamento de usuários em um post futuro no entanto). Ao iniciar o shell você será saudado por um prompt similar ao exposto na imagem abaixo:
Neste podemos fazer basicamente tudo o que quisermos com o MongoDB. Por default, estamos conectados ao banco de dados test. Para mudar de banco de dados, basta usar o comando use seguido do nome do banco de dados. Por exemplo use kico;.
Manipulando dados
Inserindo
No MongoDB, cada banco de dados é composto por um conjunto de coleções. O código abaixo, apesar de muito simples nos diz muita coisa:
> use kico
switched to db kico
> a = {posicao:1, descricao:"Primeira letra do alfabeto"}
{ "posicao" : 1, "descricao" : "Primeira letra do alfabeto" }
> db.alfabeto.save(a)
> a
{
"posicao" : 1,
"descricao" : "Primeira letra do alfabeto",
"_id" : ObjectId("4bc7b65da5ec5e132c1a53a1")
}
A primeira coisa que fiz foi selecionar o banco de dados kico usando o comando use. Se este banco de dados não existisse, o MongoDB o criaria automaticamente para nós.
Em seguida, criei uma variável chamada a, cujo valor é uma estrutura no formato JSON composta por dois atributos: posicao e descricao. Lembre-se que estamos lidando aqui com um SGBD schemaless: sendo assim posso criar documentos com o formato que eu sonhar.
Para inserir o meu documento a em uma coleção, usei o objeto db, que aponta para o banco de dados atualmente selecionado. A sintaxe para inclusão de um registro é simples:
db.[nome da coleção].save( objeto a ser salvo )
No caso, estou incluindo o documento a dentro da coleção alfabeto. Assim como no caso do banco de dados, se esta coleção não existir no banco de dados atual, esta será criada automaticamente no momento em que o primeiro documento for inserido.
Claro, eu também poderia incluir um novo registro na coleção alfabeto tal como no exemplo abaixo:
db.alfabeto.save({posicao:5, letra:"e"})
Finalmente, expus o conteúdo do documento a após ter sido incluido na coleção. Observe a inclusão de um novo atributo neste objeto: o _id .Como o próprio nome já diz, um identificador interno usado pelo MongoDB para diferenciar os objetos armazenados em nossas coleções. É importante mencionar que este atributo só será criado pelo MongoDB caso ainda não exista na estrutura a ser armazenada. Sendo assim, você é livre para criar seus próprios identificadores se quiser.
Editando e excluindo
Editar um registro também é fácil. Novamente, vamos analisar um código bem simples que nos dirá bastante coisa:
documento = db.alfabeto.findOne({posicao:1})
documento.bobagem = "Veja, estou incluindo um novo atributo completamente inútil!"
db.alfabeto.save(documento)
db.alfabeto.remove(documento)
O primeiro passo foi usar o método findOne presente na nossa coleção alfabeto. Este recebe como parâmetro um fragmento de documento e, como o próprio nome já nos diz, retorna um único resultado para nós.
Dai pra frente é simples: adiciono um novo atributo ao nosso documento e em seguida o persisto novamente na coleção usando o mesmo método save() que vimos anteriormente. A diferença é que aqui será feita uma substituição, visto que o documento em questão já possui um atributo _id.
Nota importante: você pode dar o nome que sonhar para um atributo, porém duas regras devem ser satisfeitas: O nome do atributo não deve começar com o caractere $ e o caractere ‘.’ jamais poderá ser incluido.
Continuando
No próximo post (que pretendo publicar nesta semana) vou mostrar como fazer consultas no MongoDB. Não inclui este conteúdo agora porque tornaria este post gigantesco e não trataria com o detalhamento que desejo o assunto.
Sendo assim, aguardem pelo próximo post sobre o assunto. Até lá!
Uma experiência bem sucedida com o Memcached
Memcached é um sistema de cache em memória distribuido muito fácil de usar. Como recentemente tive uma experiência maravilhosa com esta ferramenta acredito que é interessante expô-la neste post (prometo que o próximo post será sobre MongoDB). A natureza do Memcached é extremamente genérica – trata-se de um serviço de rede – sendo assim, o que descreverei pode ser aplicado sem grandes mudanças a básicamente qualquer linguagem/ambiente de execução. Mas antes de falar sobre minha experiência, vou falar um pouco sobre o funcionamento da criatura e como usá-lo com Java (consequentemente, com Groovy também).
Idéia básica
Para muitos, o conceito de cache é algo novo. Sendo assim, convém fazer uma introdução ao conceito. Imagine que você possua um conjunto de informações que repetidas vezes precise ser buscado na sua base de dados. A cada consulta, você precisa:
- Enviar a consulta (por exemplo: SQL)
- Esperar o processamento do SGBD
- Receber o resultado obtido
- Transformá-lo, tornando-o útil para sua aplicação
O objetivo do cache é evitar temporáriamente os três últimos passos do procedimento que descrevi acima, retornando para o usuário o resultado do processamento dos dados em estado cru. Se 2 + 2 são 4, por que calcular este valor toda vez que você receber esta pergunta se é possível armazenar apenas o resultado e reaproveitá-lo quando necessário?
O Servidor Memcached
O Memcached é um serviço de rede. No site oficial (http://www.memcached.org) é possível baixar a última versão, que vêm como código fonte (veja este link para maiores detalhes sobre como proceder com a instalação). Se estiver usando Linux, instalá-lo é ainda mais fácil, visto que muito provávelmente a criatura já estará disponível nos repositórios de sua distribuição.
Instalado, basta executar o comando memcached para iniciar o serviço. É importante conhecer alguns parâmetros, cuja listagem segue abaixo:
-m : quanta memória (em Mbs) o Memcached irá usar. Caso omitido, o valor default é 64 Mb.
-p : qual a porta TCP a ser usada. Caso omitido, o valor default é 11211
-u : qual a porta UDP a ser usada. Como a porta TCP, o valor default é 11211 caso omitido.
-v : Modo verboso: o Memcached irá expor na tela o que está executando. É bacana quando estamos aprendendo a usar o bichinho. Interessante mencionar que há duas outras opções: -vv (mais verboso) e -vvv (ainda mais verboso)
Sendo assim, se eu executar o comando memcached -m 540 -v -p 11000 -u 11000 iniciará o serviço com 540 Mb de memória no modo verboso definindo como portas UDP e TCP a 11000.
Como mencionei, o Memcached é um servidor distribuido, mas como minha experiência até o momento envolveu apenas uma instância ainda não tenho conhecimento suficiente para compartilhar.
O que é e como é armazenado
Pense no Memcached como uma tabela de hash gigante. Toda informação individual armazenada possui basicamente 3 elementos:
Identificador: um texto com tamanho máximo de 250 caracteres que identifica um corpo de informação. Equivale à chave primária com a qual já estamos acostumados a trabalhar no modelo relacional. Não há regras com relação ao seu valor: sendo assim, você é livre para identificar suas informações como quiser.
Tempo de duração: o tempo (em segundos) que o Memcached manterá esta informação na memória. O tempo máximo suportado é 30 dias.
Corpo: a informação em si. No caso do Memcached, esta possui tamanho máximo de 1 Mb. Se for pouco pra você, sempre é possível dividir a sua informação em mais de um bloco, compactá-la ou, se preferir, alterar o código fonte do Memcached (eu o li inteiro, e é BEM fácil de entender (se você souber C)).
Lembre-se: não se trata de um banco de dados. Tudo no Memcached, assim como na vida (sôou poético!) é passageiro. A idéia é evitar que tenhamos de acessar o SGBD, que é um processo MUITO mais caro computacionalmente, e não substitui-lo!
O cliente Memcached
O primeiro passo é escolher qual biblioteca cliente usar para acessar o Memcached. Há diversas, implementadas em tudo o que você imaginar: C, C++, PHP, MySQL, Python, Perl, Ruby… No nosso caso, vou falar do SpyMemcached, que é um cliente para Java. Uma lista com “alguns” dos clientes disponíveis atualmente pode ser acessada neste link.
O SpyMemcached é composto por um único arquivo Jar, o que torna seu deploy muito simples. Basicamente o único pacote que você vai precisar é do net.spy.memcached.
Obtendo uma conexão com o Memcached
Basta criar uma nova instância da classe MemcachedClient, tal como no exemplo abaixo:
MemcachedClient client =new MemcachedClient(AddrUtil.getAddresses("0.0.0.0:11211 10.10.10.69:11211"));
Repare que passei dois servidores distintos. Usando este construtor você poderá adicionar um ou mais servidores aonde serão feitas as suas buscas.
Buscando e inserindo informações
Buscar e inserir informações com o SpyMemcached é simples. O código abaixo é quase que auto-explicativo.
MemcachedClient client =new MemcachedClient(AddrUtil.getAddresses("localhost:11211"));
// O que irei armazenar no Memcached
Pessoa pessoa = new Pessoa();
pessoa.setNome("Kico");
pessoa.setCidade("BH");
// Incluindo informações
client.add("chave_pessoa", 120, pessoa);
// Buscando a informação
Pessoa noCache = (Pessoa) client.get("chave_pessoa");
Quando incluimos uma informação no Memcached, devemos passar 3 parâmetros: a chave de identificação, o tempo em segundos e o que queremos armazenar. No caso de um objeto, este obrigatóriamente deverá implementar a interface java.io.Serializable. Caso contrário será disparada uma excessão.
Já para obter a informação, basta passar a chave que a identifica e em seguida fazer o type casting para o tipo desejado.
Ah: e como fechar a conexão com o servidor? Simples: execute o método shutdown() da classe MemcachedClient.
Conhecendo os métodos abaixo da classe MemcachedClient você já pode começar a trabalhar (e bem) com o Memcached:
void MemcachedClient.add(String chave, int segundos, Object valor): insere uma informação no servidor Memcached. Se já existir um valor definido para esta chave no servidor, este será mantido pelo Memcached.
Object MemcachedClient.get(String chave): retorna um valor armazenado no Memcached
void MemcachedClient.shutdown(): fecha a conexão com o Memcached
void MemcachedClient.remove(String chave): remove uma informação armazenada no servidor
void MemcachedClient.replace(String chave, int segundos, Object valor): substitui um valor armazenado no servidor.
Dica: aproveite ao máximo suas conexões com o Memcached buscando o maior número possível de registros, mas nunca se esqueça de fechá-las, pois o serviço começa a apresentar problemas quando o número de conexões simultâneas é muito alto.
Minha experiência
Eis a situação: possuimos uma aplicação feita em Grails cuja base é uma biblioteca escrita em Java. Esta biblioteca é também usada por diversas aplicações executadas no ambiente desktop dentro da empresa. Fiz uma imagem que, espero, ilustre a situação.
Em nosso servidor físico aonde já se encontrava instalado o Tomcat aproveitei para colocar em execução o servidor do Memcached.
Como sou o pai da biblioteca legada que mencionei acima, a refatorei para que ao invés de usar a biblioteca de cache anterior, passasse a usar o Memcached.
Em seguida, atualizei tanto a nossa aplicação Grails quanto os clientes desktop (nestas horas você começa a AMAR o Java Webstart) e voilá: resultado imediato.
Como todos acessam o mesmo servidor Memcached, no momento em que uma aplicação desktop ou web alimentam o servidor de cache, automáticamente todas as demais instâncias se beneficiam. Resultado? Nossa performance global aumentou no mínimo 3 vezes, e o número de chamadas ao nosso SGBD diminuiu em aproximadamente 40%.
É importante mencionar que em nosso ambiente é muito comum mais de um usuário concorrentemente necessitar do mesmo conjunto de informações. Isto é fundamental, pois caso contrário não teriamos um ganho de performance, mas sim perda, pois antes de executar uma consulta no SGBD, sempre seria feita uma busca no Memcached.
É fundamental lembrar o seguinte aqui: não temos um cache local, mas remoto. O ganho da performance é obtido em grande parte porque não precisamos popular objetos, visto os mesmos já virem “prontos” do servidor para nós.
Antes do Memcached haviamos pensado sériamente em usar o Terracota. Mas como nosso ambiente é heterogêneo, e há programas escritos em .net, C/C++, VB6 e PHP, o Memcached caiu como uma luva, pois assim podemos aproveitar a mesma estrutura (e dados!) entre estas diferentes plataformas de execução/desenvolvimento (claro, com os devidos cuidados para evitar a bagunça).
Recomendadíssimo portanto o seu uso. Espero que este post seja útil aos que estejam interessados em usar a ferramenta.
Quarto artigo da série “Grails: do Groovy á Web” publicado na Java Magazine
Foi publicado na Java Magazine nº 78 o quarto artigo da série “Grails: do Groovy à Web”: desta vez o foco é o GORM, que é a camada de persistência adotada pelo Grails.
De todos os artigos publicados pela série, muito provávelmente este é o mais abrangente, pois abordo desde o básico (as quatro operações básicas do CRUD: inserção, edição, pesquisa e exclusão), passando pelo mapeamento objeto-relacional (em detalhes: veremos como lidar com bases de dados legadas) até assuntos mais avançados que influenciam significativamente a performance de sistemas baseados em Grails.
Espero que gostem do artigo tanto quanto eu gostei de escrevê-lo (pois eu adorei!). Por enquanto só saiu a versão digital, porém a impressa deve estar vindo nos próximos dias.
Sendo assim, até o próximo artigo e aguardo o feedback de vocês!
Introdução ao MongoDB: um banco de dados NoSQL
Já faz algum tempo que venho estudando o MongoDB. Dentro da turma dos SGBDs NoSQL este foi aquele com o qual acabei criando maior simpatia pela sua simplicidade e documentação (apesar de muita gente falar do Apache Cassandra, sua documentação ainda é horrível).
O MongoDB é um banco de dados orientados a documentos. Sendo assim, se você, assim como eu (e 99% dos desenvolvedores) vêm de um ambiente dominado pelo modelo relacional, em um primeiro momento verá este SGBD como um alienígena – o que é incrívelmente empolgante e assustador. Meu objetivo neste post não é ensinar a usar o MongoDB (será assunto do próximo), mas sim expor as principais diferenças entre este e o confortável modelo relacional.
Este assustador (e maravilhoso) “mundo novo”
Para os acostumados com o modelo relacional, o MongoDB se mostrará assustador no primeiro contato porque a maior parte dos conceitos que nos forneciam uma certa sensação de segurança basicamente “desaparecem”. Aqui é obrigatório saber lidar com o medo: conforme mostrarei neste post, há riscos, mas os ganhos os compensam.
Não acho que o modelo não relacional possa ser aplicado a todos os casos, porém é sempre importante conhecer mais de um paradigma para que possamos no mínimo ampliar nossos horizontes quando nos deparamos com situações que fogem da nossa zona de conforto (e o MongoDB pode ser bastante desconfortável neste primeiro momento).
Não há registros, mas documentos
Algo sempre me incomodou no modelo relacional: com ele tentamos representar o mundo real (que é n-dimensional) usando uma abordagem bidimensional. Tudo o que eu for representar em minhas tabelas possui apenas duas dimensões: linhas e colunas. É verdade que podemos representar quantas dimensões quisermos no modelo relacional a partir de relacionamentos, porém sempre fica aquela sensação de se estar “forçando a barra”.
Além disto, por mais bem feita que seja o processo de análise, sempre há a possibilidade de posteriormente mais um atributo ser encontardo. O mundo é um ambiente complexo: acredito que para representá-lo, precisamos também de uma terminologia complexa.
No MongoDB, o equivalente aos registros são os documentos, que utilizam a sintaxe JSON. A melhor maneira de se ter um feeling do que quero dizer é ver o bicho. Sendo assim, observe o código abaixo:
Kico = {
nome: "Henrique Lobo Weissmann",
apelido: "Kico (ou seria este o nome?)",
cidade: "Belo Horizonte"
}
Eu criei um documento chamado kico que possui 3 atributos: nome, apelido e cidade. Repare que em momento algum defini o tamanho máximo de cada atributo, regras de validação ou qualquer tipo de restrição. Em seguida, se quiser armazená-lo em um banco de dados, bastaria executar o código abaixo:
db.kicodb.save(Kico)
Neste caso, eu estaria armazenando o documento Kico no banco de dados kicodb. Agora, observe o código abaixo:
Nanna = {nome:"Maria Angélica Alvares da Silva e Silva",
apelido:"Nãnna",
esposaDo:"Kico",
cidade:{nome:"Belo Horizonte", estado:{nome:"Minas Gerais", pais:"Brasil"}},
caes:[{nome:"Fraude", raça:"Pinscher?"}, {nome:"Zé", raça:"Schnauzer"}]}
db.kicodb.save(Nanna)
Repare que um registro com estrutura completamente diferente foi incluida no banco de dados. Até o atributo cidade é diferente. Enquanto no registro “Kico” eu tenho apenas uma string, no objeto Nanna eu tenho um outro documento. Outro ponto interessante: repare que eu tenho inclusive uma coleção associada ao objeto Nanna.
E tudo é mesmo assim salvo no mesmo banco de dados sem problema algum. Na realidade, eu poderia armazenar até o registro abaixo sem problemas:
esquisitao = {quantidade:34, poemaFavorito:"Batatinha"}
Como pode ser visto, não há regras de validação rígidas: qualquer tipo de documento pode ser armazenado no banco de dados. Claro: na prática somente objetos semelhantes são armazenados na base de dados, porém é bacana saber que se um dia aparecer algum novo atributo, poderemos inclui-lo apenas nos documentos aonde o mesmo é necessário, ao contrário do modelo relacional, aonde uma coluna se aplica a todos os registros.
Desvantagem: o desenvolvedor precisa ficar esperto para que suas bases de dados não virem um “samba do criolo doido”
Vantagens:
- Finalmente você se livrou de uma abordagem bidimensional e pode representar objetos do mundo real como realmente são: complexos e únicos.
- Caso no futuro surja algum caso no qual novos atributos apareçam, você pode aplicá-los somente aonde é necessário, e não em todos os casos, como no modelo relacional, aonde normalmente cria-se uma nova “coluna” na tabela relacionada
Redundância de dados máxima
No modelo relacional somos o tempo inteiro incentivados a reduzir ao máximo possível a redundância de dados. Aliás, os relacionamentos existem justamente para isto. E é um modelo que inegávelmente funciona muito bem. Já no MongoDB a situação é inversa: não há relacionamentos, e a duplicação de dados, pelo que pude observar é até incentivada.
Dê uma olhada no código abaixo:
pessoa1 = {nome:"Peçonhento", cidade:{nome:"Belo Horizonte", estado:"MG"}}
pessoa2 = {nome:"Zequinha", cidade:{nome:"Belo Horizonte", estado: "MG"}}
pessoa3 = {nome:"Joca", cidade:"Lagoa Santa"}
pessoa4 = {nome:"Complexado", cidade:{nome:"Rio de Janeiro", estado:{nome:"Rio de Janeiro", pais:{nome:"Brasil"}}}
Lembre-se de que aqui não há tabelas: há coleções de documentos. Em cada documento armazeno os dados da forma que eu quiser. Eu poderia criar uma coleção contendo apenas cidades e em seguida criar um relacionamento entre duas ou mais coleções distintas, é verdade (foge do assunto deste post), mas isto iria contra a idéia básica por trás do modelo orientado a documentos.
A idéia básica aqui é a de que um documento deve ser auto-contido, ou seja, isolado já deve conter todas as informações de que necessita. Por que isto? Simples: porque assim você ao invés de fazer uma consulta com vários joins como é o caso do modelo relacional executa uma única consulta, que já te retorna o documento inteiro. Resultado: mais performance.
Desvantagem: se você quiser alterar todos os registros relacionados a uma unidade semântica, precisa tratá-los um a um
Vantagem: maior performance. Uma única consulta já te retorna tudo o que você precisa saber a respeito do documento. Esta é uma das razões pelas quais vêm sendo adotado em projetos que exigem alta performance.
Concluindo
Estas são as duas principais diferenças (que só são vantagens de acordo com o caso) que vi no MongoDB (do modelo baseado em documenots na realidade) com relação ao modelo relacional. É aplicado a todos os casos? Óbvio que não.
O importante a meu ver é sair da área de conforto do modelo relacional: isto, como mencionei, amplia os nossos horizontes, faz com que vejamos outras possibilidades além de tabelas para armazenar nossos dados. Fico assustado quando topo com desenvolvedores que só conseguem desenvolver algo que envolva tabelas, colunas e registros. Aliás, a grande vantagem que vejo nesta “moda” de modelos noSQL é justamente esta: a exposição de “novos” paradigmas a um mundo dominado pelo modelo relacional, que só considero ruim quando tomado como a única alternativa viável pela maior parte das pessoas.
Este post é fundamental para que eu possa partir para os próximos, nos quais exporei como usar o MongoDB e, ainda mais importante, como aplicá-lo com Groovy e Java. Grande abraço!
Ah, quer baixar o MongoDB? Este é o site oficial: http://www.mongodb.org
Melhorando seus layouts com 960 Grid System (para não designers como eu)
Em um post anterior expliquei como usar SiteMesh com Grails. Agora é hora de expor uma descoberta recente que fiz: o 960 Grid System (960gs), criado por Nathan Smith. Para aqueles que não conhecem, o 960gs é um framework CSS. Como não sou designer (apesar de tentar com toda a minha teimosia), o termo framework CSS é novidade pra mim também.
A definição do termo na Wikipédia é a seguinte: “trata-se de uma biblioteca pré-configurada cujo objetivo é facilitar a criação de layouts o mais próximo possível dos padrões web”. A definição Kiconiana é mais simples: “arquivos CSS prontos para que você possa criar layouts bacanas e dentro dos padrões web de forma rápida”.
Um sistema de grade (grid system) é uma técnica adotada em layouts para se organizar o conteúdo de uma página impressa. Por sorte, a técnica também é adotada com sucesso em aplicações web!
Idéia central
A idéia básica do sistema é fornecer uma grade aonde possamos organizar o conteúdo de forma consistente. No caso do 960gs, esta grade encontra-se sobreposta a uma área de 960 píxels de largura. Por que 960 pixels? Por que é a resolução mais comum dos navegadores atualmente, sendo assim resolveram adotar esta convenção. No caso do 960gs, ele já vêm pré-configurado com 3 possibilidades: 12,16 ou 24 colunas. Na imagem abaixo está um exemplo de layout usando 12 colunas:
Como pode ser observado, há 12 colunas de cor rosa, com um espaço entre elas. No padrão 960gs, cada coluna possui 10 pixels de margem tanto esquerda quanto direita.
Abaixo está um site que acabei de terminar usando o layout. Como você pode perceber, as áreas em vermelho encontram-se exatamente dentro do espaço delimitado pelas colunas.
Preparando o terreno
O primeiro passo para usar o 960gs é fazer o download no site oficial: http://960.gs. Trata-se de um arquivo zipado que, ao ser descompactado, irá apresentar a seguinte estrutura de diretórios:
code: o que nos interessa: são os arquvos .css
templates: arquivos de imagem para quem quiser fazer mockups usando algum editor gráfico como Gimp ou Photoshop
sketch_sheets: um arquivo no formato PDF que você pode imprimir e desenhar em cima
licenses: bla bla bla jurídico
Copie os arquivos 960.css, reset.css e text.css para o diretório da sua aplicação (seja ela feita em PHP, Grails, HTML puro ou qualquer outra coisa). Em seguida, dentro da tag <head> da sua página, inclua o código abaixo:
<link rel="stylesheet" href="css/reset.css" /> <link rel="stylesheet" href="css/text.css" /> <link rel="stylesheet" href="css/960.css" />
Lembre-se de referenciar os arquivos css de acordo com a sua localização dentro da aplicação.
Entendendo a lógica
A regra é a seguinte: o layout da sua aplicação será organizado em linhas e colunas. Cada linha deverá possuir n colunas, aonde n representa o padrão que você adotou ao usar o 960gs. É desnecessário, mas se você quiser saber a largura de uma coluna, use a fórmula abaixo:
largura da coluna = (960 / (número de colunas)) – (margem da coluna * 2)
Como mencionei acima, cada coluna possui duas margens (direita e esquerda), cada uma com 10 pixels de lado. Sendo assim, no nosso exemplo cada coluna terá 60 pixels de largura.
Pondo em prática
O 960gs é aplicado em um container. Sendo assim, escolha uma div dentro da sua página que conterá todas as demais e altere-a para que fique tal como no exemplo abaixo:
<div class="container_12"> ... </div>
A classe container_12 define que aquele elemento está adotando uma grade de 960 pixels com 12 colunas. Se quisesse usar uma grade com 16 colunas, bastaria usar a classe container_16.
A melhor maneira de explicar o funcionamento da técnica é visualmente. Sendo assim, observe a imagem abaixo, que é o exemplo fornecido com o framework:
Repare que é um layout composto por duas linhas. A primeira ocupa todas as 12 colunas, enquanto o segundo é dividido em dois grupos: um contendo uma coluna e outro contendo as 11 restantes. Para obter este resultado, escreve-se o código abaixo:
<div class="container_12"> // Primeira linha <div class="grid_12"></div> // Segunda linha <div class="grid_1"></div> <div class="grid_11"></div> </div>
A classe grid_[número de colunas] representa o número de colunas que o elemento deverá ocupar. Sendo assim, na primeira linha usamos a tag grid_12, pois queriamos que toda a largura fosse ocupada.
Já na segunda linha, como queriamos dividir a largura em dois blocos, definimos para o primeiro elemento a tag grid_1 (uma coluna) e grid_11 para o seguinte (11 colunas).
A regra se manteve: cada linha deve possuir 12 colunas.
Aumentando a flexibilidade
Agora, vamos aumentar a flexibilidade dos nossos layouts. E se quiséssemos apenas um componente que não ocupasse a página inteira, mas que ao mesmo tempo não estivesse próximo às margens da página, tal como no exemplo abaixo?
Agora entra em prática mais duas classes: prefix[colunas] e suffix[colunas] que representam respectivamente quantas colunas deverão vir antes do nosso componente e quantas depois. Reparou? Mantivemos aqui a regra de manter o número de colunas fixo!
Obteriamos o resultado acima portanto com o código abaixo:
<div class="grid_1 suffix_2 prefix_9"></div>
Duas colunas como sufixo e 9 como prefixo e uma coluna no meio. 2 + 9 + 1 = 12!
Aproveitando as margens laterais das colunas
É possível também aproveitar as margens direita e esquerda da coluna. Se quiser que seu componente ocupe a largura da margem esquerda, adicione a ele a classe alfa. Quer aproveitar a coluna da direita? Adicione a classe omega!
Simples assim!
Considerações finais: não interfira no trabalho do 960gs
No meu aprendizado observei o seguinte: como o objetivo do 960gs é dispor os elementos da sua página pra você, em momento algum o designer deverá definir em seus arquivos CSS o tamanho dos seus componentes. Isto irá interferir com o estilo definido pelo 960gs e, consequentemente, as coisas não sairão tão bacanas quanto gostaríamos.
Lembre-se: o objetivo do 960gs é resolver o problema da largura e disposição dos elementos da página. Tentar interferir neste processo é a mesma coisa que ir a um médico e começar a dar pitaco em seus diagnósticos, resumindo: não da certo (a não ser que você também seja um médico).
Você também deverá ignorar o atributo float: o 960gs já faz isto pra vocë. Defini-lo nestes componentes só irá anular o framework.
Indo além
E se você quiser um layout com menos ou mais de 960 pixels, ou mesmo um número de colunas diferente de 12, 16 ou 24? Como fazer? Neste caso você precisa de um sistema de grade variável. A SprySoft tem um gerador de grades customizados online e gratuito para você. Basta acessar este endereço: http://www.spry-soft.com/grids/
Grails: entendendo o SiteMesh
Ao aprender Grails um dos componentes que mais me confundiu foi o SiteMesh. Intuitivamente eu sabia o que estava acontecendo, mas toda vez que buscava escrever a respeito acabava me enrolando.
E acredite: você só conhece de fato algo se consegue descrevê-lo em palavras, por escrito. Trabalhando na última parte da minha série “Grails: do Groovy à Web” que está sendo publicada na Java Magazine tive a certeza de finalmente compreender de fato o que é o SiteMesh e como funciona. E a razão pela qual tinha tanta dificuldade é simples: estava viciado no Tiles.
Enquanto o Tiles é baseado no padrão composição (composite), o SiteMesh é baseado no padrão decorador (decorator). A diferença entre os dois é: no composite temos um layout central que contém uma série de espaços a serem preenchidos por templates.
Já o padrão decorator possui um layout central que também possui espaços a serem preenchidos: a diferença é que apenas os elementos ausentes serão preenchidos. Eu não preciso adicionar todos os componentes tal como estava acostumado na época do Struts 1/Tiles.
Bla bla bla demais, é hora de irmos à prática. No Grails, todos os layouts do SiteMesh ficam armazenados no diretório grails-app/views/layouts. Por padrão já há um layout pré-definido, cujo nome é main.gsp armazenado neste diretório. É importante lembrar que se trata de um arquivo GSP convencional, cujo código exponho abaixo:
<html>
<head>
<title><strong><g:layoutTitle default="Grails" /></strong></title>
<link rel="stylesheet" href="${resource(dir:’css’,file:’main.css’)}" />
<link rel="shortcut icon" href="${resource(dir:’images’,file:’favicon.ico’)}" type="image/x-icon" />
<strong><g:layoutHead /></strong>
<g:javascript library="application" />
</head>
<body>
<div id="spinner" style="display:none;">
<img src="${resource(dir:’images’,file:’spinner.gif’)}" alt="Spinner" />
</div>
<div id="grailsLogo"><a href="http://grails.org"><img src="${resource(dir:’images’,file:’grails_logo.png’)}" alt="Grails" border="0" /></a></div>
<strong><g:layoutBody /></strong>
</body>
</html>
A única diferença entre o arquvo GSP e uma view convencional é a presença de três tags: g:layoutTitle, g:layoutHead, g:layoutBody. Falarei delas logo a seguir, porém antes de continuar, vou expor a view mais idiota possível: algo que não exponha basicamente nada, e cujo código fonte é o seguinte:
<html> <head> <meta name="layout" content="main"/> </head> <body> </body> </html>
Colocando a aplicação para executar, e acessando-a, no entanto, é renderizado algo inicialmente inexperado:
De onde saiu este logotipo do Grails? Do layout main que defini anteriormente. No caso, eu instrui o Grails a usar o SiteMesh ao inserir a seguinte tag na minha view:
<meta name="layout" content="main"/>
Esta tag basicamente diz: “aplique o layout definido no arquivo grails-app/views/layouts/main.gsp a esta view”. E aqui entra a jusitificativa do mesh no nome SiteMesh: ao invés de incluir o conteúdo de um arquivo em outro, o que é feito na realidade é a fusão do conteúdo da view no corpo do layout!
Isto fica claro com a descrição das 3 tags que descrevi acima (consulte a primeira listagem para que fique claro):
g:layoutTitle – define qual será o conteúdo da tag title embutido na tag head. Repare qeu esta tag possui um atributo chamado “default”. Caso na view a tag title já esteja preenchida, será incluido no arquivo HTML final o conteúdo da tag title da view. Caso contrário, o conteúdo será aquele especificado no parâmetro default
g:layoutHead – o conteúdo da tag <head> da view será inserido no local do layout aonde a tag g:layoutHead se encontra.
g:layoutBody – o conteúdo da tag <body> da view será inserido no local do layout aonde a tag se encontra.
Resumindo: no SiteMesh não temos inclusão, mas sim fusão.
Espero que com esta descrição o recurso fique tão claro para vocês quanto pra mim.
Grande abraço e até a próxima!
Dica Groovy: simplificando seu código com ‘with’
Imagine que você tenha uma classe tal como a abaixo:
class Pessoa {
String nome
String sobrenome
}
Há duas maneiras de preencher suas propriedades: você poderia usar um construtor como o código abaixo:
new Pessoa(nome:"Henrique", sobrenome:"Lobo Weissmann")
que é bem bacana, mas também poderia escrever um código bem mais tedioso, como este:
def pessoa = new Pessoa() pessoa.nome = "Henrique" pessoa.sobrenome = "Lobo Weissmann"
Entra a instrução with, que é muito similar à que encontramos no Delphi:
def pessoa = new Pessoa()
pessoa.with {
nome = "Henrique"
sobrenome = "Lobo Weissmann"
}







