32
comentários post favorito (2) .net Magazine 116 - Índice Aprenda com esse artigo a criar suas classes obedecendo estes princípios de orientação a objetos. 0 1 Curtir Curtir 1 CONTEÚDO REVISTAS CURSOS DEVWARE MVP Anuncie | Loja | Publique | Assine | Fale conosco Hospedagem web por Porta 80 Web Todos os Direitos Reservados a SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe... 1 de 32 25/08/2014 10:09

SOLID_ Padrões Flexíveis Para Suas Classes C#

Embed Size (px)

Citation preview

Page 1: SOLID_ Padrões Flexíveis Para Suas Classes C#

comentários post favorito (2)

.net Magazine 116 - Índice

Aprenda com esse artigo a criar suas classes obedecendo estes

princípios de orientação a objetos.

0 1CurtirCurtir1

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

Anuncie | Loja | Publique | Assine | Fale conosco

Hospedagem web por Porta 80 Web Todos os Direitos Reservados a

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

1 de 32 25/08/2014 10:09

Page 2: SOLID_ Padrões Flexíveis Para Suas Classes C#

Veremos as vantagens e as maneiras corretas de aplicar este princípio passo a passo.

Ainda veremos como eles se relacionam com vários dos vinte três Designs Patterns do

GoF, através de exemplos práticos de aplicação destes princípios, com situações reais que

todo desenvolvedor enfrenta no dia a dia de seu trabalho.

Uma das maiores dificuldades nos dias atuais em termos de desenvolvimento de software se

refere à manutenção de sistemas computacionais. Pesquisas indicam que as empresas

gastam mais de 80% do orçamento destinado ao software em manutenção.

Isso ocorre porque na maioria dos desenvolvedores de sistemas não seguem os princípios da

orientação a objetos e não utilizam os padrões de projetos e técnicas corretas de

desenvolvimento.

São sistemas mal codificados que o tornam difícil de manter e evoluir. Outros ainda utilizam

outros paradigmas, como a programação estruturada, que demanda muito mais manutenção

que o paradigma orientado a objetos.

Em sistemas de informação que adotam o paradigma orientado a objetos, existem vários

padrões, princípios e técnicas que o desenvolvedor deve seguir para que o sistema seja de

fácil entendimento para outros desenvolvedores, de fácil manutenção após o sistema estar

em ambiente de produção, que mudanças e novas funcionalidades não causem impacto em

todo o sistema já existente.

Para um melhor entendimento sobre padrões de projetos é necessário um sólido

conhecimento de orientação a objetos, do contrário, os padrões não serão bem

compreendidos e o leitor acaba não sabendo aplicar estes no seu dia a dia.

Os princípios SOLID são a base para vários padrões de projetos criados e tornam softwares

mais evolutivos, de fácil manutenção e mudanças efetuadas depois de finalizado, não

impactando em outras áreas do programa, mudanças não propagam erros por outras partes

desse sistema.

Muitos desenvolvedores discutem sobre os padrões de projeto de software, alguns dizem

que os eles servem simplesmente para resolver problemas das linguagens de programação

orientadas a objetos e que outras linguagens, com mais recursos, não precisam implementar

nenhum desses padrões, mas esse não é um tópico abordado neste artigo.

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

2 de 32 25/08/2014 10:09

Page 3: SOLID_ Padrões Flexíveis Para Suas Classes C#

para todo e qualquer projeto que siga este paradigma de desenvolvimento.

Com certeza, um código que não segue estes princípios não é de qualidade e um

desenvolvedor ao olhar para esse código percebe isso. Existem várias dicas, macetes e

técnicas para aplicação de todos estes princípios.

Para um código limpo e de qualidade, ele deve estar bem modularizado, cada classe deve

ter a sua responsabilidade e as relações entre essas classes devem ser claras e bem

definidas. É aqui que entra a ideia de código sólido, de onde vem o tema deste artigo.

Antes de entrarmos no estudo destes princípios, veremos quais os principais problemas

encontrados em sistemas e que poderiam ser evitados com a aplicação de padrões de

projetos e princípios de orientação a objetos (BOX 1):

· Rigidez: o sistema foi desenvolvido de forma que é muito difícil de mudar, qualquer

alteração provoca uma cascata de operações por todo o restante do sistema;

· Imobilidade: a codificação foi feita de forma que o reuso é muito difícil, nenhuma parte do

sistema pode ser reaproveitada em outro sistema;

· Fragilidade: o sistema foi feito de maneira que qualquer mudança o desestabiliza e o torna

inoperante;

· Complexidade: o sistema foi desenvolvido utilizando-se de muitos padrões para resolver

problemas simples, algo desnecessário (dependendo do caso);

· Repetição: mesmos trechos de códigos espalhados por todo o sistema, ao invés de estarem

encapsulados em um método ou classe.

Aplicar boas práticas de engenharia de software nos rende muitos benefícios como

manutenção facilitada, código organizado, dependências mais leves e uma arquitetura

completamente aberta a receber atualizações, melhorias e novos recursos.

Além disso, quando temos o sistema com várias classes desempenhando bem o seu papel e

cada método tendo o seu objetivo bem definido, ficam muito mais fáceis de ser realizados

os testes unitários do sistema.

BOX 1. Padrões de Projeto GoF

Padrões de Projeto do GoF tem como objetivo solucionar problemas comuns de software

relacionados as orientação a objetos.

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

3 de 32 25/08/2014 10:09

Page 4: SOLID_ Padrões Flexíveis Para Suas Classes C#

Design Patterns: Elements of Reusable Object-Oriented Software por Erich Gamma,

Richard Helm, Ralph Johnson e John Vlissides, a chamada Gangue of Four. São

organizados em três grupos:

· Padrões de criação: relacionados à criação de objetos (Abstract Factory, Builder,

Factory Method, Prototype, Singleton);

· Padrões estruturais: tratam das associações entre classes e objetos (Adapter, Bridge,

Composite, Decorator, Facade, Flyweight, Proxy).

