SlideShare uma empresa Scribd logo
1 de 108
Baixar para ler offline
design de aplicações
orientadas a objeto
uma visão rubista
olar
Elaine Naomi Watanabe
Desenvolvedora de Software (Plataformatec)
Mestre em Ciência da Computação (USP)
github.com/elainenaomi
twitter.com/elaine_nw
http://careers.plataformatec.com.br
quais são os conceitos básicos de orientação a objeto
como identificar problemas na nossa base de código
como melhorar o design do nosso código
o que vamos ver?
orientação a objeto
uma versão super resumida
Objeto abstração de uma parte do domínio/problema
estados/valores específicos para seus atributos
Classe template/gabarito para definição de objetos
um conjunto de atributos (características) e
métodos (comportamentos)
Herança herdar atributos/métodos comuns de uma
classe base (ou superclasse) e
adicionar novos atributos/métodos
Polimorfismo ter uma interface única de acesso para diferentes
classes/objetos
Composição combinar objetos simples de modo a ter
objetos mais complexos
objetos + mensagens = app
no mundo do Ruby...
$ gem install rails
$ gem install rails
+ Rails way
ViewModel
Controller
apresentação
intermediador
dados +
lógica de negócio
e se o projeto começa a crescer?
+ Funcionalidades
+ Funcionalidades
+ Modificações
+ Funcionalidades
+ Modificações
+ Bugs
Tamanho da base de código
Tempoparadeploy
como reconhecer os
sintomas?
Muitas regras de negócio nos controllers
Métodos muito longos
Classes muito grandes
Excesso de callbacks (controllers/models)
Dificuldade para escrever testes
Classes de difícil manutenção
Ctrl + F / ⌘ + F para qualquer alteração
Arquivos constantemente alterados
e agora, como faz?
DRY
don't repeat yourself
Helpers
Presenters
Single Table Inheritance
Polymorphic Association
Concerns (cuidado!)
Service Objects
Uso de Plain Old Ruby Object (PORO)
Casos de uso
Regras de negócio explícitas
class ReserveBookService
attr_reader :user, :book, :notification_service
def initialize(user, book, notification_service)
@user = user
@book = book
@notification_service = notification_service
end
def confirm!
user.books << book
notification_service.reservation_completed(user, book)
end
end
SOLID
Single Responsibility Principle
O que a minha classe faz?
Indicativo de problemas: usar "e" ou "ou" na explicação
Métodos relacionados?
Uma única razão para mudar?
Alterações com efeitos previsíveis?
class BooksUser < ApplicationRecord
belongs_to: :book
belongs_to: :user
after_commit :send_notification_reservation_completed
def send_notification_reservation_completed
NotificationService.reservation_completed(user, book)
end
end
class BooksUser < ApplicationRecord
belongs_to: :book
belongs_to: :user
after_commit :send_notification_reservation_completed
def send_notification_reservation_completed
NotificationService.reservation_completed(user, book)
end
end
Uma classe de persistência não deveria saber sobre
notificações a um usuário, por ex.
Que tal um Service Object para isso?
class ReserveBookService
attr_reader :user, :book, :notification_service
def initialize(user, book, notification_service)
@user = user
@book = book
@notification_service = notification_service
end
def confirm!
user.books << book
notification_service.reservation_completed(user, book)
end
end
Open/Closed Principle
Adicionar nova regra = modificar uma ou mais classes?
Se sim, é um indicativo de problema
Aberto para extensão, fechado para modificação
Defina interfaces/super classes
Reduza o acoplamento
class FinancialReport
def generate(account, file_format)
case file_format
when :csv
file = FormatCSV.generate_file(account.transactions)
when :xml
file = XML.parse_list(account.transactions)
end
Mailer.send(account.email, file)
end
end
class FinancialReport
def generate(account, file_format)
case file_format
when :csv
file = FormatCSV.generate_file(account.transactions)
when :xml
file = XML.parse_list(account.transactions)
when :pdf
file = PDFGenerator.create(account.transactions)
end
Mailer.send(account.email, file)
end
end edição
class FinancialReport
def generate(account, file_format)
case file_format
when :csv
file = FormatCSV.generate_file(account.transactions)
when :xml
file = XML.parse_list(account.transactions)
when :pdf
file = PDFGenerator.create(account.transactions)
end
Mailer.send(account.email, file)
end
end
class FinancialReport
def generate(account, file_creator)
file = file_creator.create(account.transactions)
Mailer.send(account.email, file)
end
end
class FileCreator
def create(items)
raise NotImplementedError
end
end
contrato
class FileCreatorXML < FileCreator
def create(items)
XML.parse(items)
end
end
class FileCreatorCSV < FileCreator
def create(items)
FormatCSV.generate_file(items)
end
end
class FileCreatorPDF < FileCreator
def create(items)
PDFGenerator.generate(items)
end
end
adição
class FinancialReport
def generate(account, file_creator)
file = file_creator.create(account.transactions)
Mailer.send(account.email, file)
end
end
FinancialReport.new.generate(account, FileCreatorPDF.new)
Liskov Substitution Principle
Design by contract
respeitar os contratos definidos pela classe base
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
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
class PayrollAccount < CheckingAccount
class OperationNotAllowed < StandardError; end
# ...
def compute_bonus
raise OperationNotAllowed
end
end
CheckingAccount.all.each do |account|
account.compute_bonus
end
CheckingAccount.all.each do |account|
begin
account.compute_bonus
rescue PayrollAccount::OperationNotAllowed
false
end
end
CheckingAccount.all.each do |account|
begin
account.compute_bonus
rescue PayrollAccount::OperationNotAllowed
false
end
end contrato quebrado
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
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
Deveriam ser classes diferentes
Interface Segregation Principle
Uma classe derivada não deveria ser obrigada
a implementar métodos que ela não usa
class CoffeeMachine
def brew_coffee
# brew coffee logic
end
def fill_coffee_beans
# fill coffee beans
end
end
class Person
attr_reader :coffee_machine
def initialize
@coffee_machine = CoffeeMachine.new
End
def quero_cafe
coffee_machine.brew_coffee
end
end
class Staff
attr_reader :coffee_machine
def initialize
@coffee_machine = CoffeeMachine.new
end
def fill_coffee_beans
coffee_machine.fill_coffee_beans
end
end
Várias interfaces específicas é melhor do
que uma interface generalizada
class CoffeeMachineUserInterface
def brew_coffee
# brew coffee logic
end
end
class CoffeeMachineServiceInterface
def fill_coffee_beans
# fill coffee beans
end
end
class CoffeeMachineUserInterface
def brew_coffee
# brew coffee logic
end
end
class CoffeeMachineServiceInterface
def fill_coffee_beans
# fill coffee beans
end
end
class Person
attr_reader :coffee_machine
def initialize
@coffee_machine = CoffeeMachineUserInterface.new
end
def quero_cafe
coffee_machine.brew_coffee
end
end
`
class Person
attr_reader :coffee_machine
def initialize
@coffee_machine = CoffeeMachineUserInterface.new
end
def quero_cafe
coffee_machine.brew_coffee
end
end
`
`
class Staff
attr_reader :coffee_machine
def initialize
@coffee_machine = CoffeeMachineServiceInterface.new
end
def fill_coffee_beans
coffee_machine.fill_coffee_beans
end
end
class Staff
attr_reader :coffee_machine
def initialize
@coffee_machine = CoffeeMachineServiceInterface.new
end
def fill_coffee_beans
coffee_machine.fill_coffee_beans
end
end
Dependency Inversion Principle
Dependa de abstrações,
não de implementações
class FinancialReport
def generate(account, file_creator)
file = file_creator.create(account.transactions)
Mailer.send(account.email, file)
end
end
class FileCreatorCSV < FileCreator
def create(items)
FormatCSV.generate_file(items)
end
End
FinancialReport.new.generate(account, FileCreatorCSV.new)
class FileCreatorCSV < FileCreator
def create(items)
FormatCSV.generate_file(items)
NewCSVGenerator.parse(items, header: false)
end
End
FinancialReport.new.generate(account, FileCreatorCSV.new)
Tell, don't ask
Não exponha a regra de negócio
Não deixe quem usa o objeto tomar decisões
por ele com base no seu estado
Confie no seu objeto!
Encapsule estados
Crie uma interface pública mínima
class Subscription
def charge(user)
if user.has_credit_card?
user.charge(total)
else
false
end
end
end
class Subscription
def charge(user)
if user.has_credit_card?
user.charge(total)
else
false
end
end
end
class User
def charge(total)
if has_credit_card?
payment_gateway.charge(credit_card, total)
true
else
false
end
end
end
class User
def charge(total)
if has_credit_card?
payment_gateway.charge(credit_card, total)
true
else
false
end
end
end
class Subscription
def charge(user)
user.charge(total)
end
end
TL;DR;
TL;DR:
Alta coesão
Baixo acoplamento
Encapsulamento
vamos refatorar tudo?
esses conceitos nos ajudam a criar
aplicações mais flexíveis
converse com seu time
analisem juntos os trade-offs
cuidado com big design up front
e não esqueçam:
codar é um processo de comunicação
Mais sobre design?
Padrões de projeto
TDD, DDD
minhas referências
Refactoring rails apps
Flavia Fortes
http://bit.ly/rubyconfbr-refactoring
https://speakerdeck.com/flaviafortes
RAILS GIRLS SP
17 e 18 de agosto
railsgirls.com/saopaulo
obrigada
speakerdeck.com/elainenaomi

Mais conteúdo relacionado

Semelhante a Design de aplicações orientadas a objeto

Programação Web com Zend Framework e Ajax com Dojo
Programação Web com Zend Framework e Ajax com DojoProgramação Web com Zend Framework e Ajax com Dojo
Programação Web com Zend Framework e Ajax com Dojofabioginzel
 
Padrão De Projeto Adapter
Padrão De Projeto AdapterPadrão De Projeto Adapter
Padrão De Projeto AdapterMatheus Andrade
 
Transição - Orientação a objeto para Funcional
Transição - Orientação a objeto para FuncionalTransição - Orientação a objeto para Funcional
Transição - Orientação a objeto para FuncionalIsmael Velten
 
Intro padroesprojetoadaptertemplateobserver
Intro padroesprojetoadaptertemplateobserverIntro padroesprojetoadaptertemplateobserver
Intro padroesprojetoadaptertemplateobserverEduardo Jorge
 
JavaServer Faces Produtividade em Desenvolvimento
JavaServer Faces Produtividade em DesenvolvimentoJavaServer Faces Produtividade em Desenvolvimento
JavaServer Faces Produtividade em DesenvolvimentoEduardo Bregaida
 
Curso de Ruby on Rails - Aula 04
Curso de Ruby on Rails - Aula 04Curso de Ruby on Rails - Aula 04
Curso de Ruby on Rails - Aula 04Maurício Linhares
 
Tutorial java orientação a objetos parte 1
Tutorial java orientação a objetos parte 1Tutorial java orientação a objetos parte 1
Tutorial java orientação a objetos parte 1Elaine Cecília Gatto
 
Java 08 Modificadores Acesso E Membros De Classe
Java 08 Modificadores Acesso E Membros De ClasseJava 08 Modificadores Acesso E Membros De Classe
Java 08 Modificadores Acesso E Membros De ClasseRegis Magalhães
 
UML - Criando Diagramas Eficientes
UML - Criando Diagramas EficientesUML - Criando Diagramas Eficientes
UML - Criando Diagramas EficientesRodrigo Cascarrolho
 
Construção de Frameworks com Annotation e Reflection API em Java
Construção de Frameworks com Annotation e Reflection API em JavaConstrução de Frameworks com Annotation e Reflection API em Java
Construção de Frameworks com Annotation e Reflection API em JavaFernando Camargo
 
CURSO DELPHI FUND. CLIENT SERVER (DIURNO)
CURSO DELPHI FUND. CLIENT SERVER (DIURNO) CURSO DELPHI FUND. CLIENT SERVER (DIURNO)
CURSO DELPHI FUND. CLIENT SERVER (DIURNO) Grupo Treinar
 

Semelhante a Design de aplicações orientadas a objeto (20)

Aula1
Aula1Aula1
Aula1
 
Tutorial Java: Interface
Tutorial Java: InterfaceTutorial Java: Interface
Tutorial Java: Interface
 
Programação Web com Zend Framework e Ajax com Dojo
Programação Web com Zend Framework e Ajax com DojoProgramação Web com Zend Framework e Ajax com Dojo
Programação Web com Zend Framework e Ajax com Dojo
 
Working with legacy code 3
Working with legacy code 3Working with legacy code 3
Working with legacy code 3
 
Padrão De Projeto Adapter
Padrão De Projeto AdapterPadrão De Projeto Adapter
Padrão De Projeto Adapter
 
Transição - Orientação a objeto para Funcional
Transição - Orientação a objeto para FuncionalTransição - Orientação a objeto para Funcional
Transição - Orientação a objeto para Funcional
 
Intro padroesprojetoadaptertemplateobserver
Intro padroesprojetoadaptertemplateobserverIntro padroesprojetoadaptertemplateobserver
Intro padroesprojetoadaptertemplateobserver
 
Ruby & Rails
Ruby & RailsRuby & Rails
Ruby & Rails
 
JavaServer Faces Produtividade em Desenvolvimento
JavaServer Faces Produtividade em DesenvolvimentoJavaServer Faces Produtividade em Desenvolvimento
JavaServer Faces Produtividade em Desenvolvimento
 
Clean Code
Clean CodeClean Code
Clean Code
 
Curso de Ruby on Rails - Aula 04
Curso de Ruby on Rails - Aula 04Curso de Ruby on Rails - Aula 04
Curso de Ruby on Rails - Aula 04
 
Modelo de desenvolvimento de software em 3 camadas para Wordpress
Modelo de desenvolvimento de software em 3 camadas para WordpressModelo de desenvolvimento de software em 3 camadas para Wordpress
Modelo de desenvolvimento de software em 3 camadas para Wordpress
 
Tutorial java orientação a objetos parte 1
Tutorial java orientação a objetos parte 1Tutorial java orientação a objetos parte 1
Tutorial java orientação a objetos parte 1
 
Java 08 Modificadores Acesso E Membros De Classe
Java 08 Modificadores Acesso E Membros De ClasseJava 08 Modificadores Acesso E Membros De Classe
Java 08 Modificadores Acesso E Membros De Classe
 
Introdução a php
Introdução a phpIntrodução a php
Introdução a php
 
Programando php com excelência
Programando php com excelênciaProgramando php com excelência
Programando php com excelência
 
UML - Criando Diagramas Eficientes
UML - Criando Diagramas EficientesUML - Criando Diagramas Eficientes
UML - Criando Diagramas Eficientes
 
Construção de Frameworks com Annotation e Reflection API em Java
Construção de Frameworks com Annotation e Reflection API em JavaConstrução de Frameworks com Annotation e Reflection API em Java
Construção de Frameworks com Annotation e Reflection API em Java
 
CURSO DELPHI FUND. CLIENT SERVER (DIURNO)
CURSO DELPHI FUND. CLIENT SERVER (DIURNO) CURSO DELPHI FUND. CLIENT SERVER (DIURNO)
CURSO DELPHI FUND. CLIENT SERVER (DIURNO)
 
Aula2
Aula2Aula2
Aula2
 

Mais de Elaine Naomi

Hacking Evening - Liskov Substitution Principle
Hacking Evening - Liskov Substitution PrincipleHacking Evening - Liskov Substitution Principle
Hacking Evening - Liskov Substitution PrincipleElaine Naomi
 
Code Smells: o que eles dizem sobre seu código?
Code Smells: o que eles dizem sobre seu código?Code Smells: o que eles dizem sobre seu código?
Code Smells: o que eles dizem sobre seu código?Elaine Naomi
 
Guru SP: Decodificando o code review
Guru SP: Decodificando o code reviewGuru SP: Decodificando o code review
Guru SP: Decodificando o code reviewElaine Naomi
 
Bootcamp de Rails - CaquiCoders Meetup
Bootcamp de Rails - CaquiCoders MeetupBootcamp de Rails - CaquiCoders Meetup
Bootcamp de Rails - CaquiCoders MeetupElaine Naomi
 
TDC SP 2019 - Decodificando o code review
TDC SP 2019 - Decodificando o code reviewTDC SP 2019 - Decodificando o code review
TDC SP 2019 - Decodificando o code reviewElaine Naomi
 
Além da programação funcional com Elixir e Erlang
Além da programação funcional com Elixir e ErlangAlém da programação funcional com Elixir e Erlang
Além da programação funcional com Elixir e ErlangElaine Naomi
 
Code review: o que isso diz sobre a cultura dos times de desenvolvimento?
Code review: o que isso diz sobre a cultura dos times de desenvolvimento?Code review: o que isso diz sobre a cultura dos times de desenvolvimento?
Code review: o que isso diz sobre a cultura dos times de desenvolvimento?Elaine Naomi
 
Explorando o Paralelismo em Workflows Intensivos em Dados com o Uso de Anotaç...
Explorando o Paralelismo em Workflows Intensivos em Dados com o Uso de Anotaç...Explorando o Paralelismo em Workflows Intensivos em Dados com o Uso de Anotaç...
Explorando o Paralelismo em Workflows Intensivos em Dados com o Uso de Anotaç...Elaine Naomi
 
Uso de Anotações Semânticas para Exploração de Paralelismo em Workflows Inten...
Uso de Anotações Semânticas para Exploração de Paralelismo em Workflows Inten...Uso de Anotações Semânticas para Exploração de Paralelismo em Workflows Inten...
Uso de Anotações Semânticas para Exploração de Paralelismo em Workflows Inten...Elaine Naomi
 
Dealing with a search engine in your application - a Solr approach for beginners
Dealing with a search engine in your application - a Solr approach for beginnersDealing with a search engine in your application - a Solr approach for beginners
Dealing with a search engine in your application - a Solr approach for beginnersElaine Naomi
 
Um Método para Paralelização Automática de Workflows Intensivos em Dados
Um Método para Paralelização Automática de Workflows Intensivos em DadosUm Método para Paralelização Automática de Workflows Intensivos em Dados
Um Método para Paralelização Automática de Workflows Intensivos em DadosElaine Naomi
 
O que é BIG DATA e como pode influenciar nossas vidas
O que é BIG DATA e como pode influenciar nossas vidasO que é BIG DATA e como pode influenciar nossas vidas
O que é BIG DATA e como pode influenciar nossas vidasElaine Naomi
 
Introdução ao MongoDB
Introdução ao MongoDBIntrodução ao MongoDB
Introdução ao MongoDBElaine Naomi
 
Workflows científicos
Workflows científicosWorkflows científicos
Workflows científicosElaine Naomi
 
Algoritmos para economia de energia no escalonamento de workflows em nuvens c...
Algoritmos para economia de energia no escalonamento de workflows em nuvens c...Algoritmos para economia de energia no escalonamento de workflows em nuvens c...
Algoritmos para economia de energia no escalonamento de workflows em nuvens c...Elaine Naomi
 

Mais de Elaine Naomi (16)

Hacking Evening - Liskov Substitution Principle
Hacking Evening - Liskov Substitution PrincipleHacking Evening - Liskov Substitution Principle
Hacking Evening - Liskov Substitution Principle
 
Code Smells: o que eles dizem sobre seu código?
Code Smells: o que eles dizem sobre seu código?Code Smells: o que eles dizem sobre seu código?
Code Smells: o que eles dizem sobre seu código?
 
Guru SP: Decodificando o code review
Guru SP: Decodificando o code reviewGuru SP: Decodificando o code review
Guru SP: Decodificando o code review
 
Bootcamp de Rails - CaquiCoders Meetup
Bootcamp de Rails - CaquiCoders MeetupBootcamp de Rails - CaquiCoders Meetup
Bootcamp de Rails - CaquiCoders Meetup
 
TDC SP 2019 - Decodificando o code review
TDC SP 2019 - Decodificando o code reviewTDC SP 2019 - Decodificando o code review
TDC SP 2019 - Decodificando o code review
 
Além da programação funcional com Elixir e Erlang
Além da programação funcional com Elixir e ErlangAlém da programação funcional com Elixir e Erlang
Além da programação funcional com Elixir e Erlang
 
Code review: o que isso diz sobre a cultura dos times de desenvolvimento?
Code review: o que isso diz sobre a cultura dos times de desenvolvimento?Code review: o que isso diz sobre a cultura dos times de desenvolvimento?
Code review: o que isso diz sobre a cultura dos times de desenvolvimento?
 
Explorando o Paralelismo em Workflows Intensivos em Dados com o Uso de Anotaç...
Explorando o Paralelismo em Workflows Intensivos em Dados com o Uso de Anotaç...Explorando o Paralelismo em Workflows Intensivos em Dados com o Uso de Anotaç...
Explorando o Paralelismo em Workflows Intensivos em Dados com o Uso de Anotaç...
 
Uso de Anotações Semânticas para Exploração de Paralelismo em Workflows Inten...
Uso de Anotações Semânticas para Exploração de Paralelismo em Workflows Inten...Uso de Anotações Semânticas para Exploração de Paralelismo em Workflows Inten...
Uso de Anotações Semânticas para Exploração de Paralelismo em Workflows Inten...
 
Dealing with a search engine in your application - a Solr approach for beginners
Dealing with a search engine in your application - a Solr approach for beginnersDealing with a search engine in your application - a Solr approach for beginners
Dealing with a search engine in your application - a Solr approach for beginners
 
Um Método para Paralelização Automática de Workflows Intensivos em Dados
Um Método para Paralelização Automática de Workflows Intensivos em DadosUm Método para Paralelização Automática de Workflows Intensivos em Dados
Um Método para Paralelização Automática de Workflows Intensivos em Dados
 
O que é BIG DATA e como pode influenciar nossas vidas
O que é BIG DATA e como pode influenciar nossas vidasO que é BIG DATA e como pode influenciar nossas vidas
O que é BIG DATA e como pode influenciar nossas vidas
 
Introdução ao MongoDB
Introdução ao MongoDBIntrodução ao MongoDB
Introdução ao MongoDB
 
Workflows científicos
Workflows científicosWorkflows científicos
Workflows científicos
 
Algoritmos para economia de energia no escalonamento de workflows em nuvens c...
Algoritmos para economia de energia no escalonamento de workflows em nuvens c...Algoritmos para economia de energia no escalonamento de workflows em nuvens c...
Algoritmos para economia de energia no escalonamento de workflows em nuvens c...
 
Qt Apresentação
Qt ApresentaçãoQt Apresentação
Qt Apresentação
 

Design de aplicações orientadas a objeto