среда, 2 марта 2011 г.

Красивый код

ruby Благодаря некоторым особенностям Ruby, код на нем можно писать значительно более лаконичный, чем вы можете себе это представить. Например, благодаря тому, что Ruby возвращает значение последнего выражения, можно сократить количество кода не только за счет отказа от использования return, там, где это возможно, но и за счет написания простых методов, которые в итоге своей работы возвращают только true или false не используя при этом логический конструкций типа if..else, и т.д.





Пример:

1def young? (age)
2  if age < 30
3    return true
4  else
5    return false
6  end
7end
Данный код мы можем переписать следующим образом:

1def a_bigger? (a, b)
2  a > b
3end
Мы сократили код в 2 раза! И не потеряли при этом его ясности.
Давайте представим, что у нас есть следующий код:

1breakfast = nil
2if breakfast == nil
3  breakfast = "глазунья с беконом"
4end
Как его можно улучшить? Давайте попробуем воспользоваться методом nil? вместо сравнения с объектом nil:

1if breakfast.nil?
2  breakfast = "глазунья с беконом"
3end
Можно ли еще улучшить код? – Конечно!

1if !breakfast
2  breakfast = "глазунья с беконом"
3end
Конструкция if !… – это то же самое, что и unless:

1unless breakfast
2  breakfast = "глазунья с беконом"
3end
Можно ли сделать еще лучше? – Делаем!

1breakfast = "глазунья с беконом" unless breakfast
Хотите еще лучше?! Получите!

1breakfast || = "глазунья с беконом"
Уже устали? А ведь это только начало статьи об оптимизации кода!
Допустим у нас есть следующий код:

1val =12
2if val == 1 || val == 12 || val == 42
3  puts "е-ху!"
4end
Сразу видно, что мы повторяемся, а именно повторяме операцию сравнения. Терпеливый программист может позволить себе написать 10 и 20 и 100 проверок, но ленивый и умный программист сделает следующим образом:

1if [1,12,42].include?(val)
2  puts "е-ху!"
3end
С помощью вышеописанных приемов мы можем сделать код еще более лаконичным, например:

1puts "е-ху!" if [1,12,42].include?(val)
Еще один пример оптимизации кода. Допустим, нам необходимо добавить в массив уникальное значение, для этого, разумеется, необходимо сделать проверку, имеется ли в массиве такой же элемент, как тот, что мы хотим добавить, в результате мы пишем следующий код:

1fruits = ['apple', 'banana', 'apricot']
2
fruits << 'apple' unless fruits.include?('apple')

Оказывается можно сделать проще! пример:

1fruits |= ['apple']

Метод | присоединяет к первому массиву второй удаляя при этом повторяющиеся элементы.
Давайте представим, что у нас имеется следующий монстро-код, с которым срочно необходимо что-то сделать:

1user_id = nil
2if comments
3  if comments.first
4    if comments.first.user
5      user_id = comments.first.user.id
6    end
7  end
8end
Этот код можно легко уложить в одну строку и не повторять надоедливые блоки if…end:

1user_id = comments && Comments.first && comments.first.user && comments.first.user.id

Логические операции производятся в порядке слева направо и возвращается значение последнего выражения – значит все отлично!
Вы можете вставлять код непосредственно в строку при этом сам код в итоге будет заменен на результат его выполнения, но для этого сам код необходимо поместить в “магические” скобки.
Пример без магических скобок:

1puts "User name:" + name.capitalize + "\n user last name:" + lastname.capitalize + "\n user father name:" + ...
Делаем как лучше:

1puts "User name: #{name.capitalize}\n user last name: #{lastname.capitalize}\n user father name: ..."

Нельзя сказать, что код вышел короче, зато нет путаницы с кавычками!
Представьте, что у нас есть массив:

1a = ['ant', 'bee', 'cat', 'dog', 'elk']

Существует более короткий способ создания подобных массивов:
1a = %w{ ant bee catdog elk}
Не стоит забывать об итераторах. Код:

1for i in 0..9
2  puts i
3end

Используя итератор times мы можем записать тот же функционал более изящно:

110.times {|i| puts i}
Еще один пример того, как итераторы делают жизнь лучше:

1for i in 0...people.size
2  puts people[i].name
3end

Используя итератор each мы добиваемся совершенства:

1people.each {|p| puts p.name}

Благодарю Karmen Blake (karmenblake) за предоставление большинства примеров кода к этому посту.

источник: http://rubydev.ru/2010/10/ruby-and-beautiful-code/

2 комментария:

  1. Жестко, у меня голова кругом идет когда я пытаюсь представить такой код =)

    ОтветитьУдалить
  2. А мне нравится рубин, но Си всё же надежней!

    ОтветитьУдалить