· Padrões comportamentais: tratam das interações e divisões de responsabilidades entre

as classes ou objetos (Chain of Responsibility, Command, Interpreter, Iterator,

Mediator, Memento, Observer, State, Strategy, Template Method, Visitor).

SOLID são cinco princípios básicos que todos os analistas e desenvolvedores deveriam

seguir para uma boa modelagem de classes. Cada letra da palavra SOLID representa um

princípio, são eles:

· S – Single Responsibility Principle (SRP): princípio da responsabilidade única;

· O – Open Closed Principle (OCP): princípio do aberto/fechado;

· L – Liskov Substituition Principle (LSP): princípio da substituição de Liskov;

· I – Inteface Segregation Principle (ISP): princípio da segregação de interfaces;

· D – Dependency Inversion Principle (DIP): princípio da inversão de dependência.

O princípio de responsabilidade única de classes indica que cada classe deve ter uma única

responsabilidade e esta deve estar totalmente encapsulada pela classe e todos os seus

métodos devem agir em conjunto para resolver esta tarefa e, por isso, tem uma única razão

ou motivo para ser alterada.

Isto não significa que uma classe deva ter somente um método, mas que tenha métodos

que juntos cheguem a um determinado objetivo comum. Uma classe poderá ser responsável

por uma funcionalidade que pode precisar de cinco métodos para resolver sua tarefa.

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

4 de 32 25/08/2014 10:09

Page 5: SOLID_ Padrões Flexíveis Para Suas Classes C#

necessidade de alteração.

Um exemplo muito popular que viola o princípio da responsabilidade única é o padrão

ActiveRecord (BOX 2) que mistura regras de negócio com persistência de dados.

BOX 2. Active Record

Active Record é um padrão de projeto de alguns sistemas que armazenam seus dados

em banco de dados relacionais. A interface de objetos deste padrão, além de manter

seus atributos que representam cada coluna de uma tabela, possuem métodos como

Insert(), Update(), Delete(). Esta técnica diminui o número de classes do sistema, pois

mantém as regras de negócio e persistência juntas. Este padrão é bastante utilizado por

programadores PHP.

O princípio da responsabilidade única está intimamente relacionado ao princípio da coesão

(BOX 3). O ferimento deste princípio acarreta também em um alto acoplamento (BOX 4).

Em resumo, este princípio nos indica que uma classe deve ter apenas um único objetivo no

sistema. Se uma classe tiver mais do que um objetivo ou responsabilidade, esta deve ser

decomposta em duas ou mais classes no sistema.

Cada uma dessas responsabilidades é um eixo de mudança e estas fontes de mudanças

devem estar sempre bem isoladas. Este conceito é muito fácil de entender, mas muitas

vezes muito difícil de ser posto em prática.

BOX 3. Coesão

O grau de Coesão na Orientação a Objetos nos indica a forma como foi projetada uma

classe. Nos indica o grau de funcionalidade única e bem definida de uma classe bem

orientada. Isso quer dizer que quando mais focada for a classe em resolver um

problema, maior será a sua coesão, o que é uma coisa boa.

O principal benefício da alta coesão é que essas classes são mais fáceis de manter e são

menos necessárias alterações frequentes nelas do que as de baixa coesão. Outro grande

benefício é que classes com alta coesão são mais fáceis de serem reutilizadas

posteriormente.

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

5 de 32 25/08/2014 10:09

Page 6: SOLID_ Padrões Flexíveis Para Suas Classes C#

Acoplamento é o grau de conhecimento que uma classe tem sobre outra. Se o único

conhecimento que a classe X tem sobre a classe Y for o que a classe Y expos através de

sua interface, então a classe X e a classe Y são fracamente acopladas, o que é muito

bom.

Porém, se a classe A se baseia em partes da classe B que não fazem parte de sua

interface, então elas estão fortemente acopladas, o que não é uma boa prática em

sistemas orientados a objetos.

Existem muitos exemplos deste princípio espalhados por toda a rede, mas em sua grande

maioria trazem uma abordagem muito abstrata que foge do dia a dia do desenvolvedor,

com exemplos muito superficiais e simplórios.

Iniciando o pensamento do princípio, pensamos numa classe Cliente, ela abstrai os clientes

da empresa, então ela só deve mudar se uma das características abstraídas dos clientes da

empresa mudarem. Se por acaso, a classe Cliente mandar um e-mail quando houver um

atraso de um pagamento, essa já é uma nova razão para ela mudar.

Como exemplo rápido para o perfeito entendimento, basta considerar uma classe que

processa e imprime um relatório. Esta classe tem duas razões para ser modificada, uma

mudança na consulta que busca os dados deste relatório e uma mudança no layout do

relatório.

Essas mudanças ocorrem por causas muito diferentes, uma por causa dos dados, outra por

causa da estética do relatório. Isso significa que esta classe tem duas responsabilidades

distintas e que deveriam ser separadas em duas classes.

Agora veremos um exemplo prático da implementação de uma classe sem o princípio e

depois com o princípio seguido. Veja a classe da Listagem 1.

Listagem 1. Implementação da Classe Aluno sem obedecer o princípio da SRP.

01 namespace SRP

02 {

03 public class Aluno

04 {

05 public void Adicionar()

06 {

07 try

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

6 de 32 25/08/2014 10:09

Page 7: SOLID_ Padrões Flexíveis Para Suas Classes C#

10 }

11 catch (Exception e)

12 {

13 System.IO.File.WriteAllText("C:\Erro.txt", e.ToString);

14 }

15 }

16 }

17 }

Observe que a classe Aluno tem duas responsabilidades bem distintas. A primeira é fazer a

persistências dos dados, a segunda é gravar um log para o caso de ocorrer um erro durante

o processo de persistência.

Observamos então que esta classe pode ser mudada por duas razões distintas, uma

mudança na parte de persistência e uma mudança na forma de gerar o log de erros.

