Desenvolvendo um Sistema Financeiro em Delphi – Partes 1 e 2
Artigo no estilo: Curso
O Delphi, no que diz respeito a linguagem, implementa todos os requisitos de uma linguagem orientada a objetos, pois nos permite fazer abstração, encapsulamento, herança e polimorfismo. Porém, o que mais vemos nos desenvolvedores Delphi é o desenvolvimento de aplicações de forma estruturada, onde são explorados apenas os recursos RAD que o IDE proporciona.
Um dos grandes pontos negativos de trabalhar com Delphi é a falta de um framework de mapeamento objeto-relacional robusto e que seja apoiado pela Embarcadero.
Existem iniciativas como o DORM (open-source) e o Aurelius (comercial), mas são soluções que ainda não se tornaram populares. Neste artigo veremos uma solução manual para resolver esse problema de mapeamento objeto-relacional.
Existem boas práticas, como a Inversão de Controle (BOX 1), que no Delphi não possui um framework apoiado e incentivado pela Embarcadero.
Apesar da ferramenta não oferecer um framework nativo para trabalharmos com orientado a objetos, a Delphi Language possui todos os recursos necessários para desenvolvermos orientado a objetos, como Generics e Métodos Anônimos.
Este princípio é a base para qualquer bom design de software orientado a objetos. O princípio da Inversão de Dependência nos diz que módulos de alto nível não devem ser dependentes de módulos de baixo nível, ambos devem depender de abstrações, que por sua vez, não devem depender de detalhes.
Inverter a dependência faz com que o cliente não fique frágil a mudanças relacionadas a detalhes de implementação, isto é, mudar um detalhe da implementação não faz com que sejam necessárias alterações no cliente.
Este princípio é bastante presente em muitos padrões de projeto, pois a maioria deles definem uma interface para que não haja dependências de implementações.
Outro padrão que geralmente anda junto com o princípio de inversão de dependência é a Injeção de Dependências, que é uma forma de conseguir a inversão de controle. Nesta solução, as dependências entre os módulos não são definidas programaticamente, mas sim pela configuração de uma infraestrutura de software (container) que é responsável por injetar em cada classe suas dependências declaradas.
O padrão de Injeção de dependências sugere que uma conexão com banco de dados seja injetada na classe. Com isso, além de inverter a dependência, a classe não precisa se preocupar com o ciclo de vida das suas dependências (no exemplo da conexão, a classe não precisa abrir ou fechar conexão, apenas receber uma referência desta conexão e a utiliza).
Impedância Objeto Relacional
A Orientação a Objetos traz como principal vantagem sobre a estruturada a representação de objetos de maneira bastante semelhante ao mundo real, o que torna-se um desafio a mais quando precisamos fazer a persistência destes nos bancos de dados relacionais.
Existem soluções de bancos de dados orientados a objetos, mas estes ainda não se tornaram populares, sendo os bancos de dados relacionais ainda muito mais utilizado que estes.
Não existe uma conversão direta entre os objetos que construímos nas linguagens de programação e o banco de dados relacionais, por isso é necessário criarmos o que é chamado de Mapeamento Objeto-Relacional, onde objetos são transformados geralmente em registros em uma tabela e vice-versa.
Mapeamento Objeto Relacional
Isso surgiu porque precisamos salvar o estado de um objeto (atributos, herança, polimorfismo) em tabelas do banco de dados. O mapeamento básico pode ser feito através de conversões manuais ou através de frameworks de persistência, onde ambas possuem vantagens e desvantagens, mas a conversão manual nos dá uma melhor performance, enquanto que com frameworks de persistência não precisamos nos preocupar com escrita de SQL.
Em Delphi os frameworks de mapeamento objeto relacional geralmente nos possibilitam a configuração de persistência através de arquivos XML ou o recurso de annotations ou custom atributes.
No mapeamento objeto relacional básico o que temos é o mapeamento de classes para uma tabela do banco de dados, temos também o mapeamento de objetos da classe para registros da tabela e as propriedades da classe para colunas da tabela.
Padrão DAO (Data Access Object)
O padrão de projeto DAO surgiu com a necessidade de separarmos a lógica de negócios da lógica de persistência de dados.
Este padrão permite que possamos mudar a forma de persistência sem que isso influencie em nada na lógica de negócio, além de tornar nossas classes mais legíveis.
Classes DAO são responsáveis por trocar informações com o SGBD e fornecer operações CRUD e de pesquisas, além de ser capaz de buscar dados no banco e transformar em objetos ou lista desses através de listas genéricas.
Também deverá receber os objetos, converter em instruções SQL e mandar para o bando de dados. Toda interação com a base se dará através destas classes, nunca das classes de negócio, muito menos de formulários.
Se aplicarmos este padrão corretamente será abstraído completamente o modo de busca e gravação dos dados, tornando isso transparente para aplicação, facilitando muito na hora de fazermos manutenção na aplicação ou migração de banco de dados.
Também conseguimos centralizar a troca de dados com o SGBD, assim teremos um ponto único de acesso a dados e nossa aplicação um ótimo design orientado a objeto.
Generics
Generics é um recurso que foi incorporado na versão 2009 do Delphi, que permite criar estruturas genéricas. Na orientação a objetos podemos definir o tipo de retorno de uma lista de objetos e somente serão permitidas inserções de objetos daquele tipo, do contrário ocorrerá um erro ainda em tempo de compilação, assim, evitando erros em tempo de execução do tipo Invalid Type Casting, muito comum para quem trabalhava com listas de objetos em versões anteriores a 2009 em Delphi.
Para fazer uso de Generics temos que declarar o namespace System.Generics.Collections na seção uses do código.
As duas principais classes deste namespace são a TList<T> e TobjectList<T>.
A Classe TList<T> possibilita guardar coleções de qualquer tipo de dados, tanto primitivos quanto objetos. Já a classe TObjectList<T>, que é uma especialização de TList, pode armazenar somente objetos.
Ela tem a vantagem de que no momento que liberarmos sua instância da memória, todos os objetos contidos nela também são liberados, diferentemente das instâncias de TList, onde no caso de as usarmos para armazenar objetos, precisamos liberar cada objeto individualmente da memória.
FireDAC
FireDAC é a versão da Embarcadero para o AnyDAC, que foi adquirida e integrada ao Delphi e o C++ Builder. No Delphi o FireDAC está disponível na versão XE3 e XE4 com um conjunto de componentes extras, e a partir da versão XE5 vem na instalação padrão.
É um conjunto de componentes de alta performance, de fácil utilização e provê conexão com vários bancos de dados, tanto locais quanto coorporativos.
Cada banco de dados possui um driver e trabalhado de forma diferente. Os drivers do FireDAC são nativos para cada banco de dados e ainda possui pontes para ODBC e dbExpress. Vários bancos de dados são suportados, entre eles temos: MySQL, SQL Server, Oracle e SQLite.
Para quem tem projetos multicamadas com Delphi e DataSnap (BOX 2), ou também servidores REST, basta migrar a parte Server de DBExpress para FireDAC, pois o TFDQuery é um TDataSet, portanto compatível com o TDataSetProvider e TClientDataSet.
Na parte Client, continua o TClientDataSet sem necessidade de qualquer alteração. Tem suporte a Firemonkey e VCL e possui um conjunto de componentes visíveis e não-visíveis, DataSets, Adapters.
ODatasnapé o mecanismo desenvolvimento multicamadas do Delphi.Servidoresde aplicaçãoDatasnappodem ser desenvolvidos tanto em Delphi quanto C++Builder, porém a grande vantagem está no cliente, que pode ser desenvolvido em qualquer linguagem de programação que tenha suporte a JSON.
Em 2009 foi criado um novo driver para oDBExpress, mas ao invés deste driver conectar-se a um banco de dados qualquer, ele se conectaria a um servidor de aplicação.
Assim, a partir do Delphi 2009 a conexão do cliente com o servidor de aplicação passou a ser feita utilizandoDBExpresstrafegando os dados utilizando o protocolo TCP/IP.
Classe Base DAO
Abra o projeto no Delphi para continuarmos. Para facilitar o trabalho com as classes DAO, criamos uma classe base a qual será herdada por todas as classes DAO que irão interagir com o banco de dados, conforme pode ser visto na Listagem 1.
Listagem 1. Classe base TDAO
01 unit DAO.Base;
02 interface
03 uses
04 DAO.ConnectionFactory, FireDAC.Comp.Client;
05 type
06 TDAO = class
07 protected
08 Connection: TFDConnection;
09 function GetKeyValue(ATable: string): Integer;
10 public
11 constructor Create;
12 destructor Destroy; override;
13 end;
14 implementation
15 { TDAO }
16 constructor TDAO.Create;
17 begin
18 Connection := TConnectionFactory.GetConnection;
19 end;
20 destructor TDAO.Destroy;
21 begin
22 Connection.Free;
23 inherited;
24 end;
25 function TDAO.GetKeyValue(ATable, AColumn: string): Integer;
26 var
27 SQL: string;
28 Id: Integer;
29 begin
30 SQL := 'select coalesce(max(‘ + AColumn + ‘),0) + 1 from ' + ATable;
31 Id := Integer(Connection.ExecSQLScalar(SQL));
32 result := Id;
33 end;
34 end.
Nesta classe temos a declaração de uma referência para TFDConnection com escopo protegido, de maneira que possamos acessar este atributo em todas as classes derivadas desta. Usaremos este objeto em todas as classes descendentes, tanto para executar comandos de consulta quanto comandos de atualização no banco de dados.
Temos também o método GetKeyValue, que deverá ser chamado toda vez que precisarmos gerar uma nova chave para alguma tabela, bastando passar por parâmetro o nome e a coluna que desejamos receber a chave.
Utilizamos o método ExecSQLScalar do FireDAC para buscarmos o valor desejado. Este deve ser usado sempre que nossa consulta retornar apenas uma informação. O seu retorno é do tipo variant, por isso fizemos um typecast antes de fazermos atribuição à variável Id.
O mecanismo de geração da chave que escolhemos foi o de pegar o máximo valor existente na coluna da tabela mais um, porém poderíamos usar qualquer outro mecanismo, como o uso de Generators do Firebird, por exemplo.
Toda comunicação com o banco de dados será feita através de um objeto da classe TFDConnection que será disponibilizado pela classe TConnectionFactory, como mostra a Listagem 2.
Listagem 2. Relembrando a classe TConnectionFactory
Quer ler esse conteúdo completo? Tenha acesso completoConfira outros conteúdos:
Por Filipe Em 2015Black November
Desconto exclusivo para as primeiras 200 matrículas!
Pagamento anual
12x no cartão
De: R$ 69,00
Por: R$ 54,90
Total: R$ 658,80
Garanta o desconto
- Formação FullStack Completa
- Carreira Front-end I e II, Algoritmo e Javascript, Back-end e Mobile
- +10.000 exercícios gamificados
- +50 projetos reais
- Comunidade com + 200 mil alunos
- Estude pelo Aplicativo (Android e iOS)
- Suporte online
- 12 meses de acesso
Pagamento recorrente
Cobrado mensalmente no cartão
De: R$ 79,00
Por: R$ 54,90 /mês
Total: R$ 658,80
Garanta o desconto
- Formação FullStack Completa
- Carreira Front-end I e II, Algoritmo e Javascript, Back-end e Mobile
- +10.000 exercícios gamificados
- +50 projetos reais
- Comunidade com + 200 mil alunos
- Estude pelo Aplicativo (Android e iOS)
- Suporte online
- Fidelidade de 12 meses
- Não compromete o limite do seu cartão
<Perguntas frequentes>
CarreiraMetodologiaAssinatura e PagamentosCadastroNossos casos de sucesso
Eu sabia pouquíssimas coisas de programação antes de começar a estudar com vocês, fui me especializando em várias áreas e ferramentas que tinham na plataforma, e com essa bagagem consegui um estágio logo no início do meu primeiro período na faculdade.
Estudo aqui na Dev desde o meio do ano passado! Nesse período a Dev me ajudou a crescer muito aqui no trampo.
Fui o primeiro desenvolvedor contratado pela minha empresa. Hoje eu lidero um time de desenvolvimento!
Minha meta é continuar estudando e praticando para ser um Full-Stack Dev!Economizei 3 meses para assinar a plataforma e sendo sincero valeu muito a pena, pois a plataforma é bem intuitiva e muuuuito didática a metodologia de ensino. Sinto que estou EVOLUINDO a cada dia. Muito obrigado!
Nossa! Plataforma maravilhosa. To amando o curso de desenvolvimento front-end, tinha coisas que eu ainda não tinha visto. A didática é do jeito que qualquer pessoa consegue aprender. Sério, to apaixonado, adorando demais.
Adquiri o curso de vocês e logo percebi que são os melhores do Brasil. É um passo a passo incrível. Só não aprende quem não quer. Foi o melhor investimento da minha vida!
Foi um dos melhores investimentos que já fiz na vida e tenho aprendido bastante com a plataforma. Vocês estão fazendo parte da minha jornada nesse mundo da programação, irei assinar meu contrato como programador graças a plataforma.
Wanderson Oliveira
Comprei a assinatura tem uma semana, aprendi mais do que 4 meses estudando outros cursos. Exercícios práticos que não tem como não aprender, estão de parabéns!
Obrigado DevMedia, nunca presenciei uma plataforma de ensino tão presente na vida acadêmica de seus alunos, parabéns!
Eduardo Dorneles
Aprendi React na plataforma da DevMedia há cerca de 1 ano e meio... Hoje estou há 1 ano empregado trabalhando 100% com React!
Adauto Junior
Já fiz alguns cursos na área e nenhum é tão bom quanto o de vocês. Estou aprendendo muito, muito obrigado por existirem. Estão de parabéns... Espero um dia conseguir um emprego na área.
Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.
Aceitar