Codemountain, Paulo Suzart's Blog

Archive for the ‘Java’ Category

Python, Java NIO => JTornado

leave a comment »

Desde o últmimo post parei com Scala. 0.o

Devido a um problema com as versões da linguagem (incompatibilidade binária e mudanças na estratégia de Collections para aumentar a compatibilidade com o Java), muito se especulou sobre a estabilidade da linguagem e muitas discussões acirradas (vejam os tweets entre @jboner e @codemonkeyism. Por este motivo tirei férias de Scala e mergulhei profundamente em Python.

Fui surpreendido com uma linguagem extremamente madura, poderosa e completa. Foi tão apaixonante quanto Scala. Como já desejava construir algo no GAE usando python, não perdi tempo e criei o Twittograph (@twittograph), o que deve ser em breve a nova maneira de pedir autógrafos aos seus ídolos.

Então estudei muito (não só Python): Eventlet, Twisted, Tornado, Linux Epoll, Python Select, Python Fabric, fiz Gists, Avro, Boost e Java NIO, clojure. Devo com certeza ter esquecido algo. Não dá pra comentar de cada um destes ou o post ficaria bastante extenso. Fica a dica: Python, Tornado e Clojure. Usem.

Passei a usar o Python Fabric no dia-a-dia, e usei o Tornado para construir o Twittograph. Como vocês podem perceber eu estava navegando pra todos os lados ao mesmo tempo, e as chances de ficar parado eram grandes, até que @abraaoisvi me alertou que eu deveria focar. Foi então que @rafaelfelini – até então recém apaixonado por python – sugeriu “construir” uma versão do Tornado em Java.

Assim nasce o JTornado. Construído em conjunto com o Rafael. Tá, o nome não é lá essa criatividade. Pensamos em Cyclone, Transtornado, Huracan, etc. Bom, deixa JTornado mesmo.

Se você quer praticidade, precisa conhecer o Tornado, feito pelo Facebook (link acima). Mas se você quer esta mesma praticidade em Java e sabe que Java para Web != Servlet. Conheça o JTornado. O JTornado pode ser visto como um framework web com um servidor de alta performance embutido, ou um servidor de alta performance com um framework web embutido. Este é um direcionamento que ainda vamos discutir.

O próprio @felipejcruz, criador do easy_tornado já se mostrou a favor do foco num framework para aplicações assíncronas de rede, que eventualmente oferece um framework web. Vamos ver!

Logo logo devo postar os percalços enfrentados para usar Java NIO e ao mesmo tempo usar low-level concurrency, leia-se threads. Como foi construir um server baseado em processos (Tornado) utilizando a JVM que nos limita neste aspecto. E muito mais. Devo escrever sobre algumas boas práticas – que acreditamos que sejam boas – para o uso de NIO aliado à alta performance com threads.

Veja algumas discussões no Stackoverflow.com durante este tempo:

Como não pode faltar código num post, segue uma micro app usando o JTornado, mas escrita em Clojure:

;Starts an JTornado HTTP Server and a sample RequestHandler.
; Bit verbose due to compilation directives. Recommendation is to generate
; a set of macros to hide this.
(ns org.ctornadoweb
; Compiled and implements a static main method to start the server
  (:import (org.jtornadoweb HttpServer)
           (org.jtornadoweb.Web$Application)
           (org.jtornadoweb.Web$RequestHandler))
  (:gen-class :prefix "server-"))

(gen-class
 :name org.ctornadoweb.MyHandler
 :extends org.jtornadoweb.Web$RequestHandler
 :prefix "do-")

(defn do-get [this]
  "Handles the HTTP GET method"
  (.write "hello clojure"))
(defn do-post [this]
  "Handles the HTTP POST method"
  (.write (.getArgument "name" "default" false)))

(defn server-main []
  "main method"
 (.listen
  (org.jtornadoweb.HttpServer.
   (.add (org.jtornadoweb.Web$Application.) "/" org.ctornadoweb.MyHandler)
     false nil false) 8089))

;use (compile 'org.ctornadoweb)

Basta fazer um curl http://localhost:8089 e tudo funcionará 🙂

Aguarde o próximopost para informações completas de Java NIO  e JTornado. 😉

Update: Desde que a versão Scala 2.8.0 final foi liberada, retomei os estudos e meu interesse pela linguagem continua. A propósito, o único motivo para o JTornado ser construído em Java é ganhar tempo, pois os colaboradores se sentem mais a vontade com Java. Provavelmente algumas funcionalidades podem ser escritas em Scala ou até mesmo Clojure.

Written by paulosuzart

julho 23, 2010 at 2:51 pm

Publicado em Java, nio, python

Tagged with , ,

Oracle Coherence: Além do Put e do Get

with 4 comments

Segundo a querida Wikipedia, “Cache é uma coleção de dados duplicando valores existentes em algum lugar ou previamente calculados, …” [Tradução minha]. Aplicações frequentemente utilizam cache para poupar recursos com custo alto de acesso tais como Bases de Dados Relacionais, arquivos, comunicações remotas. A intenção é manter o mais próximo da aplicação, de maneira rápida e barata o acesso a dados necessários para alguma computação, ou seja: Caches são em sua maioria um conjunto de dados em memória.

Alguma vez na vida já utilizamos Cache no desenvolvimento de uma aplicação. E muito frequentemente este Cache está fortemente integrado a um framework ORM como Hibernate ou TopLink. O lado bom é que abstrai-se para o desenvolvedor os meios necessários para obtenção de dados a partir do cache, ou a partir da fonte de dados real (Banco de Dados nesse caso).  Mas essa é de longe a estratégia mais simples e, de fato, mais pobre quando se trata de tirar o máximo da sua ferramenta de Caching ou data grid.

Outro uso comum de Cache são os Caches locais, os que residem na memória da aplicação. É aí que o uso dos cache.get(key) e cache.put(key, value) aparecem, mas o simples uso destes dois métodos traz uma série de questões:

  • Toda vez que uma entrada no cache é atualizada, como e quando devo aplicar tais mudanças para a fonte de dados original (ex.:  Base de Dados)?
  • E se eu obtiver uma entrada no cache, iniciar um processamento e, antes de concluir este processamento a entrada for alterada?
  • Eu tenho servidores geograficamente distribuídos, como compartilhar um mesmo cache para um recurso extremamente custoso entre estes servidores?
  • Utilizo Cache para evitar acesso constante à Base Relacional, mas minha aplicação é “Clusterizada” e uma próxima requisição frequentemente é destinada a um servidor cuja entrada ainda não foi inserida no Cache. Como evitar acessos repetidos para os mesmos dados processados em servidores diferentes?
  • Acessar uma entrada pela chave não é suficiente, isso me força a criar chaves modificadas – como “SP-Republica”, uma junção entre dados de dois campos distintos de uma mesma entidade (supondo Endereco(UF, Bairro)) – ou mesmo ignorar o cache e efetuar consultas constantemente na Base de Dados.
  • Preciso realizar uma operação em milhares de entradas no cache, mas cada get() executado traz os dados para a memória local o que pode causar OutOfMemory, como contornar isso?

Poderíamos ter um Post inteiro só com questionamentos do gênero. Pelo menos um destas dúvidas você já teve, certo? Resolvi apresentar o Oracle Coherence desta maneira, respondendo estas. O Coherence é uma suite poderosa para Data Grid e Cache provida pela Oracle e permite a replicação (particionada) de dados em cluster.

Não é minha intenção (nem seria possível) cobrir todos os aspectos da ferramenta, mas sim de oferecer um Overview, um ponto de vista e até mesmo dicas para o uso da ferramenta baseado na minha experiência.

Neste Post trago uma resposta ao menos à primeira pergunta:

Toda vez que uma entrada no cache é atualizada, como e quando devo aplicar tais mudanças para a fonte de dados original (ex.:  Base de Dados)?

A técnica comumente utilizada para escrita simultânea no cache e na fonte de dados é conhecida por Write-Through (veja artigo na Wikipedia). É possível utilizar um DAO conhecedor do Cache que faz um put e um insert em uma tabela, por exemplo. Dessa maneira o Write-Through é feito com o Cache-aside, ou seja o cache participa passivamente neste processo.

O Oracle Coherence utiliza o conceito de CacheStore e oferece a interface com.tangosol.net.cache.CacheStore para onde a operação de persistência é delegada:


public class YourCacheStore implements com.tangosol.net.cache.CacheStore {
   ...
   @Override
   public void store(Object key, Object value) {
   ... // code to actually persist the value.
   }

   @Override
   public void storeAll(Map cached) {
      for (Object key : cached.keySet()) {
        ... //persist it!
      }
   }
}

O CacheStore é uma classe qualquer que conhece como obter e salvar definitivamente as informações para uma entrada no Cache. Logo, não é relevante para o Coherence como o dado é acessado, seja via JDBC, JPA, WebService, RMI, etc. O Coherece delagará a execução para a classe configurada em um cache do tipo read-write-backing-map-scheme:

	<read-write-backing-map-scheme>
		<scheme-name>DB</scheme-name>
		<internal-cache-scheme>
			<local-scheme/>
		</internal-cache-scheme>
		<cachestore-scheme>
			<class-scheme>
				<class-name>com.codemountain.grid.store.YourCacheStore</class-name>
			</class-scheme>
		</cachestore-scheme>
		<write-delay>5s</write-delay>
                <write-batch-factor>0.3</write-batch-factor>
	</read-write-backing-map-scheme>

Note o parâmetro write-delay:5s, isso significa que o Coherence vai iniciar a escrita após o tempo especificado de 5 segundos. Assim passamos a fazer o uso da técnica de Write-Behind, ou seja os dados se mantém consistentes e disponíveis para a aplicação, enquanto num momento futuro o Coherence iniciará uma escrita Assíncrona para o repositório de dados.

Até aqui temos um mecanismo integrado à ferramenta de Cache, garantindo consistência dos dados em cache e em Base de Dados. O Coherence executa o que ele chama de coalescing , ou seja, sucessivas escritas a uma mesma entrada não gerarão diversos updates/inserts para a entrada.

Write-Behind é uma técnica particularmente interessante e pode reduzir drasticamente o acesso a uma base de dados enviando em lote uma quantidade maior de registros alterados ou inseridos. É possível configurar um fator (write-bacth-factor:0.3), tal que, toda entrada cujo tempo de espera para persistência tenha atingido uma percentagem do  tempo total de delay, será enviada em lote para escrita. A formula para o wirte-batch-factor é : (1 – 0.3) * 5 = 3.5s.

Sem esta possibilidade de definir uma janela de tempo, as escritas só aconteceriam num momento diferente do insert da entrada no cache, mantendo a alta carga carga no banco de dados.  Um CacheStore implementado corretamente deve tirar proveito disso e utilizar apenas uma conexão/transação para a escrita do lote através do método storeAll(). Ah! Fique atento as necessidades de negócio e até mesmo acesso de outras aplicações a esta base dedados, estes são pontos determinantes para a adoção desta técnica.

Com o Write-Behind você pode cortar pela metade a quantidade de acesso à base de dados. Numa aplicação onde eu e minha equipe aplicamos o Oracle Coherence, eliminamos um INSERT + SELECT + UPDATE por apenas um INSERT. Ou seja, o dado era criado em memória no cluster, obtido em um momento posterior e então atualizado. Com o Coherence, e as operações ocorrendo em memória, todas as manipulações se traduzem para um único INSERT no final do procedimento. Multiplique 3 acesso à base de dados por 2 milhoes de transações e note que uma operação é muito menos custosa para todo o seu ambiente.

A geração de IDs para registros na base de dados pode ser feita em cluster de forma segura (leia-se consistente) evitando até mesmo um MY_SEQUENCE.nextval. 🙂

É importante saber que há também aqueles que não acreditam em Caches como a melhor solução. Como disse Greg Linden: “Camadas de Cache adicionam complexidade ao design, latência para entradas não encontradas no cache, e uso infeficiente de recursos ‘clusterizados’” (Tradução livre minha). Greg ainda advoga a favor da remoção das camadas de cache e transferência de tais máquinas para a camada de banco de dados, que por sua vez deve apostar alto no particionamento e em seus próprios mecanismos de cache.

Ao tomar decisões de design para aplicações que demandam alta disponibilidade, baixar latência e alta performance, esteja ciente das vantagens e desvantagens das diversas topologias e abordagens disponíveis, inclusive o caching.

Todas as informações sobre o produto podem ser encontradas na documentação do próprio produto Oracle Coherence de propriedade da Oracle. Este blog não expressa direta ou indiretamente quaisquer opinião da Oracle.

Written by paulosuzart

novembro 3, 2009 at 12:59 am

Publicado em coherence, escalabilidade, Java, oracle

Tagged with , ,

Adeus GenericAbstractBaseWhateverDAO!

with 3 comments

Update (09/10/09): Conversando com Daniel Guggi (Desenvolvedor Grepo), ele me alertou sobre a possibilidade de uma configuração mais enxuta no applicationContext.xml do Spring. Eu mantive essa configuração no post por ser a utilizada no projeto em questão. Daniel também falou sobre a versão estável do framework que será lançada até o final da semana que segue.

Outra vez longe do blog! Passei o último mês até o pescoço em um projeto um pouco apertado. Algo que acontece só as vezes não é mesmo?

Despois de quase um ano focado apenas em SOA e todo seu “pequeno” universo, precisei fazer o setup e os primeiros códigos/camadas deste projeto. Logo, juntando o pouco tempo para entrega com minha ausência na construção de aplicações standalone no último ano, temos como resultado: Desespero! 🙂 Mas um desespero divertido. ;p

A aplicação possui bastante CRUD, e na equipe começaram os rumores dos famosos AbstractDAO. Wow! Realmente não dá pra fazer o mesmo código sempre pra operações básicas. Mas construir seu próprio AbstractDAO tem lá seus riscos e desvantagens, a saber: não atingir um nível de abstração satisfatório que permita a construção realmente rápida de telas básicas, perda de tempo fazendo a abstração se não existir uma, discussões sobre quem não obedeceu a abstração corretamente, e coisas do gênero.

E é aí que entra o GREPO, um framework da Codehaus que se entitula como simples, flexível e consistênte. E é verdade. A simplicidade pode ser atribuída ao fato de nenhum implementação ser necessária para o seus DAOs. Isso sim é ganhar tempo!

O Grepo, ou Generic Repository permite iterações via JPA, Hibernate e ainda execução de procedures. Meu foco aqui é JPA. O Grepo trabalha em conjunto com o spring, então os exemplos aqui foram construídos numa aplicação com Spring. Chega de conversa e vamos ao primeiro DAO:

//Entidade
@Entity
public class Administrador {
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Integer id;

  @Basic
  private String email;

  @Temporal(TemporalType.TIMESTAMP)
  private Date cadastro;
  //get/set etc ...
}

//Código do DAO
public interface AdministradorDAO extends ReadWriteJpaRepository<Administrador, Integer> {}

Supondo uma entidade Administrador de Primary Key do tipo Integer, criamos a nossa interface AdministradorDAO que extende ReadWriteJpaRepository passando a entidade e o tipo da sua chave como parâmetro de tipos (generics).

ReadWriteJpaRepository, como o nome já diz, fornece operações de leitura e escrita em uma entidade, ao contrário de ReadOnlyJpaRepository. E é só! Imagine agora o código de uma classe Service:

@Autowired
private AdministradorDAO dao;

public Administrador findById(Integer id) {
  return dao.find(id);
}

public void removeAdministrador(Administrador admin) {
  dao.remove(dao.merge(admin));
}

Na verdade, a interface herdada fornece todos os métodos do EntityManager JPA: find, remove, refresh, merge, lock e persist. E isso sem sem escrever código algum para o DAO. Mas sim, há necessidade de escrevermos consultas que permitam retornar entidades que não seja pelo seu id.

Mantendo a abordagem de código zero, definimos um método na interface do dao assim:

public interface AdministradorDAO extends ReadWriteJpaRepository<Administrador, Integer> {
   @GenericQuery(query = "from Administrador where email = :email")
   public Administrador getByEmail(@Param("email") String email);
}

Quase dispensa explicações! adicionando este método, definimos via anotação a query que deve ser executada. O parâmetro nomeado JPA é mapeada para o argumento email passado ao método via anotação @Param(“email”). É possível usar named queries, passando em @GenericQuery o valor de queryName. O Grepo fornece algumas possibilidades para um bind de um método na interface para uma named query definida, por exemplo, na entidade.

Todo tipo de query jpa, incluindo o uso de QueryHints é possível. Operações de deleção, update, etc, tudo pode ser usado normalmente sem limitações.

Outra sitaução comum é a filtragem de entidades a partir de parâmetros preenchidos em um formulário de filtro html, o que exige uma query gerada dinamicamente a partir dos dados pesquisados. Numa tela de filtro de administradores onde a busca por e-mail e/ou data de cadastro usamos o AbstractJpaQueryGenerator para gerar a consulta:

public interface AdministradorDAO extends ReadWriteJpaRepository<Administrador, Integer> {
  @GenericQuery(query = "from Administrador where email = :email")
  public Administrador getByEmail(@Param("email") String email);

  @GenericQuery(queryGenerator=AdministradorFiltro.class)
  public List<Administrador> findByFilter(AdministradorFiltroBean filtro)

  public static class AdministradorFiltro extends  AbstractJpaQueryGenerator {
    @Override
    public String generate(QueryMethodParameterInfo info) {
      AdministradorFiltroBean bean = info.getParameter(0, AdministradorFiltroBean.class);
      StringBuilder query = new StringBuilder();
      query.append(" from Administrador where 1=1 ");
      if (bean.getEmail() != null){
        query.append(" and email = :email ");
        this.addDynamicNamedParam(new DynamicNamedJpaParam("email", bean.getEmail()));
      }

      if (filtro.getDe() != null) {
       query.append(" and cadastro >= :de");
       this.addDynamicNamedParam(new DynamicNamedJpaParam("de", bean.getDe()));
      }

      if (filtro.getAte() != null) {
       query.append(" and cadastro <= :ate");
       this.addDynamicNamedParam(new DynamicNamedJpaParam("ate", bean.getAte()));
      }

      return query.toString();
    }
  }
}

Preenchendo o Bean de pesquisa que guarda o e-mail e data de início e fim de cadastro a pesquisar, passamos como argumento para o método findByFilter de AdministradorDAO e automagicamente o Grepo invoca o AdministradorFiltro, que por sua vez implementa o método generate.

QueryMethodParameterInfo armazena os parâmetros passados para a inferface de pesquisa, no nosso caso o único parâmetro passado é o Bean de Filtro. Note tambémm as classes DybamicNamedJpaParam, que é responsável por fazer o mapeamento do valor do Bean e um parâmetro nomeado.

Pronto, temos um filtro conciso!

Outro ponto que vale a pena observar é que os nomes de métodos no DAO estão todos em inglês. Isto por que o Grepo usa convention over configuration para decidir pela invocação de getSingleResult() ou getResultList() por exemplo. As convenções seguidas são a partir do prefixo dos métodos e podem ser: is|has|find|get|load|delete|updat.

Mas o Grepo não força o uso destes prefixos, voce pode escolher um nome qualquer e construir seu próprio QueryExecutor, ganhando flexibilidade como prometido. Confesso que foi ótimo usar estas convenções e a equie absorveu muito rápido o uso delas.

Você deve estar se perguntando onde configurar isso, ta tudo muito bonito e muito simples até agora. E continuará simples. Mas afinal de onde vem o código para a interface do DAO? Qual a instância injetada classe service acima via @Autowired?

Com pequenas configurações no seu Spring applicationContext.xml, você define seu repositório abstrato de onde todos os seus repositórios (leia-se DAO) irão herdar, passando pra ele o EntityManagerFactory, configurações de transação (opcional) e outras configurações do Grepo:


<!-- Configuracao repositorios -->
<import resource="classpath:META-INF/spring/grepo-query-jpa-default.cfg.xml" />
<bean id="abstractRepositoryTarget" abstract="true">
  <property name="entityManagerFactory" ref="entityManagerFactory" />
  <property name="executorFindingStrategy" ref="grepo.queryExecutorFindingStrategy" />
  <property name="resultConversionService" ref="grepo.resultConversionService" />
  <property name="executorFactory" ref="grepo.defaultQueryExecutorFactory" />
</bean>

<!-- Todo repositorio sera um filho do repositorio abstrato -->
<bean id="abstractRepository" abstract="true">
  <property name="interceptorNames" value="grepo.genericQueryIntroductionInterceptor" />
</bean>

<!-- nossa interface -->
<bean id="administradorDAO" parent="abstractRepository">
  <property name="proxyInterfaces">
    <value>com.codemountain.dao.AdministradorDAO</value>
  </property>
  <property name="target">
    <bean parent="abstractRepositoryTarget">
      <constructor-arg value="com.codemountain.Administrador" />
    </bean>
  </property>
</bean>

A interface é registrada no Spring, e o Grepo fornece a implementação que por traz utiliza Spring JPA Template através de um proxy dessa interface. A EntityManager Factory utilizada foi previamente configurada.

Um DAO Grepo pode ser transacional se a propriedade transactionTemplate for configurada com um transactionManager para o  bean abstractRepositoryTarget.

A intenção do post é apresentar o básico deste framework que realmente conseguiu me chamar atenção. O projeto que citei no início do post está entrando em produção e os desenvolvedores envolvidos ficarm muito satisfeitos com o uso desta ferramenta.

De fato um DAO capaz de fornecer operações básicas é frequentemente necessário, o que não precisamos é gastar tempo construindo ou utilizando implementações não capazes de satisfazer as necessidades do projeto. Experimente, vale a pena. Até a próxima. 🙂

Written by paulosuzart

outubro 8, 2009 at 3:49 pm

Publicado em Java, jpa, spring

Tagged with , , ,

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

Scala, Scala, Scala, em Java

with 3 comments

Isso, mais uma vez vamos falar do Scala, Scala, Scala. Este post rendeu. E rende até hoje pequenas discussões interessantes com amigos.

A diferença agora é que resolvi fazer a mesma coisa usando Java 1.5 com o auxílio da API Functional Java, que promete deixar o Java 7 com uma cara bem característica de Scala. Isso por conta da adição de Closure e outras características funcionais.

A API Functional Java vem sendo criada por Tony Morris, e pelo pouco que pude fuçar, está ficando bem interessante.

Eu não quero parecer tão ingrato com Java, afinal é a linguagem/Plataforma que garante o pão nosso de cada dia. Por isso vamos aos mesmo exemplo com esta tão querida linguagem que está tentando acompanhar a onda funcional:

1. Obter o quadrado de cada elemento em um List de 1 a 5.


import static fj.data.List.list;
import fj.F;
import fj.data.List;
//Observe os imports

private static final List&amp;lt;Integer&amp;gt; numbers = list(1, 2, 3, 4, 5);
//... aqui começa nosso método main

		List<Integer> c = numbers.map(new F<Integer, Integer>() {



			public Integer f(Integer arg) {

				return arg * arg;

			}

		});



		System.out.println(makeString(c, ",")); // {1,4,9,16,25}



A função map também está disponível na API, o que facilita muito. Note que o código é identico, o que muda é a verborágica syntax Java. 😉 (Também é possível fazer com foreach de List que é outra opção quando não se quer criar uma segunda lista com os resultados).

2. Imprimir os elementos maiores que 3.

		List<Integer> gt3 = numbers.filter(new F<Integer, Boolean>() {



			public Boolean f(Integer arg) {

				return arg > 3;

			}

		});



		System.out.println(makeString(gt3, ",")); // 4,5

A API não possui a função reduceLeft nem reduceRight, mas podemos alcançar um resultado semelhante usando uma função que compõe as funções de reduce: folding. Aqui temos o foldLeft, uma função aplicada da esqueda para a direita para cada resultado esquerda operação direita. ou seja: 1 + 2 = 3 + 3 = 6 + 4 = 10 + 5 = 15 + 0, zero é o segundo argumento de fold. Mas sinceramente, fazer isso sem a promessa do Java 7 chega a ser cansativo. 😦

Continuando com o último exemplo temos:

3. Soma de todos os elementos.

		final int b = numbers.foldLeft(new F<Integer, F<Integer, Integer>>() {

			public F<Integer, Integer> f(final Integer i) {

				return new F<Integer, Integer>() {

					public Integer f(final Integer j) {

						return i + j; 

					}

				};

			}

		}, 0);



		System.out.println(b); // 15

Filter e os métodos de 1 e 2 recebem um objeto do tipo F, que é uma interface com um único método chamado f, cuja implementação é por nossa conta.

Ah! o makeString é só um método statico para adicionar uma ‘,’ entre os elementos do list. Na listagem completa deste post você pode conferir este método que foi feito usando recursividade de uma forma bem exagerada pra fazer essa simples tarefa. Mas mostra como declarar funções dentro de funções faz muita falta em Java. Digo isso por que a função subMakeString não faz sentido algum sem a função printipal makeString, tornando nossa classe de exemplo com métodos sem muito nexo. A verdade é que fica bem ruim pra fazer certas coisas.

Construções desse tipo (com classes anônimas) já vem sendo usada há muito tempo, e eu particularmente gosto muito e uso, mas é cansativo de escrever tanta coisa, sem falar que em muitas situações é complicado para ler e entender o que se passa.

Resumindo, podemos construir uma ou outra coisa funcional com Java, e com auxílio de APIs como estas a coisa se torna mais interessante. Mas a syntax sempre vai nos surpreender negativamente como a grande vilã e o grande impecílio para o comportamento funcional em Java puro.  Além disso, note que os exemplos não são identicos, pois se fossem identicos, teriam muuuuuuuuito mais código. E afinal, vale a pena? Até que ponto esta linguagem suporta programação funcional se ela não se tornar de fato uma linguagem hibrida OO/Funcional?

O pessoal do Java tem que correr, pois muito se tem questionado a respeito da linguagem Java, do quanto ela já evoluiu e do quanto ela ainda poderá (?) evolir. Talvez, transformando a liguagem, ela ainda permaneça outa década no mercado, caso contrário, vamos continuar a assistir grandes sistemas sendo construídos em outras linguagens.

Dê uma olhada nesta API, os métodos para manipulação de lista com um pensamento funcional podem ajudar muitosuas  soluções no dia-a-dia.

Written by paulosuzart

março 23, 2009 at 10:48 pm

Publicado em Java, scala

Igualdade em Scala

leave a comment »

Post curto outra vez enquanto nos recuperarmos de um outro mais longo que fiz duas semanas atrás.

O título Igualdade foi uma referência ao inglês Iquality, que traduzindo pra programação, é um ponto de falha extremamente comum entre programadores Java, sejam principiantes, sejam veteranos.

Voltemos à nossa classe Person, dessa vez em Java:


public class Person {

	private String name;

	public Person(String name) {
		this.name = name;
	}

	public String getName() {
		return this.name;
	}

	@Override
	public boolean equals(Object obj) {
		return this.name.equals(((Person) obj).getName());
	}

	public static void main(String[] args) {
		Person p1 = new Person("Yo mismo");
		Person p2 = new Person("Yo mismo");
		System.out.println(p1 == p2); //false
		System.out.println(p1.equals(p2)); //true
	}
}

O método equals foi sobrescrito em Person para permitir comparações entre dois objetos do tipo Person. Assim, se dois objetos Person com um mesmo valor para nome forem comparados, a invocação de equals deve ser verdadedeira. Mas note que ao fazermos o uso do operador ==, temos um resultado negativo.

Tudo bem, já sabemos que o operador == da linguagem Java irá comparar as referências, e não seus valores, ainda que sobreescrevamos o método equals. É por isso que sempre que desejarmos comparar a igualdade de dois Person, temos uma forma não intuitiva de comparação utilizando equals, humanamente falando. É verdade que temos que ficar bastante atentos para evitar grandes dores de cabeça por conta de equals/==.

E como Scala resolve esta questão? Vamos à mesma classe Person, agora em Scala:

//A gigante classe person
class Person(val name: String) {
	override def equals(that: Any) = name == that.asInstanceOf[Person].name
}
//Objeto que usa a classe Person
object Main{
	def main(args: Array[String]) = {
		val p1 = new Person("Yo mismo")
		val p2 = new Person("Yo mismo")
		println(p1 == p2) //true
		println(p1 equals p2) //true
                println(p1 eq p2) //false
	}

Calma, não tem trecho de código faltando, esta classe é equivalente à escrita logo acima em Java. Exceto pelo uso de parametric fields, que por hora vamos entender como um parâmetro de uma classe, que ao ser definido com um val ou var, se torna membro público desta classe. Ver post longo para mais sobre classes parametrizadas.

O modificador override é utilizado de forma semelhante à annotation @Override para equals. Aqui, o compilador infere que o tipo de retorno do método deve ser Boolean, pois a última operação (e única) do método é uma comparação entre o name da instância alvo e o nome de that. Veja também um cast de that para Person, permitindo-nos alcançar a propriedade name.

Abaixo, temos o nosso método main invocando a mesma sequencia de operações que o trecho Java além de uma invocação a um méto chamado eq. A grande diferença a ser notada na realidade é a invocação do método == de p1 que retorna TRUE. Este método é  originado de AnyRef, a classe mãe de todas as referências em Scala (semelhante a Object em Java).

Além de não ser um operador nativo, o que dá uma cara mais orientada à biblioteca para a linguagem, o método == é um alias à invocação x.equals(arg0), construído sob o conceito de relação de equivalência matemática. Ao fornecermos uma implementação customizada para equals como neste caso, devemos garantir que este métodos se comporte como uma equivalência matemática para então compararmos nossos próprios objetos Person de mesmo nome com o método == e obter um retorno verdadeiro ao invés do surpreendente e intrigante false.

Note que a comparação entre dois objetos do tipo Person é delegada para a comparação entre seus nomes, que são do tipo String. Diferente de java, duas Strings ou qualquer outra coisa com mesmos valores tem retorno verdadeiro para invocações de ==. E isso garante a nossa igualdade entre p1 e p2.

O código em Scala ainda traz a invocação de um terceiro método, o método eq. Este se destina exclusivamente a comparar referências. Logo, temos uma opção clara, à prova de equívocos e sob nosso controle para comparação de valores ou de referências. O método eq, além de obedecer ao conceito de relação de equivalência, adiciona três outras características ao seu comportamento que são:

  • Para toda instância diferente de null de x e y do tipo AnyRef, multiplas invocações de x.eq(y), devem retornar consistêntemente true, ou consistêntemente false.
  • Para toda instância diferente de null de x do tipo AnyRef, x.eq(null) e null.eq(x) devem retornar false.
  • null.eq(null) retorna true.

De fato, é muito natural entender que dois objetos iguais possam ser comparados com ==, evitando qualquer dúvida. Tudo agora vai depender da necessidade em questão. Quer comparar o conteúdo lógico, valores, etc, use o ==. Quer comparar referências, use eq.

Se quiser matar a curiosidade sobre comparações numéricas, as chamadas Value Classes, clique aqui.

O fonte da classe Java você encontra aqui, e o da classe Person aqui. Boa diversão!

Obs: Este post não cobre todas as características de Any, AnyRef, ou AnyVal. Além disso é importante observar sempre as questões envolvendo hashCode quando fazemos nossa própria implementação  de comparação.

Written by paulosuzart

março 12, 2009 at 11:35 pm

Publicado em Java, scala

Update Scala, Scala, Scala

with one comment

Como tudo, eu também venho evoluindo em escala nos últimos mêses.

Hoje resolvi re-ler um post chamado Scala, Scala, Scala publicado em Janeiro, e me senti un tanto quanto envergonhado com o que vi. Então resolvi re-escrever os três exemplos assim:

1. Novo: numbers foreach (x => println(x*x))

1. Velho: List[Int](1,2,3,4,5) map (x => Console.println(x*x))

A função map retorna uma lista, e meu interesse é apenas imprimir o resultado. Por isso o uso do foreach.

2. Novo: (for (i <- numbers if i > 3) yield i) foreach println

2. Velho: for (i <- numbers if i > 3) yield Console.println(i)

O resultado produzido, também é o mesmo. A diferença é que no caso do modelo antigo, na verdade não necessitaria de um yield que permite um for retornar um valor relavante. Então para dar uma utilidade ao yield, resolvi aplicar um foreach na lista retornada pelo for e então imprimir cada valor, semelhante ao primeiro exemplo.

3. Novo: println( numbers reduceLeft(_ + _) )

3. Velho: numbers.reduceLeft((x,y) => x + y)

O resultado do modelo velho, na verdade não imprimia o valor da soma entre os membros da minha lista. Agora imprime, e usa placeholder syntax, ou seja, uso o wildcard _ para me referir ao primeiro e segundo argumento pasado para minha literal function _ + _. Para entender melhor, seria importante verificar um pouco da API Scala.

No final, temos um código ainda mais reduzido e mais elegante. Menos repetitivo (e acredite, eu poderia me repetir ainda menos neste código) e mais claro. Aqui sim o estilo funcional foi materializado.

OBS: Oficialmente _ é considerado como um valor em branco que deve ser preenchido, a designação wildcard foi usada neste post para facilitar o entendimento.

Written by paulosuzart

fevereiro 24, 2009 at 4:12 am

Publicado em Java, scala