Construindo aplicações
confiantes
Photo by Samuel Zeller on Unsplash
Carolina
Karklis
@carolkarklis
carolina@rubyladies.com.br
magnetis.workable.com
Esse é o livro que me inspirou a falar sobre isso. Eu
realmente sou uma entusiasta do Ruby e acredito que o
código não tem que trazer dor de cabeça pra gente, e sim
ser um meio pra chegarmos aonde queremos. O código
deveria passar confiança pra quem mantém ele, mas nem
sempre é assim
🤔
O que não é um código
confiante
Code smells
💩 métodos MacGyver
💩 excesso de condicionais
💩 excesso de type checking
💩 nil driven development
Métodos MacGyver
Problema:
Métodos longos que fazem muita coisa
Solução:
Identificar mensagens e papéis,
separando o código em partes menores
Photo by Caleb Woods on Unsplash
Sistema legado de registro de compras
Em resumo, precisamos de um
método para migrar os dados de
um sistema legado para o novo
Photo by Annelies Geneyn on Unsplash
Primeiro, vamos
pensar na história
que queremos contar
Photo by Annelies Geneyn on Unsplash
4 partes de um
método para contar
uma boa história
Photo by Annelies Geneyn on Unsplash
4 partes de um
método para contar
uma boa história
1. Coletar input
Photo by Annelies Geneyn on Unsplash
4 partes de um
método para contar
uma boa história
1. Coletar input
2. Realizar o trabalho
Photo by Annelies Geneyn on Unsplash
4 partes de um
método para contar
uma boa história
1. Coletar input
2. Realizar o trabalho
3. Entregar output
Photo by Annelies Geneyn on Unsplash
4 partes de um
método para contar
uma boa história
1. Coletar input
2. Realizar o trabalho
3. Entregar output
4. Lidar com falhas
Realizando o trabalho
“The foundation of an object
oriented system is the message”
- Sandi Metz
Mensagens = Ações
#parse_legacy_purchase_records
Mensagens = Ações
#parse_legacy_purchase_records
for #each purchase record we want to:
Mensagens = Ações
#parse_legacy_purchase_records
for #each purchase record we want to:
use #email_address to #get_customer
Mensagens = Ações
#parse_legacy_purchase_records
for #each purchase record we want to:
use #email_address to #get_customer
use #product_id to #get_product
Mensagens = Ações
#parse_legacy_purchase_records
for #each purchase record we want to:
use #email_address to #get_customer
use #product_id to #get_product
#add_purchased_product to the customer record
Mensagens = Ações
#parse_legacy_purchase_records
for #each purchase record we want to:
use #email_address to #get_customer
use #product_id to #get_product
#add_purchased_product to the customer record
#log_successfull_import from the purchase record
Realizando o trabalho
“A role is a set of responsibilities”
- Rebecca Wirfs-Brock
Messages 💖 Roles
Message Role
#parse_legacy_purchase_records
#each
#email_address, #product_id
#get_customer
#get_product
#add_purchased_product
#log_successfull_import
Messages 💖 Roles
Message Role
#parse_legacy_purchase_records data_parser
#each
#email_address, #product_id
#get_customer
#get_product
#add_purchased_product
#log_successfull_import
Messages 💖 Roles
Message Role
#parse_legacy_purchase_records data_parser
#each purchase_list
#email_address, #product_id
#get_customer
#get_product
#add_purchased_product
#log_successfull_import
Messages 💖 Roles
Message Role
#parse_legacy_purchase_records data_parser
#each purchase_list
#email_address, #product_id purchase_record
#get_customer
#get_product
#add_purchased_product
#log_successfull_import
Messages 💖 Roles
Message Role
#parse_legacy_purchase_records data_parser
#each purchase_list
#email_address, #product_id purchase_record
#get_customer customer_list
#get_product
#add_purchased_product
#log_successfull_import
Messages 💖 Roles
Message Role
#parse_legacy_purchase_records data_parser
#each purchase_list
#email_address, #product_id purchase_record
#get_customer customer_list
#get_product product_list
#add_purchased_product
#log_successfull_import
Messages 💖 Roles
Message Role
#parse_legacy_purchase_records data_parser
#each purchase_list
#email_address, #product_id purchase_record
#get_customer customer_list
#get_product product_list
#add_purchased_product customer
#log_successfull_import
Messages 💖 Roles
Message Role
#parse_legacy_purchase_records data_parser
#each purchase_list
#email_address, #product_id purchase_record
#get_customer customer_list
#get_product product_list
#add_purchased_product customer
#log_successfull_import data_importer
def import_legacy_purchase_data(data)
purchase_list = data_parser.parse_purchase_records(data)
end
def import_legacy_purchase_data(data)
purchase_list = data_parser.parse_purchase_records(data)
purchase_list.each do |purchase|
end
end
def import_legacy_purchase_data(data)
purchase_list = data_parser.parse_purchase_records(data)
purchase_list.each do |purchase|
customer = customer_list.get_customer(purchase.email_address)
product = product_list.get_product(purchase.product_id)
end
end
def import_legacy_purchase_data(data)
purchase_list = data_parser.parse_purchase_records(data)
purchase_list.each do |purchase|
customer = customer_list.get_customer(purchase.email_address)
product = product_list.get_product(purchase.product_id)
customer.add_purchased_product(product)
end
end
def import_legacy_purchase_data(data)
purchase_list = data_parser.parse_purchase_records(data)
purchase_list.each do |purchase|
customer = customer_list.get_customer(purchase.email_address)
product = product_list.get_product(purchase.product_id)
customer.add_purchased_product(product)
log_successfull_import(purchase_record)
end
end
Um pouco verboso,
mas conta uma história👌
Detalhe 

