Just Java 2011 – Baixo Acoplamento e Alta Coesão

maio 18, 2011 às 12:56 am | Publicado em apresentações, Desenvolvimento, Java | 2 Comentários

Este ano eu participei do Just Java  com uma palestra sobre o seguinte tema:

Desenvolvendo em java visando o baixo acoplamento.

A apresentação foi bem legal e creio que consegui passar a mensagem para o pessoal. Por falar nisso, agradeço a todos que pararam alguns minutos pra me escutar.

Abaixo segue os slides da apresentação. O código fonte utilizado durante a apresentação está aqui.

Anúncios

Introdução ao Hibernate

dezembro 8, 2010 às 7:43 pm | Publicado em apresentações, Java | Deixe um comentário

Hoje fiz uma pequena apresentação para o time sobre o Hibernate.

No time temos bons programadores que sempre utilizaram o hibernate mas não conheciam todo o potencial deste framework.

Abaixo segue os slides utilizados na apresentação.

OSGI – Modularizando sua aplicação

novembro 12, 2009 às 11:27 pm | Publicado em Java | 3 Comentários

Semana passada fui conhecer a maior livraria de Vancouver. Como sempre, gastei mais do que devia. Dentre minhas aquisições, não podia faltar um livro sobre OSGI. Como sou um grande defensor de modularização, baixo acoplamento, alta coesão, etc… creio que esta tecnologia é um grande avanço na forma como criamos aplicações utilizando a plataforma Java. Com OSGI, é muito simples criar aplicações altamente extensíveis, veja como exemplo a IDE Eclipse.

Meu objetivo aqui não é mostrar a fundo como funciona a tecnologia e sim demonstrar em um pequeno exemplo algumas de suas vantagens. O exemplo consiste em um sistema de envio de mensagens. O usuário digita uma mensagem em um textfield e esta mensagem pode ser enviada de diversas formas, como email ou sms. Porém, no exemplo, teremos quatro módulos. A interface gráfica, o domínio, o enviador de mensagens por email e o enviador por SMS.

Seguindo a nomenclatura do OSGI, cada módulo é um Bundle. Um Bundle nada mais é do que um “jar” com algumas informações adicionais do MANIFEST.MF. Estas informações são utilizadas pelo framework OSGI. Como quase tudo no Java, a tecnologia OSGI é uma especificação e portanto, temos diversas implementações para escolher. Dentre elas, as mais famosas são Equinox (Projeto Eclipse) e Felix (Apache). Neste artigo utilizaremos o Equinox.

Faça o download no Equinox. Para este artigo precisaremos apenas do Jar. Execute o Jar para ter acesso ao console do Equinox.

java -jar org.eclipse.osgi_3.4.2.R34x_v20080826-1230.jar -console

Para visualizar os Bundles instalados, basta digitar o comando ss.

OSGI console

Como podemos ver, neste momento só temos um bundle instalado. O bundle do Equinox. Agora iremos criar o nosso bundle e adicioná-lo do Equinox. Criar um bundle é muito simples. Crie um simples projeto com a seguinte classe:

OSGI Activator

Esta classe é o activator do nosso bundle. O activator é utilizado pelo framework OSGI para iniciar ou parar um bundle.  Neste primeiro exemplo, o activator irá apenas imprimir mensagens quando for iniciado e parado. Agora precisamos alterar o MANIFEST do jar para torná-lo um bundle OSGI.

osgi metainf

Veja que no MANIFEST passamos para o OSGI algumas informações do nosso bundle. Dentre elas o nome do bundle (SymbolicName) e qual a classe Activator. Agora vamos instalar este bundle no Equinox. Gere um jar do projeto e para instalá-lo no Equinox é simples:

install file:<nomeDoBundle>.jar

osgi4

Para verificar se o bundle foi corretamente instalado, basta executar o comando ss:

osgi5

O bundle está corretamente instalado, agora basta iniciá-lo:

start <idDoBundle>

osgi6Para parar o bundle:

stop <idDoBundle>

osgi7

Agora que já sabemos como criar um bundle, vamos iniciar nosso exemplo. No exemplo, teremos quatro bundles.

  • Domínio:  Como o próprio nome diz, ele armazena as classes de domínio do nosso exemplo. Teremos duas classes: Message e IMessageSender.
  • EnviadorSMS: implementação de IMessageSender que envia mensagens por SMS.
  • EnviadorEmail: implementação de IMessageSender que envia mensagens por Email.
  • UI: interface gráfica do exemplo

