
Pensando e repensando em nossos objetivos, em se adotando a tal da arquitetura em 3 camadas, vi que existem algumas questões que precisam ficar bem esclarecidas. Só que agora o foco não está no nível puramente conceitual, mas sim na aplicação prática do modelo.
Por isso decidi postar este artigo, descrevendo um pouco mais a arquitetura e com isso, ajudar a defini-la o mais rápido possível.
Conceitos básicos
Action (link - também conhecido como padrão Command)
Responsável pelas interações com o usuário, seja ele um navegador, um dispositivo móvel ou qualquer outro "robô". Recebe uma requisição de uma operação, conceitualmente atômica, que deverá ser realizada pelo sistema. Ele invoca quem sabe realizar a tal tarefa, e depois formata o resultado da forma mais conveniente.
As responsabilidade dos Actions são:
- Receber a requisição de execução de uma operação;
- Receber e tratar os dados enviados;
- Delegar a execução a quem de direito;
- Obter o resultado das operações;
- Formatar os dados para exibição;
- Enviar as respostas ao solicitante;
Business Objects (BO) (link)
Um objeto de negócio é uma classe que geralmente está no modelo de domínio dos processos de negócio. Ele pode ser persistente ou não, mas possui tanto os atributos quanto os métodos de negócio.
Ele não deve ser entendida como um simples mapeamento para a camada de dados, uma vez que quem faz isso é o Active Record (AR).
O BO concentra os métodos de acesso aos atributos (getters e setters) e os de negócio, onde estão encapsuladas as regras de negócio.
O ato de persisitir um BO consiste em um conjunto de operações de instanciação de objetos AR, atribuição de valores, testes e efetivação da gravação. Um BO pode ter mais de um AR associado, e por isso o processo pode ser complexo.
Active Record (AR) (link)
O Active Record é um objeto que mapeia a tabela no banco, permitindo o fácil acesso à base, através de uma camada de abstração de banco de dados.
Os nomes dos atributos devem ser iguais às das colunas nas tabelas do banco de dados, e a classe possui apenas os métodos getters e setters.
A importância do AR está na sua simplicidade, visto que seu papel é apenas um: transportar dados entre a camada de negócios e a de persistência.
Data Access Object (DAO) (link)
O Data Access Object é responsável pelo trânsito de dados entre o sistema e o "mundo externo". O mundo externo pode ser outros sistemas, serviços, arquivos hospedados em servidores FTP, HTTP, webservices, etc. É um objeto que realiza serviços de integração. Seu uso depende do tipo de sistema e das necessidades de integração. Alguns tipos de integração permitem que um serviço rode periodicamente e realize a integração entre os sistemas; já outros precisam que a integração seja imediata. O uso do DAO deve ser visto com muito cuidado, e exige um bom planejamento.
Perguntas e Respostas
P. Posso usar operações com lógica de negócio embutida, em classes AR?
R. Até poderiamos fazer isso, mas a complexidade dos ARs poderia dificultar as manutenções. Além disso, o AR é o mapeamento fiel ao modelo de dados, e nem sempre teremos classes de negócio que reflitam exatamente o modelo persistente. Assim, o melhor será separar o controle (BO) da persistência (AR), e colocar nos BOs a lógica de negócio.
P. Um BO pode acessar mais de um AR?
R. Sim. Embora na maioria dos casos o BO será um espelho de um AR, podem haver casos em que um BO tenha que recuperar um AR e atualizar outro. Além disso, por questões de performance, podemos criar um BO que tenha atributos de ARs diferentes. Por fim, o BO é um modelo de classe de negócio, e por isso, poderá conter elementos como listas e objetos, coisa que um AR não terá.
P. Por que 'burocratizar' as operações simples, como a pesquisa de um registro no banco, tendo que obrigatoriamente passar pelo BO?
R. Embora o acesso direto seja mais prático e rápido de se implementar, o uso de etapas e responsabilidades em camadas dá um isolamento entre estas, que permite uma manutenção com pouco impacto final nas demais. A inclusão de um campo, ou mudança de tipo, pode afetar menos um projeto grande do que se o mesmo fosse todo feito usando acessos diretos.
P. Como faço para recuperar um objeto que é atributo de um BO ?
R. Quando um atributo de um BO for na verdade um outro objeto BO, ao invés de um inteiro simples que contenha o ObjectID, recomenda-se manter o objeto e quando na recuperação do AR do banco de dados, instanciar o BO e atribuir sua chave. Quando for acessar algum outro atributo deste BO, então invoca-se o método de carga e ele é completado. Estou estudando uma forma de implementar o padrão lazy-load, como no Hibernate do Java.
P. Um Action pode acessar diretamente um AR, para fazer gravações simples?
R. Não. Se começarmos a simplificar nesse ponto, teremos problemas mais tarde. Imagine quando, por exemplo, for necessário dar manutenção em um sistema, onde deverá ser inserido um tratamento de verificação de dados antes de ser gravado; Se os actions acessarem diretamente o AR em questão, será necessário ir de action em action fazendo a manutenção, enquanto que se for centralizado no BO, o ponto de manutenção é um só.
P. Pode haver um BO que não seja persistido?
R. Sim. Os BOs que realizam operações de negócio, dentro do escopo do sistema, como a geração de relatórios específicos e cálculos , por exemplo, além daqueles que possuem apenas regras de negócio, funcionando como helpers.
P. Quando usar DAO?
R. O DAO deve ser usado quando for necessário realizar alguma comunicação de algum componente do sistema com o mundo externo, como a consulta de dados disponíveis em uma página na web, por exemplo. Outros exemplos seriam a leitura ou gravação de arquivos em servidores de FTP, acesso a bancos de dados de terceiros, importação e parsing de arquivos CSV. Se a integração for assíncrona, recomenda-se registrar o serviço em uma instância do PHPCron, por exemplo; já se for necessário realizar o sincronismo no momento das operações de persistência, recomenda-se usar os métodos do DAO a partir dos BOs - nestes casos, cria-se métodos do tipo 'preInserir', 'preAtualizar', 'preExcluir', 'posInserir', etc., e neles coloca-se as chamadas aos métodos dos DAOs correspondentes;
P. Quando devo usar o BO?
R. Sempre. Todo Action deve reponder com o resultado do processamento do sistema - e neste caso, a ponte é o Action, e a "cabeceira" é o BO. A menos em um protótipo visual que apenas simule o funcionamento do sistema, qualquer sistema deverá ter seus BOs implementados. A política de agrupar funcionalidades em um mesmo BO só deve ser usada quando o mesmo é uma entidade abstrata do modelo de domínio.
P. Quando devo usar o AR?
R. O AR deve ser usado sempre para mapear uma tabela do banco de dados no sistema. Eventualmente podemos pensar em ARs associados aos DAOs - um DAO pode retornar uma lista de ARs.
P. Quando devo usar o Action?
R. O Action é a interface entre o sistema e o mundo real (frontend), que disponibiliza um serviço, onde o cliente faz uma solicitação e recebe uma resposta. Então, sempre que for necessária uma interface com o cliente, esta será um Action.
P. Em algumas arquitetura os elementos de persistência (AR) possuem um método bind, onde passo um vetor associativo e o objeto "se vira" para atribuir os valores. Como funcionará na nova arquitetura?
R. O bind provavelmente será implementado, mas com algumas restrições: já que não estamos mapeando fielmente os campos dos formulários para tabelas, ou mesmo para objetos intermediários (BOs), o método deverá ser sobrecarregado nas classes finais. Assim, um BO terá um método bind que saberá que campos vindos do formulário vão ser atribuídos aos seus atributos; O AR poderá ter a mesma coisa. Embora haja um trabalho um pouco maior, isso dá uma certa segurança haja visto que todos os atributos que forem aceitos no bind serão de conhecimento do desenvolvedor.
P. Na nova arquitetura, o que preciso fazer para criar um novo "serviço" disponibilizado por um dado Action?
R. No construtor do Action em questão, o método deverá ser registrado, para evitar que um hacker subverta o sistema solicitando um método não-registrado. Depois, implemente o método normalmente. Os links que darão acesso ao novo método deverão conter o parâmetro 'acao' com o valor do nome do novo método.
Nenhum comentário:
Postar um comentário