C# - Aplicando os conceitos da Programação Orientada a Objetos na prática


 Neste artigo vou mostrar como podemos aplicar os conceitos da programação orientada a objetos (POO) na prática para criar um código limpo e fácil de manter.

Os conceitos da programação orientada a objetos (POO) já não são novidades para quem atua na área de TI. O mínimo que se espera de um bom desenvolvedor que atue na área é que ele conheça bem os conceitos da POO e saiba aplicá-los no seu dia a dia.

Pensando nisso resolvi escrever este artigo e mostrar como podemos aplicar os conceitos da POO para realizar uma tarefa simples.

Nosso objetivo será criar um projeto que permita de forma simples e rápida carregar, ler e salvar informações de configurações personalizadas.

A primeira questão que pode vir a sua mente quando você se debruçar sobre essa tarefa é procurar saber qual o tipo de informações pretendemos acessar : XML, JSON , arquivos INI, etc. ?

Na verdade, o objetivo é criar um projeto genérico que possa tratar com quaisquer tipo de informações, incluindo tipos de dados que ainda não conhecemos.

Você agora pode estar pensando: "Essa tarefa esta ficando complicada...", e, você tem toda a razão, se a abordagem adotada para resolver o problema não usar os conceitos da POO.

Se você estiver pensando em criar classes concretas para carregar, ler e salvar informações de configuração então eu já lhe adianto que você vai conseguir concluir o projeto mas com certeza o código vai te dar muito trabalho.

Aplicando os conceitos da POO podemos usar Generics e Interfaces, e, nessa tarefa é isso o que faremos para mostrar todo o poder da POO.

Então vamos ao código...

Recursos usados:

Nota: Baixe e use a versão Community 2015 do VS ela é grátis e é equivalente a versão Professional.

Criando o projeto no VS Community

Abra o VS Community 2015 e clique em New Project;

Selecione a linguagem Other Project Types -> Visual Studio Solutions;

Selecione o template Blank Solution e informe o nome Aplicando_Conceitos_OOP e clique no botão OK;

Será criada uma solução vazia onde iremos incluir nossos projetos.

Criando o projeto para a definição do Gerenciador de Configurações

Vamos criar um projeto do tipo Class Library em nossa solução e neste projeto definir o nosso Gerenciador de Configurações.

Fazendo assim teremos ao final uma DLL que pode ser distribuída.

No menu File clique em Add -> New Project ;

Selecione o template Class Library e informe o nome Gerenciador_Configuracoes e clique em OK;

Se pensarmos em um gerenciado de configurações que realize as tarefas básicas então teremos que implementar as seguintes funcionalidades:

Vamos iniciar criando uma interface chamada ISerializeTool que importa e exporta dados para string e arquivos.

No Project clique em Add -> New Item e selecione o template Interface e informe o nome ISerializeTool e digite o código abaixo nesta interface:

    public interface ISerializeTool
    {
        string ExportarParaString<T>(T obj);
        T ImportarDeString<T>(string obj);
        void ExportarParaArquivo<T>(T obj, string arquivo);
        T ImportarDoArquivo<T>(string caminho);
    }

Vamos definir outra interface chamada ISettings que dever definir um contrato para carregar e salvar informações. O código pode ser visto a seguir:

    public interface ISettings<out T>
    {
          T Atual { get; }
          void Salvar(string destino = "");
          void Carregar(string localizacao = "");
    }

Aqui usamos a premissa da POO : "Programe para uma interface e não para uma implementação"

Definimos as funcionalidades em interfaces distintas para estar aderente ao princípio ISP (Princípio da segregação da interface).

Assim já temos um contrato que permite implementar funcionalidades para serializar objetos e strings e arquivos e também carregar e salvar informações.

A utilização de interfaces permite que o nosso código fique com um baixo acoplamento, ou seja, com poucas dependências, e,  isso é uma boa prática.

Implementando a interface ISettings : Carregando e Salvando informações

Vamos implementar as funcionalidades para carregar e salvar informações criando a classe concreta GerenciaConfiguracao() via menu Project -> Add Class;

A seguir inclua o código abaixo nesta classe :

using System.IO;
namespace Gerenciador_Configuracoes
{
    public class GerenciaConfiguracao<T>  :  ISettings<T>
    {
        public T Atual { get; set; }
        public string CaminhoPadrao { get; set; }
        public ISerializeTool SerializarConfiguracoes { get; set; }
        
        public void Carregar(string localizacao = "")
        {
            try
            {
                if (string.IsNullOrEmpty(localizacao))
                    localizacao = CaminhoPadrao;
                if (!File.Exists(CaminhoPadrao))
                    throw new FileNotFoundException("Dados de configuração não existem.");
                Atual = SerializarConfiguracoes.ImportarDoArquivo<T>(CaminhoPadrao);
            }
            catch
            {
                throw;
            }
        }
        public void Salvar(string destino = "")
        {
            try
            {
                if (string.IsNullOrEmpty(destino))
                    destino = CaminhoPadrao;
                SerializarConfiguracoes.ExportarParaArquivo(Atual, destino);
            }
            catch
            {
                throw;
            }
        }
    }
}

A classe concreta implementa a interface ISettings  e possui o método para converter de json para object e de object para json.

Implementando a interface ISerializeTool : Serializando informações XML

Agora vamos implementar a interface ISerializeTool que cuida da serialização das informações.

Vamos fazer uma implementação considerando a abordagem XML e para isso vamos criar a classe concreta XmlSerializeTool e definindo o código abaixo nesta classe:

using System.IO;
using System.Text;
using System.Xml.Serialization;
namespace Gerenciador_Configuracoes
{
    public class XmlSerializeTool : ISerializeTool
    {
        public void ExportarParaArquivo<T>(T obj, string arquivo)
        {
            using (var gravarArquivo = new StreamWriter(arquivo, false, Encoding.UTF8))
            {
                gravarArquivo.Write(ExportarParaString(obj));
            }
        }
        public string ExportarParaString<T>(T obj)
        {
            var serializer = new XmlSerializer(typeof(T));
            using (var gravarString = new StringWriter())
            {
                serializer.Serialize(stringWriter, obj);
                return gravarString.ToString();
            }
        }
        public T ImportarDeString<T>(string obj)
        {
            var serializer = new XmlSerializer(typeof(T));
            using (var gravarString = new StringReader(obj))
            {
                return (T)serializer.Deserialize(gravarString);
            }
        }
        public T ImportarDoArquivo<T>(string arquivo)
        {
            using (var leitorArquivo = new StreamReader(arquivo, Encoding.UTF8))
            {
                return ImportarDeString<T>(leitorArquivo.ReadToEnd());
            }
        }
    }
}      

Testando a implementação em um projeto Console

Vamos criar um projeto Console Application para testar a nossa implementação

No menu File clique em Add -> New Project ;

Selecione o template Console Application e informe o nome Testando_Projeto e clique em OK;

Clique com o botão direito sobre o nome do projeto e a seguir em Add Reference;

Vamos marcar uma referência ao projeto Gerenciador_Configuracoes conforme mostra a figura a seguir:

Agora vamos definir o código que usa os recursos implementados para um tipo definido que chamamos GeradorConfiguracaoAleatorio para um arquivo XML de configurações com nomes e sobrenomes.

Digite o código abaixo no arquivo Program.cs do projeto Console :

using System;
using System.Collections.Generic;
using Gerenciador_Configuracoes;
namespace Testando_Projeto
{
    public static class Program
    {
         public static ISettings<GeradorConfiguracaoAleatorio> GerenciaConfiguracao { get; set; }
        static void Main(string[] args)
        {
            // cria as configurações com nomes e sobrenomes
            var configuracoes = new GerenciaConfiguracao<GeradorConfiguracaoAleatorio>
            {
                SerializarConfiguracoes = new XmlSerializeTool(),
                CaminhoPadrao = @"c:\dados\xml\MacTeste.xml",
                Atual = new GeradorConfiguracaoAleatorio
                {
                    Nomes = new List<string> { "José Carlos", "Miriam", "Jessica" },
                    SobreNomes = new List<string> { "Macoratti", "Siqueira","" }
                }
            };
            // Define ISettings com nossa implementação
            GerenciaConfiguracao = configuracoes;
            // Salva as configurações para o arquivo e as carrega do arquivo
            GerenciaConfiguracao.Salvar();
            GerenciaConfiguracao.Carregar();
            // Exibe os nomes da configuração atual
            foreach (var config in GerenciaConfiguracao.Atual.Nomes)
            {
                Console.WriteLine(config);
            }
            // Adiciona um nome na configuração
            GerenciaConfiguracao.Atual.Nomes.Add("Janice");
            // Salva para o arquivo novamente
            GerenciaConfiguracao.Salvar();
            // Limpa os nomes atuais
            GerenciaConfiguracao.Atual.Nomes.Clear();
            // Carrega as configurações novamente do arquivo padrão
            //  que nos dará os novos dados que foram alterados
            GerenciaConfiguracao.Carregar();
            // Verifica
            Console.WriteLine("---------------------------------------");
            foreach (var configuracao in GerenciaConfiguracao.Atual.Nomes)
            {
                Console.WriteLine(configuracao);
            }
            Console.ReadKey();
        }
    }
    public class GeradorConfiguracaoAleatorio
    {
        public List<string> Nomes { get; set; }
        public List<string> SobreNomes { get; set; }
    }
}
 

 

 

 

Ao lado do código vemos o resultado da aplicação Console o arquivo XML MacTeste.xml gerado na pasta c:\dados\xml.

Podemos conferir a flexibilidade do código implementado usando os recursos das interfaces e Generics.

Deixo para você fazer a implementação para arquivos INI ou JSON como um exercício.

Pegue o projeto completo aqui : Aplicando_Conceitos_POO.zip

Jesus Cristo é o mesmo, ontem, e hoje, e eternamente.
Hebreus 13:8

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

Referências:


José Carlos Macoratti