Identificado este problema, basta isolarmos uma destas responsabilidades, no caso a de log

de erros em outra classe e fazer com que a classe Aluno use esta nova classe através da

composição para efetuar o log de erros, conforme a Listagem 2.

Listagem 2. Implementação das classes Aluno e ArquivoLog seguindo o princípio SRP

01 namespace SRP

02 {

03 public class ArquivoLog

04 {

05 public void Gravar(string erro)

06 {

07 System.IO.File.WriteAllText(@"C:\Erro.txt, erro");

08 }

09 }

10

11 public class Aluno

12 {

13 private ArquivoLog _Log = new ArquivoLog();

14

15 public virtual void Adicionar()

16 {

17 try

18 {

19 // Grava no banco de dados

20 }

21 catch (Exception ex)

22 {

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

7 de 32 25/08/2014 10:09

Page 8: SOLID_ Padrões Flexíveis Para Suas Classes C#

25 }

26 }

27 }

Neste momento, ocorrendo uma alteração na persistência ou no log, basta alterarmos uma

das classes. Esta classe ainda poderia aplicar o princípio da Inversão de Controle, o que

veremos no tópico Dependency Inversion Principle.

Vamos fazer mais um exemplo para ficar mais claro o foco deste princípio. Temos uma

classe que representa a abstração de uma conta bancária, ela possui Número, Saldo e um

método que calcula os juros, conforme a Listagem 3.

Listagem 3. Classe Conta que fere o princípio de Responsabilidade Única

01 namespace SRP

02 {

03 public class Conta

04 {

05 public Conta() {}

06 public string Numero { get; set; }

07 public decimal Saldo { get; set; }

08

09 public decimal CalculaJuros()

10 {

11 // Lógica do cálculo de juros

12 }

13 }

14 }

Veja que esta é a classe modelo para a Conta e também efetua o cálculo de juros. Para

ficarem bem claras as duas responsabilidades, imagine que nos solicitem duas mudanças:

· Adicionar o nome do titular desta conta;

· Alterar a regra de cálculo de juros.

Estes são duas mudanças completamente diferentes uma da outra, a primeira está

mudando a característica da conta, o segundo está afetando uma funcionalidade, ou seja,

temos dois tipos de responsabilidade nessa classe. Muitas vezes os desenvolvedores

mantêm funções em suas classes de domínio, isso fere o princípio de responsabilidade única.

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

8 de 32 25/08/2014 10:09

Page 9: SOLID_ Padrões Flexíveis Para Suas Classes C#

lugar criamos a interface IConta e a classe Conta que implementa esta interface. Neste

momento essa classe tem somente as propriedades referentes à abstração da conta. Se

precisarmos mudar qualquer regra referente ao cálculo de juro, não será necessária a

alteração desta classe e interface.

Para calcular os juros criamos uma nova classe chamada CalculoJuros e um método

Calcular() para a realização do cálculo. Atente para o que passamos como parâmetro para a

classe CalculoJuros, a interface IConta e não a classe concreta Conta, o que torna o sistema

ainda mais propenso a alterações e extensões, conforme a Listagem 4.

Listagem 4. Implementação que respeita o princípio de Responsabilidade Única

01 namespace SRP

02 {

03 public interface IConta

04 {

05 string Numero { get; set; }

06 decimal Saldo { get; set; }

07 }

08

09 public class Conta : IConta

10 {

11 public string Numero { get; set; }

12 public decimal Saldo { get; set; }

13 }

14

15 public class CalculoJuros

16 {

17 public decimal Calcular(IConta)

18 {

19 return IConta.Saldo * 0.05;

20 }

21 }

22 }

O princípio do aberto/fechado é um dos mais interessantes da orientação a objetos e nos

indica que uma classe deve estar aberta para a extensão, mas fechada para modificação.

Pode parecer meio confuso esse conceito, mas é decisivo para uma boa modelagem de

classes.

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

9 de 32 25/08/2014 10:09

Page 10: SOLID_ Padrões Flexíveis Para Suas Classes C#

necessário, sem a alteração de seu código fonte. Essa extensão pode ser feita através de

herança, interface e composição.

Isso acontece geralmente com classes abstratas ou com métodos virtuais, onde estendemos

a classe base sem modificá-la, apenas complementando seu comportamento.

Isto é muito importante quando temos classes em ambiente de produção, porque

estendendo uma classe, não alteramos o código fonte da classe original, nos liberando de

tarefas como: revisar o impacto que mudanças na classe implicam em outros módulos do

sistema, realizar testes unitários para encontrar possíveis problemas, erros desconhecidos

em partes do sistema que estavam bem estáveis anteriormente, ou seja, não deve ser

necessária a abertura desta classe para alterações, porque isso pode gerar erros inesperados

na aplicação (bugs).

O conceito de extensão desta classe nos indica principalmente o uso da herança na

programação orientada a objetos. A ideia é que uma classe depois de concluída e em

funcionamento no ambiente de produção, esta classe tenha sua implementação alterada

somente no caso de correção de erros ocorridos na fase de desenvolvimento ou em uma

mudança na abstração de classes de modelo, como por exemplo a adição de uma nova

propriedade. Outras modificações como novos recursos, modificação nos recursos existentes

devem ser implementados como extensão desta classe.

Em resumo este princípio nos indica que devemos ter várias abstrações espalhadas pelo

software desenvolvido.

Para exemplificar este princípio consideremos uma Universidade que irá conceder descontos

para alunos de Graduação (10%) e Pós-Graduação (5%).

Temos neste caso a mesma classe Aluno, só que agora precisamos de um atributo chamado

Tipo de Aluno (Graduação, Pós-Graduação), porque dependendo deste tipo, ele terá um

desconto maior ou menor para o valor de uma mensalidade.

Para isso adicionamos uma propriedade TipoAluno e um método GetDesconto para

verificarmos qual o desconto será dado a esse Aluno no ato da matrícula.

Neste caso se o aluno for do tipo 1 = Graduação, terá 10% de desconto, se for

Pós-Graduação será 5% no valor da mensalidade. Observe o código da Listagem 5.

Listagem 5. Classe Aluno que não está seguindo o princípio de OCP

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

10 de 32 25/08/2014 10:09

Page 11: SOLID_ Padrões Flexíveis Para Suas Classes C#

03 public class Aluno

04 {

05 private int _TipoAluno;

06

07 public int TipoAluno

08 {

09 get { return _TipoAluno }

10 set { _TipoAluno value }

11 }

12

13 public double getDesconto(double TotalMensalidade)

14 {

15 if (_TipoAluno == 1)

16 {

17 return TotalMensalidade * 0.1;

18 }

19 else

20 {

21 return TotalMensalidade * 0.05;

22 }

23 }

24 }

25 }

