Какой пример кода 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

Не то, чтобы я не соглашался с кешированием вычисления, это могло быть намного более ясным.