Để có 1 dòng code Ruby đẹp
Bài đăng này đã không được cập nhật trong 6 năm
Ruby là một ngôn ngữ lập trình đẹp.
Ruby là một "ngôn ngữ lập trình mã nguồn mở tập trung vào sự đơn giản và hiệu quả. Nó có cú pháp tự nhiên, dễ đọc và dễ viết " được tạo ra bởi Matz , một kỹ sư phần mềm Nhật Bản.
Matz thường nói rằng ông "đang cố gắng làm cho Ruby tự nhiên, nhưng nó không đơn giản " phản chiếu cuộc sống của chúng ta.
Ruby nhìn thì đơn giản, nhưng bên trong lại rất phức tạp, giống như cơ thể của chúng ta vậy - Matz
Mảng
Tôi thấy Ruby là một ngôn ngữ lập trình phức tạp, nhưng rất tự nhiên, có cú pháp đẹp và trực quan. Để thể hiện điều này, tôi lấy vài ví dụ về cách xử lý trong mảng.
Map
Map "trả về một mảng mới với kết quả sau khi chạy một khối mã cho mỗi phần tử trong enum" . Ví dụ:
an_array.map { |element| element * element }
Nhìn thật đơn giản! Nhưng khi bạn mới làm quen với ruby, tôi cá là bạn sẽ sử dụng vòng lặp:
user_ids = []
users.each { |user| user_ids << user.id }
Cách đơn giản hơn để có một dòng code đẹp:
user_ids = users.map { |user| user.id }
Hoặc thậm chí đẹp hơn (và nhanh hơn):
user_ids = users.map(&:id)
Select
Khi dùng map
, đôi khi code của bạn nhìn như sau:
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]
Dùng map
để chọn các số chẵn nhưng cũng trả về đối tượng nil
. Vì vậy, bạn sử dụng compact
để loại bỏ tất cả các đối tượng nil
.
Come on, có thể làm tốt hơn với select
:
[1, 2, 3, 4, 5].select { |element| element.even? }
Chỉ cần một dòng đơn giản, dễ hiểu.
Bonus :
[1, 2, 3, 4, 5].select(&:even?)
Sample
Bạn cần lấy một phần tử ngẫu nhiên từ một mảng. Bạn chỉ mới bắt đầu học ruby, vì vậy suy nghĩ đầu tiên của bạn sẽ là dùng random
, và code ra thế này:
[1, 2, 3][rand(3)]
Dễ hiểu, nhưng không chắc là nó đủ tốt. Và nếu chúng ta sử dụng shuffle
thì sao?
[1, 2, 3].shuffle.first
Hmm. Tôi thực sự thích shuffle
thay vì rand
. Nhưng khi tôi phát hiện ra sample
, nó có ý nghĩa hơn rất nhiều:
[1, 2, 3].sample
Thực sự đơn giản, tự nhiên và trực quan. Chúng ta cần 1 số từ một mảng và phương thức sample
trả về nó.
Cú pháp
Như tôi đã đề cập trước đây, tôi thích cách code trong Ruby. Nó tự nhiên như trong ví dụ dưới đây.
Return
Bất kỳ một phương thức nào trong ruby đều trả về giá trị của biểu thức cuối cùng trong method đó. Ví dụ tôi gọi một phương thức và mong đợi một số giá trị trả về:
def get_user_ids(users)
return users.map(&:id)
end
Nhưng như đã biết, ruby luôn trả về giá trị của biểu thức cuối cùng, vậy tại sao phải sử dụng return
?
def get_user_ids(users)
users.map(&:id)
end
Từ khi biết điều này, tôi sử dụng hầu hết các phương thức mà không cần return
.
Multiple Assignments
Ruby cho phép gán nhiều biến cùng lúc. Khi mới bắt đầu, bạn có thể code thế này:
def values
[1, 2, 3]
end
one = values[0]
two = values[1]
three = values[2]
Sao không chỉ định nhiều biến cùng lúc?
def values
[1, 2, 3]
end
one, two, three = values
Tuyệt vời!
Phương thức dạng câu hỏi
Một trong số các tính năng thú vị trong Ruby là phương thức dạng câu hỏi. Bạn có thể code thế này:
movie.awesome # => true
Ok ... không sai. Nhưng thử sử dụng dấu hỏi:
movie.awesome? # => true
Nhìn diễn cảm hơn và thể hiện rằng phương thức trả về sẽ có giá trị true/false
.
Tôi hay sử dụng any?
. Nó check xem một mảng có phần tử nào thoả mãn điều kiện hay không.
[].any? # => false
[1, 2, 3].any? # => true
Interpolation
Đối với tôi, chuỗi interpolation
trực quan hơn so với chuỗi concatenation
.
Ví dụ chuỗi concatenation
:
programming_language = "Ruby"
programming_language + " is a beautiful programming_language" # => "Ruby is a beautiful programming_language"
Chuỗi interpolation
:
programming_language = "Ruby"
"#{programming_language} is a beautiful programming_language" # => "Ruby is a beautiful programming_language"
Tôi thích interpolation
. Còn bạn?
If
Một cách tôi thực sự thích khi sử dụng lệnh If:
def hey_ho?
true
end
puts "let’s go" if hey_ho?
Nhìn thật tự nhiên.
Try
Khi try
một phương thức hoặc thuộc tính nào đó của 1 object, nếu object đó không tồn tại thì sẽ trả về nil
.
Sử dụng if/unless
:
user.id unless user.nil?
Sử dụng try
:
user.try(:id)
Từ Ruby 2.3, chúng ta có thể sử dụng toán tử &.
thay cho try
:
user&.id
Double Pipe Equals/Memoization
Tính năng này rất tuyệt! Nó giống như việc lưu trữ một giá trị trong một biến.
some_variable ||= 10
puts some_variable # => 10
some_variable ||= 99
puts some_variable # => 10
Bạn không cần phải sử dụng khai báo nào cả. Chỉ cần ||=
và nó được thực hiện! Đơn giản và dễ dàng.
Class Static Method
Tôi muốn tạo một "static method" (class method).
GetSearchResult.call(params)
Đơn giản. Đẹp. Trực quan. Điều gì xảy ra đằng sau?
class GetSearchResult
def self.call(params)
new(params).call
end
def initialize(params)
@params = params
end
def call
# ... your code here ...
end
end
Phương thức self.call
khởi tạo một thể hiện và đối tượng này là phương thức call
.
Getters & Setters
Với class GetSearchResult
, nếu muốn sử dụng params
, chúng ta có thể sử dụng các 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
Định nghĩa một setter/getter
cho biến instance
này.
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
Hoặc có thể khai báo attr_reader
, attr_writer
hoặc 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
Không cần phải định nghĩa các phương thức getter và setter. Code trở nên thật đơn giản.
Tap
Ví dụ phương thức create_user
thiết lập các thông số, lưu và trả lại new user.
def create_user(params)
user = User.new
user.id = params[:id]
user.name = params[:name]
user.email = params[:email]
# ...
user.save
user
end
Không có gì sai ở đây. Nhưng nếu sử dụng phương thức 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
Chỉ cần quan tâm đến các tham số, và phương thức tap
sẽ trả về đối tượng người dùng cho bạn.
Happy Coding!
Nguồn: Medium
All rights reserved