O primeiro problema ao analisarmos a classe é que se adicionarmos outro tipo de aluno,

como mestrado, por exemplo, teremos mais um IF no método getDesconto(), tornando o

código mais poluído e propenso a erro. Outro problema é o “número mágico” 1, o que ele

significa? No caso de outro desenvolvedor se deparar com esse código terá que analisar a

documentação do sistema (se houver) para saber o que significa este número ou conversar

com um analista de sistemas ou analista de negócios que possa “lembrar” do significado.

Nota: Em alguns sistemas encontramos uma enorme quantidade de IFs, o que torna o

sistema de difícil entendimento e algumas vezes bem confusos.

Muitos desses IFs podem ser substituídos por soluções muito mais elegantes como o uso

de herança e polimorfismo para alterar o comportamento de um método. Excessos de

IFs são sintomas de classes mal estruturadas e que não seguem as boas práticas de

orientação a objetos.

O mais correto neste caso é não adicionarmos mais uma condição, e sim fazermos uma

extensão desta classe Aluno. Fazendo isso, a cada novo tipo de aluno, não se altera as

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

11 de 32 25/08/2014 10:09

Page 12: SOLID_ Padrões Flexíveis Para Suas Classes C#

especialização desta classe com novos recursos e mudanças em métodos existentes que

permitam a reescrita.

Poderíamos adicionar mais um tipo de aluno Mestrado e simplesmente codificarmos o

método getDesconto() conforme a necessidade, neste caso com 20% de desconto. Observe

como o código da Listagem 6 é mais claro, lógico e objetivo. Outro desenvolvedor o

entenderia facilmente e teria muito mais facilidade em modificá-lo e expandi-lo.

Listagem 6. Classes de Alunos obedecendo o princípio de OCP

01 namespace OCP

02 {

03 public class Aluno

04 {

05 public virtual double getDesconto(double TotalMensalidade)

06 {

07 return TotalMensalidade * 0.1;

08 }

09 }

10

11 public class AlunoPos : Aluno

12 {

13 public override double getDesconto(double TotalMensalidade)

14 {

15 return TotalMensalidade * 0.05;

16 }

17 }

18

19 public class AlunoMestrado : Aluno

20 {

21 public override double getDesconto(double TotalMensalidade)

22 {

23 return TotalMensalidade * 0.15;

24 }

25 }

26 }

Conforme nos diz o princípio, agora a classe Aluno está fechada para modificações e aberta

para extensões.

Seguindo com exemplos, para respeitarmos o princípio a primeira coisa ao criar uma classe é

analisar o que pode e o que não pode ser mudado nela. As partes que podem mudar

devemos deixar como abstratas ou virtuais.

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

12 de 32 25/08/2014 10:09

Page 13: SOLID_ Padrões Flexíveis Para Suas Classes C#

veja a declaração na Listagem 7

Listagem 7. Implementação ferindo o princípio de Aberto/Fechado

01 namespace OCP

02 {

03 enum TIPO_CONTA { CORRENTE, POUPANCA }

04

05 public class Conta

06 {

07 public string Numero { get; set; }

08 public decimal Saldo { get; set; }

09 public TIPO_CONTA TipoConta { get; set; }

10 }

11

12 public class CalculaJuros

13 {

14 public decimal Calcular(Conta pConta)

15 {

16 if (pConta.TIPO_CONTA == TIPO_CONTA.CORRENTE)

17 {

18 return pConta.Saldo * 0.05

19 } else if (pConta.TIPO_CONTA == TIPO_CONTA.POUPANCA)

20 {

21 return pConta.Saldo * 0.07

22 }

23 }

24 }

25 }

Observe que no código apresentado temos diversos problemas de design, o principal deles é

que se fizermos uma mudança no cálculo de juros, seja na mudança da forma ou qualquer

outro detalhe, pode causar comportamentos inesperados na classe.

O recomendado nessa situação é a decomposição desta classe em três, aplicando o princípio

do Aberto Fechado, conforme mostra a Listagem 8.

Listagem 8. Classes de Contas respeitando o principio do aberto/fechado.

01 namespace OCP

02 {

03 public abstract class Conta

04 {

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

13 de 32 25/08/2014 10:09

Page 14: SOLID_ Padrões Flexíveis Para Suas Classes C#

07 }

08

09 public class ContaCorrente : Conta

10 {

11 public override decimal CalculaJuros()

12 {

13 return Saldo * 0.05;

14 }

15 }

16

17 public class ContaPoupanca : Conta

18 {

19 public override decimal CalculaJuros()

20 {

21 return Saldo * 0.10;

22 }

23 }

24 }

Veja que a classe base não irá mudar com a adição de novos tipos de conta, ou seja, é

fechada para modificação, passando ser responsabilidade das classes filhas as

implementações dos comportamentos necessários de acordo com o cenário.

Este princípio nos indica que uma instancia de uma classe deve possibilitar sua substituição

em um software por instâncias de suas classes filhas, sem que seja necessária qualquer

alteração no programa, ou seja, classes derivadas devem poder ser substituídas por suas

classes base.

Isso significa que se pode usar o polimorfismo e considerar que todo e qualquer método ou

