Ідіоматичний Ruby: написання прекрасного коду

Ruby - прекрасна мова програмування.

Відповідно до офіційної веб-сторінки Рубі, Рубі є:

Динамічна мова програмування з відкритим кодом з акцентом на простоті та продуктивності. Він має елегантний синтаксис, який природно читати і легко писати ».

Ruby був створений Юкіхіро Мацумото, японським інженером-програмістом. З 2011 року він є головним дизайнером та інженером-програмістом Ruby в Heroku.

Мацумото часто говорив, що намагається зробити Рубі природною, а не простою , відбиваючи життя.

«Рубін на вигляд простий, але всередині дуже складний, як і наше людське тіло» - Юкіхіро Мацумото

Я відчуваю те саме до Рубі. Це складна, але дуже природна мова програмування з прекрасним та інтуїтивно зрозумілим синтаксисом.

Завдяки більш інтуїтивно зрозумілому та швидшому коду ми можемо створювати більш якісне програмне забезпечення. У цьому дописі я покажу вам, як я висловлюю свої думки (він же код) за допомогою Ruby, використовуючи фрагменти коду.

Висловлюючи свої думки методами масивів

Карта

Використовуйте метод map, щоб спростити свій код і отримати бажане.

Метод карта повертає новий масив з результатами роботи блоку один раз для кожного елемента в перерахуванні.

Давайте спробуємо:

an_array.map  element * element 

Просто як це.

Але коли ви починаєте кодування з Ruby, легко завжди користуватися кожним ітератором.

Кожен итератор , як показано нижче

user_ids = [] users.each user

Можна спростити за допомогою карти в одному красивому рядку коду:

user_ids = users.map  user.id 

Або ще краще (і швидше):

user_ids = users.map(&:id)

Виберіть

І коли ви звикли кодувати за допомогою карти , іноді ваш код може бути таким:

even_numbers = [1, 2, 3, 4, 5].map element # [ni, 2, nil, 4, nil] even_numbers = even_numbers.compact # [2, 4]

Використання карти для вибору лише парних чисел поверне значеннянульовий об'єкт. Використовуйте компактний метод, щоб видалити всі нульові об'єкти.

І ось, ви вибрали всі парні числа.

Місію виконано.

Давай, ми можемо зробити краще за це! Ви чули про метод select із переліченого модуля?

[1, 2, 3, 4, 5].select  

Всього один рядок. Простий код. Легко зрозуміти.

Бонус

[1, 2, 3, 4, 5].select(&:even?)

Зразок

Уявіть, що вам потрібно отримати випадковий елемент із масиву. Ви щойно почали вивчати Рубі, тож ваша перша думка буде: "Давайте скористаємося випадковим методом", і ось що трапляється:

[1, 2, 3][rand(3)]

Ну, ми можемо зрозуміти код, але я не впевнений, чи він достатньо хороший. А що, якщо ми застосуємо метод перетасовки ?

[1, 2, 3].shuffle.first

Хм Я насправді віддаю перевагу використанню перетасовки через rand . Але коли я виявив зразок методу, це мало набагато більше сенсу:

[1, 2, 3].sample

Справді, дуже просто.

Досить природний та інтуїтивно зрозумілий. Ми запитуємо зразок з масиву, і метод повертає його. Тепер я щаслива.

Що з вами?

Висловлюючи свої думки синтаксисом Рубі

Як я вже згадував раніше, мені подобається те, як Рубі дозволяє мені кодувати. Для мене це справді природно. Я покажу частини прекрасного синтаксису Ruby.

Неявне повернення

Будь-яке твердження в Ruby повертає значення останнього обчисленого виразу. Простий приклад - метод геттера . Ми викликаємо метод і очікуємо певне значення у відповідь.

Подивимось:

def get_user_ids(users) return users.map(&:id) end

Але, як ми знаємо, Рубі завжди повертає останній оцінений вираз. Навіщо використовувати оператор return ?

Після використання Ruby протягом 3 років я почуваюся чудово, використовуючи майже всі методи без оператора повернення .

def get_user_ids(users) users.map(&:id) end

Кілька завдань

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

Досить приголомшливо.

Методи, що задають питання (їх також називають предикатами)

One feature that caught my attention when I was learning Ruby was the question mark (?) method, also called the predicates methods. It was weird to see at first, but now it makes so much sense. You can write code like this:

movie.awesome # => true

Ok… nothing wrong with that. But let’s use the question mark:

movie.awesome? # => true

This code is much more expressive, and I expect the method’s answer to return either a true or false value.

A method that I commonly use is any? It’s like asking an array if it has anything inside it.

[].any? # => false [1, 2, 3].any? # => true

Interpolation

For me string interpolation is more intuitive than string concatenation. Period. Let’s see it in action.

An example of a string concatenation:

programming_language = "Ruby" programming_language + " is a beautiful programming_language" # => "Ruby is a beautiful programming_language"

An example of a string interpolation:

programming_language = "Ruby" "#{programming_language} is a beautiful programming_language" # => "Ruby is a beautiful programming_language"

I prefer string interpolation.

What do you think?

The if statement

I like to use the if statement:

def hey_ho? true end puts "let’s go" if hey_ho?

Pretty nice to code like that.

Feels really natural.

The try method (with Rails mode on)

The try method invokes the method identified by the symbol, passing it any arguments and/or the block specified. This is similar to Ruby’s Object#send. Unlike that method, nil will be returned if the receiving object is a nil object or NilClass.

Using if and unless condition statement:

user.id unless user.nil?

Using the try method:

user.try(:id)

Since Ruby 2.3, we can use Ruby’s safe navigation operator (&.) instead of Rails try method.

user&.id

Double pipe equals (||=) / memoization

This feature is so C-O-O-L. It’s like caching a value in a variable.

some_variable ||= 10 puts some_variable # => 10 some_variable ||= 99 puts some_variable # => 10

You don’t need to use the if statement ever. Just use double pipe equals (||=) and it’s done.

Simple and easy.

Class static method

One way I like to write Ruby classes is to define a static method (class method).

GetSearchResult.call(params)

Simple. Beautiful. Intuitive.

What happens in the background?

class GetSearchResult def self.call(params) new(params).call end def initialize(params) @params = params end def call # ... your code here ... end end

The self.call method initializes an instance, and this object calls the call method. Interactor design pattern uses it.

Getters and setters

For the same GetSearchResult class, if we want to use the params, we can use the @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

We define a setter and 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

Or we can define attr_reader, attr_writer, or 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

Nice.

We don’t need to define the getter and setter methods. The code just became simpler, just what we want.

Tap

Imagine you want to define a create_user method. This method will instantiate, set the parameters, and save and return the user.

Let’s do it.

def create_user(params) user = User.new user.id = params[:id] user.name = params[:name] user.email = params[:email] # ... user.save user end

Simple. Nothing wrong here.

So now let’s implement it with the tap method

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

You just need to worry about the user parameters, and the tap method will return the user object for you.

That’s it

We learned I write idiomatic Ruby by coding with

  • array methods
  • syntax

We also learned how Ruby is beautiful and intuitive, and runs even faster.

And that’s it, guys! I will be updating and including more details to my blog. The idea is to share great content, and the community helps to improve this post! ☺

I hope you guys appreciate the content and learned how to program beautiful code (and better software).

If you want a complete Ruby course, learn real-world coding skills and build projects, try One Month Ruby Bootcamp. See you there ☺

This post appeared first here on my Renaissance Developer publication.

Have fun, keep learning, and always keep coding!

My Twitter & Github. ☺