Drawspace: curso on-line de desenho gratuito

24 de Julho de 2008

Desenterrando este blog para uma notícia boa.

Há muito tempo atrás eu costumava desenhar, mas parei no tempo. Ultimamente venho pensando em voltar, então procurei no Google algum curso de desenho. Acabei achando este excelente site, que dispõe de mais de 300 lições devidamente categorizadas para Iniciante, Intermediário e Avançado.

Segue o link:

http://www.drawspace.com/


Enrolação de dependências - parte III

6 de Junho de 2008

Finalmente, a parte final deste artigo!

Antes de prosseguir, leia: http://cabritin.wordpress.com/2008/03/07/enrolacao-de-dependencias-parte-ii/

Observe novamente a figura publicada na parte 1:

O diagrama ilustra uma relação um-para-muitos entre empresa e funcionário, este podendo ser um gerente ou um empregado.

Vamos traduzir este diagrama em um pouco de código. Inicialmente, poderíamos implementá-lo da seguinte maneira:

public class Empresa {
    private List<Funcionario> funcionarios;

    public Empresa() {
        funcionarios = new ArrayList<Funcionario>();
    }

    public void addGerente() {
        funcionarios.add(new Gerente()); // Linha 9
    }

    public void addEmpregado() {
        funcionarios.add(new Empregado()); // Linha 13
    }
}

public interface Funcionario {

}

public class Empregado implements Funcionario {
    // Construtores, atributos, métodos, etc
}

public class Gerente implements Funcionario {
    // Construtores, atributos, métodos, etc
}

Há algum problema nessa implementação? Aparentemente, não. Ela está bonitinha, usando polimorfismo, inversão de dependências (lembra o que é?) e tudo o mais. Mas veja só: a classe Empresa está instanciando diretamente as classes Gerente e Empregado (linhas numeradas). Tá, mas e qual o problema nisso? Ora, simples: se por acaso os construtores dessas classes mudarem, precisaremos modificar também as linhas 9 e 13. Agora, imagine se eu tivesse 50 classes, todas dependendo de Empregado e Gerente! Ia sobrar pro estagiário fazer a modificação em todas elas…

Mas vamos facilitar a vida do estagiário. Vamos tentar aplicar Inversão de Controle à situação.

O que queremos, então? Queremos evitar que Empresa instancie Empregado e Gerente diretamente; queremos diminuir o acoplamento entre as classes. A criação das instâncias é a responsabilidade que queremos inverter, ou seja, deixar para outra entidade fazê-lo.

Resumindo: a classe Empresa não mais criará as instâncias; ela as receberá já criadas. Como? Através dos métodos addEmpregado() e addGerente(). Vamos modificá-la então!

public class Empresa {
    private List<Funcionario> funcionarios;

    public Empresa() {
        funcionarios = new ArrayList<Funcionario>();
    }

    public void addFuncionario(Funcionario f) {
        funcionarios.add(f);
    }
}

Nossa! A classe Empresa ficou totalmente independente dos tipos concretos de Funcionario. Ela nem sabe mais que eles existem! O código cliente que utilizar as classes de domínio usará a classe como se segue:


Empresa e = new Empresa();
e.addFuncionario(new Gerente());
e.addFuncionario(new Empregado());

Ou seja, os funcionários são agora injetados dentro da empresa através do método addFuncionario(). Espere um pouco, você disse injetados?

Sim. Utilizamos um método que serve para passarmos para a (injetarmos na) classe Empresa as instâncias (dependências) de que ela precisa - neste caso, os funcionários de uma empresa. Invertemos o controle da instanciação dos objetos para o código cliente. Isto é injeção de dependências.

Há outras formas de injetar dependências em uma classe, como por exemplo fazê-lo por meio de um construtor (passando a dependência como argumento). E há também outras formas de instanciar os objetos de que sua aplicação precisa: frameworks como o Spring e o PicoContainer implementam containers que cuidam do processo de instanciação. Se não quiser utilizar um desses containers, um Factory Method resolve seu problema muito elegantemente.

Para encerrar, sugiro fortemente que você leia o artigo do Martin Fowler sobre o assunto. Estes posts não têm a intenção de substituí-lo: serve apenas para dar uma idéia geral.

Até mais.


Curso introdutório gratuito de Ruby On Rails

28 de Março de 2008

Deixem-me dar essa notícia antes que eu esqueça novamente :D

