aula 04 - princípios de projeto
DESCRIPTION
Princípios de ProjetoTRANSCRIPT
Princípios de Projeto Aula 04
Prof. Kleinner Farias Programa Interdisciplinar de Pós-Graduação
em Computação Aplicada – PIPCA Universidade do Vale do Rio dos Sinos
4
3/26/14 @KleinnerFarias 1
Agenda
• Sintomas de degradação arquitetural • Princípios de projeto • Exemplos de aplicação dos princípios
2
Sintomas de Degradação Arquitetural
• Rigidez • Fragilidade • Imobilidade • Viscosidade
3
Sintomas de Rigidez
Rigidez
Rigidity is the tendency for soMware to be difficult to change, even in simple
ways. (Robert MarUn)
4
Sintomas de Rigidez
• Mudanças nos requisitos causam uma cascata de subsequentes mudanças entre módulos dependentes do sistema
Efeito Dominó Efeito na Equipe 5
Sintomas de Rigidez
• Tudo começa com um dia de trabalho que se transforma em 2, 3, n....semanas de mudanças tentando encontrar por onde começar
• Consequência: – Alto risco de realizar mudanças – Medo de resolver problemas críUcos – Gestor sente receio de autorizar modificações – Imprevisibilidade do fim da aUvidade de mudança
6
Sintomas de Fragilidade
Fragilidade
Fragility is the tendency of the soMware to break in many places every Ume it is changed. (Robert MarUn)
7
Sintomas de Fragilidade
• Mudança em um “Módulo A” do sistema provoca mudanças indesejadas em um “Módulo B” sem qualquer relação conceitual
• Quanto mais resolvo problema, mais problemas surgem
• Consequências: – As mudanças são imprevisíveis, não é possível mensurar o impacto/consequência de mudanças
– Torna-‐se dihcil esUmar os custos e as entregas 8
Sintomas de Imobilidade
Imobilidade
Immobility is the inability to reuse soMware from other projects or from parts of the same project. (Robert MarUn)
9
Sintomas de Imobilidade
• Um módulo que foi projetado para ser reusado torna-‐se altamente acoplado
• Framework criado na empresa que deixa de ser framework devido ao alto grau de dependência
• Consequências: – Baixo grau de reuso de soMware – Menor produUvidade do Ume de desenvolvimento – Maior custo de desenvolvimento
10
Sintomas de Viscosidade
Viscosidade When faced with a change, engineers usually find more than one way to make the change. Some of the ways
preserve the design, others do not. (Robert MarUn)
11
Sintomas de Viscosidade
• É mais fácil usar arUhcios de programação (vulgo gambiarra) que implementar da forma correta – Quando verificamos isso?
• Fazendo engenharia reversa • Analisando o código
• Consequências: – Arquitetura em desacordo com o código – Refactoring....
12
O que provoca a degradação arquitetural?
13
Causas de Degradação
• Mudanças não antecipadas: – Os requisitos mudam de tal forma que a arquitetura inicial não suporta as modificações
– Desenvolvedores novos em um Ume não estão familiarizados com a cultura da empresa/padrão de trabalho
– Documento de requisitos é um dos artefatos mais voláteis dentro do processo de desenvolvimento
14
Causas de Degradação
• Gerência de Dependência – Os sintomas de degradação estão diretamente ligados ao gerenciamento de dependência entre os módulos
– Arquiteto tem dificuldade de visualizar e preservar a arquitetura, dada a dificuldade de controlar as mudanças
15
Aplicando princípios de projetos e padrões de projetos para minimizar o impacto das mudanças e gerenciar as dependências
16
Princípios de Projetos OO
• OCP: The Open Closed Principle • OCP: The Open Closed Principle • SRP: The Single Responsibility Principle • DIP: The Dependency Inversion Principle • LSP: The Liskov SubsUtuUon Principle • SDP: The Stable Dependencies Principle • SAP: The Stable AbstracUons Principle
17
Princípios de Projetos OO
• CRP: The Common Reuse Principle • CCP: The Common Closure Principle • CRP: The Common Reuse Principle • ADP: The Acyclic Dependencies Principle • GRASP: General Responsibility Assignment SoMware Paserns
18
OCP: The Open Closed Principle
A module should be open for extension but closed for modifica6on. (Bertrand Meyer)
19
OCP: The Open Closed Principle
Devemos escrever módulos visando que os mesmos sejam estendidos sem ter a necessidade de serem modificados.
20
Exemplo
Somar dois números
Subtrair dois números
Casos de Uso
Obje7vo: implementar uma calculadora
Desafio: implementar algo que seja flexível o bastante para suportar evoluções 21
Exemplo
Soma
+ somar(a,b): double
Subtracao
+ subtrair(a,b): double
Calculadora
+ executarOperacao(Upo: String, a: double, b: double): double
Resultado: possível diagrama de classe
22
Exemplo
Resultado: possível implementação da classe Calculadora
23
Exemplo
Resultado: possível implementação da classe Soma e Subtração
24
Exemplo
Somar dois números
Subtrair dois números
Casos de Uso
Evolução: implementar divisão e mulUplicação
Dividir dois números
MulUplicar dois números
25
Qual é o
da evolução? 26
Exemplo
Soma
+ somar(a,b): double
Subtracao
+ subtrair(a,b): double
Calculadora
+ executarOperacao(Upo: String, a: double, b: double): double
ANTES: possível diagrama de classe
27
Exemplo
Soma
+ somar(a,b): double
Subtracao
+ subtrair(a,b): double
Calculadora
+ executarOperacao(Upo: String, a: double, b: double): double
Resultado da Evolução: possível diagrama de classe
Divisao
+ dividir(a,b): double
MulUplicacao
+ mulUplicar(a,b): double 28
Exemplo
Resultado Anterior: implementação da classe Calculadora
Mudar Aqui
Mudar Aqui
29
Exemplo
Resultado Depois: possível implementação da classe Calculadora
30
Exemplo
IOperacao
+ executar(a: double, b: double): double
Soma
+ executar(...): double
Subtracao
+ executar(...): double
interface
realização
CalculadoraOCP
+ executarOp(...): double
Com Open-‐Closed: possível diagrama de classe
31
Exemplo
Resultado: possível implementação da classe CalculadoraOCP
32
Exemplo
Resultado: possível implementação da interface, Soma e Subtração
O que mudou?
33
Exemplo
IOperacao
+ executar(a: double, b: double): double
Soma
+ executar(...): double
Subtracao
+ executar(...): double
MulUplicacao
+ executar(...): double
Divisao
+ executar(...): double
interface
realização
CalculadoraOCP
+ executarOp(...): double
Com Open-‐Closed: possível diagrama de classe
34
Exemplo
Resultado: possível implementação da interface, Soma e Subtracao
O que mudou?
35
OCP: The Open Closed Principle
Em resumo: objeUvo arquitetural do Open-‐Closed
Criar módulos que sejam extensíveis,
porém sem ser modificados
36
SRP: The Single Responsibility Principle
• SRP: there should never be more than one reason for a class to change [MarUn2002]
• Inicialmente proposto como Coesão por – Tom DeMarco [DeMarco79] e – Meilir Page-‐Jones [PageJones88]
• Cada responsabilidade é um eixo de mudança
3/26/14 @KleinnerFarias 37
SRP: The Single Responsibility Principle • Se uma classe assume mais de uma responsabilidade, então existe mais de uma razão para modificá-‐la
• Se uma classe tem mais de uma responsabilidade, então as responsabilidade se tornam acopladas
• Consequência: – Fragile Design: o projeto quebra de forma inesperada quando modificado
3/26/14 @KleinnerFarias 38
SRP: The Single Responsibility Principle
• Exemplo [MarUn2002]: + draw() [desenha o retângulo na tela] + area() [calcula a área do retângulo]
3/26/14 @KleinnerFarias 39
SRP: The Single Responsibility Principle
• Observações: – Duas aplicações diferentes usam Rectangle – Computa6onal Geometry Applica6on
• Usa a classe Rectangle para calcular a área: + area() • Nunca desenha retângulo na tela: + draw()
– Graphical Applica6on • Pode calcular área: + area() • Desenha retângulo na tela: + draw()
3/26/14 @KleinnerFarias 40
SRP: The Single Responsibility Principle • Classe Rectangle viola o SRP:
– Tem duas responsabilidades • Calcula a área do retângulo: + area() • Desenha o retângulo na tela: + draw()
3/26/14 @KleinnerFarias 41
SRP: The Single Responsibility Principle • Consequências:
– “Acoplamento transi6vo” • Computa6onal Geometry Applica6on (CGA) depende de Rectangle que depende de GUI. Logo, CGA depende de Rectangle que depende de GUI
3/26/14 @KleinnerFarias 42
SRP: The Single Responsibility Principle • Consequências:
– Propagação de mudança • Se Rectangle mudar por causa de GraphicalApplica6on, esta mudança pode levar modificações em CGA
• Se não gerenciarmos este Upo de acoplamento, a aplicação pode sofrer propagações imprevisíveis
3/26/14 @KleinnerFarias 43
SRP: The Single Responsibility Principle • Recomendação: separar as responsabilidades
3/26/14 @KleinnerFarias 44
SRP: The Single Responsibility Principle • Consequências:
– Acoplamento transiUvo eliminado – Isolamento da classe Computa6onalGeometryApplica6on em relação à forma de desenhar o retângulo
– A classe CGA não depende mais indiretamente de GraphicalApplica6on
– Mudanças na forma como o retângulo é desenhado não afetará CGA
3/26/14 @KleinnerFarias 45
SRP: The Single Responsibility Principle
Afinal, o que seria responsabilidade?
3/26/14 @KleinnerFarias 46
SRP: The Single Responsibility Principle
• Responsabilidade: “a reason for change” • Se idenUficamos mais de um moUvo para mudar um classe, então ele terá mais de uma responsabilidade
• Modem tem quantas responsabilidades?
3/26/14 @KleinnerFarias 47
SRP: The Single Responsibility Principle
• Duas responsabilidades: ① Gerenciamento de conexão: dial e hangup ② Comunicação de dados: send e recv
3/26/14 @KleinnerFarias 48
SRP: The Single Responsibility Principle
• Duas responsabilidades: ① Gerenciamento de conexão: dial e hangup ② Comunicação de dados: send e recv
• Observações: – As responsabilidades têm quase nada em comum – Mudam por diferentes razões – Serão chamadas por diferentes partes da aplicação, as quais mudarão por diferentes razões também
3/26/14 @KleinnerFarias 49
SRP: The Single Responsibility Principle • Um responsabilidade por interface:
① Gerenciamento de conexão: dial e hangup ② Comunicação de dados: send e recv
3/26/14 @KleinnerFarias 50
DIP: The Dependency Inversion Principle
• DIP1: módulos de mais alto nível não devem depender de módulos de mais baixo nível. Ambos devem depender de abstrações
• DIP2: abstrações não devem depender de detalhes.
• Principal princípio uUlizado para projetar frameworks
3/26/14 @KleinnerFarias 51
DIP: The Dependency Inversion Principle
• Módulos de mais alto nível: – aqueles que implementam regras de negócio – suas caracterísUcas idenUficam a aplicação – devem ser desacoplados de módulos de mais baixo nível
• Módulos de mais baixo nível: – responsáveis por detalhes de implementação
3/26/14 @KleinnerFarias 52
DIP: The Dependency Inversion Principle
• Segundo Booch: “toda arquitetura bem estruturada deve ter
uma definição clara de suas camadas, com cada camada fornecendo uma conjunto coerente de serviços através de uma interface bem definida
e controlada.” [MarUn2002]
3/26/14 @KleinnerFarias 53
DIP: The Dependency Inversion Principle
• Exemplo:
3/26/14 @KleinnerFarias 54
DIP: The Dependency Inversion Principle • Exemplo:
3/26/14 @KleinnerFarias 55
Qual seria o problema com esta arquitetura?
DIP: The Dependency Inversion Principle • Problema: dependência transiUva
3/26/14 @KleinnerFarias 56
DIP: The Dependency Inversion Principle • Solução: cada camada superior define uma interface com os serviços que ela necessita
3/26/14 @KleinnerFarias 57
DIP: The Dependency Inversion Principle • Observações:
– Camada superior: • Interage com a camada inferior considerando os serviços declarados nas suas interfaces
• Fica totalmente desacoplada das camadas inferiores
– Camada inferior: • É definida considerando os serviços definidos na(s) interface(s) da camada superior
• A camada inferior depende das interfaces (das abstrações)
3/26/14 @KleinnerFarias 58
DIP: The Dependency Inversion Principle • Exemplo:
3/26/14 @KleinnerFarias 59
DIP: The Dependency Inversion Principle • Exemplo:
3/26/14 @KleinnerFarias 60
DIP: The Dependency Inversion Principle • Exemplo:
– Bu#on depende diretamente da Lamp – Observações:
• Sempre que Lamp mudar Bu#on também mudará • Não será possível reusar Bu#on sem reusar Lamp • Não será possível reusar Bu#on para controlar um Motor
• Ou seja, Bu#on apenas controla Lamp
3/26/14 @KleinnerFarias 61
DIP: The Dependency Inversion Principle • Exemplo:
– Bu#on depende diretamente da Lamp
3/26/14 @KleinnerFarias 62
DIP: The Dependency Inversion Principle • Exemplo:
3/26/14 @KleinnerFarias 63
Button depende diretamente da Lamp
Button não depende diretamente da Lamp
Importante: DIP pode ser aplicado sempre que uma classe enviar uma mensagem para outra.
LSP: The Liskov SubsUtuUon Principle
Subclasses should be subs6tutable for their base classes. (Barbar Liskov)
Design by contract (Bertrand Meyer)
64
if S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program (e.g., correctness). (Barbara Liskov)
65
LSP: The Liskov SubsUtuUon Principle
• Em outras palavras…
O “User” deve ser capaz de usar qualquer subclasse de “Base” Por que?
“User” usa a classe “Base” porque ela especifica um contrato muito bem definido Respeita o contrato
definido por “Base”
Define o contrato
66
LSP: The Liskov SubsUtuUon Principle
LSP no Exemplo da Calculadora
IOperacao
+ executar(a: double, b: double): double
Soma
+ executar(...): double
Subtracao
+ executar(...): double
MulUplicacao
+ executar(...): double
Divisao
+ executar(...): double
interface
realização
CalculadoraOCP
+ executarOp(...): double
67
LSP no Exemplo da Calculadora
IOperacao
+ executar(a: double, b: double): double
Soma
+ executar(...): double
Subtracao
+ executar(...): double
MulUplicacao
+ executar(...): double
Divisao
+ executar(...): double
interface
realização
CalculadoraOCP
+ executarOp(...): double
Com Open-‐Closed: possível diagrama de classe User Base
Derived
68
LSP no Exemplo da Calculadora
IOperacao
+ executar(a: double, b: double): double
Soma
+ executar(...): double
Subtracao
+ executar(...): double
MulUplicacao
+ executar(...): double
Divisao
+ executar(...): double
realização
CalculadoraOCP
+ executarOp(...): double
CalculadoraOCP usa a IOperacao porque ela é “muito bem definida” no que se compromete a fazer
69
LSP no Exemplo da Calculadora
IOperacao
+ executar(a: double, b: double): double
Soma
+ executar(...): double
Subtracao
+ executar(...): double
MulUplicacao
+ executar(...): double
Divisao
+ executar(...): double
realização
CalculadoraOCP
+ executarOp(...): double
CalculadoraOCP usa a IOperacao porque espera que as subclasses respeitem o contrato
70
IOperacao
+ executar(a: double, b: double): double
Soma
+ executar(...): double
Subtracao
+ executar(...): double
MulUplicacao
+ executar(...): double
Divisao
+ executar(...): double
realização
CalculadoraOCP
+ executarOp(...): double
Mudança de requisitos, e agora? Para qual 7po de mudanças estamos preparados? ! Adição de novas operações à calculadora
Exponencial
+ executar(...): double 71
Onde as mudanças não podem ocorrer?
Qual é o impacto?
72
Mudanças em classes abstratas e interfaces com alto grau de acoplamento aferente
73
IOperacao
+ executar(a: double, b: double): double
Soma
+ executar(...): double
Subtracao
+ executar(...): double
MulUplicacao
+ executar(...): double
Divisao
+ executar(...): double
realização
CalculadoraOCP
+ executarOp(...): double
Mudança de requisitos, e agora? Qual mudança causará o maior impacto/alteração? ! Mudanças em classes mais abstratas ! Classes abstratas e interfaces com alta dependência
impacto
74
Classd
+ opD(): String
ClassX
+ opx(...): double
Mudança de requisitos, e agora? Qual classe causará o maior impacto?
ClassC
+ opC(): String
ClassA
+ opA(): String
ClassB
+ opB(): String
ClassX
+ opx(...): double
75
Classd
+ opD(): String
ClassX
+ opx(...): double
Mudança de requisitos, e agora? Qual classe causará o maior impacto?
ClassC
+ opC(): String
ClassA
+ opA(): String
ClassB
+ opB(): String
ClassX
+ opx(...): double
76
SDP: The Stable Dependencies Principle
The dependencies between packages in a design should be in the direcUon of the stability of the packages.
A package should only depend upon packages
that are more stable that it is.
How can we measure the stability of a package? 77
Estabilidade • Ca: Afferent Couplings :
– The number of classes outside this package that depend upon classes within this package.
• Ce: Efferent Couplings – The number of classes inside this package that depend upon classes outside this package.
• I: Instability : (Ce/(Ca+Ce)) – This metric has the range [0,1]. – I=0 indicates a maximally stable package. – I=1 indicates a maximally instable package. 78
Estabilidade
79
Estabilidade
Acoplamento Aferente = 4
80
Estabilidade
Acoplamento Eferente = 3
0,42
81
Estabilidade
Qual é o pacote mais instável?
82
Estabilidade
• Nem todo pacote deve ser estável
83
Como estabilizar o projeto?
84
SAP: The Stable AbstracUons Principle
Packages that are maximally stable should be maximally abstract.
Instable packages should be concrete.
The abstrac6on of a package
should be in propor6on to its stability. 85
Estabilidade
86
Estabilidade packages that are maximally stable and abstract
The packages that are maximally instable and
concrete
87
Princípios de Projeto OO
• CCP: The Common Closure Principle
Classes that change together, belong together.
88
Classes that aren’t reused together should not be grouped together.
• CRP: The Common Reuse Principle
Princípios de Projeto OO
• ADP: The Acyclic Dependencies Principle
The dependencies between packages must not form cycles.
89
ADP: The Acyclic Dependencies Principle
90
....mas ciclo é ruim?
....por que é ruim? 91
ADP: The Acyclic Dependencies Principle
...exemplo de como resolver o ciclo?
92
ADP: The Acyclic Dependencies Principle
C1
C2
C3
C4 93
ADP: The Acyclic Dependencies Principle
C1
C2
C3
C4
Quebra da Arquitetura
94
ADP: The Acyclic Dependencies Principle
Princípios GRASP
“A ferramenta crucial de projeto para desenvolvimento de soMware é uma mente bem educada em princípios de projeto.” (Graig Larman)
95
Princípios GRASP
• GRASP: General Responsibility Assignment So_ware Pa`erns
• Padrões GRASP: – Criador – Especialista na Informação – Baixo acoplamento – Controlador – Alta coesão – Polimorfismo – Invenção Pura – Indireção – Variações Protegidas
96
Princípios GRASP
• Criador: – Responsável por criar objetos
• Problema: – Quem cria objetos da classe A?
• Solução: – atribuir a responsabilidade de criar uma instância da classe A se uma
das seguintes afirmaUvas for verdadeira: – B contem A, ou agrega A de forma composta
– B registra A – B usa A de maneira muito próxima – B contém os dados iniciais de A
97
Princípios GRASP
• Especialista na Informação – Trata-‐se de um dos princípios de atribuição de responsabilidades mais simples em projetos OO
– Toda responsabilidade depende de informação
• Problema: – Qual é o princípio básico para se atribuir responsabilidade às classes?
• Solução: – Atribuir responsabilidade à classe que tenha informação necessária para saUsfazê-‐la
98
Princípios GRASP
• Baixo acoplamento – Acoplamento: uma medida de quão fortemente um elemento está conectado a, tem conhecimento de, ou depende de outros elementos.
– Exemplo: uma objeto A que faz uso de operações de um objeto B tem acoplamento com os serviços de B.
• Problema: – Como reduzir o impacto de modificação?
• Solução: – Atribuir responsabilidade de tal formar que o acoplamento seja baixo
99
Princípios GRASP
• Controlador – Responsável por orquestrar as responsabilidades – Componente central no padrão MVC
• Problema: – Qual é o primeiro objeto que recebe e coordena uma operação?
• Solução: – Atribuir responsabilidade a uma classe que orquestra os comportamentos oferecidos
100
Princípios GRASP
• Alta Coesão – Classes com baixa número de responsabilidades
• Problema: – Como manter os objetos focados, inteligíveis e gerenciáveis e, como efeito colateral, apoie o baixo acoplamento?
• Solução: – Atribuir responsabilidades de tal forma que a coesão permaneça baixa
101
Princípios GRASP
• Polimorfismo – Como tratar alternaUvas com base no Upo? – Como criar componentes de soMware interconectáveis?
• Problema: – Como manter os objetos focados, inteligíveis e gerenciados e, como efeito colateral, apoiar baixo acoplamento?
• Solução: – Atribuir responsabilidades de tal forma que a coesão permaneça baixa
102
Princípios GRASP
• Invenção Pura – Como atribuir responsabilidade sem comprometer a alta coesão e o baixo acoplamento?
• Problema: – Como trabalhos com conceitos ausentes no domínio do problema?
– Como persisUr os dados de uma venda? • A classe Venda possui os dados, logo deve ter esta responsabilidade? (princípio do especialista)
– Vários conceitos sobre BD sem relação nenhuma com vendas. Logo, Venda se torna não-‐coesa. 103
Princípios GRASP
• Variações protegidas – Como projetar objetos, subsistemas e sistemas de modo que as mudanças nesses elementos não provoque mudanças indesejadas?
• Solução: – IdenUficar pontos com alta probabilidade de mudança
– Projetar orientado à interface
104
Princípios GRASP
• Indireção – Como atribuir responsabilidade de tal forma que evite o acoplamento entre dois objetos?
– Como desacoplar os objetos visando um baixo acoplamento e uma alta coesão?
• Solução: – Atribuir a responsabilidade de ser o mediador entre outros componentes ou serviços a um objeto intermediário
105
References
• [Bass2003] BASS, L., CLEMENTS, P., KAZMAN, R. So_ware architecture in prac6ce, Boston: Addison-‐Wesley Professional, 2a ediUon, 2003.
• [Buschmann2000] BUSCHMANN, F. Pa`ern-‐oriented so_ware architecture: a system of pa`erns, Chichester: John Wiley & Sons, 2000.
• [Shaw1996] SHAW, M., GARLAN, D. So_ware architecture: perspec6ves on an emerging discipline, Upper Saddle River: PrenUce-‐Hall, 1996.
106
References
• [DeMarco79] Tom DeMarco, Structured Analysis and System Specifica6on, Yourdon Press CompuUng Series, 1979.
• [PageJones88] Meilir Page-‐Jones, The Prac6cal Guide to Structured Systems Design, 2ª Ed., Yourdon Press CompuUng Series, 1988.
• [Mar7n2002] Robert C. MarUn, Agile So_ware Development, Principles, Pa`erns, and Prac6ces, Pearson EducaUon, 2002.
107