Vous êtes sur la page 1sur 32

comentrios post favorito (2)

.net Magazine 116 - ndice


Aprenda com esse artigo a criar suas classes obedecendo estes
princpios de orientao a objetos.

0 1 Curtir Curtir 1
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
Anuncie | Loja | Publique | Assine | Fale conosco
Hospedagem web por Porta 80 Web Todos os Direitos Reservados a
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
1 de 32 25/08/2014 10:09
Veremos as vantagens e as maneiras corretas de aplicar este princpio passo a passo.
Ainda veremos como eles se relacionam com vrios dos vinte trs Designs Patterns do
GoF, atravs de exemplos prticos de aplicao destes princpios, com situaes 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 manuteno de sistemas computacionais. Pesquisas indicam que as empresas
gastam mais de 80% do oramento destinado ao software em manuteno.
Isso ocorre porque na maioria dos desenvolvedores de sistemas no seguem os princpios da
orientao a objetos e no utilizam os padres de projetos e tcnicas corretas de
desenvolvimento.
So sistemas mal codificados que o tornam difcil de manter e evoluir. Outros ainda utilizam
outros paradigmas, como a programao estruturada, que demanda muito mais manuteno
que o paradigma orientado a objetos.
Em sistemas de informao que adotam o paradigma orientado a objetos, existem vrios
padres, princpios e tcnicas que o desenvolvedor deve seguir para que o sistema seja de
fcil entendimento para outros desenvolvedores, de fcil manuteno aps o sistema estar
em ambiente de produo, que mudanas e novas funcionalidades no causem impacto em
todo o sistema j existente.
Para um melhor entendimento sobre padres de projetos necessrio um slido
conhecimento de orientao a objetos, do contrrio, os padres no sero bem
compreendidos e o leitor acaba no sabendo aplicar estes no seu dia a dia.
Os princpios SOLID so a base para vrios padres de projetos criados e tornam softwares
mais evolutivos, de fcil manuteno e mudanas efetuadas depois de finalizado, no
impactando em outras reas do programa, mudanas no propagam erros por outras partes
desse sistema.
Muitos desenvolvedores discutem sobre os padres de projeto de software, alguns dizem
que os eles servem simplesmente para resolver problemas das linguagens de programao
orientadas a objetos e que outras linguagens, com mais recursos, no precisam implementar
nenhum desses padres, mas esse no um tpico abordado neste artigo.
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
2 de 32 25/08/2014 10:09
para todo e qualquer projeto que siga este paradigma de desenvolvimento.
Com certeza, um cdigo que no segue estes princpios no de qualidade e um
desenvolvedor ao olhar para esse cdigo percebe isso. Existem vrias dicas, macetes e
tcnicas para aplicao de todos estes princpios.
Para um cdigo limpo e de qualidade, ele deve estar bem modularizado, cada classe deve
ter a sua responsabilidade e as relaes entre essas classes devem ser claras e bem
definidas. aqui que entra a ideia de cdigo slido, de onde vem o tema deste artigo.
Antes de entrarmos no estudo destes princpios, veremos quais os principais problemas
encontrados em sistemas e que poderiam ser evitados com a aplicao de padres de
projetos e princpios de orientao a objetos (BOX 1):
Rigidez: o sistema foi desenvolvido de forma que muito difcil de mudar, qualquer
alterao provoca uma cascata de operaes por todo o restante do sistema;
Imobilidade: a codificao foi feita de forma que o reuso muito difcil, nenhuma parte do
sistema pode ser reaproveitada em outro sistema;
Fragilidade: o sistema foi feito de maneira que qualquer mudana o desestabiliza e o torna
inoperante;
Complexidade: o sistema foi desenvolvido utilizando-se de muitos padres para resolver
problemas simples, algo desnecessrio (dependendo do caso);
Repetio: mesmos trechos de cdigos espalhados por todo o sistema, ao invs de estarem
encapsulados em um mtodo ou classe.
Aplicar boas prticas de engenharia de software nos rende muitos benefcios como
manuteno facilitada, cdigo organizado, dependncias mais leves e uma arquitetura
completamente aberta a receber atualizaes, melhorias e novos recursos.
Alm disso, quando temos o sistema com vrias classes desempenhando bem o seu papel e
cada mtodo tendo o seu objetivo bem definido, ficam muito mais fceis de ser realizados
os testes unitrios do sistema.
BOX 1. Padres de Projeto GoF
Padres de Projeto do GoF tem como objetivo solucionar problemas comuns de software
relacionados as orientao a objetos.
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
3 de 32 25/08/2014 10:09
Design Patterns: Elements of Reusable Object-Oriented Software por Erich Gamma,
Richard Helm, Ralph Johnson e John Vlissides, a chamada Gangue of Four. So
organizados em trs grupos:
Padres de criao: relacionados criao de objetos (Abstract Factory, Builder,
Factory Method, Prototype, Singleton);
Padres estruturais: tratam das associaes entre classes e objetos (Adapter, Bridge,
Composite, Decorator, Facade, Flyweight, Proxy).
Padres comportamentais: tratam das interaes e divises de responsabilidades entre
as classes ou objetos (Chain of Responsibility, Command, Interpreter, Iterator,
Mediator, Memento, Observer, State, Strategy, Template Method, Visitor).
SOLID so cinco princpios bsicos que todos os analistas e desenvolvedores deveriam
seguir para uma boa modelagem de classes. Cada letra da palavra SOLID representa um
princpio, so eles:
S Single Responsibility Principle (SRP): princpio da responsabilidade nica;
O Open Closed Principle (OCP): princpio do aberto/fechado;
L Liskov Substituition Principle (LSP): princpio da substituio de Liskov;
I Inteface Segregation Principle (ISP): princpio da segregao de interfaces;
D Dependency Inversion Principle (DIP): princpio da inverso de dependncia.
O princpio 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
mtodos devem agir em conjunto para resolver esta tarefa e, por isso, tem uma nica razo
ou motivo para ser alterada.
Isto no significa que uma classe deva ter somente um mtodo, mas que tenha mtodos
que juntos cheguem a um determinado objetivo comum. Uma classe poder ser responsvel
por uma funcionalidade que pode precisar de cinco mtodos para resolver sua tarefa.
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
4 de 32 25/08/2014 10:09
necessidade de alterao.
Um exemplo muito popular que viola o princpio da responsabilidade nica o padro
ActiveRecord (BOX 2) que mistura regras de negcio com persistncia de dados.
BOX 2. Active Record
Active Record um padro de projeto de alguns sistemas que armazenam seus dados
em banco de dados relacionais. A interface de objetos deste padro, alm de manter
seus atributos que representam cada coluna de uma tabela, possuem mtodos como
Insert(), Update(), Delete(). Esta tcnica diminui o nmero de classes do sistema, pois
mantm as regras de negcio e persistncia juntas. Este padro bastante utilizado por
programadores PHP.
O princpio da responsabilidade nica est intimamente relacionado ao princpio da coeso
(BOX 3). O ferimento deste princpio acarreta tambm em um alto acoplamento (BOX 4).
Em resumo, este princpio 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 mudana e estas fontes de mudanas
devem estar sempre bem isoladas. Este conceito muito fcil de entender, mas muitas
vezes muito difcil de ser posto em prtica.
BOX 3. Coeso
O grau de Coeso na Orientao 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 coeso, o que uma coisa boa.
O principal benefcio da alta coeso que essas classes so mais fceis de manter e so
menos necessrias alteraes frequentes nelas do que as de baixa coeso. Outro grande
benefcio que classes com alta coeso so mais fceis de serem reutilizadas
posteriormente.
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
5 de 32 25/08/2014 10:09
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 atravs de
sua interface, ento a classe X e a classe Y so fracamente acopladas, o que muito
bom.
Porm, se a classe A se baseia em partes da classe B que no fazem parte de sua
interface, ento elas esto fortemente acopladas, o que no uma boa prtica em
sistemas orientados a objetos.
Existem muitos exemplos deste princpio 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 simplrios.
Iniciando o pensamento do princpio, pensamos numa classe Cliente, ela abstrai os clientes
da empresa, ento ela s deve mudar se uma das caractersticas abstradas 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 razo para ela mudar.
Como exemplo rpido para o perfeito entendimento, basta considerar uma classe que
processa e imprime um relatrio. Esta classe tem duas razes para ser modificada, uma
mudana na consulta que busca os dados deste relatrio e uma mudana no layout do
relatrio.
Essas mudanas ocorrem por causas muito diferentes, uma por causa dos dados, outra por
causa da esttica do relatrio. Isso significa que esta classe tem duas responsabilidades
distintas e que deveriam ser separadas em duas classes.
Agora veremos um exemplo prtico da implementao de uma classe sem o princpio e
depois com o princpio seguido. Veja a classe da Listagem 1.
Listagem 1. Implementao da Classe Aluno sem obedecer o princpio da SRP.

