Beruflich Dokumente
Kultur Dokumente
1. Introdução
Antes de começar, quero dizer que a arquitetura de um sistema vária de projeto para projeto, de
necessidade para necessidade. Mas em sua maioria para projetos de médio e grande porte, utilizo as
boas práticas de projetos de n-camadas (n-tier). Já para projetos pequenos, utilizo uma arquitetura
minimizada (a qual não irei abordar aqui).
É importante ter em mente que a organização demanda tempo. É bem mais rápido desenvolver um
projeto de maneira desorganizada do que de maneira organizada. Mas as desvantagens de criar algo
não pensado são inúmeras, como: dificuldade de manutenção, difícil refatoração, código não expressivo,
entre outras. Então é bom pensar em tudo que for fazer, pensar em cada classe, método, propriedade,
que for criar. Parece ser besteira, mas é sempre bom tomar cuidado com nomes e padrões que serão
utilizados no projeto. Mas, sem maiores delongas: "Zelar pelo código que se faz".
- Devemos entender que as camadas de baixo referenciam as de cima. NUNCA devemos fazer o
processo inverso. A única camada que não referência ninguém e todos conseguem enxerga-lá são as
entidades.
- Existem objetos próprios de cada camada, por exemplo, não iremos ter objeto da Namespace
System.Data na camada da UI (Interface com o usuário).
- Devemos lembrar que objetos que facilitam nossa vida como o SqlDataSource não estão de acordo
com padrões de projetos de muitas empresas. Pelo simples fato que ao utilizá-lo estamos indo em
contra mão ao ponto que diz (que uma camada se comunica, apenas, com a imediatamente acima). Ao
adotarmos o SqlDataSource como controle para manipular dados em nossas aplicações, estamos
fazendo com que a GUI acesse diretamente o banco de dados, e na prática apenas a DAL pode acessar
nossos meios de persistência a dados.
- As camadas podem estar distribuídas em máquinas/pastas diferentes, deste que cada camada seja
uma DLL. Em outros casos as camadas podem estar dentro de nossas aplicações ASP.NET, sendo pastas
na mesma.
- Os dados devem ser passados para as classes de cima sempre como entidade, ao invés de passar “n”
parâmetros para as camadas de cima, criando assim uma dependência entre camadas. Caso eu adicione
um atributo a mais em uma entidade, vou ter que adicionar um parâmetro a mais em meu método. Por
exemplo: Não utilize esse tipo de método em seu código:
Bem mais simples passar apenas um objeto do que passar “9271823182” de parâmetros.
OBS: O problema de se colocar todas as camadas em um único projeto é se um dia desejarmos criar
aquela mesma aplicação para outro tipo de dispositivo. Por exemplo: Temos uma aplicação ASP.NET e
desejamos agora criar uma opção para o usuário acessá-la via dispositivo móvel. Caso as camadas
estejam em um único projeto, será bem trabalhoso de fazer isto. Já no caso de cada camada ser um
projeto diferente, teremos apenas, que criar uma nova camada de “UI” e fazer com que esta referencie
as outras camadas.
Outros detalhes serão discutidos no decorrer deste artigo. Agora vamos falar sobre cada camada em
particular.
1.1 GUI
É a camada de interface com o usuário. No nosso caso é nossa aplicação ASP.NET. Poderia ser um
projeto para dispositivo móvel, Windows Form, WPF, Silverlight.
O ideal é que nessa camada encontremos apenas código que estejam diretamente relacionados com
nossas páginas aspx.
Já vi desenvolvedores de empresas grandes que faziam coisas esdrúxulas como acessar o bando direto
da GUI. Além de deixar o código seboso, o trabalho de refazer o mesmo código inúmeras vezes será
enorme.
1.2 Entidade
É a única camada que todos enxergam. Esta entidade contém nossas classes básicas (Ex: Pessoa,
Médico, Casa, Cachorro, PessoaJuridica, PessoaFisica...). Classes que representam coisas do nosso
mundo real.
1.3 Façade
É um padrão faz com que tenhamos todas as funções do sistema em uma única classe. Uma possível
implementação para este padrão é utilizar a palavra chave “partial” para ter vários arquivos físicos, mas
que no final das contas será uma única classe. A finalidade disto é evitar ter um único arquivo enorme.
OBS: Esta camada é optativa. Você pode acessar diretamente a camada de negócio. Costumo utilizar
este padrão em casos onde preciso executar chamadas consecutivas ao banco em uma única operação.
Por exemplo, no caso de uma transferência de conta bancária. Preciso retirar de uma pessoa e colocar
na conta de outra. Então a façade serviria para fazer a chamada ao devidas funções.
Teria o método “Transferência” na classe “Façade”, que este por sua vez iria ter o seguinte trecho de
código:
PessoaBus.Depositar(x);
PessoaBus.Sacar(x);
Ou seja utilizo essa classe apenas quando dou preferência a ter um local de fácil acesso que faça as
operações na ordem de execução.
Essa camada contém tudo que for lógica de negócio. Ela que irá fazer verificações e validações dos
dados vindos e que ainda vão para o banco.
É importante saber a diferencia entre regras de negócio e validações básicas. Pois existem validações
que não precisam ser feitas necessariamente nesta classe. Como por exemplo, se o CPF é válido, pois
essa é uma regra geral, e não de um específico sistema. A validação do CPF pode ser feita tanto do lado
do cliente (javascript) como na camada de entidades.
1.5 DAL
Única camada que acessa a dados. Esta camada é especifica para isso e nada mais. Então é uma boa
prática evitar colocar validações nesta classe ou qualquer trecho de código que não esteja diretamente
relacionado com acesso a dados.
Em muitos projetos tento criar camadas de acessos a dados genéricos. Mas isso não é obrigatório
(dependendo do projeto, lógico). Se você sabe que aquele projeto sempre vai acessar apenas a um
banco de dados (Sql Server, Oracle, Mysql, Postgres ou qualquer outro) e não tem a menor chance de
mudar, então não existe a necessidade de criar uma camada genérica.
OBS: Criar os repositórios para cada entidade e mapear cada tabela do banco em uma entidade dá
muito trabalho. Então existem várias ferramentas que fazem esse trabalho para nós. São as ferramentas
de mapeamento objeto relacionais. Temos em .NET como exemplo: Nhibernate, SubSonic, LINQ. Temos
um projeto da Microsoft que abstrai o acesso a banco de dados de nossa aplicação. É um projeto
grande, que nos fornece muitas utilidades, que é a Microsoft Data Access Application Block.
Caso você opte por utilizar alguma dessas ferramentas tudo bem. Mas muito cuidado ao escolher
alguma delas. Pois alguns códigos gerados podem ir contra os padrões adotados em seu projeto, o que
pode dar muita dor de cabeça ao tentar modificar o código gerado pela mesma.
Quanto a conceitos de camadas, o que posso dizer é isso. Aconselho a estudar coisas relacionadas a
“design partner”. Com bom conhecimento de padrões de projetos e bom conhecimento da regra de
negócio da aplicação você será capaz de escrever aplicações bem arquitetadas e modeladas.
2. Codificando
Como exemplo, vou mostrar um cadastro de pessoa bem simples. Apenas para dar idéia de como seria
um sistema em camadas que costumo utilizar em alguns projetos pessoais. Porém, longe de ser o
modelo ideal para suas aplicações. Para chegar a um modelo “ideal” para A aplicação procuro me sentar
com toda a equipe de desenvolvimento (se não apenas os mais experientes) para discutirmos o modelo
de nossa aplicação e de algumas classes.
Para este exemplo, irei fazer uma aplicação ASP.NET e C# 2.0, acessando os dados com ADO.NET.
Fazendo tudo isto na mão, sem o auxílio de ferramenta alguma.
Bem, em meus projetos costumo começar de cima para baixo, ou seja, crio as camadas na seguinte
sequência: Entidade -> DAL -> Business -> Façade -> GUI. Pois me faz pensar primeiramente no
problema como um todo, e me faz refletir sobre as possíveis operações e necessidade do sistema.
2.2. Entidade
A camada de entidade é básica de se fazer, é basicamente um mapeamento das tabelas do banco. Para
cada tabela do banco, teremos uma classe na camada de entidades.
Para criar as camadas de acesso a dados, costumo criar uma (ou mais) interfaces ou classes abstratas
que servirão como base criar as classes de acesso a dados de cada entidade. Esta classe ou interface
contém definições de métodos básicos, que sei que todas as classes vão conter, como por exemplo:
Inserir, Atualizar, Recuperar por ID, Deletar.
1: /// <summary>
2: /// Interface com todos os métodos necessários para uma classe de DAO
3: /// </summary>
4: /// <typeparam name="T">tipo do objeto que será manipulador pela DAO</typeparam>
5: public interface IDataAccessObject<T> where T : new()
6: {
7: T Get<K>(K id);
8:
9: void Insert(T obj);
10:
11: void Update<K>(K id, T obj);
12:
13: void Delete<K>(K id);
14: }
Esta é uma interface genérica que contém métodos básicos para outras classes. Alguns métodos são
genéricos por recebem o tipo da chave primária da entidade (int, long, short).
Outra classe da DAL que costumo utilizar é uma classe para auxiliar coisas como: criação de parâmetros,
criação de comandos, entre outras operações. Como falei anteriormente, você pode utilizar a Microsoft
Data Access Application Block para ajudar com esse tipo de coisas. Essa biblioteca contém inúmeros
métodos.
Para a aplicação de demonstração, irei utilizar uma classe bem simples que fiz apenas para esse
exemplo. Detalhe que não estou abstraindo o banco da aplicação, mas aconselho você a criar uma
classe que abstraia o banco que esta se utilizando. Outra observação é que está classe está incompleta,
fiz apenas para exemplo mesmo. Esta é uma classe que tem que ser bem pensada e bem trabalhada
com a finalidade de obter melhor desempenho do banco de dados que está usando. Garanto que não
será difícil modificar esta classe para ser genérica. Segue o código da mesma:
- Abrangência;
-Desempenho;
- Objetos que serão utilizados para manipular os dados (DataDet, DataTable, SqlDataReader);
- Se será utilizado apenas stored procedure ou se todas as querys vão estar na aplicação.
- ...;
Já temos uma interface para nossa camada de acesso a dados e uma classe que irá nos auxiliar com a
mesma. Agora nos resta criar as classe de acesso para cada entidade presente em nosso projeto. O
código da nossa classe Pessoa será o seguinte:
Simples não é?! A implementação dos métodos de “delete” e “update”, eu deixo como exercício para
você. :D
A idéia da camada de negócio é bastante simples. Como falei anteriormente, ela tem o papel de acessar
a camada de dados e é quem fará validações em cima da mesma. Geralmente, assim como a camada de
DAL, costumo criar uma interface nessa camada com os métodos mais utilizados. Mas para exemplo irei
mostrar apenas o método “insert” da classe de negócio de pessoa.
Um padrão que costumo utilizar nessa camada são as factories. Que tem o papel de criar instâncias das
classes. Ou seja, com esse padrão eu consigo ter acesso a qualquer objeto acessando apenas uma classe.
Exemplo de Factory:
Arquivo 1: Facade.cs
Arquivo 2: PessoaFacade.cs
2.5. UI Tier
Não irei mostrar exemplo de código desta camada. Pois este é o nosso projeto ASP.NET que já sabemos.
A única coisa que devemos fazer nessa camada é encapsular os dados no objeto Pessoa, por exemplo e
em seguida passar o mesmo para algum método da Façade.
Bem, espero ter ajudado. O básico de uma boa arquitetura de sistema é isto. Pode ter certeza que lendo
esse material, depois de ter entendido o mesmo por completo e depois ler profundamente sobre
padrões de projetos você estará totalmente apto para criar uma aplicação bem modelada e arquitetada.
Em outra oportunidade escreverei um pouco mais sobre arquitetura em camadas e trarei exemplos de
sistemas bem arquitetados.
Abraços.