propriedade possa ser utilizada tanto pela classe base quanto por cada uma de suas

especializações sem problemas no programa.

Isto nos ajuda na modelagem de hierarquia de classes, porque se uma classe filha não

implementa todos os métodos da classe pai ou se um método da classe pai não faz sentido

para classe filha, então há de se considerar que existe um erro neste mecanismo de herança

está incorreto e não deveria existir.

Em resumo, este princípio nos indica que devemos ter muito cuidado ao usar a herança, é

um recurso sem dúvida muito poderoso, mas deve ser usado com parcimônia, evitando

fazer extensões desnecessárias somente para aproveitar um método existente na classe

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

14 de 32 25/08/2014 10:09

Page 15: SOLID_ Padrões Flexíveis Para Suas Classes C#

Considerando o mesmo exemplo anterior, temos desconto para alunos da pós e mestrado.

Porém agora se definiu que funcionários da instituição também tenham desconto no

pagamento das mensalidades e este desconto é de 50%.

A primeira ideia parece simples, fazer a classe Funcionario estender a classe Aluno, para que

também tenha o método de conceder desconto.

O problema começa a aparecer no método Adicionar, por que este método tem a função de

incluir um novo aluno na base de dados, seja ele de graduação, pós ou mestrado.

Porém a classe Funcionario não possui os mesmos atributos da classe Aluno e, portanto se

chamarmos o método Adicionar herdado da classe base Aluno terá um grande problema.

Muitos poderiam pensar em contornar este problema da seguinte maneira, conforme a

Listagem 9.

Listagem 9. Classes ferindo o princípio de substituição de Liskov

01 namespace LSP

02 {

03 public class Funcionario : Aluno

04 {

05 public override double getDesconto(TotalMensalidade)

06 {

07 return TotalMensalidade * 0.5;

08 }

09 public override void Adicionar()

10 {

11 throw new Exception("Não aplicado");

12 }

13 }

14

15 class Program

16 {

17 static void Main(string[] args)

18 {

19 List<Aluno> Alunos = new List<Aluno>();

20 Alunos.Add(new Aluno());

21 Alunos.Add(new AlunoPos());

22 Alunos.Add(new AlunoMestrado());

23 Alunos.Add(new Funcionario());

24

25 foreach (Aluno a in Alunos)

26 {

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

15 de 32 25/08/2014 10:09

Page 16: SOLID_ Padrões Flexíveis Para Suas Classes C#

29 }

30 }

31 }

Isso impediria que o funcionário fosse persistido na base de dados na forma de aluno.

Porém o princípio de substituição de Liskov nos diz que a classe base deveria poder chamar

qualquer um de seus métodos, que todas as classes filhas não teriam problemas com isso,

ou seja, esta implementação fere gravemente este princípio.

Assim, conforme a norma do polimorfismo, uma classe pai deveria poder apontar para

qualquer classe filha durante a execução do programa sem maiores problemas, o que não

ocorre neste exemplo, que levanta uma exceção ao chamar um método que não é suportado

por uma de suas classes filhas.

Esta codificação pode prejudicar em vários pontos da aplicação, como temos na classe

Program que deseja adicionar vários tipos de aluno em simultâneo na base de dados.

Este código compilaria tranquilamente, porque segundo a modelagem, um funcionário

também é um aluno e deveria estar apto a persistência, se executarmos este código

teremos um grave erro em tempo de execução porque um funcionário não é um aluno, por

isso não deve adicionar um registro na tabela Alunos.

Em outras palavras, a classe Funcionario deve ter desconto, mas não é Aluno para herdar

desta, temos um erro na hierarquia de classes. Confira a implementação correta na

Listagem 10.

Listagem 10. Implementação correta seguindo o princípio da substituição de Liskov

01 namespace LSP

02 {

03 interface IDesconto

04 {

05 double getDesconto(double TotalMensalidade);

06 }

07

08 interface IDatabase

09 {

10 void Adicionar();

11 }

12

13 public class Funcionario : IDesconto

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

16 de 32 25/08/2014 10:09

Page 17: SOLID_ Padrões Flexíveis Para Suas Classes C#

16 {

17 return TotalMensalidade - (TotalMensalidade * 0.5);

18 }

19 }

20

21 public class Aluno : IDesconto, IDatabase

22 {

23 public void Adicionar()

24 {

25 try

26 {

27 // Persiste no banco de dados

28 }

29 catch (Exception ex)

30 {

31 // Grava o Log de Erros

32 }

33 }

34

35 public double getDesconto(double TotalMensalidade)

36 {

37 return TotalMensalidade;

38 }

39 }

40 }

Criamos uma interface IDesconto para fazer a declaração do método getDesconto(). Desta

forma podemos fazer a classe Funcionario implementar somente a interface IDesconto e ter

somente o método que lhe interessa.

O princípio da segregação de interfaces nos diz que muitas interfaces específicas são

melhores que uma interface de uso geral, ou seja, nenhuma classe cliente deve ser

dependente de métodos que não usam.

Este princípio nos indica que devemos dividir interfaces grandes em interfaces menores para

que os clientes tenham conhecimento somente de métodos que lhes interessam e que não

sejam obrigados a depender de métodos que não usam.

Obedecendo este princípio o software será mais fácil de ser expandido, alterado e

distribuído. A dica é que sempre que precisamos de novos métodos em uma interface, o

ideal seria não adicionar estes métodos novos a esta interface, e sim criar uma nova

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

17 de 32 25/08/2014 10:09

Page 18: SOLID_ Padrões Flexíveis Para Suas Classes C#

Em resumo este princípio nos diz que nossos módulos devem ser enxutos, devem ter poucos

comportamentos. Interfaces que possuem muitos comportamentos geralmente o seu uso se

espalha por todo o sistema dificultando a manutenção.

O primeiro exemplo que é bastante simples e que todo e qualquer desenvolvedor

implementa nos sistemas, é a geração de arquivos. Invariavelmente precisamos gerar

