惯用的 Ruby:编写漂亮的代码
Ruby 是一种优美的编程语言。
根据Ruby的官方网页,Ruby 是:
“动态的开源编程语言,注重简洁性和生产力。它语法优雅,阅读自然,易于编写。”
Ruby 的创始人是日本软件工程师松本行弘 (Yukihiro Matsumoto)。自 2011 年起,他一直担任Heroku的 Ruby 首席设计师兼软件工程师。
松本经常说,他试图让 Ruby 变得自然,而不是简单,以一种反映生活的方式。
“Ruby 外表简单,但内部却非常复杂,就像我们人体一样”——松本行弘
我对 Ruby 也有同样的感受。它是一种复杂但非常自然的编程语言,语法优美直观。
有了更直观、更快速的代码,我们就能构建更好的软件。在这篇文章中,我将向你展示如何用 Ruby 代码片段来表达我的想法(也就是代码)。
用数组方法表达我的想法
地图
使用map方法简化你的代码并得到你想要的。
方法map返回一个新数组,其中包含对枚举中的每个元素运行一次块的结果。
让我们尝试一下:
an_array.map { |element| element * element }
就这么简单。
但是当您开始使用 Ruby 编码时,总是很容易使用each迭代器。
each迭代器如下所示
user_ids = []
users.each { |user| user_ids << user.id }
可以用一行漂亮的代码简化map :
user_ids = users.map { |user| user.id }
或者甚至更好(更快):
user_ids = users.map(&:id)
选择
当你习惯使用map进行编码时,有时你的代码可能是这样的:
even_numbers = [1, 2, 3, 4, 5].map { |element| element if element.even? } # [ni, 2, nil, 4, nil]
even_numbers = even_numbers.compact # [2, 4]
nil对象也是如此。使用compact方法删除所有nil对象。
瞧,您已选择所有偶数。
任务完成。
来吧,我们可以做得更好!你听说过enumerable 模块中的select方法吗?
[1, 2, 3, 4, 5].select { |element| element.even? }
只需一行。简单的代码。易于理解。
奖金
[1, 2, 3, 4, 5].select(&:even?)
样本
想象一下,你需要从数组中获取一个随机元素。你刚刚开始学习 Ruby,所以你的第一个想法可能是“让我们使用random方法”,接下来会发生以下情况:
[1, 2, 3][rand(3)]
好吧,我们可以理解这段代码,但我不确定它是否足够好。如果我们使用shuffle方法呢?
[1, 2, 3].shuffle.first
嗯。其实我更喜欢用shuffle而不是rand。不过我发现了sample方法之后,感觉更合理了:
[1, 2, 3].sample
真的,真的很简单。
非常自然直观。我们从数组中请求一个样本,该方法返回它。现在我很满意了。
你呢?
用 Ruby 语法表达我的想法
正如我之前提到的,我喜欢 Ruby 的编程方式。它对我来说非常自然。我将展示 Ruby 优美语法的部分内容。
隐式回报
Ruby 中的任何语句都会返回最后一个表达式的值。一个简单的例子就是 **getter** 方法。我们调用一个方法并期望返回一些值。
让我们来看看:
def get_user_ids(users)
return users.map(&:id)
end
但我们知道,Ruby 总是返回最后一个求值的表达式。为什么要使用return语句?
def get_user_ids(users)
users.map(&:id)
end
使用 Ruby 3 年后,我感觉使用几乎所有没有return语句的方法都很棒。
多项任务
Ruby 允许我同时赋值多个变量。刚开始的时候,你可能会像这样写代码:
def values
[1, 2, 3]
end
one = values[0]
two = values[1]
three = values[2]
但为什么不同时赋值多个变量呢?
def values
[1, 2, 3]
end
one, two, three = values
非常棒。
提出问题的方法(也称为谓词)
我在学习 Ruby 时,一个引起我注意的特性是问号(?)方法,也称为谓词方法。一开始看起来很奇怪,但现在它变得非常有意义了。你可以像这样编写代码:
movie.awesome # => true
好吧……这没什么问题。但我们用问号:
movie.awesome? # => true
这段代码更具表现力,我希望该方法的答案返回真值或假值。
我常用的方法是any?这就像询问一个数组里面是否有东西。
[].any? # => false
[1, 2, 3].any? # => true
插值
对我来说,字符串插值比字符串连接更直观。就是这样。我们来实际看看。
字符串连接的示例:
programming_language = "Ruby"
programming_language + " is a beautiful programming_language" # => "Ruby is a beautiful programming_language"
字符串插值的示例:
programming_language = "Ruby"
"#{programming_language} is a beautiful programming_language" # => "Ruby is a beautiful programming_language"
我更喜欢字符串插值。
你怎么认为?
if 语句
我喜欢使用if语句:
def hey_ho?
true
end
puts "let’s go" if hey_ho?
像这样编写代码真是太好了。
感觉非常自然。
try 方法(Rails 模式开启)
try方法会调用由符号标识的方法,并向其传递任意参数和/或指定的代码块。这类似于 Ruby 的Object#send 方法。与该方法不同的是,如果接收对象是nil对象或NilClass,则返回nil 。
使用if 和 unless条件语句:
user.id unless user.nil?
使用**try**方法:
user.try(:id)
从 Ruby 2.3 开始,我们可以使用 Ruby 的安全导航运算符** (&.)** 代替 Rails 的 **try ** 方法。
user&.id
双管道等于 (||=) / 记忆
这个功能太酷了。就像把值缓存在变量里一样。
some_variable ||= 10
puts some_variable # => 10
some_variable ||= 99
puts some_variable # => 10
你根本不需要使用if语句。只需使用双竖线等于号(||=)即可。
簡單又容易。
类静态方法
我喜欢编写 Ruby 类的一种方法是定义一个**静态**方法(类方法)。
GetSearchResult.call(params)
简单。美观。直观。
后台发生了什么?
class GetSearchResult
def self.call(params)
new(params).call
end
def initialize(params)
@params = params
end
def call
# ... your code here ...
end
end
self.call方法初始化一个实例,该对象调用 **call ** 方法。Interactor设计模式使用它。
Getter 和 Setter
对于相同的GetSearchResult类,如果我们想使用参数,我们可以使用 @params
class GetSearchResult
def self.call(params)
new(params).call
end
def initialize(params)
@params = params
end
def call
# ... your code here ...
@params # do something with @params
end
end
我们定义一个setter **和 **getter:
class GetSearchResult
def self.call(params)
new(params).call
end
def initialize(params)
@params = params
end
def call
# ... your code here ...
params # do something with params method here
end
private
def params
@params
end
def params=(parameters)
@params = parameters
end
end
或者我们可以定义attr_reader、attr_writer或attr_accessor
class GetSearchResult
attr_reader :param
def self.call(params)
new(params).call
end
def initialize(params)
@params = params
end
def call
# ... your code here ...
params # do something with params method here
end
end
好的。
我们不需要定义getter和setter方法。代码变得更简单了,这正是我们想要的。
轻敲
假设你要定义一个create_user方法。此方法将实例化、设置参数、保存并返回用户。
我们开始做吧。
def create_user(params)
user = User.new
user.id = params[:id]
user.name = params[:name]
user.email = params[:email]
# ...
user.save
user
end
很简单。没什么问题。
现在让我们用tap方法来实现它
def create_user(params)
User.new.tap do |user|
user.id = params[:id]
user.name = params[:name]
user.email = params[:email]
# ...
user.save
end
end
您只需要担心用户参数,tap方法将为您返回用户对象。
就是这样
我们学会了如何使用 Ruby 语言进行编码来编写惯用的 Ruby
-
数组方法
-
句法
我们还了解到 Ruby 是多么的美观和直观,而且运行速度更快。
就这样吧,伙计们!我会更新我的博客,并添加更多细节。我的想法是分享精彩内容,也希望社区能帮助改进这篇文章!☺
我希望你们喜欢这些内容并学会如何编写漂亮的代码(和更好的软件)。
如果你想要完整的 Ruby 课程,学习实际的编程技能并构建项目,那就试试“一个月 Ruby 训练营”吧。到时候见☺
这篇文章最初出现在我的Renaissance Developer 出版物中。
玩得开心,继续学习,并始终坚持编码!
我的Medium、Twitter、Github和LinkedIn。☺
文章来源:https://dev.to/teekay/idiomatic-ruby-writing-beautiful-code-56ef