Carregando...

quarta-feira, 6 de maio de 2015

Alta disponibilidade em containers docker

quarta-feira, 6 de maio de 2015
Docker é realmente uma ferramenta incrível, estou construindo um cluster apache mesos de alta disponibilidade e tudo o que preciso é o docker, estou usando uma feature interessante do docker que é a possibilidade de reiniciar serviços que falham.

Em um cluster apache mesos, a idéia é abraçar a falha, o marathon da mesosphere é um framework que garante a alta disponibilidade das aplicações que estão sendo lançadas reiniciando as mesmas se por algum motivo elas caem, entretanto, quem garante a alta disponibilidade das aplicações que administram o cluster?

Neste ponto estou realmente apaixonado sobre o docker, vejam bem o teste que fiz para mostrar o seu poder.

Criei um script que simplesmente incrementa o conteúdo do arquivo e espera 10 segundos, ao rodar este script no docker fiz assim:

arquivo /ṭmp/script:
#!/bin/sh
echo $(($(cat /tmp/executou) + 1)) > /tmp/executou
sleep 10
Concedemos permissão de escrita para o script:
chmod +x /tmp/script 
Criamos o arquivo que terá o seu valor incrementado:
echo 0 > /tmp/executou
Rodamos o script usando o docker:
docker run -v /tmp:/tmp -dt ubuntu /tmp/script

Ao rodar o container, a imagem executa e logo em seguida sai, normalmente, quando olhamos o arquivo /tmp/executou, o conteudo dele agora é 1, ou seja executou 1 vez.

Agora imagine que este script na verdade seja um serviço critico sendo executado, como garantir a alta disponibilidade, reiniciando o serviço em caso de queda?

simples use a feature do docker --restart=always

docker run -v /tmp:/tmp --restart=always -dt ubuntu /tmp/script


Você verá que o script não para de ser executado, quando ele sai por ter encerrado o tempo, o docker reinicia automaticamente o serviço.

Vejam que isso ocorre mesmo se parar o docker (lógico que o container morre rsrsrs):

stop docker
start docker 

Ao iniciar o docker novamente o serviço está lá novamente, rodando, assim garante-se a alta disponibilidade dos containers em execução.

Realmente o docker é demais.

Espero que tenham gostado da dica.


Nenhum comentário :

terça-feira, 21 de abril de 2015

Cloud, o que é?

terça-feira, 21 de abril de 2015

No começo era apenas o programador e seu computador. Assim que terminava um sistema, copiava num disquete e levava no cliente para atualizar. Trabalhei muito assim quando desenvolvia em clipper, ainda bem que as coisas mudaram... Agora somos confrontados com sistemas rodando em nuvem. Mas o que tenho notado e que muitos desenvolvedores falam sobre o assunto  mas poucos realmente já trabalharam efetivamente com serviços em nuvem. E mesmo os que estão usando a nuvem ainda não estão tirando pleno proveito do que a computação em nuvem pode realmente fazer. Desta forma é necessária uma introdução aos termos usados neste novo cenário.

Vamos começar pelo primeiro nível : IaaS ou infraestrutura como serviço. Nesta categoria se encaixa provedores de serviço como amazon, digital ocean, linode.

O que eles oferecem? Disponibilizam poder computacional para que você possa executar qualquer coisa na infraestrutura deles. A amazon por exemplo tem serviços um pouco mais elaborados como balanceamento de carga, redes internas. Sendo possível construir todo um data center dento da infra estrutura deles.

O próximo nivel é o PaaS ou plataforma como serviço. Nesta categoria encontra-se o openshift, o heroku, etc...

Eles provem o serviço de execução de sistemas em nuvem abstraindo quase que completamente configurações extras. Geralmente essa categoria é destinada as pessoas que tem um aplicativo e simplesmente querem executá-lo sem se preocupar com detalhes de infra como uma configuração de máquina regras de firewall, como escalar o sistema para diversos servidores, etc...

E como último nível temos o SaaS. Que significa software como serviço. O gmail, é um exemplo típico de aplicação assim. A característica dessas aplicações é que a mesma aplicação atende diversos usuários diferentes. Aplicações assim damos o nome de multitenant.



Nenhum comentário :

segunda-feira, 20 de abril de 2015

Revivendo o blog

segunda-feira, 20 de abril de 2015

Uau como o tempo passa, o ultimo post foi em 2011 e de lá para cá muita coisa mudou. Fiquei maia velho, mais maduro e ganhei um anjinho, minha filhinha Layla nasceu. Adoeci e estou melhorando com o tempo. Foram transformações incríveis que somente mostram como o ser humano é mutável.

Na área de desenvolvimento muita coisa mudou em minha vida, agora  estou atuando como arquiteto de soluções na  CAPES.

Tem sido incrível o quanto me desenvolvi neste ambiente de trabalho incrível.

A tecnologia evoluiu muito e neste ponto estou procurando não ficar parado, desenvolvimento para cloud, integração de sistemas , micro serviços... Apenas para citar diversas frentes que estou estudando.

Com isso pretendo me comprometer mais e contribuir com a comunidade, agora teremos informações cada vez mais atualizadas sobre tecnologia.

Espero que gostem.



Nenhum comentário :

sexta-feira, 12 de agosto de 2011

Maus cheiros nos códigos

sexta-feira, 12 de agosto de 2011
As vezes na ânsia de terminar e ver o programa funcionando, o programador acaba implementando as funcionalidades de forma descuidada e acaba por ter um código de baixa qualidade.

vejamos um exemplo:

public void baixarCliente(){
  boolean abertas = false;
  
  for (Fatura fatura : cliente.getFaturas()){
    if (fatura.getStatus().equals(Status.EM_ABERTO)){
      abertas = true; 
      break;
    }
  }

  if (abertas)
    throw new FaturasEmAbertoException();

  cliente.setBaixado(true);
  cliente.setDataBaixa(new Date());
  MailSender mail = new MailSender("Baixa.modelo");
  mail.send(cliente.getEmail());

}
Este Código por exemplo ao ler ele com cuidado podemos entender e ele faz o que é necessário.
Mas poderia ser simplificado para poder transmitir mais conhecimento. Vejam como ficaria refatorado.

public void baixarCliente(){
  
  if (clientePossuiFaturasEmAberto())
    throw new FaturasEmAbertoException();

  registraBaixaDoClienteEEnviaEmailParaOCliente();

}

private void registraBaixaDoClienteEEnviaEmailParaOCliente(){
  cliente.setBaixado(true);
  cliente.setDataBaixa(new Date());
  enviaEmailParaOClienteNotificandoABaixa();
}

private void enviaEmailParaOClienteNotificandoABaixa(){
  new MailSender("Baixa.modelo").send(cliente.getEmail());
}

private boolean clientePossuiFaturasEmAberto(){
  for (Fatura fatura : cliente.getFaturas())
    if (fatura.getStatus().equals(Status.EM_ABERTO))
      return true;

  return false;
}


Com um código como esse fica mais claro as operações que estão sendo executadas. Ao ler o código que faz a baixa do cliente:


if (clientePossuiFaturasEmAberto())
throw new FaturasEmAbertoException();

registraBaixaDoClienteEEnviaEmailParaOCliente();

fica claro as verificações que são feitas.

ao desenvolver pense em fazer isso, pois os benefícios serão vistos na manutenção do seu sistema.



Nenhum comentário :

quinta-feira, 14 de outubro de 2010

Habilitando dominios ricos no SEAM

quinta-feira, 14 de outubro de 2010
A metodologia DDD enfatiza que ao desenvolvermos as regras de negócios devem ficar na camada de domínio, concentrando todo os relacionamentos e o funcionamento do sistema nesta camada, portanto poderíamos ter um método como:

cliente.pagar(faturaEmAtrazo);
Cliente é uma entidade do sistema, com isso não quero dizer que o cliente deve ter a lógica de pagamento de faturas, mais é ele quem inicia o processo, de onde então vem a lógica? De uma service:
public class ControleDeFaturas {
  public void receberPagamento(Cliente cliente,Fatura fatura){
    .... // aqui residiria a lógica de 
  }
}
e o cliente como fica? Ele recebe por Dependency Injection o serviço de controle de faturas, usando o framework seam teriamos algo como:
@Entity
public class Cliente {

  @In
  private ControleDeFaturas controleDeFaturas;

  ...

  public void pagar(Fatura fatura){
    controleDeFaturas.receberPagamento(this,fatura);
  }

}
Assim o modelo fica melhor, agora um problema que temos no SEAM é que ele não faz injeção de dependências nas entitys, para resolver este problema temos várias soluções, poderíamos usar a entity com uma factory que receberia o controleDeFaturas, ou mesmo fazer lookup da dependência usando Component.getInstance("controleDeFaturas"), uma abordagem que usei a qual estou gostando é o uso de Aspectos, aspecto resolve este problema, de uma forma transparente, onde mesmo se instanciarmos o Cliente por meio de um new Cliente(); ainda teríamos a injeção da dependência.

