Clojure, and Ruby

I’m gonna make a bold claim here. As a language, Clojure is much better than Ruby. But, as a means of working together with other people, Ruby can be better, and Clojure can be a nightmare.

Here’s the problem with this debate: in Ruby it’s easier to actually bootstrap something because of the Rails framework. Clojure doesn’t have anything like that, but the code tends to get less worse as time goes by – as a functional language where everything is immutable by default, there’s less “surface” that’s touched by a piece of code. For example, suppose you have a function – in Clojure, changing that function only affects callers of that function, whereas in a mutable language, the function can mutate an object/value and now everywhere that uses that same object can be affected.

Another reason, that might be counter-intuitive is because of the real framework itself. When an application grows, you might find that you need less constraints and more freedom to do stuff that was not defined originally. Unfortunately, if you are using Rails (or any other framework), this means that you have to find ways around the framework, because it’s a kind of an “all or nothing” – it’s not that easy to basically do something outside of it and then bring that into your workflow, into your web servers and things like that (for example, I once had to integrate a SQS message queue on Rails, to listen to some message and deliver a notification via websocket. It was such a bad experience that we did a Node.JS app that did just that).

My last experience with Ruby

On my last job I tried to go back to Ruby programming language. Not really by choice – but just because it was a language and was familiar with, and my last two jobs in Clojure didn’t really work out for me (not because of the language, really). I even imagined that some things would be easier in Ruby, specially while working with relational databases (something I really did miss while I was working in the Clojure language).

At the time, in my opinion, Rails was still a great framework – maybe a little too complex. And I imagined that somehow there could be better ways of doing Ruby code that could use the best parts of Rails and avoid the worst (like ActiveRecord, for example, maybe even substitute it with Sequel or ROM).

No a year and a half later I’m back to Clojure – and I will probably never go back to Ruby. And the reason is quite simple: I was working with Ruby doing exactly the same code that I did about three years ago. Rails didn’t change that much, but still was a huge mess when you had to upgrade from one version to another. The same problems I had in the past kept happening again and again, and it felt like a huge step backwards for me.

Rails’ ActiveRecord – the bad and the ugly

I’m known to not be a big fan of ActiveRecord. No, that would be a simplification: I probably hate ActiveRecord and think it adds more problems than it solves, specially after I began to work with functional programming and saw how difficult, if not utterly impossible, is to make ActiveRecord models behave like immutable structures or separate (and maybe even predict) the I/O from the rest of the code.

The ActiveRecord pattern (not the GEM) was created to hide SQL details from the users. The Gem elevates this to extremes: you never know when a query is issue, what query is issued (unless you check the logs), and sometimes a later clause modifies the way previous clauses work. Also, to extend ActiveRecord, you need to rely on monkey-patches and other internal implementation details, and there are API changes that seem innocent but are tremendously dangerous.

Now, what I want to do in this post is to elaborate the bad and the ugly parts. I’m not gonna talk about the “good parts” because we already know: auto-discovery of fields, fast prototyping, simple CRUDs, and so on. One could argue that this “easy setup, fast prototyping” is not worth the amount of technical debt you’ll have later, but let’s focus on the bad parts instead:

Object-oriented after working with functional programming

Sometimes I need to divide my knowledge in phases: when I started to program, I felt that C/C++ were the best languages to make a software. Then, I’ve began to work with Ruby and learned Test-Driven Development. I divide my knowledge “before TDD” and “after TDD”, because it literally changed the way I could think about software and tests in general. Now, I’ll probably make the same division: “before functional programming” and “after FP”, and I only discovered that things have changed this week: I just discovered I don’t know how to do object oriented programming anymore – and to be honest, it’s not really a bad thing: I also saw in practice how object-oriented programming expects you to write lots of boilerplate in most situations.

