簡體   English   中英

如何在Ruby中重構巨大的查找表

[英]How to refactor huge lookup table in Ruby

我有一個方法:

def assign_value
   ...
   @obj.value = find_value
end

和一個巨大的查詢表:

def find_value
   if @var > 0 && @var <= 30
      0.4
   elsif @var > 30 && @var <= 50
      0.7
   elsif @var > 50 && @var <= 70
      1.1
   elsif @var > 70 && @var <= 100
      1.5
   elsif @var > 100 && @var <= 140
      2.10
   elsif @var > 140 && @var <= 200
      2.95
   elsif @var > 200 && @var <= 300
      4.35
   elsif @var > 300 && @var <= 400
      6.15
   elsif @var > 400 && @var <= 500
      7.85
   elsif @var > 500 && @var <= 600
      9.65
   ...

end

以此類推1800行

不用說,它是給一個未命名國家的稅務部門的。 現在,它是手動編寫的(全部1800行)以說明整數范圍和十進制返回值的變化長度。

如果不重寫整個國家的稅法,我將如何重構呢?

范圍和值確實會每年更改,因此我們需要保持向后兼容性。 數據庫表將簡化事務,但是由於我們要處理的是多個不同的國家,每個國家都有不同的要求和稅法,因此創建數據庫表並不像聽起來那樣簡單。

@MilesStanfield的回答與您的影響幾乎相同。 如我的評論所述,我將使用散列來擺脫所有條件(或情況):

COUNTRY_TAX_RATES = {
  0..30 => 0.4,
  31..50 => 0.7,
  51..70 => 1.1
}

COUNTRY_TAX_RATES[0..30] # 0.4
COUNTRY_TAX_RATES.select { |code| code === 10 }.values.first # 0.4

如果您不更改代碼,通常可以使用它。 如果確實經常更改,則可以考慮使用另一種方法(例如,存儲在db中並通過用戶界面進行管理)。

更新:現在我不再在手機上了,我想進一步擴大這個答案。 似乎您無視@Wand Maker的建議,但我認為您不應該這樣做。

假設您使用我的哈希。 它很方便,沒有任何條件,並且易於調整。 但是,正如Wand Maker指出的那樣,每次更改范圍或十進制時,您都需要開發人員來更新代碼。 這可能沒問題,因為您只需要每年進行一次,但這不是最干凈的方法。

您希望會計師能夠代替開發人員來更新稅率和代碼。 因此,您可能應該創建一個包含這些屬性的表。 我不確定您的示例中的范圍和小數表示什么,但我希望您能理解:

Tax (ActiveRecord) with range_column (Give this an explicit, explanatory name. You could also use min and max range columns), code, rate and country_id

class Tax < ActiveRecord::Base
  serialize :range_column

  belongs_to :country
end

Country has_many :taxes

如果您想知道馬耳他的稅率(country_id:30),稅碼為40(這可能意味着什么),您可以執行以下操作:

Tax.select(:tax_rate).joins(:country).find_by(country_id: 30, range_column: 40).tax_rate # you might need a between statement instead, can't check right now if querying a serialized hash works like this

現在,當這些更改更改時,會計師可以更新范圍,小數或任何其他屬性(當然,您必須首先為其創建CRUD)。

附:不要介意命名,不確定這些數字代表什么。 :)

我將使用帶有范圍的case語句

case @var
when 0..30 then 0.4
when 31..50 then 0.7
when 51..70 then 1.1
...
end

假設inc是收入,而arr是成對的數組[bp, tax] ,其中

  • arr[0][0] = 0 ,意味着arr的第一個元素的bp (收入“斷點”)為零;
  • arr[i][0] < arr[i+1][0] ,這意味着斷點在增加;
  • 如果inc >= arr[-1][0] ,則應納稅arr[-1][1] inc >= arr[-1][0]
  • 如果arr[i][0] <= inc < arr[i+1][0]0 <= i <= arr.size-2納稅arr[i][1]

然后可以計算稅收

arr.find { |bp,_| inc >= bp }.last

因為斷點在增加。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM