Blog do Urubatan
msgbartop
Desenvolvedor, Palestrante, Escritor, Nerd Assumido e Pai do Marcus :D
msgbarbottom

31 Oct 08 Coisas que todo desenvolvedor deveria saber sobre redes

Redes de Computadores

Qualquer bom desenvolvedor de sistemas, independente de linguagem, tem a obrigação de conhecer um pouco sobre configuração de redes.
Principalmente hoje em dia em que a grande maioria das aplicações, praticamente todas, tem que acessar dados via rede.
É inconcebível um desenvolvedor web que não sabe como funciona o TCP/IP, ou pior, as vezes nem sabe o que é um endereço IP.

Então para resolver parte deste problema, seguem alguns dados básicos sobre o funcionamento de redes que todos os desenvolvedores são obrigados a saber, para evitar parecer um retardado mental em um forum, ou pior, em uma entrevista de emprego :D

Este post não vai ser o compendio de todo o conhecimento sobre redes da história, mas a idéia é possibilitar pelo menos um conhecimento básico.

Rede = Mais de um computador ligado de alguma forma.
O primeiro passo para a criação de uma rede, é a conexão fisica dos computadores, para esta conexão fisica temos diversas opções, seguem alguns exemplos:

  • Dois computadores, cada um com uma placa de rede e um cabo de rede “cross”
  • Mais de dois computadores, cada um com uma placa de rede e um HUB, ou um Switch
  • Um computador com um modem se conectando a uma rede de um servidor também com um model (nesta categoria entram conexões discadas a internet, conexões diretas a rede de uma empresa e conexões de banda larga)
  • Dois computadores ligados por uma porta serial ou paralela
  • Dois computadores com placas de rede wireless criando uma rede Ponto a Ponto (é similar a utilização de um cabo “cross”)
  • Mais de dois computadores com placas de rede wireless conectados através de um access point

Todas estas opções criam redes, simples ou complexas, dois computadores ligados atravéz de um cabo formam uma rede, a internet é uma rede.

Depois do cabo ligado, ou da conexão fisica estabelecida, normalmente existe um protocolo de baixo nível que vai permitir que os protocolos de mais alto nível funcionem. Estes protocolos normalmente são especificos para cada meio de transporte, como pode ser visto na lista abaixo:

  • Redes sem fio normalmente utilizam os protocolos 802.11 a/b/g
  • Redes ethernet (placas de rede comuns) normalmente utilizam o protocolo 802.3
  • Redes que trabalham com modem e linha telefonica normalmente trabalham com o protocolo RS232 sobre a conexão telefonica que tem o seu proprio protocolo
  • Redes que utilizam a porta serial ou paralela utilizam normalmente o protocolo RS232

Depois de uma conexão fisica estabelecida, é necessário um protocolo para a utilização desta conexão fisica. Este protocolo de mais alto nível, vai ser executado sobre o protocolo de baixo nível descrito anteriormente. Neste nível em uma rede TCP/IP temos o protoclo ARP.
ARP = Address Resolution Protocol
Este protocolo permite que computadores consigam localizar outros computadores na mesma rede física. não confundir com DNS que veremos depois.
O ARP é um protocolo baseado em broadcast, e funciona mais ou menos como se um computador gritasse no cabo de rede: Quem é o dono do endereço IP 192.168.1.1?
Todos os computadores na mesma rede física receberão a pergunta, apenas o dono do endereço vai responder, algo como: Este endereço é meu, meu endereço fisico é: 3e:43:87:a2:01:23
O endereço físico da mensagem é o famoso endereço MAC
MAC = Media Access Control
o IEEE define 3 tipos de endereço MAC
Unicast – que identifica apenas uma máquina
Broadcast – identifica todas as maquinas da rede local, tem o valor fixo FF:FF:FF:FF:FF:FF
Multicast – endereços que identificam um grupo de maquinas da rede local

Com o ARP funcionando, ja é possível que as maquinas da rede local se encontrem, descubram para qual endereço físico mandar as mensagens IP. Então chegou a hora de começarmos a falar de TCP/IP
TCP/IP = Transmission Control Protocol/Internet Protocol
Existe também o UDP/IP mas se você entender o TCP o UDP vai ser barbada.