01 namespace SRP
02 {
03 public class Aluno
04 {
05 public void Adicionar()
06 {
07 try
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
6 de 32 25/08/2014 10:09
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
persistncias dos dados, a segunda gravar um log para o caso de ocorrer um erro durante
o processo de persistncia.
Observamos ento que esta classe pode ser mudada por duas razes distintas, uma
mudana na parte de persistncia e uma mudana 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 atravs da
composio para efetuar o log de erros, conforme a Listagem 2.
Listagem 2. Implementao das classes Aluno e ArquivoLog seguindo o princpio 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 {
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
7 de 32 25/08/2014 10:09
25 }
26 }
27 }
Neste momento, ocorrendo uma alterao na persistncia ou no log, basta alterarmos uma
das classes. Esta classe ainda poderia aplicar o princpio da Inverso de Controle, o que
veremos no tpico Dependency Inversion Principle.
Vamos fazer mais um exemplo para ficar mais claro o foco deste princpio. Temos uma
classe que representa a abstrao de uma conta bancria, ela possui Nmero, Saldo e um
mtodo que calcula os juros, conforme a Listagem 3.
Listagem 3. Classe Conta que fere o princpio 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 // Lgica do clculo de juros
12 }
13 }
14 }
Veja que esta a classe modelo para a Conta e tambm efetua o clculo de juros. Para
ficarem bem claras as duas responsabilidades, imagine que nos solicitem duas mudanas:
Adicionar o nome do titular desta conta;
Alterar a regra de clculo de juros.
Estes so duas mudanas completamente diferentes uma da outra, a primeira est
mudando a caracterstica da conta, o segundo est afetando uma funcionalidade, ou seja,
temos dois tipos de responsabilidade nessa classe. Muitas vezes os desenvolvedores
mantm funes em suas classes de domnio, isso fere o princpio de responsabilidade nica.
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
8 de 32 25/08/2014 10:09
lugar criamos a interface IConta e a classe Conta que implementa esta interface. Neste
momento essa classe tem somente as propriedades referentes abstrao da conta. Se
precisarmos mudar qualquer regra referente ao clculo de juro, no ser necessria a
alterao desta classe e interface.
Para calcular os juros criamos uma nova classe chamada CalculoJuros e um mtodo
Calcular() para a realizao do clculo. Atente para o que passamos como parmetro para a
classe CalculoJuros, a interface IConta e no a classe concreta Conta, o que torna o sistema
ainda mais propenso a alteraes e extenses, conforme a Listagem 4.
Listagem 4. Implementao que respeita o princpio 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 princpio do aberto/fechado um dos mais interessantes da orientao a objetos e nos
indica que uma classe deve estar aberta para a extenso, mas fechada para modificao.
Pode parecer meio confuso esse conceito, mas decisivo para uma boa modelagem de
classes.
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
9 de 32 25/08/2014 10:09
necessrio, sem a alterao de seu cdigo fonte. Essa extenso pode ser feita atravs de
herana, interface e composio.
Isso acontece geralmente com classes abstratas ou com mtodos virtuais, onde estendemos
a classe base sem modific-la, apenas complementando seu comportamento.
Isto muito importante quando temos classes em ambiente de produo, porque
estendendo uma classe, no alteramos o cdigo fonte da classe original, nos liberando de
tarefas como: revisar o impacto que mudanas na classe implicam em outros mdulos do
sistema, realizar testes unitrios para encontrar possveis problemas, erros desconhecidos
em partes do sistema que estavam bem estveis anteriormente, ou seja, no deve ser
necessria a abertura desta classe para alteraes, porque isso pode gerar erros inesperados
na aplicao (bugs).
O conceito de extenso desta classe nos indica principalmente o uso da herana na
programao orientada a objetos. A ideia que uma classe depois de concluda e em
funcionamento no ambiente de produo, esta classe tenha sua implementao alterada
somente no caso de correo de erros ocorridos na fase de desenvolvimento ou em uma
mudana na abstrao de classes de modelo, como por exemplo a adio de uma nova
propriedade. Outras modificaes como novos recursos, modificao nos recursos existentes
devem ser implementados como extenso desta classe.
Em resumo este princpio nos indica que devemos ter vrias abstraes espalhadas pelo
software desenvolvido.
Para exemplificar este princpio consideremos uma Universidade que ir conceder descontos
para alunos de Graduao (10%) e Ps-Graduao (5%).
Temos neste caso a mesma classe Aluno, s que agora precisamos de um atributo chamado
Tipo de Aluno (Graduao, Ps-Graduao), 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 mtodo GetDesconto para
verificarmos qual o desconto ser dado a esse Aluno no ato da matrcula.
Neste caso se o aluno for do tipo 1 = Graduao, ter 10% de desconto, se for
Ps-Graduao ser 5% no valor da mensalidade. Observe o cdigo da Listagem 5.
Listagem 5. Classe Aluno que no est seguindo o princpio de OCP

CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
10 de 32 25/08/2014 10:09
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 mtodo getDesconto(), tornando o
cdigo mais poludo e propenso a erro. Outro problema o nmero mgico 1, o que ele
significa? No caso de outro desenvolvedor se deparar com esse cdigo ter que analisar a
documentao do sistema (se houver) para saber o que significa este nmero ou conversar
com um analista de sistemas ou analista de negcios que possa lembrar do significado.
Nota: Em alguns sistemas encontramos uma enorme quantidade de IFs, o que torna o
sistema de difcil entendimento e algumas vezes bem confusos.
Muitos desses IFs podem ser substitudos por solues muito mais elegantes como o uso
de herana e polimorfismo para alterar o comportamento de um mtodo. Excessos de
IFs so sintomas de classes mal estruturadas e que no seguem as boas prticas de
orientao a objetos.
O mais correto neste caso no adicionarmos mais uma condio, e sim fazermos uma
extenso desta classe Aluno. Fazendo isso, a cada novo tipo de aluno, no se altera as
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
11 de 32 25/08/2014 10:09
especializao desta classe com novos recursos e mudanas em mtodos existentes que
permitam a reescrita.
Poderamos adicionar mais um tipo de aluno Mestrado e simplesmente codificarmos o
mtodo getDesconto() conforme a necessidade, neste caso com 20% de desconto. Observe
como o cdigo da Listagem 6 mais claro, lgico 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 princpio 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 princpio, agora a classe Aluno est fechada para modificaes e aberta
para extenses.
Seguindo com exemplos, para respeitarmos o princpio a primeira coisa ao criar uma classe
analisar o que pode e o que no pode ser mudado nela. As partes que podem mudar
devemos deixar como abstratas ou virtuais.
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
12 de 32 25/08/2014 10:09
veja a declarao na Listagem 7
Listagem 7. Implementao ferindo o princpio 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 cdigo apresentado temos diversos problemas de design, o principal deles
que se fizermos uma mudana no clculo de juros, seja na mudana da forma ou qualquer
outro detalhe, pode causar comportamentos inesperados na classe.
O recomendado nessa situao a decomposio desta classe em trs, aplicando o princpio
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 {
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
13 de 32 25/08/2014 10:09
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 no ir mudar com a adio de novos tipos de conta, ou seja,
fechada para modificao, passando ser responsabilidade das classes filhas as
implementaes dos comportamentos necessrios de acordo com o cenrio.
Este princpio nos indica que uma instancia de uma classe deve possibilitar sua substituio
em um software por instncias de suas classes filhas, sem que seja necessria qualquer
alterao no programa, ou seja, classes derivadas devem poder ser substitudas por suas
classes base.
Isso significa que se pode usar o polimorfismo e considerar que todo e qualquer mtodo ou
propriedade possa ser utilizada tanto pela classe base quanto por cada uma de suas
especializaes sem problemas no programa.
Isto nos ajuda na modelagem de hierarquia de classes, porque se uma classe filha no
implementa todos os mtodos da classe pai ou se um mtodo da classe pai no faz sentido
para classe filha, ento h de se considerar que existe um erro neste mecanismo de herana
est incorreto e no deveria existir.
Em resumo, este princpio nos indica que devemos ter muito cuidado ao usar a herana,
um recurso sem dvida muito poderoso, mas deve ser usado com parcimnia, evitando
fazer extenses desnecessrias somente para aproveitar um mtodo existente na classe
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
14 de 32 25/08/2014 10:09
Considerando o mesmo exemplo anterior, temos desconto para alunos da ps e mestrado.
Porm agora se definiu que funcionrios da instituio tambm 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
tambm tenha o mtodo de conceder desconto.
O problema comea a aparecer no mtodo Adicionar, por que este mtodo tem a funo de
incluir um novo aluno na base de dados, seja ele de graduao, ps ou mestrado.
Porm a classe Funcionario no possui os mesmos atributos da classe Aluno e, portanto se
chamarmos o mtodo 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 princpio de substituio 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("No 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 {
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
15 de 32 25/08/2014 10:09
29 }
30 }
31 }
Isso impediria que o funcionrio fosse persistido na base de dados na forma de aluno.
Porm o princpio de substituio de Liskov nos diz que a classe base deveria poder chamar
qualquer um de seus mtodos, que todas as classes filhas no teriam problemas com isso,
ou seja, esta implementao fere gravemente este princpio.
Assim, conforme a norma do polimorfismo, uma classe pai deveria poder apontar para
qualquer classe filha durante a execuo do programa sem maiores problemas, o que no
ocorre neste exemplo, que levanta uma exceo ao chamar um mtodo que no suportado
por uma de suas classes filhas.
Esta codificao pode prejudicar em vrios pontos da aplicao, como temos na classe
Program que deseja adicionar vrios tipos de aluno em simultneo na base de dados.
Este cdigo compilaria tranquilamente, porque segundo a modelagem, um funcionrio
tambm um aluno e deveria estar apto a persistncia, se executarmos este cdigo
teremos um grave erro em tempo de execuo porque um funcionrio no um aluno, por
isso no deve adicionar um registro na tabela Alunos.
Em outras palavras, a classe Funcionario deve ter desconto, mas no Aluno para herdar
desta, temos um erro na hierarquia de classes. Confira a implementao correta na
Listagem 10.
Listagem 10. Implementao correta seguindo o princpio da substituio 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
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
16 de 32 25/08/2014 10:09
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 declarao do mtodo getDesconto(). Desta
forma podemos fazer a classe Funcionario implementar somente a interface IDesconto e ter
somente o mtodo que lhe interessa.
O princpio da segregao de interfaces nos diz que muitas interfaces especficas so
melhores que uma interface de uso geral, ou seja, nenhuma classe cliente deve ser
dependente de mtodos que no usam.
Este princpio nos indica que devemos dividir interfaces grandes em interfaces menores para
que os clientes tenham conhecimento somente de mtodos que lhes interessam e que no
sejam obrigados a depender de mtodos que no usam.
Obedecendo este princpio o software ser mais fcil de ser expandido, alterado e
distribudo. A dica que sempre que precisamos de novos mtodos em uma interface, o
ideal seria no adicionar estes mtodos novos a esta interface, e sim criar uma nova
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
17 de 32 25/08/2014 10:09
Em resumo este princpio nos diz que nossos mdulos devem ser enxutos, devem ter poucos
comportamentos. Interfaces que possuem muitos comportamentos geralmente o seu uso se
espalha por todo o sistema dificultando a manuteno.
O primeiro exemplo que bastante simples e que todo e qualquer desenvolvedor
implementa nos sistemas, a gerao de arquivos. Invariavelmente precisamos gerar
arquivos Texto para controles fiscais, como o Sintegra, arquivos PDF de Notas Fiscais
Eletrnicas para o envio aos clientes, alm de outros tipos de arquivos.
O que ocorre com bastante frequncia neste cenrio a criao de uma classe Arquivo com
algumas propriedades bsicas que todo arquivo possui com o nome e classes filhas que
herdam estas propriedades bsicas e possuem mtodos de gerao destes arquivos.
Podemos ainda ter uma classe chamada GeradorArquivos() que ir chamar os mtodos de
gerao das classes, conforme a Listagem 11.
Listagem 11. Classes de Arquivos e Gerao 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 // Lgica de gerao do arquivo txt
18 }
19 }
20
21 public class ArquivoPdf : Arquivo
22 {
23 public void GerarArquivoPdf()
24 {
25 // Lgica de gerao do arquivo pdf
26 }
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
18 de 32 25/08/2014 10:09
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 mtodos de gerao no
deveriam ser especficos de cada classe. Voc deve pensar neste momento, mas as formas
de gerao de arquivos Texto e PDF so completamente diferentes. Est correto, elas so
mesmo completamente diferentes, mas sua implementao que diferente, a interface de
gerao a mesma, isso que importa no momento da definio.
Uma das principais regras da orientao a objetos que devemos programar sempre
voltados a interface, no para a implementao. muito mais importante definir o que uma
classe vai fazer do como ela ir fazer.
Com esta abordagem, no momento que tivermos a gerao de um novo tipo de arquivo pelo
sistema, teremos que adicionar mais um else if, o que j vimos no ser uma boa prtica de
orientao a objetos.
Assim podemos afirmar que as classes ArquivoTxt e ArquivoPdf no esto em conformidade
com o princpio de Substituio de Liskov, uma vez que no podemos substitu-la pela
classe Arquivo na classe GeracaoArquivo, porque os mtodos de gerao so especficos de
cada classe derivada.
Sendo assim somos obrigados a verificar o tipo e fazer downcast para fazer a chamada do
mtodo apropriado.
Na Listagem 12 temos a definio correta das classes Arquivo, ArquivoTxt e ArquivoPdf,
seguindo perfeitamente o princpio de substituio de Liskov. Veja que no ser mais
necessrio o uso do downcast para fazer a gerao na classe GeradorArquivo, no mtodo
GerarArquivo().
Listagem 12. Modelagem correta das classes seguindo o princpio de LSP
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
19 de 32 25/08/2014 10:09
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 // cdigo para gerao do arquivo Txt
20 }
21 }
22
23 public class ArquivoTxt : Arquivo
24 {
25 public override void Gerar()
26 {
27 // cdigo para gerao 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 princpio 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
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
20 de 32 25/08/2014 10:09
A primeira opo, por se tratar de uma consulta e envolver banco de dados, que
adicionemos mais um mtodo na interface IDatabase, conforme a Listagem 13.
Listagem 13. Violao do princpio de segregao de interfaces

01 namespace ISP
02 {
03 interface IDatabase
04 {
05 void Adicionar(); // Outros alunos utilizam apenas este mtodo
06 void Extrato(); // Mtodo 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) sero obrigadas a implementar o mtodo Extrato()
mesmo que elas no tenham interesse em sua utilizao.
Neste caso a melhor soluo seria a criao de outra interface ao invs de alterar a interface
atual. Assim podemos manter a interface IDatabase como est e consequentemente todas
as outras classes de Alunos sem nenhuma modificao e adicionar a interface
IDatabaseConsulta no sistema. Desta forma a interface IDatabaseConsulta obtm o mtodo
Adicionar e cria o novo mtodo Extrato() para quem desejar implement-lo.
Para finalizar podemos utilizar ambas as interfaces em nossas aplicaes clientes, como na
classe Program. Observe como fica o cdigo na Listagem 14.
Listagem 14. Utilizao do Princpio de Segregao 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 // Implementao da lgica de incluso do aluno no banco
12 }
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
21 de 32 25/08/2014 10:09
15 // Implementao da lgica de impresso 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
mtodos bsicos de todas as contas bancrias, conforme a Listagem 15.
Listagem 15. Classes ignorando o princpio de Segregao 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; // No rende juros em conta corrente
19 }
20 public double CalculaTributos()
21 {
22 // Clculo da tributao da conta corrente
23 }
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
22 de 32 25/08/2014 10:09
26 public class ContaPoupanca : IConta
27 {
28 public void Sacar()
29 {
30 // Saque
31 }
32 public double CalculaJuros()
33 {
34 // Clculo de juros para a conta poupana
35 }
36 public double CalculaTributos()
37 {
38 return 0; // No existe tributos para conta poupana
39 }
40 }
41 }
Ambas as classes concretas devem implementar os mtodos existentes na interface IConta.
Tanto a conta corrente quanto a conta poupana tero a opo de saque, porm somente a
conta corrente cobra tributos do cliente para a conta, e somente a conta poupana rende
juros mensais aos clientes pelo valor contigo na conta.
Neste caso temos uma interface poluda, pois no so todas as classes que devem
implementar seus mtodos, algumas quem implementar apenas parte desses mtodos. Esse
o indcio que devemos segregar esta classe em duas.
Na Listagem 16 temos o modelo seguindo o princpio de segregao de interfaces.
Listagem 16. Modelo seguindo o princpio de segregao 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 mtodo sacar
13 // que padro para todos os tipos de conta
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
23 de 32 25/08/2014 10:09
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 clculo de tributos
32 }
33 }
34
35 public class ContaPoupanca : Conta, IContaPoupanca
36 {
37 public double CalculaJuros()
38 {
39 // Implementa o clculo de juros
40 }
41 }
42 }
Veja a sequncia de passos que resolveram o problema em questo:
Criada a interface IConta que possui apenas o mtodo Sacar() que o mesmo para todos
os tipos de contas;
Criada a classe abstrata Conta que implementa a interface IConta e o mtodo Sacar() que
ser herdado pelas classes derivadas;
Criadas duas interfaces IContaCorrente e IContaPoupanca, cada uma com a declarao de
seu mtodo necessrio;
Criada a classe ContaCorrente que herda da classe Conta e implementa a interface
IContaCorrente e o mtodo CalculaTributos();
Criada a classe ContaPoupanca que tambm herda da classe Conta que possui o mtodo
sacar e implementa a interface IContaPoupanca e o mtodo CalculaJuros();
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
24 de 32 25/08/2014 10:09
possui nada que no vai utilizar, tornando-as coesas.
Este princpio a base para qualquer bom design de software orientado a objetos
O princpio da Inverso de Dependncia nos diz que mdulos de alto nvel no devem ser
dependentes de mdulos de baixo nvel, ambos devem depender de abstraes. Abstraes
no devem depender de detalhes, detalhes devem depender de abstraes.
Inverter a dependncia faz com que o cliente no fique frgil a mudanas relacionadas a
detalhes de implementao, isto , mudar um detalhe da implementao no faz com que
seja necessrio alteraes no cliente.
Este princpio bastante presente em muitos padres de projeto, pois a maioria deles
definem uma interface, para que no haja dependncias de implementaes. Um exemplo
de aplicao deste princpio o padro Bridge, que define interfaces para favorecer um
baixo acoplamento no design do cdigo. Outro padro relacionado o Adapter (BOX 5).
BOX 5. Padro de Projeto Adapter e Bridge
O padro de projeto Adapter, tambm conhecido como Wrapper, um padro que tem
o objetivo de adaptar a interface de uma classe, fazendo com que classes com
interfaces incompatveis possam interagir.
O padro de projeto Bridge utilizado quando se deseja que uma interface possa variar,
independentemente de suas implementaes. Ou seja, tanto a interface quanto as
implementaes podem variar separadamente. O padro Bridge oferece um nvel de
abstrao maior que o padro Adapter.
Outro padro que geralmente anda junto com o princpio de inverso de dependncia a
Injeo de Dependncias. Na verdade a injeo de dependncias uma forma de conseguir
a inverso de controle.
Nesta soluo as dependncias entre os mdulos no so definidas programaticamente, mas
sim pela configurao de uma infraestrutura de software (container - BOX 6) que
responsvel por injetar em cada classe suas dependncias declaradas.
O padro de Injeo de dependncias sugere que as dependncias de uma classe, como por
exemplo, uma conexo com banco de dados sejam injetados na classe.
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
25 de 32 25/08/2014 10:09
vida das suas dependncias (no exemplo da conexo, a classe no precisa abrir ou fechar
conexo, apenas receber uma referncia desta conexo e a utiliza).
BOX 6. Container
Container um objeto que possui outros objetos que podem ser includos e excludos
dinamicamente, em tempo de execuo.
Existem basicamente algumas maneiras de fazer a injeo de dependncias numa classe:
Construtor: as dependncias da classes so injetadas no prprio construtor da classe;
Propriedade: as dependncias so injetadas via Setter nas propriedades;
Interface: o objeto a ser injetado uma abstrao da classe concreta (na forma de
interface ou classe abstrata).
Framework: existem alguns frameworks que nos ajudam a injetar a dependncia,
utilizando XML ou anotaes em classes. Alguns exemplos so o Spring.net e o UNITY;
Em resumo, este princpio nos indica que devemos depender sempre de abstraes, pois
elas mudam com bem menos frequncia, o que facilita a mudana de comportamento e a
evoluo do cdigo.
Iniciaremos com o exemplo da classe Aluno que utilizava a classe ArquivoLog para gravar
possveis erros durante a persistncia, veja novamente na Listagem 17.
Listagem 17. Classe que atende o princpio de SRP mas agora fere o princpio 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();
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
26 de 32 25/08/2014 10:09
{
try
{
// Database save
}
catch (Exception ex)
{
log.Gravar(ex.ToString());
}
}
}
}
O princpio de inverso de dependncia nos indica que no a classe Aluno que deve criar o
objeto ArquivoLog e sim ser injetada esta dependncia 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 no sejam a gravao em
arquivo, como envio por e-mail, mensagem na tela, etc. Veja na Listagem 18.
Listagem 18. Aplicando o princpio de Inverso 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
{
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
27 de 32 25/08/2014 10:09
catch (Exception ex)
{
_Log.Gravar(ex.ToString());
}
}
}
}
Agora nossa classe Aluno precisa receber uma referncia para Log em seu construtor. Isso
nos d liberdade para criar extenses da classe Log e basta modificar a referncia 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 princpio.
Se conseguirmos seguir todos estes princpios apresentados neste artigo, teremos um
cdigo limpo, de fcil manuteno e muito mais propcio a evoluo.
Mudanas no sistema sero de fcil acesso e suas correes sero em lugares bem
especficos, e problemas no sero propagados para o restante do sistema.
O problema que no fcil escrever um cdigo slido e que siga tais tcnicas, isto vai se
conseguindo com experincia no desenvolvimento de software e estudo.
O interessante termos sempre classes pequenas com mtodos 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
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
28 de 32 25/08/2014 10:09
O que voc achou deste post?
Gostei (3) (0)
Comentrio | Tire sua dvida
Luciano Paranhos MVP
Na Listagem 12 A classe ArquivoTxt esta sendo dupli cada, uma del as seria ArquivoPdf certo?
[h 6 dias] - Responder

