Spoiler: vai ter um pouco de teoria
Aguentem, por favor <3
Slide 14
Slide 14 text
Barbara Liskov
Institute Professor from MIT
The 2008 Turing Award winner
liskov at csail.mit.edu
Slide 15
Slide 15 text
Liskov Substitution Principle (1987)
Let φ(x) be a property provable about objects x
of type T. Then φ(y) should be true for objects y
of type S where S is a subtype of T.
Slide 16
Slide 16 text
Eita!
Slide 17
Slide 17 text
Liskov Substitution Principle (1987)
Let φ(x) be a property provable about objects x
of type T. Then φ(y) should be true for objects y
of type S where S is a subtype of T.
Slide 18
Slide 18 text
Liskov Substitution Principle (1987)
Teoria dos Tipos (Type Theory)
Slide 19
Slide 19 text
Teoria dos Tipos
Como representar caracteres, números inteiros e de ponto
flutuante, booleanos no nível do processador?
Abstrações! E não pensar em bits e bytes!
E cada tipo tem suas restrições/comportamentos
Slide 20
Slide 20 text
Tipos Abstratos de Dados
Conjunto de comportamentos/operações
Estrutura de dados específica (atributos)
Como representar elementos do domínio de negócio
Slide 21
Slide 21 text
Tipos Abstratos de Dados
Conjunto de comportamentos/operações
Estrutura de dados específica (atributos)
Como representar elementos do domínio de negócio
CLASSES
Slide 22
Slide 22 text
Liskov Substitution Principle (1987)
Let φ(x) be a property provable about objects x
of type T.
CLASSE
Slide 23
Slide 23 text
Liskov Substitution Principle (1987)
Let φ(x) be a property provable about objects x
of type T.
COMPORTAMENTO
Slide 24
Slide 24 text
Liskov Substitution Principle (1987)
Let φ(x) be a property provable about objects x
of type T. Then φ(y) should be true for objects y
of type S where S is a subtype of T.
"SUBCLASSES"
Slide 25
Slide 25 text
Liskov Substitution Principle (1987)
Classes vs Subclasses
Interfaces vs Implementações
Slide 26
Slide 26 text
Liskov Substitution Principle (1987)
Traduzindo:
Preciso garantir que se eu substituir um objeto de uma classe por um
outro objeto de uma subclasse dessa classe, as propriedades que
definem o objeto-pai precisam continuar funcionando.
Slide 27
Slide 27 text
1987
Slide 28
Slide 28 text
Herança: herança de comportamentos de
uma super classe
Polimorfismo: definição de uma interface única para
acessar tipos diferentes de objetos
Slide 29
Slide 29 text
ALERTA!
Cuidado com interpretações equivocadas sobre LSP:
Se uma subclasse altera o comportamento da superclasse,
nem sempre é uma violação desse princípio
Podemos e devemos usar o polimorfismo
(mas com sabedoria)
Slide 30
Slide 30 text
Design by contract
respeitar os contratos definidos pelo super tipo
Slide 31
Slide 31 text
Design by contract
respeitar os contratos definidos pela classe base
Slide 32
Slide 32 text
Pré-condições: dados de entrada
classes derivadas só podem ser mais permissivas
Pós-condições: dados de saída
classes derivadas só podem ser mais restritivas
Não podemos criar comportamentos inesperados ou incorretos!
O comportamento da super classe precisa ser mantido
Slide 33
Slide 33 text
class CheckingAccount
# ...
def deposit(value)
raise InvalidValueError if value <= 0
self.balance = self.balance + value
end
def compute_bonus
self.balance = self.balance * 1.01
end
end
Slide 34
Slide 34 text
class PayrollAccount < CheckingAccount
class OperationNotAllowed < StandardError; end
# ...
def compute_bonus
raise OperationNotAllowed
end
end
Slide 35
Slide 35 text
CheckingAccount.all.each do |account|
account.compute_bonus
end
Slide 36
Slide 36 text
CheckingAccount.all.each do |account|
begin
account.compute_bonus
rescue PayrollAccount::OperationNotAllowed
false
end
end
Slide 37
Slide 37 text
CheckingAccount.all.each do |account|
begin
account.compute_bonus
rescue PayrollAccount::OperationNotAllowed
false
end
end contrato quebrado
Slide 38
Slide 38 text
class PayrollAccount < CheckingAccount
# ...
def deposit(value)
raise InvalidValueError if value <= 100
self.balance = self.balance + value
end
def compute_bonus
self.balance = self.balance * 1.01
end
end
Slide 39
Slide 39 text
class PayrollAccount < CheckingAccount
# ...
def deposit(value)
raise InvalidValueError if value <= 100
self.balance = self.balance + value
end
def compute_bonus
self.balance = self.balance * 1.01
end
end
contrato quebrado
Slide 40
Slide 40 text
Deveriam ser classes diferentes
Slide 41
Slide 41 text
Exemplo clássico:
Retângulo x Quadrado
Slide 42
Slide 42 text
class Rectangle
attr_reader :width, :height
def initialize(width, height)
@width = width
@height = height
end
def area
width * height
end
end
Slide 43
Slide 43 text
class Square < Rectangle
attr_reader :width, :height
def initialize(width)
@width = width
@height = width
end
end
contrato quebrado
Slide 44
Slide 44 text
O que a gente precisa lembrar sobre esse princípio?
Interfaces/Abstração de comportamentos
Polimorfismo
Design by contract
Nem tudo que parece herança deveria ser uma herança