如何重构 Ruby 方法以通过 Rubocop 测试同时也是 DRY
How to refactor Ruby methods to pass Rubocop tests while also being DRY
作为 Launch School 课程的一部分,我正在研究二十一游戏(将游戏视为 Blackjack 的轻量级版本)。
我需要适当地重构我自己的代码以使其保持干燥,同时还通过所有 Rubocop 测试。我目前使用的是 Rubocop 0.85.0 版本(课程需要这个版本)。
在我的游戏中,我将所有数据存储在一个名为 Keep Score 的散列中:
keep_score = { 'player_cards' => [], \
'dealer_cards' => [], \
'player_card_values' => [], \
'dealer_card_values' => [], \
'player_points' => 0, \
'dealer_points' => 0, \
'player_move' => '', \
'dealer_move' => '', \
'end_game' => false }
到目前为止我的代码可以正常工作,到目前为止我已经做了很多重构,但是我需要进一步重构这两个方法以使代码更干,同时仍然通过 Rubocop 测试。
我有两种方法,一种 convert_face_cards
转换 K、Q 和 J(A 单独处理)。然后有一个单独的方法,add_integer_points
来处理卡片上的整数值:
def convert_face_cards(keep_score)
keep_score['player_points'] = 0
keep_score['dealer_points'] = 0
keep_score['player_card_values'].each do |card|
if card == "jack" || card == "queen" || card == "king"
keep_score['player_points'] += 10
end
end
keep_score['dealer_card_values'].each do |card|
if card == "jack" || card == "queen" || card == "king"
keep_score['dealer_points'] += 10
end
end
end
def add_integer_points(keep_score)
keep_score['player_card_values'].each do |card|
if card.is_a? Integer
keep_score['player_points'] += card
end
end
keep_score['dealer_card_values'].each do |card|
if card.is_a? Integer
keep_score['dealer_points'] += card
end
end
end
虽然这段代码从技术角度来看是可行的,但我没有通过 Rubocop 测试。 convert_face_cards
方法返回错误:Cyclomatic complexity for convert_face_cards is too high. [7/6]
.
我的代码显然不够干。例如,在 convert_face_cards
方法中,我本质上是 运行 each
方法,在 player_card_values
哈希键和 dealer_card_values
上都采用相同的方式哈希键。
但我不确定如何进一步压缩这些方法。感谢任何帮助或指导!
def convert_face_cards(keep_score)
players = keep_score['player_card_values'].select { |card| card == "jack" || card == "queen" || card == "king" }
dealers = keep_score['dealer_card_values'].select { |card| card == "jack" || card == "queen" || card == "king" }
keep_score['player_points'] = players.length * 10
keep_score['dealer_points'] = dealers.length * 10
end
由于无论是闲家还是庄家,算人牌的逻辑都是一样的,你可以把它提取到自己的方法中,稍微干点。
def convert_face_cards(keep_score)
keep_score['player_points'] = count_faces(keep_score['player_card_values'])
keep_score['dealer_points'] = count_faces(keep_score['dealer_card_values'])
end
def sum_faces(cards)
faces = cards.select { |card| face?(card) }
faces.length * 10
end
def face?(card)
%w[jack queen king].include?(card)
end
您不应该使用散列来存储此数据并编写循环遍历散列的代码。您应该使用包含这些知识的数据结构作为方法。
例如:
Card = Struct.new(:value) do
def score
case value
when :king, :queen, :jack
10
when :ace
1
else
value
end
end
end
CARDS = [
:ace,
:king,
:queen,
:jack,
10,
... # other cards here
2
].map { |card| Card.new(card) }
player_cards = []
dealer_cards = []
def score(cards)
cards.sum(&:score)
end
作为 Launch School 课程的一部分,我正在研究二十一游戏(将游戏视为 Blackjack 的轻量级版本)。
我需要适当地重构我自己的代码以使其保持干燥,同时还通过所有 Rubocop 测试。我目前使用的是 Rubocop 0.85.0 版本(课程需要这个版本)。
在我的游戏中,我将所有数据存储在一个名为 Keep Score 的散列中:
keep_score = { 'player_cards' => [], \
'dealer_cards' => [], \
'player_card_values' => [], \
'dealer_card_values' => [], \
'player_points' => 0, \
'dealer_points' => 0, \
'player_move' => '', \
'dealer_move' => '', \
'end_game' => false }
到目前为止我的代码可以正常工作,到目前为止我已经做了很多重构,但是我需要进一步重构这两个方法以使代码更干,同时仍然通过 Rubocop 测试。
我有两种方法,一种 convert_face_cards
转换 K、Q 和 J(A 单独处理)。然后有一个单独的方法,add_integer_points
来处理卡片上的整数值:
def convert_face_cards(keep_score)
keep_score['player_points'] = 0
keep_score['dealer_points'] = 0
keep_score['player_card_values'].each do |card|
if card == "jack" || card == "queen" || card == "king"
keep_score['player_points'] += 10
end
end
keep_score['dealer_card_values'].each do |card|
if card == "jack" || card == "queen" || card == "king"
keep_score['dealer_points'] += 10
end
end
end
def add_integer_points(keep_score)
keep_score['player_card_values'].each do |card|
if card.is_a? Integer
keep_score['player_points'] += card
end
end
keep_score['dealer_card_values'].each do |card|
if card.is_a? Integer
keep_score['dealer_points'] += card
end
end
end
虽然这段代码从技术角度来看是可行的,但我没有通过 Rubocop 测试。 convert_face_cards
方法返回错误:Cyclomatic complexity for convert_face_cards is too high. [7/6]
.
我的代码显然不够干。例如,在 convert_face_cards
方法中,我本质上是 运行 each
方法,在 player_card_values
哈希键和 dealer_card_values
上都采用相同的方式哈希键。
但我不确定如何进一步压缩这些方法。感谢任何帮助或指导!
def convert_face_cards(keep_score)
players = keep_score['player_card_values'].select { |card| card == "jack" || card == "queen" || card == "king" }
dealers = keep_score['dealer_card_values'].select { |card| card == "jack" || card == "queen" || card == "king" }
keep_score['player_points'] = players.length * 10
keep_score['dealer_points'] = dealers.length * 10
end
由于无论是闲家还是庄家,算人牌的逻辑都是一样的,你可以把它提取到自己的方法中,稍微干点。
def convert_face_cards(keep_score)
keep_score['player_points'] = count_faces(keep_score['player_card_values'])
keep_score['dealer_points'] = count_faces(keep_score['dealer_card_values'])
end
def sum_faces(cards)
faces = cards.select { |card| face?(card) }
faces.length * 10
end
def face?(card)
%w[jack queen king].include?(card)
end
您不应该使用散列来存储此数据并编写循环遍历散列的代码。您应该使用包含这些知识的数据结构作为方法。
例如:
Card = Struct.new(:value) do
def score
case value
when :king, :queen, :jack
10
when :ace
1
else
value
end
end
end
CARDS = [
:ace,
:king,
:queen,
:jack,
10,
... # other cards here
2
].map { |card| Card.new(card) }
player_cards = []
dealer_cards = []
def score(cards)
cards.sum(&:score)
end