você pode visualizar a classe aqui que resolveu meu problema (usa aspectj).


Com certeza a classe pode ser melhorada, mas inicialmente resolveu o problema e permitiu uma habilitação de um domínio rico usando o SEAM, basicamente ele injeta uma instancia sempre que encontra uma classe com a anotação @Entity e um @In tanto faz ser nos atributos da classe, ou nos métodos acessores.

Devo agradecer ao Alessandro Lazarotti que sugeriu o aspecto acima como solução no fórum do guj.


Nenhum comentário :

quarta-feira, 6 de outubro de 2010

Fluent Interfaces e operadores Lógicos

quarta-feira, 6 de outubro de 2010
Algo com que todos os desenvolvedores tiveram como problema é a multiplicade de operações repetidas, creio que um exemplo seja melhor.

Reparem neste trecho de código:
public class LocalizadorDeClientes{
    public List<cliente> buscarPorCPF(String cpf){
        //implementação da busca.
    }
    
    public List<cliente> buscarPorNome(String nome){
        // implementação da busca.
    }
}
O cliente solicita agora que a busca seja feita por cliente inadimplente, a implementação mais comum seria mais um método de pesquisa:
public List<cliente> buscarInadiplentes(){
...
}
Essa abordagem é ruim? Não necessariamente, mas podemos usar um esquema diferente, o cliente te solicita agora quero combinar os filtros, muitos diriam que não dá ou fariam métodos diversos para todas as combinações possíveis.

Para casos como estes em que queremos combinar comportamentos poderemos tirar proveito da fluent interfaces:

Os exemplos apresentados aqui foram feitos apenas para exemplificar a metodologia podendo variar em implementação.

Reparem no exemplo modificado, usando fluent interfaces:
public class LocalizadorDeClientes{
public LocalizadorDeClientes porCPF(String cpf){
//configura a busca para ser realizada por cpf
return this;
}

public LocalizadorDeClientes porNome(String nome){
//configura a busca para ser realizada por nome
return this;
}

public LocalizadorDeClientes inadimplente(){
//configura a busca para ser realizada por inadimplentes
return this;
}

public List<cliente> fazerBusca(){
//configura a busca para ser realizada por inadimplentes
return this;
}

}
o uso seria assim:
LocalizadorDeClientes buscador = new LocalizadorDeClientes();
buscador.PorCPF(numCPF).porNome("carlos").inadimplente().fazerBusca();
Reparem que agora você pode encadear a chamada, fazendo com que a busca por exemplo possa ser configurável.

Este exemplo pode ser estendido usando um esquema de operadores lógicos, bastaria adicionar os métodos na classe:
public LocalizadorDeClientes e(){
// configura a busca para executar com o operador e
// no hibernate seria um conjunction em memória seria um &&
return this;
}

public LocalizadorDeClientes ou(){
// configura a busca para executar com o operador ou
// no hibernate seria um disjunction em memória seria um ||
return this;
}

public LocalizadorDeClientes nao(){
// configura a busca para executar com o operador nao
// no hibernate seria um Restriction.not em memória seria um !
return this;
}
Agora poderia fazer as consultas por exemplo assim:
LocalizadorDeClientes buscador = new LocalizadorDeClientes();
buscador.PorCPF(numCPF).e().porNome("carlos").nao().inadimplente().fazerBusca();
um esquema como este de fluent interfaces permite compor comportamento complexo a partir de um conjunto de comportamentos simples, a projetos que já utilizam isso como o Calopsita isso foi até mesmo discutido recentemente o Tectura no tópico nomes Complexos/descritivos no modelo e Martin flower fala exatamente sobre isso em seu artigo sobre fluent interfaces.

Tente entender o que é fluent interfaces, e o seu uso com operadores lógicos, pois ajudam a ter um domínio mais rico em seu software.


Nenhum comentário :

quinta-feira, 19 de agosto de 2010

Repita comigo cada teste no seu galho

quinta-feira, 19 de agosto de 2010
Algo que pode dificultar um pouco para quem está iniciando a programar usando TDD ou BDD e conseguir fazer a distinção do que é um teste de unidade de um teste funcional.

O problema que geralmente se encontra é o que o teste funcional pode parecer muito com o seu teste de unidade, mas sem estar mockado.

Isso é normal e não deve ser encarado como uma duplicação do código de teste.