TCP/IP como pode ser visto no nome, é uma combinação de 2 protocolos, o Internet Protocol e o Transmission Control Protocol.

A pilha de protocolos IP começa no ARP, inclui o ICMP (o protocolo utilizado pelo Ping e Traceroute) e o IP.
Aqui é importante saber que existem 4 categorias de endereços IP:

  1. Endereços Públicos – são os endereços que as maquinas conectadas a internet possuem
  2. Endereços Reservados apra redes internas – São endereços normalmente utilizados por roteadores ADSL e redes internas de empresas
  3. Endereços de Multicast – São endereços utilizados para multimidia, por exemplo, streaming de video
  4. Endereços de rede e broadcast – estes últimos não são reservados de verdade, eles dependem da configuração da rede

Para explicar estas categorias vou falar um pouco de Endereçamento IP, se quiser mais detalhes siga o link para a Wikipedia.

Endereços Públicos são os que não são reservados, nem de multicast.

Existem as seguintes faixas de endereços reservados para utilização em redes internas:

Faixa de endereços de IP No de Redes No de IPs IPs por rede
10.0.0.0 – 10.255.255.255 126 16.777.215 16.777.216
172.16.0.1 – 172.31.255.254 16.382 1.048.576 65 534
192.168.0.0 – 192.168.255.255 2.091.150 65.535 256

Alem destes endereços reservados para redes privadas, a rede 127.0.0.0/8, é toda reservada para apontar para “localhost”, o endereço utilizado normalmente é 127.0.0.1 mas qualquer endereço desta rede funciona exatamente igual.

Alem destes endereços reservados, as redes são dividias em 5 classes (A, B, C, D e E) a classe D é a rede de multicast mencionada anteriormente.

Classe Gama de Endereços
A 1.0.0.0 até 127.255.255.255
B 128.0.0.0 até 191.255.255.255
C 192.0.0.0 até 223.255.255.255
D 224.0.0.0 até 239.255.255.255
E 240.0.0.0 até 247.255.255.255

Para se utilizar um endereço IP que não esteja reservado para redes privadas, é necessário pagar por ele, empresas compram faixas de endereços IP. Todos os provedores precisam ter uma faixa de endereços IP. Por isto os endereços começaram a acabar, e a pelo menos 10 anos, se fala em substituir os endereços IP de 4 bytes que utilizamos hoje, por endereços IP de 16 bytes. Mas acredito que isto vai deporar um pouco ainda.

Bom, isto é o mínimo que você precisa conhecer sobre redes, algum dia destes escrevo um pouco mais sobre algum assunto especifico, mas se você não conhecer isto sobre redes, você não deveria programar aplicações que utilizam rede (ou seja, qualquer uma hoje em dia).

O assunto ficou inacabado com certeza, mas ja escrevi bastante e perdi a vontade de falar sobre isto, provavelmente volte a vontade assim que eu ler outra atrocidade em algum forum como a que deu origem a este post :D )

Para saber mais sobre redes leia sobre o Modelo OSI, Endereçamento IP, Domain Name System, Enderaçamento CIDR e principalmente sobre Roteamento IP.

Espero que este post seja útil para alguem, e meus parabéns para os que leram até aqui!

23 Oct 08 AOP fácil com o Guice

Como eu ja comentei em outro post o Guice é um framework de injeção de dependências muito fácil de utilizar.
Depois de utilizar o Guice por algum tempo, comecei também a utilizar alguns recursos de AOP do Guice, e como é muito fácil de utilizar, acho que alguns de vocês podem aproveitar isto (se é que alguem ainda lê este blog cheio de poeira :D ).

Para quem não sabe o que é AOP segue uma rápida introdução:
AOP = Aspect Oriented Programming ou Programação Orientada a Aspectos
Aspectos são uma forma de de isolar partes de um problema e reutilizar as soluções deste problema em diversos pontos do software que tenham o mesmo problema.
Um exemplo disto, o exemplo mais batido depois do logging, é o controle de transações …
Em todo o código de negócio na sua aplicação deve existir inicio e fim de transações, o que na verdade é uma dependência da regra de negócio mas não faz parte de verdade da regra de negócio sendo implementada.
Então este é um bom candidato a ser implementado como um aspecto, da mesma forma que é feito no EJB3 por exemplo, que é remover o código de controle de transações de dentro do código de negócios, e adicionar um marcador no código informando como se deseja que a transação se comporte para aquele trecho.

