De que se trata o artigo

Este artigo trata da aplicação dos padrões de projeto e suas boas práticas em projetos já existentes, em situações comuns que podem ser reescritas de forma orientada a objetos, mostrando que mesmo em poucas partes pode-se obter flexibilidade.


Em que situação o tema é útil

Quando se deseja ter partes de um projeto que possam responder de forma mais rápida às mudanças de requisitos dos clientes, seguindo boas práticas conceituadas.

Padrões de projeto no dia a dia

Saber como aplicar uma teoria da orientação a objeto é a dúvida de todos que estão começando ou estudando o assunto. Nesse artigo vamos abordar os conceitos que formam a base dos padrões de projeto e como podemos aplicar os padrões em trechos de código já existente.

Por mais que sempre se fale de padrões de projeto, ou da própria orientação a objetos, sempre existem aqueles que dizem: “isto não é para mim”, ou “não consigo aplicar, meu projeto não está totalmente desenvolvido com OO”.Engana-se quem acredita que não é possível seguir algumas boas práticas só por não ter todo o sistema desenvolvido de forma orientada a objetos. É possível sim aplicar em pequenas partes algumas boas práticas e padrões. Como fazer isso? É justamente o que esse artigo traz. Mas antes, uma visão do que está por de trás dos padrões.

Princípios

Existe um fato irrefutável no desenvolvimento de sistemas: requisitos sempre mudam. Outro fato que sempre vejo nas organizações é que elas sabem disso e por isso, tentam melhorar sua forma de captação desses requisitos. Isso é bom. Contudo, a atenção não deve estar presa somente a isso, não significa que por se ter requisitos de qualidade, teremos um sistema de qualidade ou, se esses requisitos modificarem será fácil aplicar a modificação pedida.É aí que a orientação a objetos em conjunto com os padrões pode ajudar. Existem alguns princípios de modelagem e programação OO que levam os padrões de projetos a serem considerados como boas práticas, esses mesmos conceitos podem ser aplicados sem a utilização dos padrões. Portando, a ideia é entender esses princípios e procurar aplicá-los em nosso desenvolvimento. São eles: Modelar para interfaces, favorecer composição sobre herança e encontrar o que varia, e encapsulá-lo.

Modelando, desenvolvendo para interfaces

Em qualquer desenvolvimento, seja ele orientado a objetos ou não, temos dois problemas que impedem do mesmo ser fácil de ser alterado: baixa coesão e alto acoplamento.A baixa coesão é quando encontramos rotinas/classes que realizam várias funções, mais do que deveriam fazer por seu conceito. Já o alto acoplamento é quando temos rotinas/classes que são muito dependentes de outras, aonde um alteração nessa conduz a um cascateamento de alterações, ou seja, é o quanto as rotinas/classes estão dependentes uma das outras.Mas porque uma interface resolveria esse problema? Uma interface ou classe abstrata simplesmente expõem uma assinatura de métodos que pode ser utilizada por outra rotina. A implementação real não está nela, mas sim outra classe que a implementa. Dessa forma, se esperarmos por uma interface, teremos acesso somente à definição dos métodos, como eles serão implementados não será importante. Mais adiante teremos a parte prática onde será possível ver isso acontecendo.

Compor ou herdar?

Quem está aprendendo orientação a objetos sempre se atenta muito ao recurso de herança. É a primeira coisa que estudantes aprendem. É a primeira forma de realizar a tão sonhada reutilização de funcionalidades, isso porque ela permite que o interior de uma classe base seja vista pelas suas subclasses. Esse é o modo mais fácil. Existe um segundo recurso para reutilização de funcionalidade, a composição. Nela objetos diferentes são interligados através de suas interfaces para garantir reutilizações mais complexas. A composição pode ser um pouco mais difícil de entender inicialmente, mas possui vantagens sobre a herança.A herança permite que de forma fácil seja alterada a implementação de uma funcionalidade. Isso é obtido através da técnica de sobrecarga de operações. Por ser fácil de implementar, passa uma ideia de que agora aquele trecho de código está flexível, mas não é verdade. Ela é resolvida em tempo de compilação e isso deixa o sistema um pouco inflexível porque em tempo de execução qualquer alteração na implementação de uma classe base não é permitida. Os mais puristas em orientação a objetos dizem que a principal desvantagem da herança está na exposição do interior de uma classe base à suas subclasses, quebrando assim o conceito de encapsulamento. Essa exposição conduz a um modelo de dependência de implementações entre as classes envolvidas, isso porque a parte exportada da classe base faz parte também das subclasses. Qualquer alteração na classe base implica em alterações nas subclasses, o que não é recomendado quando se deseja um modelo flexível. A composição por sua vez é resolvida em tempo de execução. Ela exige que as interfaces sejam respeitadas, consequentemente devem ser bem planejadas para que não haja impedimentos de reutilização, isso porque a implementação de composição é feita através de referências. Algumas desvantagens vistas na herança, como quebra de encapsulamento e dependência de implementação, não são vistas na composição, isso porque os objetos envolvidos são acessados somente por suas interfaces. O impacto disso na modelagem, é que classes manterão seu encapsulamento e estarão voltadas para sua tarefa apenas, porque não há o que herdar de outras classes, obedecendo assim o conceito de alta coesão.Porém, como nada é perfeito, o uso de composição prende o comportamento do modelo aos relacionamentos entre os objetos, que pode implicar em maior complexidade. Os padrões de projeto fazem uso extenso de composição e quando é necessário criar heranças, elas são baseadas em classes abstratas. Esse é um dos motivos que consagram os padrões de projeto como prática de flexibilização de modelos, deixando um código preparado para eventuais mudanças de requisitos.

...

Quer ler esse conteúdo completo? Tenha acesso completo