Bundle UI

Iremos começar pelo bundle UI. O activator irá apenas criar o frame para o usuário entrar com a mensagem.

osgi8

Veja que o bundle depende de uma classe chamada Message. Esta classe é nosso domínio, portanto, ela não faz parte deste bundle. Aqui entra outro detalhe do OSGI. A comunicação entre bundles é feita através de serviços. Podemos considerar este modelo como sendo um SOA dentro da VM. O bundle UI irá utilizar serviços do bundle Core. Vamos analisar o MANIFEST do bundle UI.

osgi9

Veja a declaração Import-Package. Estamos importando um pacote do bundle core. Neste pacote estão os serviços que nosso domínio está disponibilizando. Importamos também o pacote javax.swing.

Agora precisamos criar o serviço.

Bundle Core

O Bundle Core possui duas classes de domínio. A interface dos enviadores e o domínio Message.

Interface:

osgi10

Domínio:

osgi11

Veja que a classe Message é composta por uma lista de services. Estes services são os enviadores de mensagens que serão utilizados. Veja que o método send apenas itera sobre a lista enviando a mensagem. Até aqui tudo é muito simples. Agora precisamos exportar a classe Message como sendo um serviço do bundle core. O módulo UI irá iteragir diretamente com este serviço para enviar as mensagens.

Primeiro precisamos dizer ao OSGI para exportar este pacote para outros bundles. Veja o MANIFEST:

osgi13

Veja a informação Export-Package. Para uma classe ser visível para outro bundle, ela precisa estar dentro de um pacote exportado. No nosso caso, o bundle UI precisa da classe Message, portanto, precisamos exportar o pacote onde a classe está. Lembre-se que o bundle UI importou este pacote.

Para registrar o componente Message como um serviço, teremos que interagir diretamente com a API do OSGI. Quando o bundle core for iniciado, iremos registrar o serviço no contexto do OSGI. O código é simples:

osgi12

O método registerService espera como parâmetros o nome do serviço (por recomendação é o nome da classe), o serviço em si e algumas configurações adicionais.

Agora precisamos alterar o bundle UI para utilizar o serviço Message. No activator do bundle UI, basta fazer o “lookup” do serviço utilizando seu nome (nome da classe) :

osgi17

Se adicionarmos os dois bundles no Equinox, veremos que os dois bundles estão se comunicando. Agora precisamos criar os bundles que realmente enviam as mensagens.

Bundle Enviador Email e SMS

Os serviços de envio por email e por SMS serão novos serviços de nosso sistema. Portanto, deveremos criar um bundle para cada um. Desta forma poderemos controlá-los separadamente. Por exemplo, podemos parar o serviço de envio por SMS e deixar apenas o de Email sem afetar o funcionamento do sistema. O dois bundles possuem praticamente a mesma estrutura, portanto, irei economizar um pouco de linhas aqui.

O bundle enviador terá apenas uma classe que implementa a interface IMessageSender e a classe Activator. Esta interface está no bundle core, portanto, precisaremos importar o pacote da mesma forma que fizemos no bundle UI.

osgi14

A classe enviador apenas implementa a nossa interface:

osgi15

Enviar por SMS será um serviço do nosso sistema. Portanto, precisamos registrá-lo no contexto OSGI:

osgi16

O bundle de Email é praticamente o mesmo código. A única diferença é a mensagem no System.out.

Veja que registramos o serviço com o nome da interface. Portanto, teremos dois serviços com o mesmo nome. Sempre que pedimos para o contexto o serviço com o nome da interface, ele irá executar uma lógica de prioridade para retornar apenas uma implementação.

Agora que temos dois serviços de envio de mensagem, precisamos alterar nosso bundle core para utilizá-los.  Para isso, utilizaremos um ServiceTrackerCustomizer.

ServiceTrackerCustomizer e ServiceTracker

Como vimos, utilizamos o serviceTracker para fazer o lookup de um serviço. Porém, no caso dos enviadores, precisamos saber quando um novo serviço de enviador está disponível ou quando um enviador for removido. Estas informações são importantes para alimentar a lista de serviços dentro do objeto Message.

Para ter acesso a estas informações, usaremos um ServiceTrackerCustomizer. O código é simples:

osgi18

