Немного про подход к программированию

336 views
Skip to first unread message

Max Lapshin

unread,
Sep 30, 2012, 6:14:45 PM9/30/12
to RubyOnRails to russian
Рельсы — прекраснейший продукт. На момент выхода версий 2.3, они были
на несколько лет впереди всей остальной индустрии,
решая очень внятно обозначенный круг задач так оптимально, что даже
монстры типа Микрософта начали равняться на них.

При этом внутри код рельс никогда не был чем-то достойным особого
подражания. Код как код, местами довольно дрянной.

API рельс — прекрасен, кишки нет. Но пофиг, потому что юнит-тесты,
оперативное обновление, динамичное развитие.

Но с релизом 3 ситуация поменялась. На самом деле, проблема назрела
ещё раньше, когда группа «хакеров» (а на самом деле, бестолочей)
решила сделать merb под эгидой «пусть внутри будет красивый объектный код».

Сложно объяснить, в чём именно состояла проблема. Возможно в том, что
в руби так удобен манкипатчинг и для того, что бы он работал,
код должен быть буквально на каждой строчке распилен на методы
классов, возможно в том, что тяжелое наследие перла из людей просто
так
не выходит. Но сухой остаток таков: мерб был красив кодом, но так и не
смог превратиться во что-то работающее.


3-и рельсы создавались неоправданно долго и одной из причин было так
же то, что во главу угла вместо работоспособности и скорости, была
поставлена эфемерная внутренняя красота кода. Что это такое — описать сложно.


Но сухой остаток таков: «внутренняя красота кода» не дала никаких
реальных бонусов ни по скорости работы, ни по потребляемым ресурсам,
ни по скорости программирования (!). Термин «внутренняя красота кода»
в кавычках, потому что это крайне тонкое понятие,
которое можно в этом случае охарактеризовать скорее как «ООП головного мозга»


Недавно я столкнулся с особым проявлением такой «внутренней красоты»,
когда полез в библиотеку https://github.com/mojombo/grit
Не, Том молодец и при отсутствии внятной документации разобрался в
кишках гита. Молодец, спору нет. Но так писать нельзя.

Вот пример: https://github.com/mojombo/grit/blob/master/lib/grit/git-ruby/internal/pack.rb#L143
Вывернутое наизнанку управление кода с помощью лямбд
с адскими side-эффектами ни капельки не помогает сокращать код. Он
лишь растет и распухает, становясь рваным как коллбеки на
джаваскрипте.


Глядя на такой «ООП» код, начинаешь ценить простоту линейного кода на
C, который с копипащенными кусками всё таки прост, читаем и
поддерживаем.
Особенно это разительно при сравнении аналогичных кусков кода на Ruby
и на Erlang.


В самом деле: выделение куска кода в отдельный метод, который ещё и в
другом файле — очень серьезное действие, которое надо обдумать.
Если функция используется только один или два раза, то её вычленение
может быть серьезной ошибкой лишь ухудшающей читаемость.

Самое страшное, когда в борьбе с копипастой начинают выделяться
методы, которые немножко отличаются по их использованию в разных
местах.
В итоге начинаются всякие непонятные пробрасывания дополнительных
управляющих флагов. Ах, это ведь руби, здесь среди хипс.. хакеров не
принято
передавать управляющие флаги, надо запутать читающего, передав блок
внутрь обобщенной функции.

В итоге строк кода больше, читаемость меньше, хрупкость кода зашкаливает.

Слава богу, что ещё никто не посмотрел на монады в хаскеле и не
потащил их в ActiveSupport.

Резюме такое. Многие из модных библиотек написаны на самом деле не
очень хорошо. Они могут использовать всякие вычурные конструкции,
но практика показывает, что как правило, сделать модульную
архитектуру, не зная списка модулей, невозможно. Попытка сделать
обобщенную архитектуру
на все случаи жизни приводит к мербу (который, кстати, был непригоден
для ряда вещей =).

