Por que não tentar de outra maneira?

Eu nunca programei uma única linha sequer de código em Clojure, apenas dei uma boa olhada no site oficial da linguagem para conhecer sua proposta – que é muito interessante, digasse de passagem – e tenho acompanhado as notícias que rolam aqui e ali. (Coisa de quem é vidrado por programação.)

No entanto, hoje, li uma notícia sobre Clojure que me fez pensar um pouco além da própria programação…

“Por que as pessoas normalmente não tentam fazer as coisas de outra maneira?”

Achei muito interessante o fato de terem usado Clojure, que é uma linguagem jovem, para implementar concorrência em um grande e importante sistema de informação, mesmo não havendo ainda relatos de que já o tenham feito antes.

Inovação, pioneirismo, pragmatismo… Pensamento fora da caixa!!!

Isso também é sobre ser inteligente. Se já inventaram a solução do problema de concorrência, de maneira elegante, por que ainda ficar batendo cabeça com linguagens “consolidadas”, mas que não o resolvem tão eficientemente? Aham? Por que a linguagem ainda é muito nova?

Esse é só um exemplo, mas há muitos outros em nosso dia a dia. Dê uma olhada ao seu redor. Dê uma olhada em seus próprios desafios. Aliás, aproveite, e dê uma olhada em suas próprias soluções!

O quanto você tem sido tradicionalista e conservador?

O medo das novas soluções, das novas maneiras de fazer as coisas, normalmente, são um atraso para os novos bons resultados. Afinal de contas, normalmente, quem sai na frente lucra primeiro…

Campus Party 2009: Scrum Agile Development

Agora a pouco o Antonio Carlos, gerente de tecnologia do Yahoo!, postou os slides de sua apresentação na Campus Party 2009 sobre desenvolvimento ágil de software com Scrum.

Resolvi postar aqui também, porque achei bem interessante para quem quer ter uma visão introdutória sobre o assunto.

Divirtam-se!

Hammm? Declínio e queda do Agile?

Ontem foi publicado no InfoQ Brasil a tradução de um post bem legal de Chris Sims entitulado James Shore: The Decline and Fall of Agile. O texto começa falando sobre o cenário atual dos novos times ágeis e como isso é decadente se comparado ao verdadeiro espírito ágil:

James Shore declarou que agile está em declínio. Ele cita como por exemplo os vários times fazendo ‘sprints’ e stand-up meetings, sem adotar nenhuma das práticas técnicas necessárias para produzir software de alta qualidade no longo prazo. Em sua estimativa, este fato tem levado milhares de times Scrum praticar métodos Ágeis tão pobremente que eles quase certamente fracassarão, e provavelmente levarão o movimento ágil com eles.

Esse é um bom ponto de partida para que novos times ágeis façam uma reflexão sobre o quão ágeis realmente são.

Aqui na CVC Turismo estamos praticando desenvolvimento ágil há pelo menos um ano e meio, e uma das coisas que aprendemos durante esse período foi que, manter o espírito ágil realmente vivo em nós, é mais importante do que seguir “regras de caixinha”. Afinal de contas:

Indivíduos e interações são mais importantes que processos e ferramentas!

Então, muito embora Scrum seja a nossa base, não é e nem jamais será o nosso limite. Além de Scrum, há também outras práticas ágeis que estão presentes em nosso dia a dia, tais como:

Integração Contínua (mesmo antes de adotarmos Scrum);
– Code review;
Refactoring;
Código coletivo;
– E testes, testes e mais testes!

Ainda temos muito que aprender, crescer e amadurecer – mas acreditamos que estamos no caminho certo.

E você, o que tem a dizer sobre seu ambiente de trabalho? O quão ágil ele realmente é?

Meu último post aqui!

Sim, este é meu último post aqui. Mas não o último da minha vida! 🙂

O que acontece é que acabei de me mudar para casa própria:

leandrosilva.com.br

Espero ver todos vocês por lá!

Ah! Não se esqueçam de atualizar o RSS.

Update (18-11-08): Eu tinha feito a besteira de colocar o blog no /codezone, mas depois voltei à sanidade e resolvi botar na raíz do domínio mesmo. I’m sorry!