Basta lembrar do objeto dos testes, um teste Funcional responde se determinada funcionalidade esta ok, portanto não usamos mocks mas objetos reais, o que desejamos é validar a interação entre os objetos, esse tipo de teste te responde "você está com problema aqui nessa funcionalidade", o que difere do teste de unidade pois o objetivo dele é validar a lógica interna de sua classe, portanto a resposta de uma falha em um teste de unidade é "você esta com problema na linha x".


Um comentário :

quinta-feira, 12 de agosto de 2010

TDD e o design de sua aplicação

quinta-feira, 12 de agosto de 2010
Ao programarmos é muito comum não termos um escopo muito bem definido do deve ser desenvolvido, embora saibamos como devemos criar os nossos códigos.

Em que TDD ajuda no design da sua aplicação? Simples, ele o mantém limpo a medida que descobre novas funcionalidades.

Suponhamos que estamos usando o estilo de fora para dentro na construção de nossos testes, devemos então começar pela interface do usuário, portanto teríamos o seguinte teste:

public class CadastroClienteTest {
  @Test public void deveriaEmitirMensagemDeAvisoParaClienteEmAtrazoAoSelecionarCliente(){}
}

Esse teste serve de ponto de partida para o seu design lembre-se que aqui você ainda não pensou em acesso ao banco e em nada de services etc..., apenas disse uma funcionalidade que a sua interface deveria ter, ao ir implementando os métodos e usando uma classe para mockar as suas dependências, você vai desenhando o seu código, implementando apenas aquilo que deve ser implementado.

Teriamos o seguinte teste:
public class CadastroClienteTest {
  
  private CadastroClienteManageBean telaCadastro;  
  private FacesMessages facesMessages;

  @Before public void configuraDependencias(){
    facesMessages = Mockito.mock(FacesMessages.class);
    telaCadastro = new CadastroClienteManageBean();
    telaCadastro.setFacesMessages(facesMessages);
  }

  @Test public void deveriaEmitirMensagemDeAvisoParaClienteEmAtrazoAoSelecionarCliente(){
     telaCadastro.selecionarCliente(1);
     Mockito.verify(facesMessages).add(FacesMessage.SEVERITY_ERROR,"cliente em atrazo");
  }
}
e sua respectiva classe:

public class CadastroClienteManageBean {

  private FacesMessages facesMessages;

  public void selecionarCliente(Integer id){
    // deveria ir ao banco
    facesMessages.add(FacesMessage.SEVERITY_ERROR,"cliente em atrazo");
  }
  
  public void setFacesMessages(FacesMessages facesMessages){
    this.facesMessages = facesMessages;
  }

}

Agora reparando neste código perceba que o sistema não está indo até o banco, para de fato trazer o resultado, ai entra algo que acho incrível do TDD, ele te ajuda a ter um design limpo.

vamos agora melhorar o teste, para fins de simplificação não iremos criar um service para o acesso ao banco, vamos conectar diretamente:

public class CadastroClienteTest {
  
  private CadastroClienteManageBean telaCadastro;  
  private FacesMessages facesMessages;

  @Before public void configuraDependencias(){
    facesMessages = Mockito.mock(FacesMessages.class);
    registrosDeClientes = Mockito.mock(RegistrosDeClientes.class);
    telaCadastro = new CadastroClienteManageBean();
    telaCadastro.setFacesMessages(facesMessages);

  }

  @Test public void deveriaEmitirMensagemDeAvisoParaClienteEmAtrazoAoSelecionarCliente(){
     Cliente clienteEmAtrazo = new Cliente();
     clienteEmAtrazo.setEmAtrazo(true);
     Mockito.when(registrosDeClientes.buscarCliente(1)).thenReturn(clienteEmAtrazo);
     telaCadastro.selecionarCliente(1);
     Mockito.verify(registrosDeClientes).buscarCliente(1);
     Mockito.verify(facesMessages).add(FacesMessage.SEVERITY_ERROR,"cliente em atrazo");
  }
}

public interface RegistrosDeClientes {

  public Cliente buscarCliente(Integer id);

}

Repare que o seu teste agora está sugerindo que você tenha um método de busca, uma vez que você tenha terminado o seu teste na tela, uma abordagem seria descer o nível e pegar todas as classes que você mockou no teste da interface e agora ir implementando o teste para as camadas mais baixas.

TDD ajuda a melhorar o design, fazendo você programar aquilo que você precisa implementar, ao invés de ficar criando métodos para classes que você acha que irá precisar.

O método usado aqui baseasse no teste de fora para dentro, onde fomos construindo um teste para a interface e mockando os objetos das camadas abaixo, e posteriormente deveríamos implementar os testes das camadas mais baixas, com os dados que coletamos dos mocks da camada superior.