This realization came to me when I was working in a peculiar kind of problem – it’s basically a ruby code that needs to connect on messaging system and, when it receives a message, needs to persist it in a relational database. The problem is that this specific system have a strong consistency requirement, so the message could only be updated on DB before a specific event happens: after that, we can’t change it anymore, except for some specific fields. Also, as we’re working with messaging, we can receive the message multiple times, out of order, and all of those strange things that happens on Internet-land. So, to summarize:

  1. The system will receive a message
  2. It’ll UPSERT a record on DB, just with some identification fields (they’ll never change, and if they do, they characterize another message to be persisted – think about an external id)
  3. It’ll BEGIN a transaction and SELECT ... FOR UPDATE my just upserted message
  4. It’ll find, on another table, the rest of the fields on the message
    1. If this record doesn’t exist, we’ll create it (and log)
    2. If it does exist, we’ll check additional info, and decide: or we ignore it (and log), or we upsert (and log), or raise an error

Now, for the implementation. Because consistency is a must have on this system, I don’t want to expose for future programmers (be it myself or some of my friends) some code that’ll induce me to errors: after all, who wants to do with_consistency_check(msg) { Message.upsert!(msg) } when I can just do Message.upsert!(msg), right? So, I don’t want to allow people to be able to modify, find, update, or anything else outside of the with_consistency_check (or whatever name I decide). So, how to do it?

Understanding Ruby’s Awesome Nested Set

Recently, I saw people migrating from Awesome Nested Set to Ancestry. The reasons are simple – Ancestry is very simple, it just need a new string field in your table, and it’s easier to reason about. So, why should I even consider to use an alternative?

The answer is simple, and I’m going to quote H. L. Mencken: For every complex problem there is an answer that is clear, simple, and wrong.

And the reason that using Ancestry is a bad idea is simple: it doesn’t reflect good design. It treats a single field as a multi-valored column that keeps the ancestry of your object. This means that there’s no way to fetch all records AND their parents in a single query, or fetch all records AND their children, because we need to split the string (ruby-side) and then create a query (also ruby-side). So, in this post, I’ll show some tricks of what we can do with Awesome Nested Set, or even beter, how does it implements the tree pattern (and why it calls it a “set”, not a “tree”).

First, when we think about categories and sub-categories, we think like this:

But this is, in fact, a terrible way of representing trees in SQL. So, the alternative, is to transform it in a group of sets: Parent 1 (P1, for short), is a super-set containing subsets C1 and C2 (Children 1 and Children 2, for short). Each of the children have its own grandchildren, so C1 is a super-set containing G1, and C2 is a super-set containing G2 and G3.


Don’t be a Copperfield

After a year and a half working in other languages, I’m back to Ruby. And, one of the things that I was amazed at Clojure is how simple things were.

Back to Ruby, I’m really surprised on how people overcomplicate things.

There’s no perfect language, nor perfect community of languages. In Clojure, there are fewer abstractions, which is not exactly a good thing – if you, let’s say, just want to create a simple page to show data from a database, you’ll find it extremely tedious to do it in Clojure, where in Ruby/Rails it’s just a few lines of code away. Ruby’s moto is “programmer happiness”, and this reflects in every library that they write.

But this kind of higher abstraction pays off with time. At least where I live, working with Ruby means working with Rails almost all the time. There are no “big competitions” for Rails or ActiveRecord (Sequel is a close one, but at the time of this post, AR have 10 times more downloads than Sequel), and other web frameworks are mostly “Rails-like”. But what bugs me most is “magic”.

Experiências com o Atom

Para adicionar um pouco de fogo na velha “editor wars”, eu resolvi testar o SublimeText, Zed, e o Atom.

Antes, um disclaimer: eu sou um usuário VIM. Não um super usuário VIM – eu, por exemplo, uso as setas para navegar dentro de um arquivo (oh, o horror!), uso poucos plugins, enfim. Aí resolvi testar o SublimeText, e achei ele fantástico – rápido, estável, e funciona bem. Só tem um problema: 70 dólares.