Para ficar mais claro de uma olhada neste exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package example;
 
import java.math.BigDecimal;
 
public class CodigoDeNegociosImpl {
	private InterfaceParaOutroServico outroServico;
	private ControleDeTransacoes transacao;
 
	public void metodoDeNegocios(String parametro1, int parametro2, BigDecimal parametro3) {
		transacao.inicia();
		try {
			algumMetodo(parametro1);
			outroMetodo(parametro2);
			agoraUmCalculo(parametro3);
			transacao.commita();
		} catch (Exception e) {
			transacao.fazRollback();
		}
	}
 
	private void algumMetodo(String parametro1) {
		outroServico.metodoDeNegocio(parametro1);
	}
 
	private void outroMetodo(int parametro2) {
		// implementa regra de negocio
	}
 
	private void agoraUmCalculo(BigDecimal parametro3) {
		// faz um calculo complicado
	}
}

Este é um código bem simples, onde dentro do “metodoDeNegocios” existe código para iniciar e finalizar transações.
O código esta bem simplificado, mas imagine uma situação um pouco mais complicada, onde por exemplo, dentro de “outroServico.metodoDeNegocio” também fosse necessário participar da mesma transação, mas apenas se a transação ja estivesse iniciada, caso contrario seria necessário criar uma nova transação, o código começaria a ficar cada vez mais complicado, e este é um código que não faz parte da regra de negócios sendo implementada por estes métodos. Agora imagine se fosse possível resolver estes problemas simplesmente alterando o código para o seguinte:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package example;
 
import java.math.BigDecimal;
 
import com.google.inject.Inject;
 
public class CodigoDeNegociosImpl implements CodigoDeNegocios {
	@Inject
	private InterfaceParaOutroServico outroServico;
 
	/* (non-Javadoc)
   * @see example.CodigoDeNegocios#metodoDeNegocios(java.lang.String, int, java.math.BigDecimal)
   */
	@PrecisaDeTransacao
	public void metodoDeNegocios(String parametro1, int parametro2, BigDecimal parametro3) {
		algumMetodo(parametro1);
		outroMetodo(parametro2);
		agoraUmCalculo(parametro3);
	}
 
	private void algumMetodo(String parametro1) {
		outroServico.metodoDeNegocios(parametro1);
	}
 
	private void outroMetodo(int parametro2) {
		// implementa regra de negocio
	}
 
	private void agoraUmCalculo(BigDecimal parametro3) {
		// faz um calculo complicado
	}
}

Não seria bem mais simples? (Antes que alguem pergunte, eu acabei de criar a anotação @PrecisaDeTransacao)
Podemos também imaginar outro problema. A aplicação tem um requisito que diz que o tempo total de cada chamada ao “metodoDeNegocio” deve ser logado, e também devem ser logadas todas as chamadas a “outroServico.metodoDeNegocio” informando o tempo total de execução do método.
A forma padrão de fazer isto é em cada um dos métodos que precisa do tempo logado, adicionar código no inicio e no final do método para fazer este registro, mas utilizando AOP é possível fazer sem tocar no código das classes.
Na AOP este logging e o controle de transações, são chamados de “preocupações transversais da aplicação”, ou seja, são aspectos da aplicação que permeam o código de diversas classes, mas não pertencem realmente as partes do código “sujas” por estes “aspectos”.
Ninguem vai programar puramente orientado a aspectos, mas AOP é uma excelente forma de contornar limitações de linguagens burocraticas demais, como o Java.

OK, mas o que o Guice tem a ver com isto?
Bom, o Guice possibilita a implementação de recursos simples de AOP utilizando a criação dinâmica de proxies para as classes gerenciadas por ele.
Acha que eu falei grego? Bom, vamos fazer um exemplo simples então.
Todos vocês sabem que anotações não fazem absolutamente nada, certo? Anotações são apenas metadados, ou dados extras que decoram o código com mais informações.
Então, vamos aproveitar os dados extras adicionados no exemplo anterior, e vamos implementar o controle de transações utilizando AOP e o Guice.

