Fala ai Radizeiros e Radizeiras, tudo bem com vocês?
Nesse post estarei falando sobre um tema que causa dúvida em muita gente, hoje vou falar sobre objetos e estrutura de dados.
Muita gente entende como estrutura de dados o trabalho de forma procedural, e que objeto é só quando tenho uma classe, mas não é só isso.
Então, vou exemplificar isto para vocês e colocar algumas boas práticas dentro disso.
A primeira coisa é que toda vez que a pessoa está começando a aprender Delphi orientado a objeto, ele aprende sobre property, então o que ele faz? Tudo que é variável dentro da classe ele quer colocar dentro de property.
Ai eu te pergunto, para que property e para que encapsulamento, se você irá dar acesso através de métodos a alteração e a leitura de uma variável privada?
Não tem necessidade nenhuma disso, se todas as suas variáveis vão ser property, não tem porque você encapsula-las, você deixa essa variável como pública.
Dados estruturados ou estrutura de dados, é quando você monta uma estrutura de dados e dá acesso aos dados que estão dentro de uma determinada estrutura.
Se eu tenho uma classe com todas suas variáveis públicas e tudo mais, não tenho nada encapsulado, tenho tudo estruturado da forma de classe.
Se eu trabalho com o conceito de objetos, eu tenho que encapsular esses dados para trazer a tona somente aquilo que for relevante, então eu tenho que encapsula-las e tratar esse dados.
Não quer dizer, que dando acesso através de uma property eu estou encapsulando alguma coisa.
O Martin Fowler, diz bastante sobre isso, ele chama isso de sacolas de Get e Sets.
Quando trabalhamos com objetos, o intuito é de você dar acesso, como você me vê sempre falando, programe para interface e não para uma classe concreta.
O ideal é você dar exposição para aquilo que seja relevante.
Poderia fazer desta forma, por exemplo.
TCarro = class private FCapacidadeTanque: Integer; FLitrosDisponiveis: Integer; procedure SetCapacidadeTanque(const Value: Integer); procedure SetLitrosDisponiveis(const Value: Integer); published property CapacidadeTanque : Integer read FCapacidadeTanque write SetCapacidadeTanque; property LitrosDisponiveis : Integer read FLitrosDisponiveis write SetLitrosDisponiveis; end;
Normalmente nós criamos property para essas variáveis, se observar foi criado duas variáveis privadas, duas procedures para setar essas variáveis, e estou dando acesso as essas variáveis privadas.
Desta forma não estou encapsulando nada, o fato de estar dentro da procedure ele está simplesmente pegando os valores e atribuindo valor a ele.
Eu não estou encapsulado nada, isso simplesmente são dados estruturados.
Quando eu trabalho com objetos, não precisamos dar visibilidade para o usuário, como fizemos no código anterior.
Digamos que usuário só precisa saber a capacidade disponível do tanque.
Então para isso devemos fazer desta forma.
iCarro = interface function CapacidadeDiponivelTanque : Integer; end; TCarro = class(TInterfacedObject, iCarro) private FCapacidadeTanque: Integer; FLitrosDisponiveis: Integer; public function CapacidadeDiponivelTanque : Integer; end;
Veja que agora só temos acesso somente a capacidade disponível no meu tanque, dessa forma ele está realmente encapsulado, eu não dei acesso porque não é interessante eu dar acesso às informações para o usuário neste contexto, apenas irá estar disponível os objetos realmente encapsulados.
O fato de você colocar property e definir o acesso direto, você está criando uma sacola de GET e SET, você não está propriamente tratando nenhum problema, você não está encapsulado nada, não está fazendo nenhum tipo de validação.
Mas você deve está falando, eu preciso dar acesso ao meu usuário a uma property, por exemplo a Marca do carro.
TCarro = class(TInterfacedObject, iCarro) private FCapacidadeTanque: Integer; FLitrosDisponiveis: Integer; FMarca: String; procedure SetMarca(const Value: String); public function CapacidadeDiponivelTanque : Integer; property Marca : String read FMarca write SetMarca; end;
Ao fazer desta forma e você tentar acessar essa property em outra camada veja o resultado.
Observe que não temos acesso, isso ocorre porque estamos acessando através da interface.
Então como eu faço isso?
Primeiro não devemos por campos dentro de nossas interfaces, e caso queira expor essa sua property, se ainda assim isso se fazer necessário, o que você irá precisar na sua property é adicionar um GET.
iCarro = interface function CapacidadeDiponivelTanque : Integer; procedure SetMarca(const Value: String); function GetMarca : String; property Marca : String read GetMarca write SetMarca; end; TCarro = class(TInterfacedObject, iCarro) private FCapacidadeTanque: Integer; FLitrosDisponiveis: Integer; FMarca: String; procedure SetMarca(const Value: String); function GetMarca : String; public function CapacidadeDiponivelTanque : Integer; property Marca : String read GetMarca write SetMarca; end;
Deixando nossa property visível na interface veja agora como ela irá aparecer na camada externa.
Agora eu tenho Marca, ele não mostrou nem o GET e SET, ele simplesmente mostrou Marca que é uma string e é uma property, dessa forma as interface aceita trabalhar com property dentro do Delphi.
Mas ainda vale ressaltar, procure encapsular os objetos dentro de sua classe, e não simplesmente dar acesso a eles através property, aí podendo ficar uma bagunça.
Esse post faz parte de um dos meus treinamentos a CERTIFICAÇÃO ESPECIALISTA EM CLEAN CODE E BOAS PRÁTICAS DE PROGRAMAÇÃO.
A Certificação Especialista em Clean Code e Boas Práticas de Programação 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 essas técnicas 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.