Arquivo

Arquivo do Autor

Layer Supertype Pattern

superman logoUm bom código deve evitar ao máximo a replicação de suas partes, favorecendo a manutenção. Nesse post, vamos apresentar um artifício para combater esse problema.

O padrão Layer Supertype tem como objetivo definir uma classe que agrupa operações que são semelhantes em todas as classes de uma camada. Vamos ao exemplo:

public class Teacher
{
    private string name;
    private int Age;

    public int Id { get; set; }

    public void Insert()
    {
       this.IsValid();
       //código de persistência comum a todas as classes
    }

    public void Update()
    {
        this.IsValid();
        //código de persistência comum a todas as classes
    }

    private bool IsValid()
    {
       //código de validação específico para a entidade Teacher
    }
}

public class Lesson
{
    private int level;

    public int Id { get; set; }

    public void Insert()
    {
       this.IsValid();
       //código de persistência comum a todas as classes
    }

    public void Update()
    {
       this.IsValid();
       //código de persistência comum a todas as classes
    }

    private bool IsValid()
    {
      //código de validação específico para a entidade Lesson
    }
}

Note que as classes possuem os mesmos métodos Insert, Update e IsValid, além da propriedade Id. Utilizando o padrão Layer Supertype, criaremos uma classe base que vai agrupar essas operações e será herdada pelas demais classes da camada.

O código fica assim:

public class BaseEntity
{
    public int Id { get; set; }

    public void Insert()
    {
       this.IsValid();
       //código de persistência comum a todas as classes
    }

    public void Update()
    {
       this.IsValid();
       //código de persistência comum a todas as classes
    }

    protected abstract bool IsValid();
}

public class Teacher : BaseEntity
{
   private string name;
   private int Age;

   protected override bool IsValid()
   {
      //...
   }
}

public class Lesson : BaseEntity
{
    private int level;

    protected override bool IsValid()
    {
      //...
    }
}

Com isso, evitamos duplicação de códgio, centralizando a lógica de negócio que estaria repetida por diversas classes em uma única classe. O código ficou mais limpo e mais fácil de manter.

Anúncios

Boas Práticas no uso de Exceções

AtrExceção Null Referenceavés da manipulação de exceção podemos tratar situações indesejadas que podem acontecer durante a execução de um código. Nesse post, vamos discutir sobre algumas práticas para melhor utilizar esse recurso em nossos códigos.

Primeiramente, exceções não devem ser usadas para controlar o fluxo da aplicação, como se fosse uma estrutura if-then-else. Veja o exemplo abaixo:

IManager manager;
try
{
manager = businessManagerRepository.GetManager(managerId);
//Lógica para o Gerente de Negócio
}
catch(BusinessManagerNotFoundException ex)
{
manager = projectManagerRepository.GetManager(managerId);
//Lógica para o Gerente de Projetos
}

A estrutura try-catch não deve ser usada como meio de escolha do caminho a ser tomado segundo o levantamento de uma exceção.

Outra boa prática é diferenciar as exceções de sistemas das exceções de negócio. Ao serem lançadas exceções de negócio devem permitir que o usuário refaça a operação. Geralmente elas são exceções personalizadas, inerentes ao domínio da aplicação.

No caso de exceções de sistema, é importante adicioná-la ao log e verificar se ela foi gerada por uma falha no processo de comunicação com algum serviço, como o banco de dados por exemplo. Esse tipo de exceção pode gerar um estado inconsistente da aplicação. Dessa forma, é necessário voltar ao estado correto (ou até mesmo ao estado inicial) garantindo que as operações futuras não sofram alterações de comportamento devido ao erro ocorrido.

Nos dois casos, sempre exiba uma mensagem amigável ao usuário. Mensagens como “Ocorreu um erro durante o cadastro do cliente” são muito melhores que “Null Reference exception on line 25”.

Outra técnica importante é apenas capturar exceções são “esperadas”. Veja o exemplo:

try
{
this.SendMessageToCustomer(message);
}
catch(Exception ex)
{
//tratamento da exceção
//...
errorMessage = "Não foi possível enviar a mensagem";
}

O código captura uma exceção do tipo Exception. Esse é um tipo muito genérico e pode acabar encobrindo de forma indesejada algum erro na aplicação (principalmente se um log não estiver sendo utilizado). No exemplo acima, pode ter ocorrido um erro no formato da mensagem, ou na conexão com o servidor de email ou outra falha qualquer. Em ambos os casos, não será possível rastrear a verdadeira causa do levantamento da exceção.

O melhor nesse caso é capturar uma exceção mais especializada. Se nenhuma exceção já existente servir para esse caso, crie uma que possua essa responsabilidade. O código ficaria assim:

try
{
this.SendMessageToCustomer(message);
}
catch(CanNotConnectToEmailServerException ex)
{
//tratamento da exceção
//...
errorMessage = "Não foi possível enviar a mensagem. Ocorreu um erro na conexão com o Servidor de Email.";
}

Lembre-se que o framework já possui exceções para diversas situações diferentes. Utilize-as sempre que puder, para não reinventar a roda.

Sockets em Ruby

Redes de ComputadoresHá um tempo atrás eu escrevi um post sobre a utilização de Sockets em C#. Pois bem, agora vou voltar ao assunto mostrando como fazer isso usando a linguagem Ruby.

Pra quem não sabe o que é Ruby, aqui está uma definição tirada do site oficial:

“O Ruby é uma linguagem com um equilíbrio cuidado. O seu criador, Yukihiro “matz” Matsumoto, uniu partes das suas linguagens favoritas (Perl, Smalltalk, Eiffel, Ada, e Lisp) para formar uma nova linguagem que equilibra a programação funcional com a programação imperativa.”

No site você pode encontrar um tutorial bem interessante chamado Ruby em Vinte Minutos.

Para a plataforma .NET, temos o IronRuby que é muito legal! Entretanto, nesse exemplo irei utilizar o Ruby “simples”. Falarei mais do IronRuby em outro post.

Bem, vamos começar logo com isso!

Primeiro vamos criar o Cliente. Essa classe vai criar um Socket que utiliza o protocolo TCP. Veja como é simples:

# file TCPClient.rb
require 'socket'

port = 9090
hostname = 'localhost'

serverSocket = TCPSocket.open(hostname, port)

#Envia mensagem para o Servidor
serverSocket.puts "Hello, Server!"

#Recebe mensagem do servidor
while message = serverSocket.gets
   puts message.chop
end

serverSocket.close

Agora, criaremos o Servidor:


# file MultiClientServer.rb
require 'socket'

port = 9090
server =  TCPServer.open(port)

loop{
  Thread.start(server.accept) do |client|
    #Recebe a mensagem do Servidor
    receivedMessage = client.gets
    puts receivedMessage

    #Envia mensagem de confirmação para o Cliente
    client.puts "Your message was received: #{receivedMessage}"

    client.close
  end
}

Esse é um exemplo bem simples, mas serve para mostrar um pouco da linguagem e a facilidade de se utilizar Sockets com ela.

Categorias:Ruby

Números Mágicos

Um dos principais fatores que tornam um código ruim e difícil de ler é o aparecimento dos Números Mágicos.

Os Números Mágicos são um dos problemas mais antigos da programação. São valores contantes que representam valores próprios do domínio da aplicação. Eles geralmente não são óbvios, ou seja, não explicam o que fazem ou o motivo pelo qual estão sendo usados. Veja um exemplo:


public void MoverPartícula(double tempo)
{
this.posicao += 10.5 * tempo;
}

O método acima movimenta uma partículá utilizando a equação do movimento uniforme S = So + V x T. Dessa forma, o valor 10.5 representa a velocidade da partícula. Note que essa informação não está explícita no código, sendo necessário alguma explicação a respeito desse valor.

Números MágicosEncontramos o primeiro problema nos Números Mágicos: eles não deixam claro o que são (nem o que representam).

Outro problema ocorre quando um Número Mágico aparece em vários locais do código. Caso seja necessário modificar o valor, será preciso alterar todos os locais em que ele aparce. E esse procedimento pode ser trabalhoso, se ele aparecer 50 lugares diferentes, por exemplo.

Aí está mais um problema: Números Mágicos deixam o código difícil de ser mantido/alterado.

Para solucionar esses problemas, o melhor a se fazer é criar uma variável (ou atributo) que encapsule esse número.


private double readonly VELOCIDADE_PARTICULA = 10.5;

Alteramos agora os locais onde valor aparece, para utilizar a variável. O método MoverPartícula fica assim:


public void MoverPartícula(double tempo)
{
this.posicao += VELOCIDADE_PARTICULA * tempo;
}

Agora, qualquer alteração no valor da velocidade será feita apenas em um lugar (alterando-se o atributo) e o código ficou mais fácil de ser entendido, devido ao nome explicativo que representa totalmente o valor encapsulado. Criamos, assim, um código limpo.

Chamando Métodos de uma Página ASPX usando JQuery e AJAX

Logo JQueryMuitas vezes no ASP.NET queremos evitar os Postbacks, chamadas para a mesma página, no intuido de melhorar a usabilidade de algum componente ou da própria página. Para isso utilizamos artifícios providos pelo Javascript, JQuery e AJAX.