Primeiro vamos criar um modulo com a configuração básica da aplicação:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package example.guice;
 
import com.google.inject.AbstractModule;
 
import example.CodigoDeNegocios;
import example.CodigoDeNegociosImpl;
import example.ControleDeTransacoes;
import example.InterfaceParaOutroServico;
import example.impl.ExemploDeTransacoes;
import example.impl.OutroServicoComRegrasDeNegocio;
 
public class BasicAppModule extends AbstractModule {
	@Override
	protected void configure() {
		bind(ControleDeTransacoes.class).to(ExemploDeTransacoes.class);
		bind(InterfaceParaOutroServico.class).to(OutroServicoComRegrasDeNegocio.class);
		bind(CodigoDeNegocios.class).to(CodigoDeNegociosImpl.class);
	}
}

As classes “ExemploDeTransacoes” e “OutroServicoComRegrasDeNegocio” estão em branco, apenas implementam as interfaces correspondentes sem nenhum código nos métodos.
Até aqui não temos nenhuma novidade, código Guice padrão.
Mas vamos agora criar um outro modulo apenas para a configuração de AOP para deixar tudo bem separado.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package example.guice;
 
import java.lang.reflect.Method;
 
import org.aopalliance.intercept.MethodInterceptor;
 
import com.google.inject.AbstractModule;
import com.google.inject.matcher.Matcher;
import com.google.inject.matcher.Matchers;
 
import example.PrecisaDeTransacao;
import example.aop.LoggingInterceptor;
import example.aop.TransactionInterceptor;
 
public class AOPConfigModule extends AbstractModule {
	@Override
	protected void configure() {
		MethodInterceptor transactionInterceptor = new TransactionInterceptor();
		bindInterceptor(Matchers.any(), Matchers.annotatedWith(PrecisaDeTransacao.class), transactionInterceptor);
		MethodInterceptor loggingInterceptor = new LoggingInterceptor();
		Matcher<? super Method> machMethodsByNameMatcher = new MatchMethodsByNameMatcher("metodoDeNegocio");
		bindInterceptor(Matchers.any(), machMethodsByNameMatcher, loggingInterceptor);
	}
}

Agora explicando um pouco o código deste modulo.
Estamos utilizando o metodo “bindInterceptor” que configura o Guice para criar um proxy das classes e métodos que fecharem com os dois matchers passados (o primeiro para classes e o segundo para metodos).
Os matchers são como filtros, eles servem para informar ao Guice onde devem ser aplicados os interceptors.
A classe com.google.inject.matcher.Matchers do Guice facilita bastante a vida provendo diversos matchers prontos, mas nenhum deles leva em consideração o nome do metodo como queriamos fazer para o logging, então eu criei um matcher novo, vejam o código a baixo e verifiquem que é bem simples.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package example.guice;
 
import java.lang.reflect.Method;
 
import com.google.inject.matcher.AbstractMatcher;
 
public class MatchMethodsByNameMatcher extends AbstractMatcher<Method> {
	private String methodName;
 
	@Override
	public boolean matches(Method method) {
		return methodName.equals(method.getName());
	}
 
	public MatchMethodsByNameMatcher(String methodName) {
		super();
		this.methodName = methodName;
	}
}

O único metodo que precisa ser implementado é o “matches” que faz as comparações no objeto “Method” recebido e retorna true ou false.

Depois disto, a parte mais importante é a implementação do “MethodInterceptor”. Vamos dar uma olhada no código do interceptor de logging.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package example.aop;
 
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
 
public class LoggingInterceptor implements MethodInterceptor {
	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		long start = System.currentTimeMillis();
		try {
			return invocation.proceed();
		} finally {
			long end = System.currentTimeMillis();
			System.out.format("%s.%s - %d\n", invocation.getThis().getClass().getName(),invocation.getMethod().getName(),end-start);
		}
	}
}

