НЕНАВИЖУ, когда мой код выглядит как чудовищное количество условий.
If this, do that; else if this + 5, do this; else if this - 5, do this*5; else don't do anything.
Слишком много логики и никаких попыток ее упростить. Кому-то еще труднее понять это, не говоря уже о том, когда вы сами оглядываетесь на это позже. Должен быть количественный способ решить эту спагетти с кодом!
На Rails Conf 2014 Сэнди Мец выступил с отличным докладом Все мелочи, в котором говорится об этом.
Ее подход очень прост - возьмите свою огромную монолитную логику и разбейте ее на более мелкие, управляемые и повторно используемые компоненты. С остальным со временем разберетесь.
Вот несколько моих приемов уменьшения сложности:
Вернуться с вершины
Если у вас есть очень простая функция, которая сравнивает условие, чтобы вернуть значение, если оно совпадает, и другое, если оно не совпадает. Довольно простой сценарий.
def pretty_time(time) if time time.strftime("%B %e, %Y") else nil.to_s end end
Конечно, это не так уж плохо, но может выглядеть еще лучше, если вы сделаете это,
def pretty_time(time) return nil.to_s unless time time.strftime("%B %e, %Y") end
Вы можете попрощаться с вашими заявлениями о повешении else!
Отличные трубы
Символ трубы, || является фаворитом разработчиков Ruby. Вы можете быстро присвоить значения по умолчанию, когда переменная равна нулю.
> nil || 6 => 6
Но со струнами он не слишком дружит.
> "" || "six" => ""
Когда вы используете это с методом присутствия, происходит волшебство!
> "".presence || "six" => "six"
Попробуйте, попробуйте еще раз
Если бы я получал доллар каждый раз, когда сталкивался с ошибкой nil: NilClass, я был бы миллионером! Это сделало меня параноиком, чтобы повсюду использовать «если объект присутствует?».
if user.present? return user.name end
Фу! Есть способ лучше, просто продолжайте попытки.
user.try(:name)
Простой! Теперь, когда вашего пользователя не существует, он незаметно завершится ошибкой и вернет ноль.
Это работает и с методами (спасибо Стиву Робинсону за указание на это).
Если у вас есть метод под названием fullname, попробуйте это,
user.try(:fullname)
Отправка отправлена
У меня есть ужасная привычка организовывать второстепенных рабочих, как если бы они были логическими классами. Я имею в виду, что если у меня есть несколько задач, которые нужно обработать для пользователя в фоновом режиме, я помещаю их все в один воркер (если он не слишком большой). Этим легче управлять, и у меня не возникает проблем с рабочими, когда другие сотрудничают.
Поскольку у меня есть разные задачи, которые нужно обрабатывать для каждого вызова рабочего, я передаю «идентификатор». Что-то, что сообщает рабочему классу, какую функцию выполнять.
class UserWorker include Sidekiq::Worker def perform(action, options={}) if action == :welcome user.welcome_email(options) elsif action == :process user.process_profile_picture(options) elsif .... elsif .... end end end
УЖАСНО!
К счастью, есть более чистый способ сделать это. Вот где пригодится мощное метапрограммирование Ruby. Используйте send ().
Что такое отправка?
send( ) is an instance method of the Object class. The first argument to send( ) is the message that you're sending to the object - that is, the name of a method. You can use a string or a symbol, but symbols are preferred. Any remaining arguments are simply passed on to the method.
Итак, из приведенного выше беспорядка, вот как выглядит мой сокращенный рабочий.
class UserWorker include Sidekiq::Worker def perform(action, options={}) send(action, options) end def welcome(options) user.welcome_email(options) end def process(options) user.process_profile_picture(options) end end
Намного чище, и его намного легче расширить.
Переопределить
К этому конкретному совету нужно отнестись с недоверием. Это не для всех, и при неосторожном использовании может серьезно повредить вашей логике.
Что замечательно в Ruby, как жалобе на ООП, - это простота расширения базовых классов, таких как String, TrueClass и Integer. При осторожном использовании можно творить чудеса.
Я ненавижу выполнять условие if для логических значений, это просто неправильно. Что-то вроде этого,
"You are an admin" if user.admin
Мне пришлось бы создать специальную функцию в классе User, чтобы справиться с такой простой задачей, как печать сообщения, если атрибут истинен. Вот хитрый трюк,
class TrueClass def message(m) return m end end
Это переопределяет TrueClass, поэтому вы можете делать что-то столь же простое, как это,
user.admin.message("You are an admin")
Так просто! Теперь не забудьте обойти и FalseClass, чтобы не столкнуться с ошибками, связанными с отсутствием какого-либо метода.
class FalseClass def message(m) end end
С помощью этого небольшого трюка вы можете внести так много мелких изменений! Прокомментируйте ниже, если у вас есть собственные улучшения.
Sudo vs Root - это публикация, управляемая и управляемая Skcript.
Если вам понравилось это читать, нажмите «Рекомендовать» ниже. Ты классный.