Codemountain, Paulo Suzart's Blog

Archive for the ‘couchdb’ Category

Caindo do Divã (CouchDB)

leave a comment »

No último Post, confesso que estava bem extasiado com o CouchDB. Acho que deu pra perceber. Então veio a brilhante ideia:

Vou fazer algo pra mapear JSON – Objetos – JSON em Scala e junto com isso, fazer uma forma mais transparente de interagir com o Couch.

Acontece é que eu e umas 8 mil pessoas tivemos esta mesma idéia, claro. 😦

Antes de constatar que outros estavam fazendo o mesmo, e enquanto tentava construir algo, me veio uma questão:

Is CouchDB best suited for dynamic languages?

Na verdade eu deveria ter perguntado: Are dynamic languages best suited for CouchDB? Enfim… de qualquer forma me entenderam e tive o prazer de receber a resposta do Jorge Ortiz, que fez uma grande contribuição pra nós Scaladores. esta semana. Ortiz criou um conjunto de classes e funções utilitárias para tornar a programação Java/Scala ainda mais  fácil.

Em sua resposta, Ortiz  dizia não só que linguagens estaticamente tipadas – como Scala – são perfeitamente candidatas a trabalhar como um banco de dados schema-free, mas também me mostrou alguns materiais.  Lá, estava  o blog do @n8han, o Coderspiel, onde n8han (criador do Wichet Databinder) mostra sua habilidade com Scala, CouchDB, Twitter API, além de fazer exatamente o que eu tinha proclamado fazer no meu post anterior.

Nathan (n8han), criou uma pequena API chamada Dispatch que facilita iterações sobre Http, agindo como um Wrapper para o Apache HttpClient, facilita a iteração com o CouchDB, e de maneira inusitada e muito interessante, utiliza Symbols e Extractors em Scala para fazer o mapeamento JSON – Objeto – JSON. Breve postarei uns exemplos utilizando Couch + Scala + o Dispatch.

Um ponto negativo da API do @n8han é que ele até agora forneceu pouco, ou quase nenhum exemplo prático/real de como usar sua API. E como ele construiu tudo utilizando recursos como Extractors e muito Pattern Matching em Scala, deu um grande trabalho pra entender como as coisas funcionavam, pois as funções implementadas por ele quase nunca declaram o tipo de dados retornado. Daí o trabalho de ler e tentar entender o código das funções pra detectar que tipo de objeto ela pode retornar. Se não fosse pelo eclipse, eu estaria até agora tentando entender. 😛

Ainda assim, o Dispatch do n8han me permitiu bons momentos de diversão com o SBT (Simples Build Tool) e com o GIT. Depois pretendo falar sobre isso.

Outros caras como o @frank06 e Debasish Ghosh também estão engajados em temas desse tipo, e aqui você pode ver uma palavrinha dos dois neste post – super atual, por sinal – do Alexander Lag.

Alexander até  postou no Slideshade, sua apresentação no  Scotland on Rails, onde ele mostrou alguns frameworks em Ruby para trabalhar com o CouchDB. E para me desanimar de vez, ele não mostrou um, mas meia-dúzia de frameworks pra Ruby com objetivo de facilitar mapeamento JSON – Objeto – JSON e interagir com o CouchDB. Ou seja, por que estou gastando meu tempo tentando fazer algo assim? 🙂 Se gastar, terei que fazer algo muito melhor e revolucionário.

Dos frameworks mostrados, o Active Couch realmente me surpreendeu, e vai surpreender muita gente que trabalha com Ruby on Rails, permitindo um modelo de dados mais uniforme entre objetos persistidos em uma base relacional e no Couch. De certa forma foi bom pra dar umas boas ideias.

Mas foi aí que o Debasish Ghosh entrou no circuito, complementando o que o Alex Lang vem pregando.
Debasish falou sobre Convenience over Correctness. A prerrogativa é que o Active Couch fornece uma forma tão semelhante de trabalhar com mapeamento de dados em relação ao Active Record que, pra Debasish, programar assim é usar a conveniência. A conveniência do programador conviver com o Framework de estimação sempre.

Debasish fala ainda que consequencia disso é a inércia que o uso de frameworks nos traz, nos deixando comodamente casados com ele (o framework), tal que nos colocamos cegos diante de novos paradigmas e abordagens que fazem o nosso bom e velho parceiro/framework de estimação parecer irrelevante.