arquivos Texto para controles fiscais, como o Sintegra, arquivos PDF de Notas Fiscais

Eletrônicas para o envio aos clientes, além de outros tipos de arquivos.

O que ocorre com bastante frequência neste cenário é a criação de uma classe Arquivo com

algumas propriedades básicas que todo arquivo possui com o nome e classes filhas que

herdam estas propriedades básicas e possuem métodos de geração destes arquivos.

Podemos ainda ter uma classe chamada GeradorArquivos() que irá chamar os métodos de

geração das classes, conforme a Listagem 11.

Listagem 11. Classes de Arquivos e Geração de Arquivos

01 namespace LSP

02 {

03 public class Arquivo

04 {

05 public string Nome { get; set; };

06

07 public Arquivo(string pNome)

08 {

09 Nome = pNome;

10 }

11 }

12

13 public class ArquivoTxt : Arquivo

14 {

15 public void GerarArquivoTxt()

16 {

17 // Lógica de geração do arquivo txt

18 }

19 }

20

21 public class ArquivoPdf : Arquivo

22 {

23 public void GerarArquivoPdf()

24 {

25 // Lógica de geração do arquivo pdf

26 }

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

18 de 32 25/08/2014 10:09

Page 19: SOLID_ Padrões Flexíveis Para Suas Classes C#

29 public class GeradorArquivos

30 {

31 public void GerarArquivo(pArquivo Arquivo)

32 {

33 if (pArquivo is ArquivoTxt)

34 ((ArquivoTxt)pArquivo).GerarArquivoTxt();

35 else if (pArquivo is ArquivoPdf)

36 ((ArquivoPdf)pArquivo).GerarArquivoPdf();

37 }

38 }

39 }

Existe um erro grave de modelagem dessas classes, esses métodos de geração não

deveriam ser específicos de cada classe. Você deve pensar neste momento, mas as formas

de geração de arquivos Texto e PDF são completamente diferentes. Está correto, elas são

mesmo completamente diferentes, mas sua implementação que é diferente, a interface de

geração é a mesma, isso que importa no momento da definição.

Uma das principais regras da orientação a objetos é que devemos programar sempre

voltados a interface, não para a implementação. É muito mais importante definir o que uma

classe vai fazer do como ela irá fazer.

Com esta abordagem, no momento que tivermos a geração de um novo tipo de arquivo pelo

sistema, teremos que adicionar mais um else if, o que já vimos não ser uma boa prática de

orientação a objetos.

Assim podemos afirmar que as classes ArquivoTxt e ArquivoPdf não estão em conformidade

com o princípio de Substituição de Liskov, uma vez que não podemos substituí-la pela

classe Arquivo na classe GeracaoArquivo, porque os métodos de geração são específicos de

cada classe derivada.

Sendo assim somos obrigados a verificar o tipo e fazer downcast para fazer a chamada do

método apropriado.

Na Listagem 12 temos a definição correta das classes Arquivo, ArquivoTxt e ArquivoPdf,

seguindo perfeitamente o princípio de substituição de Liskov. Veja que não será mais

necessário o uso do downcast para fazer a geração na classe GeradorArquivo, no método

GerarArquivo().

Listagem 12. Modelagem correta das classes seguindo o princípio de LSP

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

19 de 32 25/08/2014 10:09

Page 20: SOLID_ Padrões Flexíveis Para Suas Classes C#

01 namespace LSP

02 {

03 public abstract class Arquivo

04 {

05 public string Nome { get; set; };

06

07 public Arquivo(string pNome)

08 {

09 Nome = pNome;

10 }

11

12 public abstract void Gerar();

13 }

14

15 public class ArquivoTxt : Arquivo

16 {

17 public override void Gerar()

18 {

19 // código para geração do arquivo Txt

20 }

21 }

22

23 public class ArquivoTxt : Arquivo

24 {

25 public override void Gerar()

26 {

27 // código para geração do arquivo Pdf

28 }

29 }

30

31 public class GeradorArquivo

32 {

33 public void GerarArquivo(Arquivo pArquivo)

34 {

35 Arquivo.Gerar();

36 }

37 }

38 }

Esta maneira de resolver este problema é muito mais elegante e aproveita todo o poder do

polimorfismo.

Este princípio nos alerta para o cuidado que devemos ter com nossas hierarquias de classes.

Para exemplificar outra vez, consideramos novamente o exemplo da hierarquia de classes

dos alunos, imagine agora que os alunos de mestrado no ato do pagamento precisam de um

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

20 de 32 25/08/2014 10:09

Page 21: SOLID_ Padrões Flexíveis Para Suas Classes C#

A primeira opção, por se tratar de uma consulta e envolver banco de dados, é que

adicionemos mais um método na interface IDatabase, conforme a Listagem 13.

Listagem 13. Violação do princípio de segregação de interfaces

01 namespace ISP

02 {

03 interface IDatabase

04 {

05 void Adicionar(); // Outros alunos utilizam apenas este método

06 void Extrato(); // Método exclusivo de alunos de mestrado

07 }

08 }

Esta abordagem é muito errada para resolver este problema, pois neste caso todas as

outras classes (Aluno, AlunoPos, etc) serão obrigadas a implementar o método Extrato()

mesmo que elas não tenham interesse em sua utilização.

Neste caso a melhor solução seria a criação de outra interface ao invés de alterar a interface

atual. Assim podemos manter a interface IDatabase como está e consequentemente todas

as outras classes de Alunos sem nenhuma modificação e adicionar a interface

IDatabaseConsulta no sistema. Desta forma a interface IDatabaseConsulta obtém o método

Adicionar e cria o novo método Extrato() para quem desejar implementá-lo.

Para finalizar podemos utilizar ambas as interfaces em nossas aplicações clientes, como na

classe Program. Observe como fica o código na Listagem 14.

Listagem 14. Utilização do Princípio de Segregação de Interfaces

01 namespace ISP

02 interface IDatabaseConsulta : IDatabase

03 {

04 void Extrato();

05 }

06

07 public class AlunoMestrado : IDatabaseConsulta

08 {

09 public void Adicionar()

10 {

11 // Implementação da lógica de inclusão do aluno no banco

12 }

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

21 de 32 25/08/2014 10:09

Page 22: SOLID_ Padrões Flexíveis Para Suas Classes C#

15 // Implementação da lógica de impressão do extrato

16 }

17 }