Não me preocupei com os colaboradores, 

e sim com a história e a usabilidade do método
#TODO: Criar a ponte entre os papéis
que criamos e objetos de verdade.
Code smells
💩 métodos MacGyver
Excesso de
condicionais e
type checkings
Photo by Javier Allegue Barros on Unsplash
💣 causa desordem e tira linearidade no código
💣 se torna difícil de testar e manter
💣 embute responsabilidades e conhecimentos desnecessários
A solução é dividida em patterns estratégias específicas:
Coagir objetos para que façam o que precisa ser feito
Rejeitar valores inesperados de maneira mais eficiente
Substituir inputs inaceitáveis por valores válidos
Photo by mauRÍCIO santos on Unsplash
Guarde as fronteiras,
não as esquinas
Isso é um código confiante.
menos type checking
menos condicionais
Code smells
💩 métodos MacGyver
💩 excesso de condicionais
💩 excesso de type checking
💩 nil driven development
Nil Driven Development
NoMethodError no Ruby
AttributeError no Python
NullPointerException no Java
TypeError no Javascript
Photo by JOSHUA COLEMAN on Unsplash
Photo by JOSHUA COLEMAN on Unsplash
YAGNI
You ain’t gonna need it
Converta de maneira
implícita ou explícita
#to_s
#to_str
#to_i
#to_f
If you know what you want,
ask for it
Use conversões do módulo
Kernel para outros tipos
Array()
Integer()
Pathname()
Hash.[*]
Defina suas próprias conversões
para tipos definidos
Não pergunte pelo tipo de
objeto, e sim peça a permissão
is_a?(Duck)
respond_to?(:quack)
Aprenda a usar structs e crie um
padrão para seu sistema
Não use nil, não passe nil
Utilize o ActiveRecord::NullRelation se
precisar retornar um objeto vazio
Joyful Driven Development
🌈
Obrigada!
Photo by Samuel Zeller on Unsplash
@carolkarklis
carolina@rubyladies.com.br

Construindo aplicações confiantes