Basta implementar a interface ServiceTrackerCustomizer e codificar o que você deseja quando um serviço for adicionado, modificado ou removido. Simples!!!!

No nosso caso iremos adicionar ou remover o serviço da lista de serviços do nosso objeto Message. Também tem uma mensagem de “log” para nos ajudar com os testes.

Agora precisamos fazer mais uma pequena alteração no activator do bundle core. Precisamos registrar o nosso ServiceTrackerCustomizer como um listener para os serviços do tipo IMessageSender.

osgi19

Utilizamos o serviceTrackerCustomizer junto com o ServiceTracker. Sempre que um serviço for adicionado, modificado ou removido, nosso componente será chamado.

Testando a aplicação

Agora que já codificamos, vamos testar a aplicação.

Crie os quatro jars ou faça ou download aqui:

  • bundleCore.jar
  • blundleUI.jar
  • bundleEnviadorEmail.jar
  • bundleEnviadorSMS.jar

Instale os quatro bundles no Equinox:

osgi20

Inicie os bundles e teste a aplicação.

osgi21

Veja que as mensagens serão enviadas por email e por SMS. No console do Equinox, pause o serviço de email:

stop <idBundle>

Tente enviar novamente uma mensagem. Como o serviço não está mais disponível, a mensagem foi enviada somente por SMS.

Poder parar módulos da aplicação sem que ela sofra efeitos colaterais é sensacional. Imagine que você descubra um erro crítico no módulo de SMS. Você não precisa tirar toda a aplicação do ar para corrigir este problema. Basta pausar o módulo de SMS. Todo o resto do sistema continuará funcionamento normal. Faça o teste com este pequeno exemplo. Pause e Inicie os serviços. Isto não afetará o Core e muito menos o UI.

Espero ter conseguido explicar um pouco do que é OSGI. Vale ressaltar que tem muito mais detalhes sobre controle de classpath e configuração de bundles que não nos atentamos aqui. Fica como tarefa para quem se interessou dar uma olhada nas outras funcionalidades.

Vale a pena olhar o projeto Spring-DM. O spring facilita muito a configuração de serviços além de propiciar um excelente conteiner de IoC.

Baixo Acoplamento

fevereiro 10, 2009 às 1:19 pm | Publicado em Desenvolvimento, Java | 3 Comentários

Programar é uma tarefa ardua e programar um código que siga os bons princípios é mais ainda. Na correria do dia a dia, acaba-se esquecendo das boas práticas e o resultado é um código “macarrônico” totalmente sem padrão. Um colega sempre dizia “Programar bem é uma arte!!!”.

Neste post será abordado um princípio muito importante para sistemas orientados a objeto, o desacoplamento do código. Todo o artigo será baseado no estudo de caso de uma pequena API para envio de malas diretas.

Abaixo segue a modelagem do problema:

Modelagem

A classe mala direta é responsável por enviar uma mensagem a um grupo de destinatários. Para isso, ela utiliza do componente “EnviadorEmail”. Segue a implementação da mesma:

 

Código

O exemplo acima demonstra um exemplo de código altamente acoplado. Isto se caracteriza pela utilização direta de uma classe concreta (new EnviadorEmail()), acarretando em um problema muito grave: Torna-se impossível trocar a forma de envio da mala direta em tempo de execução pois o código está altamente acoplado com o componente EnviadorEmail.

Desacoplando o código:

Desacoplar um código consiste em montar um design que o deixe mais fléxivel a mudanças. Programar um código desacoplado garante uma maior qualidade e facilita futuras mudanças.

Erich Gamma, o criador do Eclipse, JUnit e co-autor do famoso livro “Padrões de Projeto” disse em uma entrevista: “Program to an interface, not an implementation”.

Programar para interface deixa o código mais flexível, permitindo trocar a implementação de um componente em tempo de execução. Refatorando o nosso design para utilizar interfaces:

Modelagem

Refatorando o código da MalaDireta:

Código

Quando um código depende de uma interface, pode-se decidir em tempo de execução qual a implementação será utilizada. Um exemplo pode ser verificado na imagem abaixo:

Código

Porém ainda existe um pequeno acoplamento no método enviar. O método ainda precisa dar o new em uma implementação, o que o torna fortemente acoplado a ela. O ideal é que outro componente tome a decisão de qual implementação criar. A função da MalaDireta é enviar sua mensagem. Não é sua responsabilidade saber de qual forma.