No entanto, surge um problema quando queremos utilizar, no código que roda no lado cliente (client-side), dados que são produzidos no lado do servidor (server-side). A solução para esse problema é bem simples: fazer todo o trabalho no servidor e repassar para a página apenas o resultado das operações, através de JQuery. E para que não ocorram Postbacks, devemos usar AJAX para chamar os métodos da página aspx que produzem os dados a serem exibidos.

Como faço isso?! Desse jeito:
Crie um novo projeto Web, adicione o arquivo correspondente ao JQuery e uma classe chamada Client.
Arquivo JQuery adicionado ao Projeto

A classe Client só vai possuir duas propriedades, ficando assim:

public class Client
{
    public string Name { get; set; }
    public int Age { get; set; }
}

Adicione uma página com o nome de Clients.aspx e, em seu code-behind, crie o método GetClient para retornar um objeto do tipo Client. O método precisa ser static e assinado com o atributo [WebMethod].

public partial class Clients : System.Web.UI.Page
{
	protected void Page_Load(object sender, EventArgs e)
	{
	}

	[WebMethod]
	public static Client GetClient()
	{
		Client ada = new Client { Name = "Ada", Age = 40 };
		return ada;
	}
}

Agora, no modo Design, adicione à pagina o código JQuery que irá chamar o método GetClient. Para isso, na tag head acrescente o seguinte código:

<script type="text/javascript" src="Scripts/jquery-1.6.2.min.js"></script><script type="text/javascript">// <![CDATA[
        $(document).ready(function () {
            $("#runJasonFromPage").click(function () {
                $.ajax({
                    type: "POST",
                    url: "Clients.aspx/GetClient",
                    data: "{}",
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function (jasonResult) {
                        alert(jasonResult.d.Name);
                    }
                });
            });
        });
// ]]></script>

O que o código acima faz é assinar o evento de click de um elemento da página chamando o método GetClient da página Clients.aspx. O resultado obtido na chamada desse método é repassado para uma função javascript, na forma de um objeto JSON, JavaScript Object Notation. Essa função simplesmente exibe a propriedade Name desse objeto, através de um alert.

Note que não é preciso serializar o objeto Client no código da página Clients.aspx. O ASP.NET já faz essa serialização por padrão.

Agora precisamos criar o elemento que irá executar o código JQuery que escrevemos acima. Adicione, então, um botão HTML com o id runJasonFromPage à página:

<input id="runJasonFromPage" type="button" value="Run JSON From Page" />

Pronto! Sua página está chamando um método de servidor sem ser necessário Postback e sem utilizar controles de servidor.

Categorias:.NET, ASP.NET

Princípio da Responsabilidade Única (SRP)

Como já tinha falado no post sobre Princípios S.O.L.I.D., o Princípio da Responsabilidade Única (SRP) estabelece que uma classe, método ou variável deve fazer apenas uma coisa e deve ter apenas uma razão para mudar. Esse talvez seja o princípio mais fundamental no desenvolvimento de um código limpo. Todos os outros princípios se baseam nele ou estão sobre ele fundamentados.

Vamos mostrar como utilizar esse princípio. Antes disso, contudo, veja o exemplo de classe abaixo (que não respeita o SRP).

public class Controlador
{
	public List<Conta> contas;
	public List<Cliente> clientes;

	public void DepositarQuantiaEmConta(Guid contaId, double quantia)
	{...}

	public void SacarQuantiaEmConta(Guid contaId, double quantia)
	{...}

	public Conta ProcurarContaPeloId(Guid contaId)
	{...}

	public void CriarNovaConta(Cliente cliente)
	{...}

	public void ExcluirConta(Guid contaId)
	{...}

	public void TransferirQuantia(Conta contaOrigem, Conta contaDestino)
	{...}

	public void CadastrarCliente(Cliente cliente)
	{...}

	public void ExcluirCliente(long clienteId)
	{...}

	public void ProcurarClientePeloNome(string nomeCliente)
	{...}
}

É fácil notar que a classe tem mais de uma responsabilidade. Ela trada de operações independentes relacionadas com as entidades Cliente e Conta. O próprio nome da classe não deixa claro a sua funcionalidade.

Ao ver o nome da classe não sabemos inicialmente ao que ela se refere. “Controlador de quê?” É a primeira pergunta que fazemos. É melhor evitar esses nomes extremamente genéricos. Defina bem o nome e certamente será mais fácil delegar apenas uma responsabilidade.

Além disso, a maioria dos códigos que não respeitam o SRP recaem sobre o antipadrão The Blob. Antipadrão? O que é isso!?

Antipadrões