Sim, programação funcional é relevante hoje

[Novo endereço: leandrosilva.com.br.]

Há um tempo tenho me interessado pelo paradigma de programação funcional, estudado e tentado aplicar vez ou outra algum de seus conceitos que faça sentido no domínio do problema que estou tentando resolver.

Com base nisso, resolvi escrever este post para dizer que, sim, programação funcional é relevante hoje, tanto quanto foi ontem – se não um pouco mais; e também dar uma visão geral sobre alguns de seus conceitos.

O que é programação funcional?

Segundo a definição de Paul Hudak em seu paper de 1989, “Conception, evolution, and application of functional programming languages”:

Programação funcional é um paradigma de programação que trata a computação como uma avaliação de funções matemáticas e que evita estados ou dados mutáveis. Ela enfatiza a aplicação de funções, em contraste da programação imperativa, que enfatiza mudanças no estado do programa.

Assim, praticar programação funcional consiste em definir funções e usar o computador como um avaliador de expressões. Aliás, uma característica predominante da programação funcional é que o significado de uma expressão é o seu valor, e o papel do computador é obtê-lo através da avaliação da expressão. Por exemplo, considere a expressão 2 + 3. Qual é o seu significado? 5. Agora, considere a expressão (2 x 2) + 1. Qual é o seu significado? 5. Ou seja, a avaliação nos faz concluir que as duas expressões significam a mesma coisa.

Outra característica básica e fundamental em linguagens funcionais é que funções são valores de primeira importancia, podendo estas serem usadas como parâmetro ou retorno de outras funções. Além do que, funções também são avaliadas como qualquer outra expressão matemática.

Aplicação do paradigma funcional

Programação funcional, obviamente, pode ser aplicada para resolver problemas de domínio matemático, mas não somente isso. Absolutamente!

Atualmente, muito do revival – se é que posso dizer assim – do paradigma de programação funcional se deve a aplicação dela no campo da concorrência, do processamento paralelo. Isso por conta de sua natureza stateless. É nesse campo que estão os grandes méritos de Erlang, e a motivação de F# e Scala. (Se bem que Scala pode, sim, trabalhar com estados. Quando a F#, eu não sei. Mas isso não importa muito agora.)

Há pouco ouvi falar também sobre uma bibliotéca fantástica para construção de interfaces gráficas escrita em Haskell, mas sinceramente nunca testei. (Na verdade, nunca escrevi uma só linha de código em Haskell.)

Exemplos de linguagens funcionais

Existe uma pancada uma grande número de linguagens funcionais, talvez muito mais do que você possa imaginar. Apenas para citar algumas: Lisp, Haskell, Scheme, XSTL, OCaml, Erlang, F# e Scala. Mas, acredite, há muitas outras!

Conceitos funcionais em código

Como esse é um blog de programação, e estamos falando de programação, quero explicar rapidamente alguns conceitos de programação funcional exemplificando em código.

1- Lambda Calculus

O principal fundamento da programação funcional é a teoria Lambda Calculus, cuja qual podemos encontrar a seguinte definição na Wikipedia:

In mathematical logic and computer science, lambda calculus, also written as λ-calculus, is a formal system designed to investigate function definition, function application and recursion. It was introduced by Alonzo Church and Stephen Cole Kleene in the 1930s as part of an investigation into the foundations of mathematics, but has emerged as a useful tool in the investigation of problems in computability or recursion theory, and forms the basis of a paradigm of computer programming called functional programming.[1]

The lambda calculus can be thought of as an idealized, minimalistic programming language. It is capable of expressing any algorithm, and it is this fact that makes the model of functional programming an important one. Functional programs are stateless and deal exclusively with functions that accept and return data (including other functions), but they produce no side effects in ‘state’ and thus make no alterations to incoming data. Modern functional languages, building on the lambda calculus, include Erlang, Haskell, Lisp, ML, Scheme, Scala and F#.

Entendemos então que, em programação funcional, funções são abordadas no puro sentido matemático. A definição da Wikipedia para Lisp diz:

Lisp é uma família de linguagens de programação concebida por John McCarthy em 1958. Num célebre artigo, ele mostra que é possível usar exclusivamente funções matemáticas como estruturas de dados elementares (o que é possível a partir do momento em que há um mecanismo formal para manipular funções: o Cálculo Lambda de Alonzo Church).

