Fala ai Radizeiros e Radizeiras, tudo bom com vocês?

Mas um post onde estarei lhe mostrando como construir um controller de entidades usando MVC.

Este post é parte do treinamento Certificação especialista em arquitetura MVC.

Vamos criar nossos controles de entidades.

Mas o que é entidades?

As entidades são as representações do banco de dados, e em nossa camada de controller iremos trabalhar para que nossa camada de visão possa receber esses valores, nossa camada de visão não tem acesso ao model, a conexão com o banco, nada disso nossas views tem que saber simplesmente da factory de entidades de nosso controller que irá consumir os métodos que estão descrito para ela.

Dentro da pasta controller do nosso exemplo iremos criar uma pasta chamada Entity.

Vamos criar a entidade de PRODUTOS para poder espelhar do nosso model de PRODUTOS.


Type
    TControllerEntityProdutos = class(TInterfacedObject, iControllerEntity)
    private
        FConexao : iModelConexao;
        FDataSet : iModelDataSet;
        FEntity : iModelEntity;
    public
        constructor Create;
        destructor Destroy; override;
        class function New : iControllerEntity;
        function Lista(aDataSource : TDataSource) : iControllerEntity;
    end;

implementation

{ TControllerEntityProdutos }

constructor TControllerEntityProdutos.Create;
begin
    FConexao := TControllerConexoesFactoryConexao.New.Conexao;
    FDataSet := TControllerConexoesFactoryDataSet.New.DataSet(FConexao);
    FEntity := TModelEntityFactory.New.Produtos(FDataSet);
end;

destructor TControllerEntityProdutos.Destroy;
begin

inherited;
end;

function TControllerEntityProdutos.Lista(
aDataSource: TDataSource): iControllerEntity;
begin
    Result := Self;
    aDataSource.DataSet := TDataSet(FEntity.Listar);
end;

class function TControllerEntityProdutos.New: iControllerEntity;
begin
    Result := Self.Create;
end;

end.

Analisando o código

A nossa classe de entidade de produtos venha funcionar pegando as informações do nosso banco de dados precisa estabelecer uma conexão com o banco de dados.


...
Type
    TControllerEntityProdutos = class(TInterfacedObject, iControllerEntity)
    private
        FConexao : iModelConexao;
        FDataSet : iModelDataSet;
...

A nossa view, irá instanciar um objeto do tipo entidades de produtos, enquanto este objeto estiver instanciado, tanto o FConexao quando o FDataSet  vão estar ativos para ela trabalhar, assim que este objeto for destruído o FConexao e o FDataSet também iram ser destruídos.

Se estes objetos não estiverem instanciados em nossa entidade de produto, iremos ter problemas por trabalharmos com interfaces ARC, pois ele irá acabar destruindo o objeto antes da hora, então a conexão e o dataset precisam estar instanciados na camada de controller a onde o formulário vai ter acesso para manipular isso, e deixar o objeto instanciado até quando ele quiser, e na hora que ele destruir, ai sim ele destrói a conexão.

No create de nossa classe de entidade de produtos precisamos instancias os objetos.

...
constructor TControllerEntityProdutos.Create;
begin
     FConexao := TControllerConexoesFactoryConexao.New.Conexao;
     FDataSet := TControllerConexoesFactoryDataSet.New.DataSet(FConexao);
end;
...

Você pode observar que o nosso objeto não precisa conhecer a conexão explicitamente, e sim uma fabrica de conexão, da mesma forma foi feito para o dataset, esse objetos estarão ativos até o memento em que essa classe venha ser destruída.

Como esse nossa classe é um espelho da entidade do model iremos precisar da entidade para trabalhar.


...
FEntity : iModelEntity;
...

No create instanciamos o FEntity  com a fabrica de entidade.


...

constructor TControllerEntityProdutos.Create;
begin
...
    FEntity := TModelEntityFactory.New.Produtos(FDataSet);
end;

...

Você talvez deve esta se perguntando, por que não fez isso encadeado, pode até ser feito, mas eu tenho o problema do ARC, eu preciso que esses objetos estejam na memória enquanto o formulário de produtos estiver visível, esses objetos iram precisar estar instanciados, para que possamos trabalhar realizando o CRUD dentro de um mesmo DataSet, se nós encadearmos isso ele simplesmente irá destruir assim que ele sair do método.

Em nossa interface temos o método listar.


...

type
    iControllerEntity = interface
    ['{C4456164-F064-461D-B383-7B4E4B538585}']
        function Lista(aDataSource : TDataSource) : iControllerEntity;
    end;
...

Você deve está se perguntando, por que o TDataSource, ele é o que tem de mais genérico que temos para trabalhar dentro de nossa view.

Nosso formulário não irá precisar de ClientDataSet, FDMenTable,  ele simplesmente irá trabalhar com o DataSource que é genérico para qualquer tipo de conexão dentro do Delphi.

A implementação desse método em nossa classe de entidade de produtos.


...
function TControllerEntityProdutos.Lista(
aDataSource: TDataSource): iControllerEntity;
begin
    Result := Self;
    aDataSource.DataSet := TDataSet(FEntity.Listar);
end;
...

Como você pode observar nós fizemos um casting, do objeto aDataSource.

E agora precisamos de uma factory para nossas entidades do controller.


Type
    TControllerEntityFactory = class(TInterfacedObject, iControllerEntityFactory)
    private
    public
        constructor Create;
        destructor Destroy; override;
        class function New : iControllerEntityFactory;
        function Produto : iControllerEntity;
        function Cliente : iControllerEntity;
    end;

implementation

{ TControllerEntityFactory }

uses Menus.Controller.Entity.Clientes;

function TControllerEntityFactory.Cliente: iControllerEntity;
begin
    Result := TControllerEntityCliente.New;
end;

constructor TControllerEntityFactory.Create;
begin

end;

destructor TControllerEntityFactory.Destroy;
begin

inherited;
end;

class function TControllerEntityFactory.New: iControllerEntityFactory;
begin
    Result := Self.Create;
end;

function TControllerEntityFactory.Produto: iControllerEntity;
begin
    Result := TControllerEntityProdutos.New;
end;

end.

Nossa interface possuí somente o produto, que a entidade que estamos trabalhando.


...
iControllerEntityFactory = interface
['{9F063B38-9A72-44F6-8ABC-FF11867BAB47}']
    function Produto : iControllerEntity;
end;
...

Desta forma já podemos montar nossa tela que irá receber as informações de nossa tabela de produtos, e nosso código encontra-se completamente desacoplado.

Escrevemos um pouco de linha de código, mas o ganho que isso nos proporcionada é muito grande.

 

 

Todo o conteúdo desse post faz parte de um dos meus treinamentos, o de Certificação Especialista em Arquitetura MVC.

E o que você irá aprender nesse treinamento?

A Certificação Especialista Arquitetura MVC dará a você a oportunidade de melhorar seu software, otimizar o seu tempo e te dar a possibilidade de atender melhor os seus clientes.

Conhecer a fundo esse paradigma e utilizar todos os seus benefícios irá facilitar muito a sua vida quando houver necessidade por parte de um cliente de um update rápido ou resolver um problema.

CLIQUE AQUI E SAIBA MAIS SOBRE O TREINAMENTO CERTIFICAÇÃO ESPECIALISTA EM ARQUITETURA MVC.