Um Antipadrão de Desenvolvimento de Software descreve uma má prática que torna o código ruim, ilegível ou difícil de manter (e de ser alterado). Antipadrões (Antipatterns) são a contra-parte dos Padrões de Projeto (Design Patterns).

the blob imageO código acima está fortemente similar ao antipadrão The Blob. Isso porque temos uma única classe que controla todo o sistema. Essa “Classe-Monstro” engloba toas as reponsabilidades (e ações) que do sistema. Dessa forma, caso seja necessário adicionar mais uma funcionalidade ao código, a classe vai aumentar ainda mais e em alguns meses teremos uma “Mega Classe” que será bastante difícil de encontrar, alterar ou remover qualquer coisa. Mesmo se essa coisa for simples!

Aplicando o SRP

Para tornar nosso código mais limpo, vamos aplicar o conceito definido pelo SRP. Para isso, vamos extrair cada responsabilidade da nossa “Classe-Monstro” em várias classes pequenas que comportem cada uma delas. As pequenas classes devem  fazer apenas uma coisa, respeitanto o SRP.

Responsável pelas operações sobre a entidade Cliente:

public class RepositorioCliente
{
	public void CadastrarCliente(Cliente cliente)
	{...}

	public void CadastrarCliente(Cliente cliente)
	{...}

	public void ExcluirCliente(long clienteId)
	{...}

	public void ProcurarClientePeloNome(string nomeCliente)
	{...}
}

Classe responsável pelas operações sobre a entidade Conta:

public class RepositorioConta
{
	public Conta ProcurarContaPeloId(Guid contaId)
	{...}

	public void CriarNovaConta(Cliente cliente)
	{...}

	public void ExcluirConta(Guid contaId)
	{...}
}

A entidade Conta engloba as operações de Sacar e Depositar quantia:

public class Conta
{
	private Guid id;
	private double saldo;

	public void Depositar(double quantia)
	{...}

	public void Sacar(double quantia)
	{...}
}

Não faz muito sentido inserir a operação de transferência de quantia na classe Conta. Ela se encaixa melhor em uma entidade separada, dedicada exclusivamente a ela.

public class ContaService
{
	public void TransferirQuantia(Conta contaOrigem, Conta contaDestino)
	{...}
}

Note que o código ficou mais simples de ser entendido. E agora, caso seja necessário alterar alguma funcionalidade, modificaremos apenas a classe que a engloba, sem alterarmos todo o código. O sistema ficou mais extensível e menos emaranhado.

Até o próximo post.

Princípios S.O.L.I.D.

Canivete suíçoS.O.L.I.D. é um conjunto de boas práticas de projetos Orientado a Objetos. Essas práticas foram elencadas por Robert Martin (o “Tio Bob”) em seu livro Agile Principles, Patterns, and Practices in C#. A aplicação desses princípios tem como objetivo a construção de software mais flexível, legível, fácil de entender e de modificar.

O termo S.O.L.I.D. é um acrônimo formado pelas iniciais de cada princípio. E quais são esses princípios? Pois bem, nesse post vamos fazer um pequeno resumo sobre eles:

Single Responsibility Principle (SRP)

Esse princípio estabelece que todo objeto deve ter apenas uma razão para mudar e somente uma responsabilidade. Objetos concisos aumentam a capacidade de manutenção do sistema e o deixam mais legível. Para saber mais leia esse post.

Open-Close Principle (OCP)

Establece que classes devem ser abertas para extensões e fechadas para modificações. Deve ser simples adicionar novas funcionalidades e extender as antigas sem, contudo, alterar seu comportamento interno. Esse princípio também tenta evitar a quebra de classes em outras que dependam dela.

Liskov Substitution Principle (LSP)

Afirma que deve-se ser capaz de utilizar qualquer classe derivada no lugar da classe pai e obter o comportamento semelhante sem que seja necessária alguma modificação. O LSP acessegura que a classe derivada não deve afetar o comportamento da classe pai, estando assim de acordo com o OCP.

Interface Segregation Principle (ISP)

Estabelece que classes que utilizam a mesma interface implementem apenas métodos que sejam realmente necessários. Dessa forma é melhor dividir os métodos em grupos de responsabilidade, assinando (atribuindo) interfaces para estes grupos, evitando uma interface muito grande e métodos que não serão usados.

Dependency Inversion Principle (DIP)

Objetiva isolar classes de implementações concretas, expondo classes abstratas ou interfaces. Esse princípio promove a prática de “codificar para interface ao invés de “codificar para implementação”, aumentando a flexibilidade e desacoplando o sistema.

Se quiser saber mais sobre esses princípios dê uma olhada neste artigo do Uncle Bob, onde ele descreve cada um deles.