Wednesday, August 30, 2006

A taste of Scala

I've recently been trying to learn Scala, a programming language developed at a Swiss university. It has many (many!) cool features, such as seamless interoperability with Java - a result of being compiled to JVM bytecodes -, strong support for functional programming, sophisticated object oriented characteristics and a strong static type system. Rather than continue listing the language's capabilities I will, instead, share a personal use case.

OK, so one of the first items things I looked at was the unit testing framework, SUnit. It comes bundled in the standard library in the scala.testing.SUnit package and is dead simple. I hope the following snippet is self-explanatory enough:
object StackTest {
import scala.testing.SUnit._

def main(args:Array[String]): Unit = {
val tr = new TestResult
new TestSuite(
new Test01,
new Test02,
).run(tr)

for(val f <- tr.failures())
Console println f
}

class Test01 extends TestCase("pushing an element onto an empty stack") {
override def runTest() = {
val stack = new Stack()
val element = "asdf"
stack push element
assertEquals(stack.peek(), element)
}
}

class Test02 extends TestCase("popping an element from a stack") {
override def runTest() = {
val stack = new Stack()
val element = "asdf"
stack push element
stack.pop()
assertEquals(stack.isEmpty, true)
}
}
}

It really is pretty simple; the whole testing framework sits on a single 200-line file. But is also is a bit verbose, isn't it? All those inner classes, cluttering the code... I tried to simplify things a bit. Here is what I came up with:
import sorg.testing._;

object StackTests extends Tests with ConsoleDriver {
test ("pushing an element onto an empty stack") {
val stack = new Stack()
val element = "asdf"
stack push element
assertEquals(stack.peek(), element)
}

test ("popping an element from a stack") {
val stack = new Stack()
val element = "asdf"
stack push element
stack.pop()
assertEquals(stack.isEmpty, true)
}
}
I think it looks better. Sort of like those DSLs that are so fashionable these days... But the really cool thing is that it only took a couple dozen lines of code and a couple of hours to extend SUnit. Mind you that someone really proficient in Scala could probably do it much more quickly. See the whole unit testing domain specific language: (the name is almost larger than the code itself :)
package sorg.testing;
import scala.testing.SUnit._;

abstract class Tests extends Test with Assert {
type TestExp = () => Unit;
var tests = List[Pair[String,TestExp]]();

def test(desc: String)(t: => Unit) : Unit = {tests = Pair(desc,()=>t) :: tests};

override def run(tr: TestResult) = {
for (val Pair(desc, expression) <- tests) new TestCase(desc) {
override def runTest() = {Console println "running (" + desc + ")"; expression()}
}.run(tr)
}
}
trait ConsoleDriver extends Test {
def main(args:Array[String]): Unit = {
val results = new TestResult
Console println "running tests..."

this.run( results )

if (!results.failures.hasNext)
Console println "Success!";
else {
Console println "The following tests failed:";
for(val each:TestFailure <- results.failures)
Console println (each.toString + ":\n" + each.trace);
}
}
}

Expressiveness and power, what more can one ask of a programming language?

Tuesday, August 15, 2006

Componentes e objetos

Muito já se escreveu sobre a distinção entre programação orientada a objetos (OO), desenvolvimento baseado em componentes (CBD) e service oriented architectures (SOA). Isso significa que este post vai indubitavelmente chover no molhado. Entretanto, não se pode dizer que o assunto está resolvido e acabado; eu só espero confundir menos do que esclareço.