Код должен развиваться от потребностей, а не от пустого проектирования
на будущее и пользоваться языковыми средствами надо крайне аккуратно,
каждый раз отслеживая: действительно ли это помогает или это только
нагромождение кода.

Андрей

unread,
Sep 30, 2012, 6:46:23 PM9/30/12
to ror...@googlegroups.com
У меня perl головного  мозга. Я что хочу сказать - ruby не так то прост, как кажется на первый взгляд, даже для опытного программиста. Но вот то, что Макс описал, я не могу отнести к минусам, я же видел перл и еще пхп. Для меня руби очень удобен и достаточно понятен.

Сложно, конечно, разбираться в таких штуках, как rails, но там уже, в основном, нужно вникать в архитектуру самого решения и мысли тех, кто его писал.

sigmaray

unread,
Sep 30, 2012, 6:48:37 PM9/30/12
to ror...@googlegroups.com
​Раз в этом топике затрагивается вопрос разбиения на функции, хотел бы задать вопрос. У нас в конторе принято разбивать джаваскрипт код на функции, не превышающие 50 строчек. Даже если функция вызывается один раз. Мне это не нравится, но мне приводят аргумент, что не должно быть больших функций. И говорят, что если колбэк назначается нескольким элементам одновременно, то его нужно выносить в отдельную функцию, и передавать в bind указатель на эту функцию, чтобы код работал быстрее. Ваш пост можно спроецировать на джаваскрипт?

Андрей

unread,
Sep 30, 2012, 6:56:04 PM9/30/12
to ror...@googlegroups.com
Дело не в том, что функция должна быть не 50 а, скажем, 20 строк. Дело в том, что код должен дробиться так, что функции внутри кода должны быть как можно более универсальными. Добиться этого позволяет разбитие кода на части, в частности, соблюдение принципов DRY.

Дело тут в том, что DRY код сразу ты не напишешь, какого уровня разработчиком ты бы не являлся. Всегда приходится переписывать на несколько раз, и переписывать много. Разработчики с больщим опытом переписывают, остальные ленятся. Тут-то и отличие, как я думаю.

sigmaray

unread,
Sep 30, 2012, 7:07:52 PM9/30/12
to ror...@googlegroups.com
Проблема не только DRY. У нас в проекте ОЧЕНЬ МНОГО функций, которые вызываются один раз.

понедельник, 1 октября 2012 г., 1:56:08 UTC+3 пользователь Railman написал:

Zabazhanov Arkady

unread,
Sep 30, 2012, 10:44:56 PM9/30/12
to ror...@googlegroups.com
Весь руби построен на монадах. Нет смысла тащить их в активсуппорт.

Я тут относительно недавно нашёл рецепт хорошего кода: чистые функции и интерфейсы. Код сам будет складываться в прекрасное.

1 октября 2012 г., 6:07 пользователь sigmaray <sigm...@gmail.com> написал:
--
--
Данное сообщение отправлено Вам, так как Вы являетесь подписчиком группы "RubyOnRails to russian" на группах Google.
FAQ группы находится по адресу: http://ru.wikibooks.org/wiki/RubyFAQ
 
Для того, чтобы отправить сообщение в эту группу, пошлите его по адресу
ror...@googlegroups.com
Чтобы отменить подписку на эту группу, отправьте сообщение по адресу: ror2ru-un...@googlegroups.com
Дополнительные варианты находятся на странице группы http://groups.google.com/group/ror2ru?hl=ru

Павел Аргентов

unread,
Oct 1, 2012, 12:36:23 AM10/1/12
to ror...@googlegroups.com
Аркадий, заинтриговал :) Поясни фразу про монады (я в свое время
забросил хаскель именно из-за того, что ниасилил монады (ну, еще из-за
монстрообразности GHC))... И про чистые функции не совсем понял. Но
твой вектор разговора мне нравится!

1 октября 2012 г., 6:44 пользователь Zabazhanov Arkady
<kinw...@gmail.com> написал:

--
Yours truly, Pavel.

Zabazhanov Arkady

