Какой пример кода Ruby, который "слишком умный"?
У меня была дискуссия с некоторыми друзьями-программистами, которые сказали, что они видят программистов Ruby (в частности), производящих много кода, который "слишком умный". Так что мне интересно, как это будет выглядеть? Я имею в виду ненужное использование неясной языковой функции в контексте, в котором что-то прямое работало бы так же хорошо или лучше. Знаете ли вы о хороших примерах Ruby?
Ответы
Ответ 1
После прямого ответа на ваш вопрос, я хотел бы также оспаривать помещение; всякий раз, когда группа программистов характеризует пользователей другого языка таким образом, скорее всего, они рассказывают вам больше о себе, чем о сообществе, которое они описывают.
Вы могли бы, например, обвинить c программистов в том, что они слишком одержимы деталями низкого уровня, или программисты haskell, ослепленные их стремлением к функциональной чистоте; perl mongers для краткости и т.д. Но вы бы, ИМХО, путем получения причинности назад, когда вы это сделаете.
Когда я хочу написать программу, которая лучше всего выражается в определенном стиле, я пытаюсь выбрать язык, поддерживающий этот стиль. Иногда вам нужен инструмент, который позволяет вам делать необычные вещи, и для такой задачи с таким языком, как рубин, столь же ценно, как наличие математики для математики или javascript для манипулирования браузером в вашем наборе инструментов. Если я хочу играть с типографикой, я прыгаю в постскриптум, потому что это лучше всего.
Мне нравится говорить: "Вы когда-нибудь замечали, что люди, которые используют силовые упражнения, всегда дырят в вещах?" Это правда, но это как-то не по себе.
Ответ 2
class Tree
def initialize*d;@d,=d;end
def to_s;@l||@r?"<#{@d},<#{@l}>,<#{@r}>>":@d;end
def total;(@d.is_a?(Numeric)[email protected]:0)+(@[email protected]: 0)+(@[email protected]: 0);end
def insert d
alias g instance_variable_get
p=lambda{|s,o|d.to_s.send(o,@d.to_s)&&
(g(s).nil??instance_variable_set(s,Tree.new(d)):g(s).insert(d))}
@d?p[:@l,:<]||p[:@r,:>]:@d=d
end
end
Ответ 3
Двойной взрыв:!! что-то
Я не собираюсь писать, что он делает. Забудьте, что вы когда-либо видели этот синтаксис.
Ответ 4
Выходная фаза yaml.rb; поэтому я стал соавтором zaml.rb. Стандартная версия yaml выполняет всевозможные метапрограммирование (она была изначально написана почему-то, что я обычно восхищаюсь), но, заменив ее прямой иерархической версией, которая непосредственно сопоставляется с деревом классов, мы смогли устранить несколько случаев O (n ^ 3), что приводит к коэффициенту десяти ускорения для интересующих случаев, исправляет несколько ошибок и делает это во фракции кода.
Кроме того, даже люди, не являющиеся рубиновыми гуру, могут видеть, что он делает.
Ответ 5
Многие из примеров в этой статье, по-видимому, квалифицируются:
21 Ruby Tricks, которые вы должны использовать в своем собственном коде.
Название статьи было немного дешевой, учитывая, что она гласит: "Должен" вместо "Не должно". Код "должен" быть прозрачным. Код "не должен" быть сложным.
Ответ 6
Любое использование метапрограммирования, не задумываясь о том, есть ли лучший способ добиться этого, используя нормальные, не-йета-идиомы языка, я склоняюсь к раздражению.
Одержимость "СУХОЙ" (не повторяйте себя), где задействован какой-то дьявольский кусок метапрограммирующих спагетти, чтобы не повторять себя, скажем, дважды в простой и на самом деле, более простой и понятной, чем - альтернативная мода.
Любое использование "eval" в частности. Как метапрограммирование идет, это должно быть вашим абсолютным последним средством после пробовать все остальное. например, многие рубисты, похоже, не слышали о классе # define_method.
Ответ 7
Я не уверен, что это квалифицируется как "слишком умно", но я видел код, который заставлял меня задаться вопросом, был ли автор либо гением, либо идиотом. У одного разработчика, похоже, было правило, что ни один метод не должен содержать более двух строк кода. Это очень сильно подтолкнуло стек вызовов и затруднило отладку. Поверхность заключается в том, что его общий дизайн был очень абстрактным и даже элегантным на расстоянии.
Ответ 8
Cucumber (или RSpec Stories)
Цитата из приведенной ссылки RSpec Stories:
Основываясь на простых текстовых описаниях поведения приложения, он позволяет вам написать интеграционные тесты с хорошими повторное использование и хорошую диагностическую отчетность.
Например, здесь рассказ, который я написал проверьте процесс входа в систему.
Story: login as an existing user
As an unauthenticated user
I want to log in to Expectnation
So I can see my account details
Scenario: login details are correct
Given an event provider
And my [email protected] account
When I log in with email [email protected] and password foofoo
Then I will be logged in
And I will be shown the account page
Такие слова, как "Дано", "Когда" и "Тогда" - это реплики для рассказчика выполнить некоторый код. За историей сидит набор шагов. Здесь пару шагов от этого теста:
Given "my $email account" do |email|
@user = find_or_create_user_by_email({:email => email,
:password => 'foofoo',
:password_confirmation => 'foofoo'})
end
When "I log in with email $email and password $password" do |email, password|
post '/user/account/authenticate',
:user => {:email => email, :password => password}
end
Обратите внимание, как умный бит строки сопоставление позволяет вам передавать параметры из прозаической истории.
С небольшим количеством болтовки истории прозы затем запускаются как код и выполняются тесты.
Ответ 9
Это зависит. (Я люблю "это зависит" )
Это зависит от знания писателя и читателя. Я думал, что использование Symbol # to_proc в Rails было излишне загадочным, например, предпочитая
a.map { |e| e.downcase }
к
a.map(&:downcase)
Теперь я счастлив, когда прочитал его, хотя я все еще не думаю, что он его написал.
Есть области библиотек (Rails и др.), в которых я ощущал чрезмерное и самонадеянное метапрограммирование, но опять-таки разделение между "слишком умным" и "действительно очень умным" часто бывает бумажным. DSL - хорошая область: способы, с помощью которых "макросы" становятся доступными в классах (подумайте обо всем, что декларативная доброта в таких вещах, как ActiveRecord:: Base или ActionController:: Base) очень сложно для относительного начинающего понять и, вероятно, кажутся чрезмерными. Это было со мной. Теперь я нахожу, что ссылаюсь на один и тот же код для руководства, когда реализую аналогичные возможности.
Ответ 10
method_missing можно злоупотреблять, и это одна из тех вещей, которые могут заставить вас вытащить ваши волосы, когда вам нужно исправить ошибку через 3 месяца после того, как вы написали код.
Ответ 11
Взгляните на источник Маркаби. Insanity.
Ответ 12
Вам не нужно переходить от метода к методу, чтобы попытаться выяснить, что, черт возьми, что-то делает, с единственной целью не повторять несколько строк кода. Быть слишком сосредоточенным на подсчете LOC и ультра-тощих методах может показаться прохладным в то время, но отнимает много времени для того, чтобы кто-то еще пытался отлаживать или следовать коду (и что кто-то может быть вам месяцами позже).
Ответ 13
сравнить:
if MODELS.keys.inject(true) {|b, klass| b and klass.constantize.columns.map(&:name).include? association.options [:foreign_key]} then
# ...
end
1 строка (если), 132 символа, 132 avg len, 22.9 fl og
против
fk = association.options[:foreign_key]
columns = MODELS.keys.map { |key| key.constantize.columns.map { |c| c.name } }
if columns.all? {|column| column.include? fk} then
# ...
end
4 строки, 172 символа, 43 символа avg, 15.9 fl og
намного быстрее.
Оригинальный автор фактически утверждал ремонтопригодность для первой версии.
Ответ 14
Недавно обнаружил этого монстра:
def id
unless defined?(@id)
@id = if id = local_body.to_s[/(?:#\s*|@[[:punct:]]?)#{URL_REGEX}/,1]
id.to_i
end
end
@id
end
Не то, чтобы я не соглашался с кешированием вычисления, это могло быть намного более ясным.