Via de regra, toda linguagem funcional oferece algum tipo de construção para cálculo lambda.

Por exemplo, considere a seguinte função matemática:

f(x) = x + 30

Em Scala, ela poderia ser escrita assim:

val f = (x: Int) => x + 30
f(5)   // 35

Ou mesmo em Ruby, que apesar de não ser funcional, oferece suporte a algumas abordagens desse paradigma, poderia ser escrito assim:

f = lambda {|x| x + 30}
f[10]   # 40

2- High-order function

High-order functions são funções que podem receber outras funções como parâmetro, e também retorná-las como resultado. A estas damos o nome de função de primeira classe. Essa é uma característica extremamente importante em linguagens funcionais. Vejamos um exemplo:

def escolhido(a: Int, b: Int): Int = if (a >= b) a else b

def imprEscolhido(f: (Int, Int) => Int, a: Int, b: Int) =
  println("O escolhido foi: " + f(a, b))

...

// usando a função escolhido
imprEscolhido(escolhido, 1, 5)   // 5

// usando uma função anônima
imprEscolhido((x: Int, y: Int) => x, 12, 2)   // 12

2- Currying

Currying é a técnica de transformar uma função que recebe multiplos argumentos de maneira que ela possa ser chamada como uma cadeia de funções, com apenas um argumento por vez. Na prática, o que acontece é que a cada chamada a uma função da cadeia, uma nova função é retornada.

Vamos ver um exemplo que pode ser encontrado na integra no site A Tour of Scala:

// cria uma função para filtrar uma lista
def filter(xs: List[Int], p: Int => Boolean): List[Int] =
  if (xs.isEmpty) xs
  else if (p(xs.head)) xs.head :: filter(xs.tail, p)
  else filter(xs.tail, p)

// cria uma função "módulo" para ser usada no filtro,
// por isso ela retorna "true" ou "false"
def modN(n: Int)(x: Int) = ((x % n) == 0)

// cria uma lista com números de 1 a 8
val nums = List(1, 2, 3, 4, 5, 6, 7, 8 )

// imprime aplicando módulo em 2
println(filter(nums, modN(2)))   // List(2,4,6,8)

// imprime aplicando módulo em 3
println(filter(nums, modN(3)))   // List(3,6)

Se você não está familiarizado com código Scala, não se preocupe, à primeira vista parece meio esquisito mesmo. Por isso, não se atente aos detalhes. O importante aqui é você entender que a saída desse programa depende:

1º) Do número que é aplicado ao primeiro argumento (n) da função modN, quanto ela é chamada e o seu resultado passado como argumento à função filter – pois o seu resultado será uma “nova função” que receberá apenas o segundo argumento (x) que ela definiu;

2º) Do número que a função filter aplica ao único argumento que a função p (que é resultado da chamada a modN) aceita.

Ou seja, é como se a função modN tivesse seus dois argumentos parcialmente informados em dois momentos diferentes, tornando a sua chamada muito mais simples e flexível. Essa é a idéia da cadeia.

Vamos um ver outro exemplo, ainda em Scala, talvez um pouco mais simples:

// cria uma função que retorna "outra função" que recebe
// apenas o segundo argumento desta
def idadeAceita(m: Int)(i: Int): Boolean = i <= m

// ao ser chamada, a função idadeAceita retorna uma "nova
// função" que dei o nome de aplicarIdade e recebe apenas
// o segundo argumento definido por idadeAceita
val aplicarIdade: (Int) => Boolean = idadeAceita(18)

...

aplicarIdade(14)   // true
aplicarIdade(40)   // false

Acho que esse exemplo fala por si e dispensa maiores explicações. 🙂

Não é interessante como os diversos conceitos abordados até aqui vão se completando?

Que mais?

Bem, tudo que eu disse nesso post gigante é apenas uma visão geral. Talvez a pontinha do iceberg. Então espero que ele te motive a estudar um pouco mais sobre programação funcional. (O texto está repleto de links para outros texto interessantes.)

Valeu!

Como está seu marketing pessoal?

[Novo endereço: leandrosilva.com.br.]

Bruno Pereira escreveu dois posts (esse e esse) muito relevantes sobre marketing pessoal, em especial, para desenvolvedores de software, que eu não poderia deixar de citar e sugerir aqui em meu blog.

Ler esses posts me fez lembrar do keynote de Chad Fowler na Rails Summit sobre tornar-se uma pessoa brilhante. Facinante!

É isso ai, fica aqui a dica…

Seja brilhante!!!

Acho que Ola Bini não dorme!

[Novo endereço: leandrosilva.com.br.]

Ola Bini publicou hoje em seu blog um roadmap para sua mais nova criação, a linguagem de programação Ioke.

Ioke é, nas palavras do próprio Ola Bini, uma lingagem de programação fortemente tipada, orientada a objetos baseada em protótipos, bastante inspirada em Io, SmallTalk, Self, Ruby e Lisp (especialmente Common Lisp). Atualmente, ela está implementada em Java e rodar unicamente na JVM.

Nesse roadmap, Ola Bini anuncia que a primeira release será chamada 0 (sim, zero), e deverá ser publicada até no máximo o Natal.

Se você quiser acompanhar a evolução de Ioke, você pode segui-la no GitHub.

Agora fica a pergunta: Esse Ola Bini não dorme, não?

O que achei do workshop de DDD da Caelum?

[Novo endereço: leandrosilva.com.br.]

Hoje participei do workshop de Domain-Driven Design que a Caelum promoveu junto com Phillip Calçado, consultor da ThoughtWorks.

O workshop foi excelente. Muito dinâmico, com conteúdo bastante abrangente, e muita mão-na-massa. Aliás, não tivemos nem computador. Fizemos tudo em cartões pautados, CRC-like, no melhor estilo free style!!!

Tenho praticado DDD há aproximadamente 1 ano e meio, na CVC Turismo, e confesso que ainda carregava comigo algumas dúvidas, tanto de abordagem quanto de implementação. Porque DDD não se aprende do dia pra noite, nem decorando um conjunto de padrões. DDD é muito mais do que isso. DDD é, fundamentalmente, sobre “melhorar a comunicação entre os envolvidos num projeto”. Incrível!

Com certeza esse é um treinamento que recomendo de mais. (Principalmente àqueles que vivem atormentados por DAOs e repositórios…. kkk)

Brincadeiras à parte, se você é um desenvolvedor sério, preocupado em produzir software de qualidade, que realmente atenda às expectativas do cliente, você precisa participar desse workshop.

Mais uma vez, ao Phillip e à Caelum, parabéns!

(Ah! Paulôôô, o coffe-break, como sempre, fantástico!)

Rails Summit, o melhor evento que já participei!

[Novo endereço: leandrosilva.com.br.]

A Rails Summit Latin America foi o melhor evento de tecnologia que já participei até hoje. Simplesmente, excelente!

O meu destaque fica para as apresentações de Chad Fowler e Obie Fernandez.

Quem estiver interessado, aqui tem uma trilha legal do evento.

Se você perdeu esse ano, pel’amor, não perca ano que vem não!

Parabéns ao Akita e à Locaweb…

Intuitividade de Ruby

[Novo endereço: leandrosilva.com.br.]

Uma das coisas que mais gosto em Ruby é que ela é uma linguagem muito expressiva e intuitiva.

Quer ver um exemplo? Pois bem…

Suponha que você queira saber se uma determinada classe é filha de outra, como você faria?

irb(main):001:0> Integer < Fixnum
=> false

Logo, Integer não é filha de Fixnum. Mas, e o contrario, será que é verdadeiro?

irb(main):002:0> Integer > Fixnum
=> true

Sim, Fixnum é filha de Integer.

Percebeu a intuitividade? Ainda não? Vamos lá então…

Para dizer que uma classe é filha de outra, em Ruby, usamos o operador < (menor), pois a classe filha passará a ocupar um lugar hieraquicamente abaixo de sua classe mãe.

class Filha < Mae ... end [/sourcecode] Assim, nada mais intuitivo do que testar a posição hierarquica de uma classe em relação a outra usando os operadores > (maior) e < (menor). E agora, que tal? É ou não é intuitiva?