unread,
Oct 1, 2012, 12:59:23 AM10/1/12
to ror...@googlegroups.com
Одна из основных идей функционального программирования: чистые функции можно вызывать в любом порядке, даже в разных процессах, если результаты этих функций не используются в других функциях - суть от этого не поменяется. Чистые функции - это, скорее, математическая абстракция: данные на входе и результат на выходе. Больше ничего. Но иногда нам приходится выполнять функции по-порядку, даже, если они не связаны между собой. И для того, чтобы явно указать интерпретатору, что функции надо выполнять последовательно, вводится монада - фактически, оператор, или другая функция, типа: "сделай_раз; сделай_два; сделай_три". В этом псевдопсевдопсевдокоде монада - ";", оператор, который указывает, что функции надо выполнять именно по-очереди. Есть монады условного выполнения, например, которые говорят, что надо выполнять не только по-очереди, но и если результат выполнения предыдущей функции вообще был, был не нулевой.

Кароче, суть в том, что в руби все действия выполняются последовательно, есть условные операторы и много ещё чего, что является фактически синтаксическим сахаром для монад.

Чистые функции - суть функции в их математическом понимании. Они не имеют побочных эффектов. F(x, y). В руби это означает, что они не меняют контекст вокруг себя. Внутри классов - даже не трогают переменные класса. Конечно, ООП - это не функциональщина, но если стремиться разбивать свой код именно на чистые функции, оставляя побочные эффекты где-то в одном месте, в идеале - в коде самого верхнего уровня, то код получается намного более читабельный и понимабельный.

Третья история с интерфейсами. Тут просто пример:

def do_something_with_value value, context
  case value
  when String
    value.gsub(/#{context}/, '')
  when Integer
    (value + context.to_i).to_s
  end
end

Можно написать вот так. Но если этот код во внешней библиотеке - то в ним уже ничего не сделаешь.

def do_something_with_value value, context
  value.extract_special_value context if value.respond_to? :extract_special_value
end

А если сделать интерфейс в виде одной функции, то её можно будет добавить в любой класс, и у нас получится шикарная утковая типизация. С таким кодом удобно работать, понятно, откуда у него ноги растут.

1 октября 2012 г., 11:36 пользователь Павел Аргентов <arge...@gmail.com> написал:

Alex Vasyutin

unread,
Oct 1, 2012, 1:54:15 AM10/1/12
to ror...@googlegroups.com
Ликвидация кейзов это, скажем, классика:) 

Но в случае библиотечного кода такие вот синтетические
примеры, случается не взлетают, т.к. do_something_with_value будет содержать вагон разного рода логики.
И даже при наличии value.extract_special_value возможность повлиять на поведение целевого объекта(или что там предполагалось)
будет весьма ограниченной. И тут мы начинаем наследоваться, оверрайдить методы, вспоминать что-то про паттеры,
в общем все, как всегда:) 

Cобственно говоря, все отлично, и я не против и даже за, но раз про рецепты хорошего кода зашла речь -- 
по моим наблюдениям хороший код это такой код, которого мало:) Иногда лучше пренебречь моральными принципами
и кейз вставить, чем реализовывать решение претендующее на универсальность (даже в библиотечном коде) :)
Я когда с джавистами работал, насмотрелся на попытки pure oop -- до сих по ночами снится:)


Еще до кучи выскажусь про много функций, но не более 50-и строк (кто-то немного раньше упоминал о такой проблеме) --
по-моему вполне норм, даже если эти функции вызываются по одному разу, в том случае, если код становится более структурированным.
(ну и если функции не называются func1, func2… func50)

Третья история с интерфейсами. Тут просто пример:

def do_something_with_value value, context
  case value
  when String
    value.gsub(/#{context}/, '')
  when Integer
    (value + context.to_i).to_s
  end
end

Можно написать вот так. Но если этот код во внешней библиотеке - то в ним уже ничего не сделаешь.

def do_something_with_value value, context
  value.extract_special_value context if value.respond_to? :extract_special_value
end

-- 
Alex Vasyutin
Skype: alexander.vasyutin

Павел Аргентов

unread,
Oct 1, 2012, 2:16:41 AM10/1/12
to ror...@googlegroups.com
Спасибо. Очень внятно. В OCaml'e (там можно выбирать функ./оо по
вкусу) я столкнулся с интересной проблемой: как только ты идешь в
объектное царство, повсюду плодятся контексты и сайды, т.ч. методики
сколько-нибудь традиционного ФП теряют смысл. Ну, и vice versa.