Factory

O design pattern Factory tem como função separar a lógica de criação de objetos em um outro componente (fábrica). No exemplo acima, pode-se ter o EnviadorFactory. Uma forma de implementação do factory pode ser visto abaixo:

Código

Refatorando a classe MalaDireta para utilizar a fábrica:

Código

Utilizando a fábrica foi possível separar a lógica de criação da forma de envio das malas diretas, porém o método agora ficou acoplado com a fábrica. Utilizar fábricas solucionou apenas parte do problema, como desacoplar totalmente o código da MalaDireta???

Inversão de Controle

Martin Fowler escreveu em seu site um artigo muito interessante sobre Inversão de Controle (IoC). O artigo levanta uma interessante discussão: Qual controle da aplicação está sendo invertido???

A inversão de controle consiste em uma mudança na forma como são criadas as dependências dos objetos. No exemplo utilizando fábricas, o método “pede” para a fábrica uma dependência. Na visão da IoC, não é mais o código que pede por uma dependência, ele apenas declara que precisa de determinado componente e ele é disponibilizado.

Seguindo este princípio, Martin Fowler questiona se o nome correto para a Inversão de Controle não seria Injeção de Dependência. Segundo ele, a mudança afeta a forma como são gerenciadas as dependêcnias que agora são injetadas nos objetos, eliminando assim o uso da palavra new no código:

Código

A classe acima declara em seu construtor que precisa de uma implementação de IEnviador. Ou seja, alguém irá “injetar” esta dependência. O método enviar não sabe pra onde está enviando sua mensagem. O código está totalmente desacoplado!!!!

Exemplo de um código que utiliza a MalaDireta:

Código

 

Com um código totalmente desacoplado, fica fácil criar testes unitários e consequentemente aumenta a qualidade do código.

Infelizmente não são todos os desenvolvedores que possuem esta preocupação. Mas espero que este pequeno artigo tenha gerado uma grande reflexão sobre como construir componentes de verdade.

Sempre que for codificar, lembre-se da frase: “Programe para interfaces e não para implementações!”.

Linguagem fortemente tipada (Strong typing)

fevereiro 28, 2008 às 2:19 am | Publicado em Desenvolvimento, Java, JavaScript, ruby | 28 Comentários

Em uma conversa com uma professora da faculdade, surgiu uma pequena discussão.
O que é uma linguagem fortemente tipada?

Segundo a professora, linguagem fortemente tipada é aquela onde você precisa declarar o tipo da variável, por exemplo:

// código java
private String nome;

Na minha opinião, ela está enganada.
A principal característica de uma linguagem fortemente tipada (Strong typing), é que cada variável do programa representa um objeto de um tipo bem definido.

// codigo java
int x = 12.1; // erro, tipos incompatíveis
int j = (int) 12.1 // funciona, mas você perde as casas decimais 🙂

Java é uma linguagem formente tipada. Não é possível atribuir um double para um int.
Para executar tal operação, você terá que forçar a tranformação para o tipo definido pela variável. Chamamos isso de cast. Java também é uma linguagem com tipagem estática, ou seja, você precisa declarar qual o tipo de objeto a variável irá referenciar.

Vejamos um exemplo em Ruby.

x = ‘Marcelo’
y = 12
puts x + y

A principal diferença que podemos notar é a ausência do tipo da variável. Mas isso não torna ruby uma linguagem fracamente tipada. O que acontecerá se você tentar somar (+) um Fixnum (int) com uma String? Um belo erro no console:
can’t convert Fixnum into String (TypeError)

Ou seja, ruby também é fortemente tipada, porém de forma dinâmica. O interpretador “descobre” em tempo de execução o tipo da variável. Devido a essa característica, em ruby não existe cast. Caso os tipos envolvidos na operação sejam incompatíveis, você terá um belo erro pra se preocupar.

Veja um exemplo em javascript:

var x = “Marcelo”;
var y = 12;
alert(x + y);

JavaScript é fracamente tipada (weak typing), ou seja, este código será executado sem problemas. Você não precisa informar o tipo da variável e o intepretador do javascript sabe realizar algumas operações sobre os objetos dependendo do contexto.

Espero que a professora leia este POST. 🙂

Próxima Página »

Crie um website ou blog gratuito no WordPress.com.
Entries e comentários feeds.