serradura / Dicas De Programacao Em Ruby
Programming Languages
Labels
Projects that are alternatives of or similar to Dicas De Programacao Em Ruby
Dicas de programação em Ruby
Propósito
Registrar dicas de programação que surgiram por conta de uma conversa/pergunta que rolou no grupo Ruby Brasil do Telegram.
Por favor registre dúvidas e/ou sugestões como issues. 😉
Contribuições são mais que bem-vindas! 😊
Implementação original
A ideia deste projeto é demonstrar pequenas dicas/mudanças para aprimorar o exemplo abaixo.
Por conta disso, seguiremos a proposta original implementando o código com palavras/termos em português.
Porém, como é de conhecimento de mercado é recomendado que você pratique/desenvolva em inglês (confira alguns motivos).
class User
attr_accessor :nome, :idade, :cidade
def boasvindas
puts 'Seja bem-vindo ' << nome << '!'
puts 'Você quer jogar?'
puts 'Digite S ou N'
resposta = gets
if resposta.downcase[0] == ('s')
jogar = true
else
jogar = false
end
return jogar
end
end
# Uso:
user = User.new
user.nome = 'André'
user.idade = '30'
user.cidade = 'São José do Rio Preto'
if user.boasvindas
puts 'Iniciando jogo...'
end
Como utilizar este guia/projeto?
dicas:
1) Use o menu de2) Configure o projeto e teste cada mudança/dica:
Configurando o projeto
- Instale o Ruby (dica: rbenv)
- Instale o bundler:
gem install bundler
- Execute o bundler:
bundle install
Executando os testes
bundle exec rspec
Sugestão:
Após configurar, acesso o primeiro commit git checkout f42f6b92
e aplique os conceitos deste guia. Feito isso, use a suite de testes para verificar se o comportamento da aplicação continua sendo o garantido.
Dicas
Exemplos de boas práticas de desenvolvimento de software em Ruby + técnicas de refatoração.
-
400d121
Dica 1 - Interpolação 🔗 -
11445ef
Dica 2 - Use métodos privados 🔗 -
824501f
Dica 3 - Remova variáveis desnecessárias 🔗 -
f6300e9
Dica 4 - Defina métodos predicativos 🔗 -
9f8f36e
Dica 5 - Ternário 🔗 -
b7fb557
Dica 6 - Elimine a condicional quando o retorno for um boolean 🔗 -
baeb46e
Dica 7 - return é opcional quando usado na última linha de um método 🔗 -
f86e29d
Dica 8 - Use o construtor + getters (métodos somente leitura) 🔗 -
4d79c49
Dica 9 - Use keywords arguments 🔗 -
ec016e0
Dica 10 - Escreva métodos e variáveis no formato snake_case 🔗 -
66b1048
Dica 11 - Separe classes por responsabilidade (coesão) 🔗 -
b690234
Dica 12 - Organize os métodos por responsabilidade (coesão) 🔗
diff]
Dica 1 [Faça uso de interpolação, é mais performático que concatenar strings.
Link para aprender mais sobre o assunto.
class User
attr_accessor :nome, :idade, :cidade
def boasvindas
puts "Seja bem-vindo #{nome}!"
puts 'Você quer jogar um jogo?'
puts 'Digite S ou N'
resposta = gets
if resposta.downcase == 's'
jogar = true
else
jogar = false
end
return jogar
end
end
diff]
Dica 2 [Use métodos privados, para:
- Encapsular/esconder comportamentos
- Melhorar a legibilidade de métodos públicos
- Permitir reuso
class User
attr_accessor :nome, :idade, :cidade
def boasvindas
imprime_pergunta
resposta = gets
return prosseguir_para_o_jogo(resposta)
end
private
def imprime_pergunta
puts "Seja bem-vindo #{nome}!"
puts 'Você quer jogar?'
puts 'Digite S ou N'
end
def prosseguir_para_o_jogo(resposta)
if resposta.downcase[0] == 's'
jogar = true
else
jogar = false
end
return jogar
end
end
diff]
Dica 3 [Remova variáveis caso o valor atribuído seja o último a ser retornado.
(Mudança: Foi removido a variável jogar
do método prosseguir_para_o_jogo
).
class User
attr_accessor :nome, :idade, :cidade
def boasvindas
imprime_pergunta
resposta = gets
return prosseguir_para_o_jogo(resposta)
end
private
def imprime_pergunta
puts "Seja bem-vindo #{nome}!"
puts 'Você quer jogar?'
puts 'Digite S ou N'
end
def prosseguir_para_o_jogo(resposta)
if resposta.downcase[0] == 's'
true
else
false
end
end
end
diff]
Dica 4 [Defina métodos predicativos (terminam com ?
- interrogação) quando o resultado do mesmo for um boolean
(true
ou false
).
class User
attr_accessor :nome, :idade, :cidade
def boasvindas
imprime_pergunta
resposta = gets
return prosseguir_para_o_jogo?(resposta)
end
private
def imprime_pergunta
puts "Seja bem-vindo #{nome}!"
puts 'Você quer jogar?'
puts 'Digite S ou N'
end
def prosseguir_para_o_jogo?(resposta)
if resposta.downcase[0] == 's'
true
else
false
end
end
end
diff]
Dica 5 [Use um ternário para expressar condicionais simples/curtas.
Link para aprender mais sobre o assunto.
class User
attr_accessor :nome, :idade, :cidade
def boasvindas
imprime_pergunta
resposta = gets
return prosseguir_para_o_jogo?(resposta)
end
private
def imprime_pergunta
puts "Seja bem-vindo #{nome}!"
puts 'Você quer jogar?'
puts 'Digite S ou N'
end
def prosseguir_para_o_jogo?(resposta)
resposta.downcase[0] == 's' ? true : false
end
end
diff]
Dica 6 [Elimine o ternário/expressão condicional quando o retorno for um boolean.
class User
attr_accessor :nome, :idade, :cidade
def boasvindas
imprime_pergunta
resposta = gets
return prosseguir_para_o_jogo?(resposta)
end
private
def imprime_pergunta
puts "Seja bem-vindo #{nome}!"
puts 'Você quer jogar?'
puts 'Digite S ou N'
end
def prosseguir_para_o_jogo?(resposta)
resposta.downcase[0] == 's'
end
end
diff]
Dica 7 [Métodos sempre retornam o resultado da última linha, logo o uso de return se torna opcional/desnecessário.
class User
attr_accessor :nome, :idade, :cidade
def boasvindas
imprime_pergunta
resposta = gets
prosseguir_para_o_jogo?(resposta)
end
private
def imprime_pergunta
puts "Seja bem-vindo #{nome}!"
puts 'Você quer jogar?'
puts 'Digite S ou N'
end
def prosseguir_para_o_jogo?(resposta)
resposta.downcase[0] == 's'
end
end
diff]
Dica 8 [Faça uso do construtor + getters (métodos de leitura) para evitar que o estados do(s) seu(s) objetos se corrompa por conta de uma manipulação indevida/equivocada.
class User
attr_reader :nome, :idade, :cidade
def initialize(nome, idade, cidade)
@nome = nome
@idade = idade
@cidade = cidade
end
def boasvindas
imprime_pergunta
resposta = gets
prosseguir_para_o_jogo?(resposta)
end
private
def imprime_pergunta
puts "Seja bem-vindo #{nome}!"
puts 'Você quer jogar?'
puts 'Digite S ou N'
end
def prosseguir_para_o_jogo?(resposta)
resposta.downcase[0] == 's'
end
end
# Uso:
user = User.new('André', '30', 'São José do Rio Preto')
if user.boasvindas
puts 'Iniciando jogo...'
end
diff]
Dica 9 [Faça uso de keywords arguments para tornar os argumentos/dependências de seus métodos mais expressivos.
class User
attr_reader :nome, :idade, :cidade
def initialize(nome:, idade:, cidade:)
@nome = nome
@idade = idade
@cidade = cidade
end
def boasvindas
imprime_pergunta
resposta = gets
prosseguir_para_o_jogo?(resposta)
end
private
def imprime_pergunta
puts "Seja bem-vindo #{nome}!"
puts 'Você quer jogar?'
puts 'Digite S ou N'
end
def prosseguir_para_o_jogo?(resposta)
resposta.downcase[0] == 's'
end
end
# Uso:
user = User.new(nome: 'André', idade: '30', cidade: 'São José do Rio Preto')
if user.boasvindas
puts 'Iniciando jogo...'
end
diff]
Dica 10 [Por convensão Ruby faz uso de snake_case
na declaração de métodos e variáveis, quando o mesmo contém mais de um termo. Com isso o método boasvindas se torna boas_vindas.
class User
attr_reader :nome, :idade, :cidade
def initialize(nome:, idade:, cidade:)
@nome = nome
@idade = idade
@cidade = cidade
end
def boas_vindas
imprime_pergunta
resposta = gets
prosseguir_para_o_jogo?(resposta)
end
private
def imprime_pergunta
puts "Seja bem-vindo #{nome}!"
puts 'Você quer jogar?'
puts 'Digite S ou N'
end
def prosseguir_para_o_jogo?(resposta)
resposta.downcase[0] == 's'
end
end
diff]
Dica 11 [Separe suas classes de acordo com suas responsabilidades (que conceito elas expressam?). Isso poderá facilitar a manutenção e entendimento do código.
PS: Responsabilidade única/pouca tem haver com o que chamamos de coesão.
class User
attr_reader :nome, :idade, :cidade
def initialize(nome:, idade:, cidade:)
@nome = nome
@idade = idade
@cidade = cidade
end
end
class Game
attr_reader :user
def initialize(user)
@user = user
end
def start
boas_vindas
# Poderá receber mais métodos que venham fazer sentindo ao jogo/projeto...
end
private
def boas_vindas
imprime_pergunta
resposta = gets
prosseguir_para_o_jogo?(resposta)
end
def imprime_pergunta
puts "Seja bem-vindo #{user.nome}!"
puts 'Você quer jogar?'
puts 'Digite S ou N'
end
def prosseguir_para_o_jogo?(resposta)
resposta.downcase[0] == 's'
end
end
user = User.new(nome: 'André', idade: '30', cidade: 'São José do Rio Preto')
game = Game.new(user)
if game.start
puts 'Iniciando jogo...'
end
diff]
Dica 12 [Organize os métodos de acordo com suas responsabilidades. Assim como as classes isso poderá facilitar a manutenção e entendimento do código.
PS: Essa prática também tem haver com o que chamamos de coesão.
Mudança:
Perceba que na versão anterior, o método boas_vindas
tem diversas responsabilidades.
Além disso, ele retorna um boolean e não aplica a convenção de predicado (nem sempre isso será necessário).
O que fizemos para melhorar?
Nessa versão o início do jogo (start), tem duas etapas:
- Começa com uma pergunta
- Processa a resposta para resolver se o mesmo será ou não iniciado.
Dada essa estrutura, criamos métodos para representar cada uma dessas etapas.
class User
attr_reader :nome, :idade, :cidade
def initialize(nome:, idade:, cidade:)
@nome = nome
@idade = idade
@cidade = cidade
end
end
class Game
attr_reader :user
def initialize(user)
@user = user
end
def start
resposta = pergunta_se_deseja_jogar
prosseguir_para_o_jogo?(resposta)
end
private
def pergunta_se_deseja_jogar
imprime_pergunta
gets
end
def imprime_pergunta
puts "Seja bem-vindo #{user.nome}!"
puts 'Você quer jogar?'
puts 'Digite S ou N'
end
def prosseguir_para_o_jogo?(resposta)
resposta.downcase[0] == 's'
end
end