Кстати, вопрос аудитории: как вам мысль Literate Programing? Макс не
поддержит (точнее, поддержит до тех пор, пока собственный гемор не
снивелирует красоту кода, что само по себе неплохо), это понятно. Но
вообще-то? Как сферическая идея в вакууме либо прикладная методика?
Руби ИМО тут не самый неудачный язык )

1 октября 2012 г., 8:59 пользователь Zabazhanov Arkady

Max Lapshin

unread,
Oct 1, 2012, 2:40:42 AM10/1/12
to ror...@googlegroups.com
2012/10/1 Alex Vasyutin <alex.v...@gmail.com>:

> Ликвидация кейзов это, скажем, классика:)
>
> Но в случае библиотечного кода такие вот синтетические
> примеры, случается не взлетают, т.к. do_something_with_value будет содержать
> вагон разного рода логики.

Угу. Это как раз классический пример ООП-штопора. Пишем библиотеку,
которая принимает String и Integer.
Думаем: о, надо заэкстрактить метод. Гадим в классы String и Integer.
Потом появляется Range, для которого надо вернуть среднее и отклонение
(т.е. уже два числа, а не 1).
Пишем метод do_something2, для которого делаем кейс внутри
библиотечного кода и пошло поехало.

А проблема в чём. Очень сложно написать библиотеку на все случаи
жизни. Я бы даже сказал: невозможно. Надо сначала все эти случаи в
голове удержать, а потом уже под них всех дизайнить.

И практика показывает, что зачастую лучше забить болт на потенциальную
расширяемость (которой в 99% никто не воспользуется),
и хорошо сделать то узкое подмножество функциональности, которое можно
отладить и протестировать.
Именно так и были написаны рельсы.


Приведу пример из личного опыта. erlyvideo 2 был очень расширяемым
сервером. В каждом месте было понатыкано возможностей для расширения.
Практика такова, что когда понадобилось этим всем пользоваться,
пришлось всё равно пилить тот код, который должен был быть предельно
расширяем. Это закончилось версией 3 в которой, например, жестко
захардкожен список входящих протоколов. И это работает!

Zabazhanov Arkady

unread,
Oct 1, 2012, 3:05:59 AM10/1/12
to ror...@googlegroups.com
Не, я не об этом писал. Нужно не заниматься экстрактом логики, а использовать интерфейсы. Далеко не каждый экстракт оправдан с точки зрения использования интерфейсов. Видимо, пример не очень удачный. Более уданый пример - метод blank? из AS. Он есть у каждого объекта, но реализует разную логику, в зависимости от класса. Так же, как и нельзя написать на руби полностью функциональный код (нет функций высшего порядка). Просто берём лучшие традиции и используем из по возможности.

А фанатизм, да, к хорошему не приводит.

1 октября 2012 г., 13:40 пользователь Max Lapshin <max.l...@gmail.com> написал:

Maxim Filatov

unread,
Oct 1, 2012, 3:19:57 AM10/1/12
to ror...@googlegroups.com
On Oct 1, 2012, at 11:05 AM, Zabazhanov Arkady <kinw...@gmail.com> wrote:

Так же, как и нельзя написать на руби полностью функциональный код (нет функций высшего порядка).

Я тут немного не в тему вклинюсь, но Jim Weirich на последнем FrozenRails показывал реализацию Y-combinator'a на руби.
Функции высшего порядка и все такое, да ;)


--
Best regards,
Maxim Filatov

Zabazhanov Arkady

unread,
Oct 1, 2012, 3:36:26 AM10/1/12
to ror...@googlegroups.com
Не, в питоне и в js они есть, а в руби их заменяют экземплярами объекта Proc. Но это таки не функции. Признаю, сформулировал я мысль неправильно, правильно так: "на руби не пишут полностью функциональный код, поскольку вместо функций высшего порядка там какой-то суррогат". В общем, симулировать можно, я даже видел очень крутую статью, где кусок кода был написан полностью функционально, но какой смысл?

1 октября 2012 г., 14:19 пользователь Maxim Filatov <pipo...@gmail.com> написал:

Max Lapshin

unread,
Oct 1, 2012, 3:53:28 AM10/1/12
to ror...@googlegroups.com
2012/10/1 Zabazhanov Arkady <kinw...@gmail.com>:

> Не, в питоне и в js они есть, а в руби их заменяют экземплярами объекта
> Proc. Но это таки не функции.


Это абсолюная болтовня. В руби есть отчуждаемые функции, которые можно
передавать в другие функции.
То, что они синтаксически немножко не похожи на джаваскрипт, не
отменяет того факта, что это функции.

И не отменяет того факта, что они не являются радикальным способом
упрощения кода.

Zabazhanov Arkady

unread,
Oct 1, 2012, 4:31:45 AM10/1/12
to ror...@googlegroups.com
Какая дурная привычка - называть болтовнёй все, что не соответствует твоему мировоззрению.

Классы ООП можно определить как множество функций. И на хаскеле можно писать в ООП стиле. Это всего лишь вопрос мировоззрения.

1 октября 2012 г., 14:53 пользователь Max Lapshin <max.l...@gmail.com> написал:

Max Lapshin

unread,
Oct 1, 2012, 5:03:19 AM10/1/12
to ror...@googlegroups.com
2012/10/1 Zabazhanov Arkady <kinw...@gmail.com>:

> Какая дурная привычка - называть болтовнёй все, что не соответствует твоему
> мировоззрению.
>
> Классы ООП можно определить как множество функций. И на хаскеле можно писать
> в ООП стиле. Это всего лишь вопрос мировоззрения.

Нет, это вопрос общей терминологии между людьми. Если ты заявляешь,
что в руби нет функций высшего
порядка, в то время, как все вокруг считают, что есть, ты должен
объяснить, почему ты так считаешь.

В противном случае, ты можешь назвать функцию классом и совершенно
запутать собеседника.

Maxim Kulkin

unread,
Oct 1, 2012, 5:22:45 AM10/1/12
to ror...@googlegroups.com
У вас у обоих абстрактная болтовня. Каждый дро.. эм... пишет как он хочет. Максиму, наверно, после Erlang императивный код Ruby кажется некрасивым. Я так и не пересел на Erlang, потому что мне его код кажется некрасивым.

Возвращаясь к первоначальному разговору про Rails 3, хочу поделиться своим опытом. Да, как Макс и написал, они там много лет занимались вещами, которые снаружи и не видны. Но, who cares ? Это же некоммерческая организация. Им не надо отчитываться о том, "как вон то изменение подняло продажи". Они закладывали основу для будущих фич, которые на коде Rails 2.x было сложно добавлять. Например, очень интересно выглядят Streaming и событийный API в Rails 4.

Но бывают и огорчения. Пилил я намедни магазин на основе Spree (see http://spreecommerce.com/). Поначалу все было хорошо: модульная структура, все view можно или подменить или пропатчить (see Deface). Но к концу проекта стало заметно, что эта громада безбожно тормозит в development режиме. На каждый запрос уходит секунд по 15 из-за того, что надо просмотреть кучу гемов и перегрузить кучу классиков. Я стал ощущать, что разработка на RoR приблизилась к разработке на Java и ASP.NET. Это уже не было ни радостно, ни быстро. Было проще включить кэширование классов и перезагружать сам сервер, нежели ждать перезагрузки при каждом запросе.

Второй мыслью стало, что некоторые фичи можно было бы написать руками, нежели подключать готовые модули, потому что 1) все равно готовые модули надо допиливать путем монкипатчинга; 2) это снизит количество гемов и, возможно, скорость перезагрузки приложения.

