用ruby中的两个助手构造函数的惯用方法

vngu2lb8  于 2021-09-29  发布在  Java
关注(0)|答案(2)|浏览(357)

我为代码战争中的卡塔自恋数字编了一个解决方案。
在编写了一个函数之后,我提取了两个helper函数,以便将行数保持在最多5行(sandi metz的开发者规则)。
这产生了3个功能:

def digits(number)
  number
    .to_s
    .chars
    .map(&:to_i)
end

def checksum(digits, exp)
  digits
    .map { |d| d**exp }
    .reduce(:+)
end

def narcissistic?(number)
  digits = digits(number)
  exp = digits.length
  checksum = checksum(digits, exp)
  checksum == number
end

现在,我想假装这段代码应该添加到一个更大的实际项目中。我的问题是如何在ruby中习惯性地实现这一点。
一般来说,我有两个要求:
代码应该以某种方式命名(考虑到实际项目)。
应该清楚的是 narcissistic? 是公共api函数-位于更高的级别上,而其他两个函数 digitschecksum 处于较低的抽象级别。
到目前为止,我的理由是:这段代码实际上并不需要oop。但在ruby中,将某些内容放入命名空间的唯一方法是创建 Class 或者 Module .
可能是 Module 是更好的选择吗?不过,我不确定我是否应该:

module MathUtils::NarcissisticNumbers
  def self.narcissistic?(number)
    ...
  end

  private
  ...
end

vs

module MathUtils::NarcissisticNumbers
  def narcissistic?(number)
    ...
  end

  private
  ...
end

如何将此代码引入ruby项目?如果您知道最佳实践解决方案,请告诉我!:)
任何其他的指点也将受到高度赞赏。

twh00eeo

twh00eeo1#

在我看来,这取决于你的方法的目的,考虑2个名字 narcissistic 方法: narcissistic?(number) :这让我觉得有一个外部类负责检查输入的数字是否自恋。 narcissistic? 当前位置这让我想到了班级本身,能够检查它是否自恋。
在案例1中,假设您有一个类 Code 包括模块 MathUtils::NarcissisticNumbers ,如果该模块不支持类方法,则只支持类代码的示例 can_do 检查 narcissistic ,则方法名称应属于上述情况2。
另一方面,如果模块支持类方法,那么方法名称应该属于案例1,但是,假设您有一个类 Money 那需要检查一下 narcissistic 如果你使用 Code.narcissistic?(money.value) 这会让其他人感到困惑(至少他们需要知道发生了什么) Code ),但如果您使用 MathUtils::NarcissisticNumbers.narcissistic?(money.value) ,别人马上就会明白那是一种查数的方法。
我建议你让我来 MathUtils::NarcissisticNumbers 是一个 module_function 并为其创建另一个模块 narcissistic? ```
module MathUtils::NarcissisticNumbers
module_function
def is_narcissistic?(number)
end
end

module Narcissistic
def narcissistic?
MathUtils::NarcissisticNumbers.is_narcissistic?(self.value)
end
end

class Code
include Narcissistic
end

class Money
include Narcissistic
end

code = Code.new(...)
code.narcissistic?

for those classes that only check narcissistic? internally

then you can include MathUtils::NarcissisticNumbers

since is_narcissistic?(number) become a private method

class FormatNumber
include MathUtils::NarcissisticNumbers
def format(number)
if is_narcissistic?(number)
# ...
else
# ...
end
end
end

you can use MathUtils::NarcissisticNumbers wherever you want (as helper)

on other classes that not include Narcissistic, including views , ...

<% if MathUtils::NarcissisticNumbers.is_narcissistic?(input) %>

b4wnujal

b4wnujal2#

我同意林已经写的大部分东西。但是,我将首先提取一个类,您将在模块中使用该类。类使处理数据变得更加容易(为了遵循建议,您的方法应该是max 5loc)。

class MathUtils::NarcissisticNumber
  def initialize(number)
    @number = number
  end

  def valid?
    checksum == number
  end

  private

  attr_reader :number

  def checksum
    digits.map { |d| d**exponent }.reduce(:+)
  end

  def digits
    @digits ||= number.to_s.chars.map(&:to_i)
  end

  def exponent
    @exponent ||= digits.length
  end
end

通过使用类,我们能够删除所有方法参数和临时变量。我们现在可以在liam建议的助手模块中使用这个类。

module MathUtils::NarcissisticNumbers
  def narcistic?(number)
    NarcissisticNumber.new(number).valid?
  end
end

相关问题