Lembram do curso gratuito de Ruby, ministrado pelo indiano Satish Talim? Um amigo dele resolveu seguir a onda, e abriu um curso de Ruby on Rails. Seu nome é Sunil Kelkar. O curso terá início no dia 12 de abril.

Tá esperando o quê? Matricule-se!


Enrolação de dependências - parte II

7 de Março de 2008

Antes de prosseguir, leia: http://cabritin.wordpress.com/2008/03/06/enrolacao-de-dependencias-parte-i/

Inversion of Control - IoC (inversão de controle)

Podemos definir inversão de controle como sendo simplesmente a transferência de uma ou mais responsabilidades para uma entidade exterior, que decidirá o momento e a ordem de ocorrência dos eventos inerentes a essas responsabilidades. Esse princípio já existe há muito tempo, e não se restringe somente ao mundo da computação.

Por exemplo, se você tem uma conta pra pagar, você se encaminha ao banco e paga. Ou seja, é sua responsabilidade controlar o evento “pagar minha conta”, e é você quem toma a decisão do momento em que deseja pagá-la. Porém, se você não tem tempo e pede para sua irmã efetuar o pagamento para você, você transferiu a responsabilidade sobre o evento “pagar minha conta” para ela. Assim, ela é quem vai tomar a decisão do momento de pagar a conta, lhe devolvendo o comprovante de pagamento.

Uma expressão famosa que ilustra a IoC é enunciada pelo princípio de Hollywood: “don’t call us, we call you”.

Dentro da computação, uma aplicação do conceito de inversão de controle pode ser encontrada em ferramentas baseadas em programação orientada a eventos, como o Delphi e o Visual Basic. Um programa orientado a eventos consiste, muito simploriamente, em um laço principal com duas seções: detecção e tratamento de eventos:

main()
    repita
        // Detecta eventos registrados pelo programador
        detecte_eventos()
        // Executa os eventos registrados
        trate_eventos()
    fim
fim

Quando desenvolvemos aplicações gráficas usando as IDEs referenciadas, utilizamos um framework de criação e gerenciamento de janelas e eventos (no Delphi para Win32, por exemplo, esse framework é o VCL, que significa Visual Component Library) , e esse framework fica responsável por executar o laço acima. Tudo o que precisamos fazer é definir os eventos em nosso programa e registrá-los; nós não somos mais responsáveis por executá-los. As IDEs fornecem inúmeros recursos para facilitar o registro desses eventos.

Note que, se implementarmos o laço por nós mesmos, não estamos invertendo controle de coisa alguma! Utilizar programação orientada a eventos não implica necessariamente em utilizar inversão de controle. Para isso, devemos usar alguma entidade externa - um framework, ou uma biblioteca - que execute o laço para nós e cuide das questões inerentes à detecção e tratamento de eventos.

Podemos encontrar outra aplicação de inversão de controle no paradigma orientado a objetos. Sim, estamos falando da injeção de dependências, um tipo de inversão de controle onde a responsabilidade a ser “invertida” é o processo de obter dependências. Será o tema da próxima parte deste artigo, onde retomaremos o exemplo desenvolvido na primeira.

Até lá.


Enrolação de dependências - parte I

6 de Março de 2008

Uma das metas que mais se busca em orientação a objetos é diminuir o acoplamento entre os componentes da aplicação (componentes aqui são classes, pacotes, camadas, etc). E uma das formas mais eficientes de se fazer isso é utilizando injeção de dependências. Mas como toda boa prática que se torna popular, ela não podia deixar de gerar confusão entre aqueles que tentam utilizá-la. E também não podiam deixar de aparecer os “entendidos no assunto”: vomitam as palavras sem nem saber o que é e para quê serve esse recurso.

As expressões que estão na boca do povo nem sempre são as mais adequadas. Muitos se referem à prática em questão como “inversão de dependências”. Depois aparece outro que tenta corrigir, dizendo que “inversão de dependências não existe”. E chega outro falando de uma tal de “inversão de controle”. No final das contas, muitos acabam achando que as três expressões são sinônimas.

Pois bem. Vamos tentar desmistificar as coisas!

Inversão de dependências

Vamos supor que estamos desenvolvendo um sistema de cadastro de funcionários de uma empresa, onde os funcionários podem ser de dois tipos: gerentes e empregados.

Tentaremos uma primeira abordagem, ilustrada pelo diagrama de classes abaixo. De acordo com ele, uma empresa possui um ou mais gerentes e um ou mais empregados.

Diagrama de classes para a primeira abordagem.

Na figura, podemos verificar que a classe Empresa depende claramente de classes concretas, que são Gerente e Empregado. Ou seja, sempre que quisermos uma instância de Gerente na classe Empresa, teremos que obtê-la usando new Gerente(). Isso tem um lado ruim, pois se essas classes mudarem a forma como são instanciadas (modificações nos parâmetros dos construtores, por exemplo), teremos fatalmente que mexer no código da classe Empresa. Sem falar nas alterações decorrentes de um novo tipo de funcionário sendo adicionado.

Diante deste cenário, vamos enunciar o princípio da inversão de dependências:

“Componentes de alto nível não devem depender de componentes de baixo nível. Ambos devem depender de abstrações.”

Componentes de alto nível são assim chamados porque seu comportamento depende de outros componentes, os de baixo nível. No diagrama acima, Empresa é um componente de alto nível, enquanto Gerente e Empregado são de baixo nível.

E agora, como aplicar esse princípio ao diagrama acima? Simples. Posicione uma abstração entre os componentes de alto nível e os de baixo nível. Assim, ambos dependerão de abstrações:

Diagrama de classes para a segunda abordagem.

E pronto! O princípio da inversão de dependências está aplicado. Mas qual a vantagem? Uma delas é que, a partir de agora, a classe Empresa não conhece nada sobre as implementações de Funcionario; sabe apenas que lida com funcionários, não importando se são gerentes ou não. Ou seja, desacoplamento.

Mas ainda temos um problema. Antes, quando Empresa dependia de funcionários concretos, eu os instanciava diretamente usando o operador new. E agora? A inclusão dessa interface não retirou o meu problema; eu ainda preciso instanciar os funcionários usando new. E isso significa dizer que as classes ainda estão acopladas!

Ahhhhhhhh, garotinho… É exatamente nesse ponto que entra a Injeção de Dependências. Nós não criaremos as instâncias; alguém as criará para nós. Mas isso é assunto para a segunda parte desse artigo.

Até lá.


Grails - bug na versão 1.0

22 de Fevereiro de 2008

O Grails tem um comando chamado “generate-all”, cuja finalidade é gerar o código-fonte das classes de controle e de visão. O comando executa o script “GRAILS_HOME/scripts/GenerateAll.groovy” para realizar essa tarefa (GRAILS_HOME representa o local onde o Grails está instalado).

Entretanto, o script contido na versão 1.0 do Grails apresenta um erro na linha 53, que gera a seguinte mensagem:

Error executing script GenerateAll: startup failed, GenerateAll_groovy: 53: you
tried to assign a value to the class ‘resources’. Do you have a script with this
name?
@ line 53, column 4.
1 error

Para corrigir este erro, basta abrir o script e modificar a linha 53, adicionando “this.” (sem as aspas) na frente da variável “resources”.

Mais informações em http://www.guj.com.br/posts/list/82619.java.


Desenvolvimento ágil DE VERDADE com Grails

18 de Fevereiro de 2008

Groovy é uma linguagem de programação orientada a objetos desenvolvida para a plataforma Java, que possui recursos de Python, Ruby e Smalltalk. Está em processo de padronização através da JSR 241.

Grails, abreviação de Groovy on Rails, é um framework para desenvolvimento web com a linguagem Groovy que traz as características do Ruby on Rails para a plataforma (e não a linguagem) Java. Sua intenção é fornecer alta produtividade se baseando no paradigma “coding by convention”, escondendo muitos detalhes de implementação do desenvolvedor.

Baixei, instalei e fiz testes com o Grails, e fiquei surpreso com a produtividade do bichinho. O desenvolvedor fica realmente livre para se preocupar com aquilo que a aplicação possui de maior importância: regras de negócio. Eu poderia escrever um artigo ou um “Hello World with Grails” para este blog, mas vou simplesmente passar um link para um livro com cerca de 100 páginas - e gratuito - que é bastante agradável de ler. Ele introduz as características do framework aos poucos.

Observação: É preciso se registrar no site para obter o livro.

É… A comunidade Java há muito já se rendeu ao Python e ao Ruby, e está percebendo que há maneiras MUITO mais simples de construir coisas simples.


Testando o JRuby

16 de Fevereiro de 2008