Como bem lembrou Philip Calçado, não podemos nos esquecer de que estes conceitos todos foram concebidos em contextos diferentes por grupos distintos e sem maiores preocupações com uma coesão formal. OO por exemplo, tem origem na Noruega, mas foi conceptualizada de maneira mais completa no laboratório da Xerox em Palo Alto, sendo reificada numa sequência de protótipos da linguagem Smalltalk. O líder desse projeto foi o lendário Alan Kay, que também tem a distinção de ter cunhado o termo "programação orientada a objetos". Kay, que na época já tinha um background em biologia e matemática, imaginou um paradigma computacional centrado em entidades similares a células biológicas, que se comunicavam trocando mensagens químicas. Apesar da paternidade reconhecida, não há consenso sobre o que seria a definição de OO, então trabalharei com uma definição improvisada (não confie muito). Um objeto é caracterizado por:
  1. Comportamento. Ele é capaz de receber invocações* de outros objetos para efetuar uma computação e (a) responder com um outro objeto ou (b) alterar o seu estado. Para efetuar a computação, o objeto pode invocar outros objetos. Ele obtém acesso a estes objetos de três maneiras: criando - "instanciando" - novos objetos na hora, usando uma referência que é parte de seu estado ou recebendo-os no momento em que é invocado.
  2. Estado. Um objeto pode armazenar um conjunto de referências para outros objetos. Através dessas referências ele pode invocar comportamento dos outros objetos conforme descrito no ítem anterior.
  3. Identidade. Mesmo que o estado todo de um objeto se altere, ele ainda existe como a "mesma" entidade.
  4. Ciclo de vida. Um objeto é instanciado em algum momento, quando ele passa a existir (manter uma identidade). Ele também pode ser destruído em algum momento. As linguagens de programação que seguem o paradigma OO apresentam uma grande variedade de mecanismos para instanciar e destruir objetos (classes, protótipos, prefixos, gerenciamento manual de memória, coletor de lixo, ...).
Enquanto que objetos são entidades fundamentais de um modelo computacional, componentes são apenas uma alternativa para atender a certos requisitos encontrados em algumas aplicações. Essa afirmação pode parecer polêmica, por isso apelo para uma autoridade maior, Ralph "GoF" Johnson, que expôs bem essa consideração num post recente em seu blog:
It is important to realize the "components" are not technology, they are a customer requirement. Customers want to add on to their software system by adding a new component, and adding this component must not require that they change their existing system. It is like adding new speakers to a stereo system.
Ou seja, componentes são nada mais que uma unidade de extensão e/ou substituição dinâmica de um sistema de software. O adjetivo "dinâmico" é uma daquelas palavras que são jogadas por aí em contextos tão diversos a ponto de perder o seu significado, mas a noção aqui é bem simples: estamos considerando alterações realizadas em ambiente de produção, feitas por operadores do sistema. A partir dessa caracterização, podemos dezfazer uma série de confusões:
  • Uma aplicação pode usar componentes sem ser baseada em componentes. Isto é, é possível definir alguns poucos pontos de substituição e/ou extensão mantendo o resto do software completamente estático. Dentre os muitos exemplos estão a maioria dos programas de desktop; um exemplar típico é o Photoshop e seus plugins. É claro que também encontramos diversos casos no extremo oposto - aplicações totalmente baseadas em componentes - veja por exemplo os últimos servidores de aplicações e IDEs.
  • Um sistema pode ser modular mas não baseado em componentes, na acepção que estamos considerando. Basta que seja composto de partes pouco acopladas.
  • Não faz muito sentido projetar um sistema baseado em componentes fortemente acoplados. O motivo é simples: componentes fortemente acoplados exigem que um desenvolvedor independendente se preocupe com grandes porções do sistema, o que prejudica o atendimento ao requisito de reconfigurabilidade. Mesmo no caso de aplicações que limitam seu uso de componentes a extensões localizadas, é uma boa prática estabelecer uma interface reduzida entre o núcleo do sistema e os componentes.
  • A definição sugerida exige apenas que um sistema possa ser reconfigurado em ambiente de produção, não é necessário que ele tenha a capacidade de sofrer alterações enquanto está executando. Não obstante, existem algumas aplicações onde isto é um requisito real e soluções tecnológicas sofisticadas são necessárias.
  • O professor Johnson deixa bem claro que tecnologias como COM ou EJB não são necessárias para um sistema que use componentes. A rigor, para antender ao requisito delineado é suficiente um suporte tecnológico mínimo. Podemos imaginar até um sistema onde a escolha de componentes é feita através da substituição de arquivos objeto (em java seria um .class) no diretório de instalação.
  • Apesar do ponto anterior, é frequente que um sistema com componentes se beneficie de uma infra-estrutura básica para auxiliar na solução de problemas comuns como: controle do ciclo de vida, gerenciamento de dependências, suporte à modos de comunicação entre componentes, parametrização local (propriedades), etc.