O Guice utiliza as interfaces para aop da aopalliance, as mesmas que as primeiras versões do spring framework, então se você tem algum código AOP que parou de funcionar no spring, migre para o Guice :D
Brincadeiras a parte, as unicas interfaces que você precisa realmente conhecer são:
org.aopalliance.intercept.MethodInterceptor – interface que define apenas o método invoke, que sera chamado no lugar de qualquer método interceptado por esta classe.
Exatamente isto, o método invoke sera chamado no lugar do “metodoDeNegocios”.
O invoke recebe como parâmetro uma instância de org.aopalliance.intercept.MethodInvocation:
Que possui informações sobre a chamada atual, como pro exemplo os parâmetros que estão sendo passados para o método, o método que esta sendo chamado, em qual classe, em que instância da classe, …
E possui o método “proceed()” que chama o método real, neste caso o “metodoDeNegocios”.

O resto é só implementar a lógica do interceptor, neste caso capturar o tempo de execução do método, ou seja, o tempo de execução do “proceed()”.

Não vou implementar o interceptor de controle de transações por que não é este o objetivo do post, e alguem iria querer utilizar um exemplo simples em produção em algum momento :D

Agora só falta criar uma clase para inicializar a aplicação e chamar o método de negocios :D

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package example;
 
import java.math.BigDecimal;
 
import com.google.inject.Guice;
import com.google.inject.Injector;
 
import example.guice.AOPConfigModule;
import example.guice.BasicAppModule;
 
public class AOPTest {
	public static void main(String[] args) {
	  Injector injector = Guice.createInjector(new BasicAppModule(),new AOPConfigModule());
	  CodigoDeNegocios obj = injector.getInstance(CodigoDeNegocios.class);
	  obj.metodoDeNegocios("a", 3, new BigDecimal(200l));
  }
}

Neste código não tem muita novidade para quem leu o primeiro post sobre o Guice.
O output deste código deve ser algo parecido com:

example.impl.OutroServicoComRegrasDeNegocio$$EnhancerByGuice$$eda06b1.metodoDeNegocios - 16
example.CodigoDeNegociosImpl$$EnhancerByGuice$$54b1222d.metodoDeNegocios - 16

Com isto podemos ver que o Guice altera as classes para poder implementar o AOP.

Para finalizar algumas considerações:

  • O AOP do guice é implementado utilizando proxies, ou seja, não é possível interceptar uma chamada a um método da mesma classe ou a métodos privados
  • É preciso passar uma instância do interceptor, por tanto não é possível injetar dependências no interceptor, a única forma de contornar isto que encontrei foi utilizando atributos estáticos e chamando o requestStaticInjection

Acho que era isto por enquanto, como este não foi o post mais detalhado que ja escrevi até hoje, espero que tenham muitas perguntas, podem perguntar nos comentários que eu respondo o mais rápido possível.
Para quem ficar com preguiça de copiar e colar os códigos, ou estiver enfrentando algum problema por eu ter esquecido de colocar alguma coisa no post segue a Aplicação de exemplo Guice/AOP que desenvolvi enquanto escrevia o post.

07 Oct 08 Carregando o Rails no bolso – e programando em qualquer lugar

Sei que o blog anda meio jogado as traças, é que depois que terminei o livro a umas duas semanas fiquei meio cansado de escrever, mas acho que ja estou me recuperando :D
Este post aqui vai ser bem curto, é só uma dica para os programadores Rails por ai que não estão sempre na frente dos seus computadores e não gostam de perder tempo ou gostam de poder prototipar aquela idéia espetacular que vai te deixar rico!
Ou seja, é uma dica para os nerds de plantão :D
Também pode ser encarado como uma continuação do post onde falei sobre o PortableApps, já que utilizo o Ruby On Rails Portable e o GVim Portable junto com o PortableApps!
É isto mesmo, o pessoal da Simbisoft empacotou o Rails e o SciTE de forma que eles fiquem instalados em um Pendrive. Não gosto do SciTE para programar em Rails, mas para resolver isto, instalo o GVim Portable no mesmo pendrive e o rails.vim no GVim do pendrive!
Tudo funcionando!
E ambos funcionam integrados com o launcher do portable apps!
É quase um sonho nerd :D

(Esta última frase ficou muito gay … )

PS.: Uma última novidade, falei com o pessoal da novatec e o meu livro sobre Ruby On Rails deve chegar nas livrarias em novembro :D

Tags: , , ,