Em resumo o mock te sugere o que pode ser necessário que você tenha que implementar, caso não tenha usado ainda TDD, faça um teste e se esforce, pois realmente vale a pena.


Nenhum comentário :

quinta-feira, 14 de janeiro de 2010

Framework JBee Behavior-driven development Lançado

quinta-feira, 14 de janeiro de 2010
É bem aceito na comunidade um novo paradigma de desenvolvimento de sistemas o TDD, em que consiste o desenvolvimento de testes antes da aplicação ser construida, utimamente em ganhado muita força o BDD que é o desenvolvimento orientado a comportamento, os benefícios de aplicar o BDD é a facilidade de fazer testes de aceitação e regressão no sistema.

Para programar usando a metodologia do BDD (Behavior-driven development) o desenvolvedor escreve uma história que consiste nos passos para o usuário, sendo que esta história é coduzida pelo uso de palavras chaves (Dado que, Quando, Então, E) que são interpretadas e executadas no sistema.

Para facilitar o desenvolvimento orientado a BDD eu desenvolvi um framework chamado JBee onde o objetivo dele é facilitar o uso desta metodologia de testes.

O framework é compatível com o Junit.

Acessem a pagina http://sites.google.com/site/jbeetest/ para conhecer o framework e ver a sua utilidade em ação.


Nenhum comentário :

segunda-feira, 21 de dezembro de 2009

Best Pratices - Static factory

segunda-feira, 21 de dezembro de 2009
Ao iniciarmos no conceito da orientação a objetos, muitas vezes não entendemos plenamente como usar a orientação a objetos, ninguém está isento disso, e o maior problema é que muitas vezes as pessoas se fecham a acham que sabem tudo sobre orientação a objetos, ou que apenas por usar uma classe já está usando orientação a objetos, estes são erros comuns, por exemplo veja os programadores que utilizam o Delphi, embora usem objetos, a programação parece ser mais estruturada e a lógica fica dispersa nas ações, o código fica de difícil manutenção.

Geralmente quando ocorre este problema o mais fácil as vezes é reescrever todo o sistema, isto mesmo se você já teve este pensamento, você possivelmente está fazendo alguma coisa errada.

Martin Flower se refere a estes problemas como mal cheiros no código, bem agora iremos abordar exatamente um destes problemas.

A forma mais natural de obtermos uma instância de um objeto é através do uso de um construtor, usado em java da seguinte forma:
Relatorio relContas = new Relatorio();
ao executarmos este código obteremos um objeto chamado relatório, mas uma abordagem como está é pouco flexível, considere que você precisa configurar dados do relatório para que o mesmo seja usado, uma forma de fazer isto é por oferecer a os dados necessários para a classe relatório funcionar, como parametros no construtor, veja o exemplo:
Relatorio relContas = new Relatorio("Relatorio de contas dos clientes",new Date());
repare que agora o nosso objeto relatório é gerado usando parâmetros no construtor, qual o problema desta abordagem? apenas analisando este trecho de código você não seria capaz de dizer o que os parâmetros que estão sendo passados representam, repare que você neste momento teria de fazer uma consulta ao javadoc da classe ou mesmo acessá-la para verificar o que ela está querendo dizer.

Outro problema que temos é que não conseguimos expandir as funcionalidades da classe, repare que se requisermos fazer cache o objeto relatório isto não será possível.

Usarmos uma abordagem como está com certeza (uso do operador new), torna o sistema menos flexível e conseqüentemente de mais difícil manutenção.

Podemos resolver este problema de duas maneiras, usarmos StaticFactorys.

Uma static factory permite você configurar melhor a sua classe e expor também o que você deseja fazer.

Veja o exemplo usando o conceito de static factory:
Relatorio relContas = Relatorio.comTitulo("Relatorio de contas do Cliente");
repare que agora o código parece fazer mais sentido, ao ver esta linha fica claro que você está dizendo qual é o título do relatório.

a classe fica assim:
public class Relatorio{
    ...

    private Relatorio(){}
    
    public static Relatorio comTitulo(String titulo){
        Relatorio rel = new Relatorio();
        rel.setTitulo(titulo);
        return rel;
    }

    ...
}
O uso de static factory method possui as vantagens que se você deseja tornar o objeto um Sigleton, basta modificar a fábrica estática, se você deseja fazer cache de objetos num pool para compartilhar entre as chamadas, uma abordagem como está com toda certeza permite esta flexibilidade.

Posteriormente irei abordar o uso do padrão Builder para a construção de objetos.


Nenhum comentário :