Вот такая печальная история про разработку на RoR.

Anton Ageev

unread,
Oct 1, 2012, 6:12:26 AM10/1/12
to ror...@googlegroups.com
2012/10/1 Maxim Kulkin <maxim....@gmail.com>:

> Но бывают и огорчения. Пилил я намедни магазин на основе Spree (see http://spreecommerce.com/). Поначалу все было хорошо: модульная структура, все view можно или подменить или пропатчить (see Deface). Но к концу проекта стало заметно, что эта громада безбожно тормозит в development режиме. На каждый запрос уходит секунд по 15 из-за того, что надо просмотреть кучу гемов и перегрузить кучу классиков. Я стал ощущать, что разработка на RoR приблизилась к разработке на Java и ASP.NET. Это уже не было ни радостно, ни быстро. Было проще включить кэширование классов и перезагружать сам сервер, нежели ждать перезагрузки при каждом запросе.

Я столкнулся с такой же проблемой при разработке на spree, но это было
на rails 3.0, в rails 3.2 перезагружаются только те файлы, которые
были изменены[1] (в отличии от rails 3.0, где перезагружаются ВСЕ
файлы).

[1]: http://weblog.rubyonrails.org/2011/12/19/rails-3-2-rc1-faster-dev-mode-routing-explain-queries-tagged-logger-store/

--
WBR, Anton

Maxim Kulkin

unread,
Oct 1, 2012, 6:18:50 AM10/1/12
to ror...@googlegroups.com
Будем надеяться.

Я свой проект начинал на Spree 1.0 и поэтому был привязан к Rails 3.1
(а при попытке апгрейда на Spree 1.1 повылазило куча несовместимых
гемов и всяких других ошибок).

2012/10/1 Anton Ageev <ant...@gmail.com>:

Eugene Hlyzov

unread,
Oct 1, 2012, 3:05:07 PM10/1/12
to ror...@googlegroups.com
В целом, согласен с Максом. Есть, например, задача. Задачу можно решить потратив несколько часов, но совсем грязно и потратив несколько дней но совсем чисто. Как ее делать в бОльшей степени определяется бизнес-целями. Иногда нужно обязательно все вылизывать, т.к. ядро и все-такое. А иногда, нужно пилить как можно быстрее, потому что бизнес получит фичу, опробует ее и.. выкинет. 

Фреймворк - отдельная история. Это рабочий инструмент и к нему есть вполне понятный набор требований - быстрота, стабильность, выдержанность стиля (чтобы поменьше удивлял пользователей). И сложно сказать, можно было бы довести Rails 2.3 до Rails 3.2 без соответствующего рефакторинга. Точнее, один человек может быть и смог бы, но их же там много :-)

Oleh Khomey

unread,
Oct 2, 2012, 7:30:43 PM10/2/12
to ror...@googlegroups.com
Рельсы уже давно не full stack. 
Идея живет и свою роль исполняет на все 110%. 
Любой менее-более популярный гем имеет либо _rails версию, либо "using with rails" секцию в документации.

Круче конструктора пока не встречал.

Проблема производительности в стороннем геме всегда всплывает неожиданно, но в случае рельсов в большинстве случаев решается или выбором альтернативного гема, или манки патчингом или форком за часик-второй (ну или GC потюнить, если нужно срочно на живом продакшине).

Все остальное — стандартная реакция на что-либо, чем долго пользуешся, возникающая из за обилия свободного времени, когда есть время не решать реальные задачи.

PS: 
1 - Да — третьи рельсы медленнее вторых. 
2 - Сoffescript или SASS удобнее коммитить уже собранным. У большинства ноуты производительнее  продакшн сервера.
3. С постом согласен, в основном из за того что у авторов 3-4 рельс та же проблема что и у вас — слишком много "свободного времени".

--
Regards,
Oleh Khomey


2012/10/1 Max Lapshin <max.l...@gmail.com>
Рельсы -- прекраснейший продукт. На момент выхода версий 2.3, они были