Hoje baixei e instalei o JRuby, uma implementação 100% Java da linguagem Ruby. Já faz tempo que tenho vontade de testar, pois a possibilidade de utilizar a API Java na linguagem Ruby me atrai bastante.

Baixei a versão 1.0.3, descompactei, configurei a variável PATH para apontar para o subdiretório bin e… Voilá! Pronto para usar na linha de comando!

Então escrevi o seguinte programa:

require 'java'
include_class 'javax.swing.JFrame'

class FrameTeste
  def initialize
    @frame = JFrame.new("Teste do JRuby")
    @frame.setSize(300, 300)
    @frame.setLocationRelativeTo(nil)
    @frame.setDefaultCloseOperation(
      JFrame::DISPOSE_ON_CLOSE)
  end

  def show
    @frame.setVisible(true)
  end
end

f = FrameTeste.new
f.show

Salvei em um arquivo “frame_teste.rb”, e então executei utilizando o seguinte comando:

jruby frame_teste.rb

E o JRuby exibiu na tela uma janela em Swing. Muito legal! Imaginem só, unir o poder das duas linguagens! As possibilidades são enormes. Pode-se até mesmo rodar uma aplicação desenvolvida no Ruby on Rails!

Pra quem programa em Java e está estudando Ruby, é imprescindível conhecer essa ferramenta. Vou passar os próximos dias brincando com ela :)


Desabafo: falta de tempo

8 de Fevereiro de 2008

Como é difícil se manter atualizado no ramo de informática… O tempo todo novas tendências, tecnologias e metodologias surgem, e tento fazer um esforço enorme para absorver todas essas mudanças. Mas não consigo.

Amo esse ramo. E amo estudar. Poucas coisas me dão mais prazer do que estudar algo novo. O problema é que não consigo ter tempo para me dedicar o suficiente de forma que consiga aprender DE VERDADE o que estou estudando.

Recentemente escrevi um post sobre minhas metas nerds para 2008. Já estamos em fevereiro e ainda não esgotei nenhuma das metas. Além disso, tenho muita vontade de escrever alguns textos para este blog - cheguei a iniciar alguns - mas até agora não consegui publicar nada. Tudo isso por quê? Falta de tempo.

E agora meu tempo vai ficar mais curto ainda: na próxima semana começam minhas aulas na FARN, à noite, no horário em que eu conseguia estudar alguma coisa. Não sei mais o que vou fazer. Espero que eu consiga ao menos terminar o curso de Ruby.

Uma das pessoas que mais admiro como profissional é o Phillip Calçado “Shoes”. Ele trabalhou com Java por muito tempo, e agora é arquiteto de software da Thoughtworks - empresa cujo cientista-chefe é nada mais nada menos que Martin Fowler! Como dizemos aqui, “o bicho é fuderoso!”. O que será que uma pessoa como ele teria a dizer para mim? Como será que ele consegue estudar tanto e se manter tão atualizado?

Às vezes fico desestimulado. Se eu pudesse, pararia de trabalhar e abandonaria a faculdade para usar o tempo para estudar. Para vocês que estão lendo este desabafo, seguem alguns conselhos baseados em minha experiência: aproveitem seus pais enquanto podem; não inventem de trabalhar enquanto estiverem se formando; aprendam inglês LOGO; aprendam a dirigir LOGO; sejam organizados com suas vidas, e façam tudo no tempo certo.

Isso, claro, se vocês desejam do fundo do coração serem excelentes profissionais e estarem sempre um passo à frente.


Feliz ano novo atrasado

23 de Janeiro de 2008

Bom, passada a empolgação inicial de ter um blog, e seguindo o mesmo destino de vários blogs de amigos meus, este está entregue às baratas…

Antes de mais nada, feliz ano novo! :D

Não postei nada nas últimas semanas porque fiquei muito ocupado… No fim de ano, com tanta festa e tanta família, ficou difícil arrumar tempo. E desde o início de janeiro que estou fazendo aquele curso gratuito de Ruby (inclusive, uma nova turma será aberta em março! Fiquem atentos), além de ter começado a auto escola… Enfim.

Sei que ainda tô devendo um artigo sobre o padrão Decorator, mas brevemente ele sai. Tenho planos de escrever alguns artigos mostrando a utilização de padrões de projeto na linguagem Java, e o que fala sobre o Decorator seria apenas o primeiro.

Claro, se eu tiver tempo…

Até mais.