[autor] Fi lipe Dalepiane
Exatamente, ambas herdando da classe abstrata Arquivo.
[h 6 dias] - Responder

Luci ano Paranhos MVP
Legal! A propsito, excel ente materi al.
[h 6 dias] - Responder

Publicidade
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
29 de 32 25/08/2014 10:09
Servios
Inclua um comentrio
Adicionar aos Favoritos
Marcar como lido/assistido
Incluir anotao pessoal
Verso para impresso
+.net
Artigo
Novidades do ASP.NET vNext e do Visual Studio
Video aula
Lendo arquivos XML com DataSets - Curso de Introduo ao .NET
Framework - 39
Video aula
Cadastros com DataSets e DataTables - Curso de Introduo ao
.NET Framework - 38
Video aula
Criando um formulrio de cadastro - Curso de Introduo ao .NET
Framework - 37
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
30 de 32 25/08/2014 10:09
Managed Providers e Content Components - Curso de Introduo
ao .NET Framework - 36
Video aula
Acesso a Dados no .NET - Curso de Introduo ao .NET
Framework - 35
Video aula
Denindo a arquitetura de Acesso a Dados - Curso bsico de ASP
.NET - 49
Video aula
Inserindo dados - Curso bsico de ASP .NET - 48
Video aula
Criando a View - Curso bsico de ASP .NET - 47
Video aula
Criando o Banco de Dados - Curso bsico de ASP .NET - 46
Listar mais contedo
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
31 de 32 25/08/2014 10:09
CONTEDO

REVISTAS

CURSOS

DEVWARE

MVP
SOLID: Padres flexveis para suas classes C# http://www.devmedia.com.br/solid-padroes-flexiveis-para-suas-classe...
32 de 32 25/08/2014 10:09

Vous aimerez peut-être aussi