Como já demorei muito mais do que imaginava para escrever este post - incluíndo um tempo desperdiçado reescrevendo uma boa porção do texto quando eu fiz besteira e perdi o draft - vou deixar para uma entrada futura a discussão sobre sistemas distribuídos e serviços.

Uma última observação: o leitor atento notará que a palavra reuso não aparece nesse post; isso não foi um acidente.

* Estou evitando a terminologia baseada em "mensagens" que é padrão em Smalltalk para evitar mais confusão.

Sunday, August 06, 2006

Hmph.

Ontem eu fiz besteira e perdi o post que estava escrevendo. Para encher linguiça até que eu me anime a escrever sobre tecnologia de novo, aproveito para listar umas bandas que eu ando curtindo. Aviso que não sou um daqueles nerds indie que vendem a mãe e hipotecam a avó para pagar a assinatura do NME, por isso não espere novidades extraordinárias:
  • Art Brut. Banda excelente e engraçada... Recomendo a música "My Little Brother", mas na real todas as músicas deles são legais.
  • Arctic Monkeys. Enchi o saco de todo mundo dizendo que o hype é exagerado. A banda é boa, e não é culpa dos caras que uma parte da mídia resolveu coroá-los como O Próximo Strokes (que era para ser O Próximo Nirvana...). Ouça "Cigarete Smoke".
  • A TPM passou e o Yeah Yeah Yeahs lança um disco mais calmo. IMHO, continua ótimo, mas eu sinto falta da Karen O se esgoelando. Música: "Turn Into", uma baladinha.
  • Já o segundo disco do Dresden Dolls, "Oh, Virginia", me pareceu bem mais fraco que o primeiro....
  • Rock Rocket. Mais um expoente (que palavrinha tosca) do rock etílico (pleonasmo?) brasileiro. Ouçam o hit "Ninfomaníaca".
  • Chega por hoje.

Thursday, August 03, 2006

Model View Confusion

The development community is a strange beast. And I'm not talking about hitchhiker's jokes and D&D tournaments. The strangeness I'm referring to is that many of the most talked about concepts are used in ways that differ a lot from their original, intended, meanings. Many patterns fall in this category, but one is specially abused: MVC. This is one of the first TLA's a java developer learns on his first days in the craft. By "learn", I really mean "kinda sorta knows that it has something to do with that Struts crap".

I was in that exact position a few years ago (crazy coincidence, innit?). After a few hours of wikistumbling through c2.com, I got considerably more confused. The next step I took was to chase down a copy of the first published description. Google wasn't my friend in this process* and I had to resort to the old-fashioned route of requesting a loan from some - the only one, in fact - college library that had the aug/1988 copy of the Journal of Object Oriented Programming. I only half-understood it because at the time I wasn't conversant in Smalltalk. But I undestood enough to see that MVC was somewhat different from what the Java guys talked about.

One big difference is that Smalltalk-80 was self-hosted - it was it's own operating system**. This meant that input device processing was a responsability of objects. And that, my little friends, is how the Controller came to be. Quoting the paper:
In particular, controllers coordinate the models and views with the input devices and handles scheduling tasks. (...) Class Controller does include default scheduling behaviour...
What motivated me to write this entry was Fowler's superb article on GUI architectures. In there you'll find a thorough discussion on MVC and its subsequent variants. It will be a chapter on the upcoming second volume of his Patterns of Enterprise Application Architecture.




* Of course, now the bastard is online here.

** This control obsession can be seen still today, just look at Squeak's UI and fondly remember the glorious Win3.1 days...