18

19 class Program

20 {

21 static void Main(string[] args)

22 {

23 IDatabase i = new Aluno();

24 i.Adicionar();

25

26 IDatabaseConsulta ic = new AlunoMestrado();

27 ic.Extrato();

28 }

29 }

30 }

Agora vamos voltar ao exemplo do sistema de contas, criaremos uma interface que terá os

métodos básicos de todas as contas bancárias, conforme a Listagem 15.

Listagem 15. Classes ignorando o princípio de Segregação de Interfaces

01 namespace ISP

02 {

03 interface IConta

04 {

05 void Sacar();

06 double CalculaJuros();

07 double CalculaTributos();

08 }

09

10 public class ContaCorrente : IConta

11 {

12 public void Sacar()

13 {

14 // Saque

15 }

16 public double CalculaJuros()

17 {

18 return 0; // Não rende juros em conta corrente

19 }

20 public double CalculaTributos()

21 {

22 // Cálculo da tributação da conta corrente

23 }

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

22 de 32 25/08/2014 10:09

Page 23: SOLID_ Padrões Flexíveis Para Suas Classes C#

26 public class ContaPoupanca : IConta

27 {

28 public void Sacar()

29 {

30 // Saque

31 }

32 public double CalculaJuros()

33 {

34 // Cálculo de juros para a conta poupança

35 }

36 public double CalculaTributos()

37 {

38 return 0; // Não existe tributos para conta poupança

39 }

40 }

41 }

Ambas as classes concretas devem implementar os métodos existentes na interface IConta.

Tanto a conta corrente quanto a conta poupança terão a opção de saque, porém somente a

conta corrente cobra tributos do cliente para a conta, e somente a conta poupança rende

juros mensais aos clientes pelo valor contigo na conta.

Neste caso temos uma interface poluída, pois não são todas as classes que devem

implementar seus métodos, algumas quem implementar apenas parte desses métodos. Esse

é o indício que devemos segregar esta classe em duas.

Na Listagem 16 temos o modelo seguindo o princípio de segregação de interfaces.

Listagem 16. Modelo seguindo o princípio de segregação de interfaces

01 namespace ISP

02 {

03 interface IConta

04 {

05 void Sacar();

06 }

07

08 public abstract class Conta

09 {

10 public virtual void Sacar()

11 {

12 // Implementa o método sacar

13 // que é padrão para todos os tipos de conta

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

23 de 32 25/08/2014 10:09

Page 24: SOLID_ Padrões Flexíveis Para Suas Classes C#

16

17 interface IContaCorrente : IConta

18 {

19 double CalculaTributos();

20 }

21

22 interface IContaPoupanca : IConta

23 {

24 double CalculaJuros();

25 }

26

27 public class ContaCorrente : Conta, IContaCorrente

28 {

29 public double CalculaTributos()

30 {

31 // Implementa o cálculo de tributos

32 }

33 }

34

35 public class ContaPoupanca : Conta, IContaPoupanca

36 {

37 public double CalculaJuros()

38 {

39 // Implementa o cálculo de juros

40 }

41 }

42 }

Veja a sequência de passos que resolveram o problema em questão:

· Criada a interface IConta que possui apenas o método Sacar() que é o mesmo para todos

os tipos de contas;

· Criada a classe abstrata Conta que implementa a interface IConta e o método Sacar() que

será herdado pelas classes derivadas;

· Criadas duas interfaces IContaCorrente e IContaPoupanca, cada uma com a declaração de

seu método necessário;

· Criada a classe ContaCorrente que herda da classe Conta e implementa a interface

IContaCorrente e o método CalculaTributos();

· Criada a classe ContaPoupanca que também herda da classe Conta que possui o método

sacar e implementa a interface IContaPoupanca e o método CalculaJuros();

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

24 de 32 25/08/2014 10:09

Page 25: SOLID_ Padrões Flexíveis Para Suas Classes C#

possui nada que não vai utilizar, tornando-as coesas.

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. Abstrações

não devem depender de detalhes, detalhes devem depender de abstrações.

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

seja necessário 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. Um exemplo

de aplicação deste princípio é o padrão Bridge, que define interfaces para favorecer um

baixo acoplamento no design do código. Outro padrão relacionado é o Adapter (BOX 5).

BOX 5. Padrão de Projeto Adapter e Bridge

O padrão de projeto Adapter, também conhecido como Wrapper, é um padrão que tem

o objetivo de adaptar a interface de uma classe, fazendo com que classes com

interfaces incompatíveis possam interagir.

O padrão de projeto Bridge utilizado quando se deseja que uma interface possa variar,

independentemente de suas implementações. Ou seja, tanto a interface quanto as

implementações podem variar separadamente. O padrão Bridge oferece um nível de

abstração maior que o padrão Adapter.

Outro padrão que geralmente anda junto com o princípio de inversão de dependência é a

Injeção de Dependências. Na verdade a injeção de dependências é 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 - BOX 6) que é

responsável por injetar em cada classe suas dependências declaradas.

O padrão de Injeção de dependências sugere que as dependências de uma classe, como por

exemplo, uma conexão com banco de dados sejam injetados na classe.

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

25 de 32 25/08/2014 10:09

Page 26: SOLID_ Padrões Flexíveis Para Suas Classes C#

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).

BOX 6. Container

Container é um objeto que possui outros objetos que podem ser incluídos e excluídos

dinamicamente, em tempo de execução.

Existem basicamente algumas maneiras de fazer a injeção de dependências numa classe:

· Construtor: as dependências da classes são injetadas no próprio construtor da classe;

· Propriedade: as dependências são injetadas via Setter nas propriedades;

· Interface: o objeto a ser injetado é uma abstração da classe concreta (na forma de

interface ou classe abstrata).

· Framework: existem alguns frameworks que nos ajudam a injetar a dependência,

utilizando XML ou anotações em classes. Alguns exemplos são o Spring.net e o UNITY;

Em resumo, este princípio nos indica que devemos depender sempre de abstrações, pois

elas mudam com bem menos frequência, o que facilita a mudança de comportamento e a

evolução do código.

Iniciaremos com o exemplo da classe Aluno que utilizava a classe ArquivoLog para gravar

possíveis erros durante a persistência, veja novamente na Listagem 17.

Listagem 17. Classe que atende o princípio de SRP mas agora fere o princípio de DIP

namespace DIP

{

class ArquivoLog

{

public void Gravar(string erro)

{

System.IO.File.WriteAllText(@"C:\Erro.txt, erro");

}

}

class Aluno

{

private ArquivoLog log = new ArquivoLog();

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

26 de 32 25/08/2014 10:09

Page 27: SOLID_ Padrões Flexíveis Para Suas Classes C#

{

try

{

// Database save

}

catch (Exception ex)

{

log.Gravar(ex.ToString());

}

}

}

}

O princípio de inversão de dependência nos indica que não é a classe Aluno que deve criar o

objeto ArquivoLog e sim ser injetada esta dependência de alguma forma. Veremos nesse

caso por meio de Construtor.

Para melhorar ainda mais o exemplo, criaremos uma interface ILog, de forma que

poderemos mais tarde implementar outras formas de Log que não sejam a gravação em

arquivo, como envio por e-mail, mensagem na tela, etc. Veja na Listagem 18.

Listagem 18. Aplicando o princípio de Inversão de Controle

namespace DIP

{

public class Aluno

{

private ILog _Log;

public ILog Log

{

get { return _Log }

set { _Log value }

}

public Aluno(ILog pLog)

{

_Log = pLog;

}

public virtual void Adicionar()

{

try

{

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

27 de 32 25/08/2014 10:09

Page 28: SOLID_ Padrões Flexíveis Para Suas Classes C#

catch (Exception ex)

{

_Log.Gravar(ex.ToString());

}

}

}

}

Agora nossa classe Aluno precisa receber uma referência para Log em seu construtor. Isso

nos dá liberdade para criar extensões da classe Log e basta modificar a referência na hora

de instanciar a classe Aluno para mudarmos a forma de Log, como por exemplo, LogEmail

ou LogTela. Mais uma vez vemos o polimorfismo atuando de forma decisiva para o sucesso

deste princípio.

Se conseguirmos seguir todos estes princípios apresentados neste artigo, teremos um

código limpo, de fácil manutenção e muito mais propício a evolução.

Mudanças no sistema serão de fácil acesso e suas correções serão em lugares bem

específicos, e problemas não serão propagados para o restante do sistema.

O problema é que não é fácil escrever um código sólido e que siga tais técnicas, isto vai se

conseguindo com experiência no desenvolvimento de software e estudo.

O interessante é termos sempre classes pequenas com métodos enxutos, o que nos traz

muita modularidade.

Links

Visual Studio Express 2013

http://www.visualstudio.com/en-us/products/visual-studio-express-vs.aspx

Artigos POO Uncle Bob

http://butunclebob.com/ArticleS.UncleBob

Filipe Dalepiane

Analista de Sistemas numa Universidade. Colunista das revistas Clube Delphi e .NET Magazine. Desenvolvedor Delphi

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

28 de 32 25/08/2014 10:09

Page 29: SOLID_ Padrões Flexíveis Para Suas Classes C#

O que você achou deste post?

Gostei (3) (0)

Comentário | Tire sua dúvida

Luciano Paranhos MVP

Na Listagem 12 A classe ArquivoTxt esta sendo duplicada, uma delas seria ArquivoPdf certo?

[há 6 dias] - Responder

[autor] Filipe Dalepiane

Exatamente, ambas herdando da classe abstrata Arquivo.

[há 6 dias] - Responder

Luciano Paranhos MVP

Legal! A propósito, excelente material.

[há 6 dias] - Responder

Publicidade

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

29 de 32 25/08/2014 10:09

Page 30: SOLID_ Padrões Flexíveis Para Suas Classes C#

Serviços

Inclua um comentário

Adicionar aos Favoritos

Marcar como lido/assistido

Incluir anotação pessoal

Versão para impressão

+.net

Artigo

Novidades do ASP.NET vNext e do Visual Studio

Video aula

Lendo arquivos XML com DataSets - Curso de Introdução ao .NET

Framework - 39

Video aula

Cadastros com DataSets e DataTables - Curso de Introdução ao

.NET Framework - 38

Video aula

Criando um formulário de cadastro - Curso de Introdução ao .NET

Framework - 37

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

30 de 32 25/08/2014 10:09

Page 31: SOLID_ Padrões Flexíveis Para Suas Classes C#

Managed Providers e Content Components - Curso de Introdução

ao .NET Framework - 36

Video aula

Acesso a Dados no .NET - Curso de Introdução ao .NET

Framework - 35

Video aula

Definindo a arquitetura de Acesso a Dados - Curso básico de ASP

.NET - 49

Video aula

Inserindo dados - Curso básico de ASP .NET - 48

Video aula

Criando a View - Curso básico de ASP .NET - 47

Video aula

Criando o Banco de Dados - Curso básico de ASP .NET - 46

Listar mais conteúdo

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

31 de 32 25/08/2014 10:09

Page 32: SOLID_ Padrões Flexíveis Para Suas Classes C#

CONTEÚDO ▼ REVISTAS ▼ CURSOS ▼ DEVWARE ▼ MVP

SOLID: Padrões flexíveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...

32 de 32 25/08/2014 10:09