Eu acho válido pagar por algo que você vai usar todos os dias. Mas 70 dólares é 1/3 de um Office. Já que eu tinha alternativas, resolvi testar o Atom. Antes disso, eu tinha feito um plugin para o Sublime, para rodar coisas pelo TMUX, e resolvi portar o mesmo aplicativo para o Atom, como um exemplo.

O Atom usa tecnologias web – HTML + CSS + JS + Node.JS para funcionar. Basicamente, plugins (e customizações do Atom) são escritos em Coffeescript ou Javascript, usando Node.JS, toda a interface do Atom, incluindo menus, abas, telas, são feitas usando HTML + CSS, você pode re-estilizar a tela toda usando LESS ou CSS, e os arquivos de config são em CSON ou JSON. O ponto negativo disso é que basicamente o Atom consome tanto de memória como o Chrome / Chromium, já que na verdade, ele basicamente É a mesma coisa – um browser rodando uma página. Há muitas vantagens na abordagem do Atom – a tela inteira do seu editor é customizável.

O veredicto final eu achei bom: eu acabei gostando do Atom. Ele é um pouco mais lento do que eu gostaria, e consome uns 300 – 400mb de memória na minha máquina (o que é bem ruim na verdade para pessoas que tem máquinas com pouca RAM) . Outra coisa que é perceptível é a facilidade de se fazer plugins (há um “scaffolding” de plugins no Atom) e quão fácil é integrar dependências externas, testes dos próprios plugins, etc. O ponto baixo sempre será o consumo de memória e de disco, que o Atom simplesmente precisa melhorar – e muito.

Sobre cada um dos detalhes:


Resourceful Web

Todos sabem que, com o tempo, os frameworks web evoluem. Porém, o que poucas pessoas percebem é que além das mudanças nas APIs e na estrutura dos programas feitos com o framework, há uma mudança também nas idéias dos desenvolvedores e até mesmo nas metáforas que o sistema usou para definir-se. E o Rails não é exceção.

Por exemplo, no Ruby on Rails versão 1.x, a idéia do framework era a construção de aplicações web. Para tal, a idéia era que a aplicação fosse simples e divertida de desenvolver. Além disso, havia a idéia de web-services, XML-RPC e SOAP que nunca pegaram direito no mundo Rails (mas que estavam presentes na versão 1.x). Depois, na versão 2.x, surgiu o conceito de RESTful (em contraponto aos web-services do Rails 1) e, junto com ele, o conceito de “resource” ou “recurso”. Já no Rails 3, surgiu a idéia de separar o Javascript do HTML usando o conceito de Unobtrusive Javascript (Javascript não-intrusivo), e junto com essa idéia, veio a substituição do prototype pelo jQuery (que torna certas operações envolvendo AJAX mais fáceis). Junto também com a substituição por jQuery, o scaffold passou a fazer os controllers responderem por HTML e JSON, ao invés de HTML e XML como no rails 2.x.

E é essa a mudança mais importante.

Vamos começar pensando: qual seria o motivo de renderizar um JSON? A resposta é simples: JSON é mais fácil de ser entendido pelo browser, por Javascript, e por aplicativos de terceiros tais como em iOS ou Android. Antes, responder por XML não tinha aplicação real nenhuma nos próprios aplicativos Rails, e ficavam apenas como forma de comunicação com sistemas de terceiros (o velho “big design up front“) que nem sempre ocorriam. E hoje, renderizar JSON está muito pouco utilizado mesmo no mundo Rails, e há um motivo para isso:

Não sabemos o que é um “resource”.

Redes Neurais – Parte 3

Ok, vamos finalmente para a terceira parte sobre Redes Neurais (e também, aonde será apresentado o código completo de uma rede neural em Ruby). Este post será sobre treinamento de redes neurais, especificamente sobre o treinamento dos pesos que saem dos neurônios de entrada e vão para os neurônios ocultos da rede. Antes de mais nada, vamos relembrar nosso desenho da rede neural:


Já vimos no post anterior que para achar o valor que MAXIMIZA a função de custo, usamos o métoodo chamado de “gradiente”. O método “gradiente” usa derivadas parciais, e como vamos achar o valor de um peso que sai do neurônio de entrada para o neurônio da camada oculta, precisamos calcular a derivada parcial da função de custo em relação a um destes pesos. Vamos usar o “peso_a1_b2” para este exemplo.

Antes de mais nada, vamos relembrar todas as contas que fazemos para nossa rede neural. Para tal, eu vou usar a notação “peso_ax_by” para indicar o peso que sai do neurônio “ax” e vai para o neurônio “by”. Note que NÃO EXISTE “peso_a1_b1”, porque o neurônio “b1” é o “bias”, logo o valor dele é sempre “1” (e não faria sentido calcular um valor se ele vai descartá-lo e usar “1”, no fim das contas). Sabemos que o valor de um neurônio oculto é a soma de todos os valores dos neurônios de entrada (multiplicados por seus devidos pesos) e aplicadas uma “função de ativação” (que no nosso caso, é a “Tangente Hiperbólica”). Eu vou chamar de “b_sem_ativacao_x” o valor desta soma dos neurônios de entrada, ANTES de se aplicar a função de ativação. Logo, nossas contas são:

b\_antes\_ativacao\_2 = a1 * peso\_a1\_b2 + a2 * peso\_a2\_b2 + a3 * peso\_a3\_b2 \\  b\_antes\_ativacao\_3 = a1 * peso\_a1\_b3 + a2 * peso\_a2\_b3 + a3 * peso\_a3\_b3 \\  b\_antes\_ativacao\_4 = a1 * peso\_a1\_b4 + a2 * peso\_a2\_b4 + a3 * peso\_a3\_b4 \\  \\  b2 = tanh(b\_antes\_ativacao\_2) \\  b3 = tanh(b\_antes\_ativacao\_3) \\  b4 = tanh(b\_antes\_ativacao\_4) \\  \\  c1 = b1 * peso\_b1\_c1 + b2 * peso\_b2\_c1 + b3 * peso\_b3\_c1 + b4 * peso\_b4\_c1 \\  c2 = b1 * peso\_b1\_c2 + b2 * peso\_b2\_c2 + b3 * peso\_b3\_c2 + b4 * peso\_b4\_c2 \\  \\  custo = \frac{1}{2 * N} * \sum\limits_{n=1}^N \sum\limits_{i=1}^2 (ci(do\ exemplo\ n) - yi(do\ exemplo\ n)) ^ 2

Redes Neurais – Parte 2

No post anterior, vimos como montar a estrutura de uma rede neural. Neste post, veremos como fazer o treinamento dos pesos, para que a rede generalize nossos exemplos de teste e seja capaz de classificar exemplos que ainda não foram vistos. Num primeiro momento, vamos relembrar o desenho de uma rede neural:


Para facilitar, deixei um nome para cada neurônio (nota: provavelmente vocês não vão encontrar essa forma de nomear os neurônios em lugar algum-eu coloquei essa nomenclatura mais para facilitar o post do que para ser uma abordagem matemática mesmo). Os neurônios “a1” e “b1” são “bias”, conforme vimos no post anterior, e os neurônios “c1” e “c2” são os neurônios de saída. Note que este desenho de rede neural não representa nossa rede neural, pois nossa rede neural precisaria de 5 neurônios de entrada e 3 de saída. Bom, conforme vimos no post anterior, num primeiro momento os pesos sinápticos (as linhas ligando os neurônios, representadas pelas matrizes “input_weights” e “hidden_weights” no post anterior) são aleatórios, o que significa que a rede possuirá comportamento aleatório. A partir deste ponto, temos que alterar os pesos para tentar chegar num resultado melhor da rede. Para tal, precisamos de uma função que nos mostre quão bom é a solução atual: uma “função de custo”.