Padrões de projeto: Aplicando boas práticas para a criação de objetos

Este artigo apresenta os fundamentos sobre Padrões de Projeto e implementações de exemplos práticos reais em Delphi. Neste artigo, serão tratados os principais padrões criacionais do GoF, destinados a resolver problemas com criação de objetos.

[rotulo-mentoring/] [lead-mentoring]Softwares reais evoluem. Eles são constantemente modificados e adaptados, novos recursos são implementados, bugs são corrigidos, outros criados e aparecem do nada, novas exigências são feitas, a lei muda, o cliente pede, o código vai se tornando mais complexo e se afasta do seu projeto original, diminuindo sua qualidade. Está mais do que óbvio que a maior parte do custo total do desenvolvimento do software é dedicada à sua manutenção, em alguns casos, esse valor pode chegar a 80% do seu custo final. Se uma aplicação precisa ser modificada em um determinado momento, seja para manutenção corretiva ou evolutiva para atender novas funcionalidades, este processo precisa ser feito de forma disciplinada, correta, usando padrões, já que o custo da manutenção representa um porcentual elevado comparado ao custo total do sistema, como citado.

Com isso, o uso de padrões de projeto, ou Design Patterns, torna um software mais fácil de ser mantido em longo prazo, reduzindo custos ou otimizando o retorno do investimento, apesar de exigir um maior esforço em um primeiro momento, durante o design do projeto a ser realizado. Como muitas empresas não realizam este projeto da forma correta na concepção do software, seja pela falta de tempo devido a prazos reduzidos, desconhecimento da equipe sobre uso de boas práticas de programação orientada a abjetos, arquitetura ou uso de padrões, execução de múltiplos projetos simultaneamente, ocorre o chamado débito de projeto. São softwares que atendem aos seus requisitos em um estágio inicial, mas são extremamente rígidos em sua estrutura, difíceis de manter e evoluir, repleto de “bad smells”, principalmente se essa evolução for feita por outro desenvolvedor que não o próprio criador. Um bad smell, ou simplesmente mau cheiro, é uma indicação superficial que leva a um problema profundo no código de um sistema. O termo foi criado por Kent Beck e utilizado no livro Refactoring: Improving the Design of Existing Programs de Martin Fowler [2].

Este artigo apresenta os fundamentos sobre Padrões de Projeto e implementações de exemplos práticos reais em Delphi. Neste artigo, serão tratados os principais padrões criacionais do GoF [1], destinados a resolver problemas com criação de objetos concretos, que comprometem a reutilização de módulos do sistema e aumentam o acoplamento. Os padrões apresentados neste artigo são o Abstract Factory, Factory Method, Singleton e Builder.

Em que situação o tema é útil
Padrões de projeto são extremamente úteis para criar softwares mais fáceis de serem mantidos, evoluídos, promovendo reutilização de código, uso de boas práticas de programação orientada a objetos, redução de custos com manutenção, já que permitem que alterações em um determinado sistema de software não quebrem outras funcionalidades, reduzindo a dependência entre classes, através do uso exaustivo de abstrações. Dessa forma, são úteis para serem aplicados em projetos de média e larga escala.

[/lead-mentoring]

O conhecimento sobre padrões de projeto só faz sentido para aqueles que desenvolvem softwares de forma orientada a objetos. Não faz sentido tentar aplicar padrões de projeto se você programa centenas de linhas de código em eventos de um controle de user interface em um formulário Delphi, sem separar responsabilidades. Não faz sentido tentar usar padrões se você usa event-driven programming (programação dirigida ou orientada a eventos).

Se o software feito em Delphi da sua empresa precisa passar por uma evolução, modernização, migração, porém está mal escrito, repleto de bad smells, onde dezenas de programadores já colocaram a mão, e o custo para mantê-lo está saindo caro, talvez a melhor atividade antes de aplicar padrões de projeto seja a refatoração. Aplicar refatorações primitivas, como extrair métodos, classes, superclasses, pode tornar o seu software mais modular, simples de manter e evoluir. A partir daí, o uso de padrões de projeto pode ajudar a melhorar os atributos de qualidade do seu software.

Uma outra atividade, muito interessante, é aplicar padrões de projeto no contexto de refatorações (BOX 1).

BOX 1. Refatoração

A refatoração (do inglês Refactoring) é o processo de modificação do sistema de software sem alterar seu comportamento externo observável, como funcionalidades, tendo como alguns dos seus benefícios melhorar o entendimento do código, remover duplicidades, simplificar métodos, facilitando assim a manutenção, correção de bugs, adição de novas funcionalidades, aumentando a qualidade do produto [3].

Ou seja, nunca se aplica um padrão de forma antecipada, pois não sabe se realmente ele será necessário, causando uma complexidade desnecessária, o que chamamos de excesso de engenharia. Programadores não são videntes. Em contrapartida, nunca aplicar um padrão causa uma escassez de engenharia muito comum em aplicações que seguem o modelo RAD de desenvolvimento, como Delphi (existem programadores que usam Delphi há mais de 15 anos e nunca criaram uma classe). O software já tem 10 anos, está na versão 5, ninguém mais entende como ele funciona, o que foi feito, as pessoas perdem a credibilidade, a motivação, os erros são muitos, uma nova funcionalidade que deveria ser implementada em minutos leva horas ou dias, a correção de um bug gera novos bugs, a rotatividade de membros na equipe de desenvolvimento da empresa está alta, e isso está cada vez pior. Tão ruim que o caos já está generalizado e a empresa decide em algum momento reescrever o software do zero, pois não há mais conserto. Nesse sentido, a prática de aplicar padrões de projeto em código existente, no contexto de uma refatoração, se torna uma atividade bastante atraente.

Padrões de projeto se baseiam fortemente em princípios básicos da programação orientada a objetos, mais especificamente, na herança, abstração, encapsulamento e polimorfismo. Aqui é importante distinguir entre herança de classe da herança de abstrações. As heranças que veremos nos padrões são todas de abstrações, de interfaces, sem implementação. É uma herança de apenas dois níveis, já que criar cadeias muito grandes de hierarquia causa complexidade e dificulta a manutenção. Nesse ponto, uma herança de “caixa preta” se torna mais atraente, como faz o padrão Decorator. Se não há o domínio estes conceitos, principalmente a implementação de classes abstratas por polimorfismo, é recomendado fortemente que faça uma pesquisa e se domine estes fundamentos antes de entrar de cabeça no mundo dos padrões."

[...] continue lendo...

Artigos relacionados