Debasish se pronunciou, e com muita propriedade no que disse, pois o Active Couch tenta colocar no uso do CouchDB algo que ele não é: relação entre registros de entidades/tabelas diferentes como se os dados tivesse sido armazenados numa base relacional. Por isso a conveniência do Active Record e a forma “não correta” de tabalhar com o CouchDB, que é schema-free por natureza.

Debasish cita o CouchRest, que permite construções utilizando a mesma semântica do CouchDB: Views com funções do tipo Map-Reduce, e não operações find, find-by para iteragir com os documentos do Couch. Esta sim é uma forma que me inspirou, talvez um port pra Scala seja uma boa saída.

Aproveitando a visão do Debasish sobre deixar a conveniência de lado e procurar a “corretude”, eu penso que trabalhar de forma mais livre com objetos de domínio no CouchDB (em Scala) talvez seja uma alternativa a se considerar. Forma mais livre pode significar não ter propriedade statica alguma no objeto em tempo de desenvolvimento, e sempre obtê-las com um:

get[T]("propertyName")
//ou ainda:
with[T]('propertyName) { //doSomething }
//E mais além, onde m seria um map,
//ou objeto json detentor dos valores:
 def -:[T](s: Symbol)(op: T => Unit) = { op(m(s).asInstanceOf[T])}
// o uso poderia ser:
-:[Int]('age){ n => println("the age is " + n )}
//the age is 26
//Mas ainda dá pra fazer melhor
//se extendermos o Dispatch.
//Estou trabalhando em exemplos com o Dispatch.

Exato, pode soar como um grande Map, ou com o Delphi, mas sem ser exatamente um Map, tão pouco programar em Delphi.

É isso! Este post é como um resumo do que tenho lido, pensado e discutindo com pessoas ao redor do mundo.

Para complementar, tenho analisado com um amigo sobre a possibilidade do uso do CouchDB ou o MongoDB para armazenar logs/auditoria na empresa em que ele trabalha. Outra base não relacional na mira é o Voldemort.

Este final de semana não postei nada por ter utilizado ele pra estudar Erlang 😉 e recrusos avançados de Pattern Matching em Scala.

Vamos vendo o que acontece daqui pra frente.

Written by paulosuzart

abril 7, 2009 at 12:40 am

Publicado em couchdb, scala

Scala no Divã (CouchDB)

with 2 comments

Muito se tem falado em bases de dados não relacionas. Então, desde que comecei a ler sobre o Dynamo da Amazon e o Big Table do Google me interessei pelo tema.

De fato, uma Base de Dados Relacional não é a bala de prata da persistência de dados. Existem muitas situações onde uma abordagem livre de schema, orientada a documentos ou chave-valor é mais conveniente.

A verdade é que ultimamente eu e muitos amigos discutimos bastante sobre o por quê de certas coisas dentro da tecnologia de desenvolvimento de software, e uma delas é a “obrigatoriedade” de persistir dados no que se tornou padrão pra aplicações corporativas: Bases de Dados Relacionais. Existem outros questionamentos sobre a natureza estatica da web e a escravidão que nos sujeitamos ao usar certas tecnologias. Mas isso é outro tema.

O post de Dion Hinchcliffe foi o que faltava motivação para estudar uma base não-relacional. A escolhida foi o Apache CouchDB, depois que Ted Neward opinou sobre o Book of JOSH, que compartilhei no meu Reader esta semana. Ted sugeriu o Couch como mecanismo de persistência na pilha Json Osgi Scala e Http.

CouchDB

O CouchDB é orientado a documentos expressos no formato JSON, e o mais interessante é que ele é acessado via HTTP por uma API REST. A princípio também soou estranho pra mim.

O CouchDB conta com algumas libs (construídas por terceiros) que evitam invocações HTTP “manualmente” para diversas linguagens. Dentre as linguagens encontramos Java, Ruby, PHP, Erlang, e até Javascript. Que tal persistir direto do seus formulário HTML usando Javascript? Não vejo mal algum. Alias, as receita de bolo 3 e 4 camadas para a construção de aplicações tendem a se tronar mais raras com o fortalecimento do SOA, das próprias bases de dados não-relacionais dentre outros fatores. Veja o post do Dion.

Instalei o Couch no meu Ubuntu 8.04 com sucesso seguindo este passo-a-passo (observe um comentário no final do post, é o que faz funcionar corretamente) e comecei a brincar usando CouchDB4J e o Futon, uma especie de console Web muito legal.

Obviamente iniciei meus teste com um objeto Person de todos os meus posts :). Que em JSON vira:

{"_id":"4b32206602c372304530a69813a7a0ae","_rev":"741003815","name":"Paulo","age":"26","type":"Person"}

O Couch não possui tabelas, ou seja, todos os documentos são tratados igualmente, por isso adicionei uma propriedade type pra facilitar a criação de Views no Couch. O _id foi fornecido pelo próprio Couch, nos livrando da preocupação de um identificador único, _rev é a revisão do documento, que se alterado ganha um novo valor neste campo junto com as alterações. As revisões permitem enchergarmos um mesmo documento em pontos distintos no tempo.

As Views são o recurso mais interessante do Couch, e permitem a aplicação de funções Map/Reduce nos documentos. O que isso quer dizer? Quer dizer que é possível construir consultas e relatórios com os documentos e até mesmo junções. Views são armazenadas em documentos, que devem possuir no seu identificador o valor _design/ como prefixo . As Views são então armazenadas no campo views deste documento.

Aqui um documento que define três Views de exemplo:

{"_id":"_design\/pview",
 "_rev":"713212252",
 "views":{
       "by-name":{
           "map":"function(doc) { if (doc.type == 'Person') emit(doc.name, null) }"},
       "by-age":{
           "map":"function(doc) { if (doc.type == 'Person') emit(doc.age, null) }"},
       "teens":{
           "map":"function(doc) { if (doc.type == 'Person' && doc.age <= 18) emit (doc.name, null) }"}
  },
 "language":"javascript"}

As views foram escritas em Javascript, mas podem ser escritas em Ruby e Erlang também. Ao acessar http://localhost:5984/mydb/_view/pview/teens, que retorna o nome dos documentos de type Person menores de 18 anos, o resultado é:

{"total_rows":1,"offset":0,"rows":[
{"id":"1f8630284bbe5912a32990908933f00b","key":"Gabriel","value":null}
]}

Bem, a intenção do post não é mesmo fazer uma mega introdução, nem um tutorial sobre o CouchDB, mas sim  anunciar que a partir de agora você não vai encontrar apenas posts sobre Scala, mas também sobre essa maravilha criada por Damien Katz

Como pontapé inicial, comecei a escrever uma pequena lib pra facilitar o mapeamento de um objeto em scala
para documentos JSON, para então fazer comunicação com o Couch. Você pode dizer, por que não usar o
CouchDB4J? A princípio para que Scala possua um lib para este fim construída em Scala.

Aqui vai uma prévia. Mas comecei a escrever de uma forma desordenada e sem muito planejamento e devo recomeçar.
Os primeiros testes já funcionam, mas não achei muito bonito:

class JSONPerson(n: String, a : Int) extends Person(n, a) with JSONifier {

  property("name"){
    mapsTo (name) (name = _)}

  property("age") {
    mapsTo (age.toString)( (n) => age = Integer.parseInt(n))
  }

  metaProperty("type", "Person")

}

Lembrando que Person possui apenas dois atributos (name, age), a propriedade type se comporta como uma meta-propriedade que ajuda na hora das Views. Ou seja, a função property recebe a chave da propriedade e  um objeto que deve conhecer como ler  e gravar a propriedade, respectivamente. Pra isso a função mapsTo foi usada pra gerar este objeto, recebendo como parâmetro as duas funções de leitura/escrita.

Para gerar um Document (do CouchDB4J) basta usar a função json da trait  JSONifier e então usar o CouchDB4J (por enquanto) para salvar o documento. É um misto de DSL que permite mapear Objetcts2JSON/JSON2Object em Scala com a criação de uma lib para se comunicar com o Couch. De repente não vai ser necessário criar uma forma de mapear os objetos pra JSON, e sim uma forma mais conveniente de usar o proprio XStream, ou o JSON-lib.

É isso. Estou avaliando a viabilidade disso e o quanto vale a pena fazer tal coisa, enquanto isso aguarde mais coisas sobre CouchDB e Scala, e claro, relaxe.

Written by paulosuzart

março 30, 2009 at 12:28 am

Publicado em couchdb, Java, scala