на несколько лет впереди всей остальной индустрии,
решая очень внятно обозначенный круг задач так оптимально, что даже
монстры типа Микрософта начали равняться на них.

При этом внутри код рельс никогда не был чем-то достойным особого
подражания. Код как код, местами довольно дрянной.

API рельс -- прекрасен, кишки нет. Но пофиг, потому что юнит-тесты,

оперативное обновление, динамичное развитие.



Но с релизом 3 ситуация поменялась. На самом деле, проблема назрела
ещё раньше, когда группа <<хакеров>> (а на самом деле, бестолочей)
решила сделать merb под эгидой <<пусть внутри будет красивый объектный код>>.

Сложно объяснить, в чём именно состояла проблема. Возможно в том, что
в руби так удобен манкипатчинг и для того, что бы он работал,
код должен быть буквально на каждой строчке распилен на методы
классов, возможно в том, что тяжелое наследие перла из людей просто
так
не выходит. Но сухой остаток таков: мерб был красив кодом, но так и не
смог превратиться во что-то работающее.


3-и рельсы создавались неоправданно долго и одной из причин было так
же то, что во главу угла вместо работоспособности и скорости, была
поставлена эфемерная внутренняя красота кода. Что это такое -- описать сложно.



Но сухой остаток таков: <<внутренняя красота кода>> не дала никаких
реальных бонусов ни по скорости работы, ни по потребляемым ресурсам,
ни по скорости программирования (!).  Термин <<внутренняя красота кода>>
в кавычках, потому что это крайне тонкое понятие,
которое можно в этом случае охарактеризовать скорее как <<ООП головного мозга>>


Недавно я столкнулся с особым проявлением такой <<внутренней красоты>>,
когда полез в библиотеку https://github.com/mojombo/grit
Не, Том молодец и при отсутствии внятной документации разобрался в
кишках гита. Молодец, спору нет. Но так писать нельзя.

Вот пример: https://github.com/mojombo/grit/blob/master/lib/grit/git-ruby/internal/pack.rb#L143
  Вывернутое наизнанку управление кода с помощью лямбд
с адскими side-эффектами ни капельки не помогает сокращать код. Он
лишь растет и распухает, становясь рваным как коллбеки на
джаваскрипте.


Глядя на такой <<ООП>> код, начинаешь ценить простоту линейного кода на
C, который с копипащенными кусками всё таки прост, читаем и
поддерживаем.
Особенно это разительно при сравнении аналогичных кусков кода на Ruby
и на Erlang.


В самом деле: выделение куска кода в отдельный метод, который ещё и в
другом файле -- очень серьезное действие, которое надо обдумать.

Если функция используется только один или два раза, то её вычленение
может быть серьезной ошибкой лишь ухудшающей читаемость.

Самое страшное, когда в борьбе с копипастой начинают выделяться
методы, которые немножко отличаются по их использованию в разных
местах.
В итоге начинаются всякие непонятные пробрасывания дополнительных
управляющих флагов. Ах, это ведь руби, здесь среди хипс.. хакеров не
принято
передавать управляющие флаги, надо запутать читающего, передав блок
внутрь обобщенной функции.

В итоге строк кода больше, читаемость меньше, хрупкость кода зашкаливает.



Слава богу, что ещё никто не посмотрел на монады в хаскеле и не
потащил их в ActiveSupport.



Резюме такое. Многие из модных библиотек написаны на самом деле не
очень хорошо. Они могут использовать всякие вычурные конструкции,
но практика показывает, что как правило, сделать модульную
архитектуру, не зная списка модулей, невозможно. Попытка сделать
обобщенную архитектуру
на все случаи жизни приводит к мербу (который, кстати, был непригоден
для ряда вещей =).

Код должен развиваться от потребностей, а не от пустого проектирования
на будущее и пользоваться языковыми средствами надо крайне аккуратно,
каждый раз отслеживая: действительно ли это помогает или это только
нагромождение кода.
Reply all
Reply to author
Forward
0 new messages