Создание и хранение общих методов c в ruby на рельсах - PullRequest
0 голосов
/ 13 июля 2020

Я создаю внутри приложения Ruby on Rails метод под названием «print», который может принимать любую строку и преобразовывать ее в png. Мне сказали, что создавать методы классов для базовых классов ruby, таких как String, Array или Ha sh, et c, нехорошо. поэтому "some string to print".print, вероятно, не то, что мне следует делать.

Я думал о создании подкласса String с именем Print (class Print < String) и сохранении его в моей папке lib / assets. Это будет выглядеть так: Print.new("some string to print"). Итак, мой вопрос: на правильном ли я пути, 1) создав подкласс из String и 2) сохранив его в lib / assets?

Любые рекомендации будут очень признательны!

1 Ответ

2 голосов
/ 13 июля 2020

Ответы на ваш вопрос обязательно будут субъективными, потому что всегда есть много ответов на вопрос «где разместить функциональность?», В соответствии с предпочтениями, принципами, привычками, обычаями и т. Д. c. Я перечислю несколько и опишу их, возможно, добавлю некоторые из моих личных мнений, но в конечном итоге вам придется выбрать и принять последствия.

Примечание: я обычно ссылаюсь на распространенный дегенеративный случай «потеря области пространства имен» или «так же плохо, как наличие глобальных методов».

Monkeypatch / Extend String

Удобный и очень «объектно-ориентированный» стиль за счет глобального воздействия на всех String в вашем приложении. Эта стоимость может быть большой, потому что это нарушает неявную границу между ядром Ruby и вашим приложением, а также разбрасывает компонент «вашего приложения» во внешнем месте. Функциональность будет иметь глобальную область видимости и в худшем случае будет непреднамеренно взаимодействовать с другими вещами, которых не должна.

Заслуживает упоминания 2: Ruby также позволяет вам includes модулей в существующие классы, например String.class_eval { include MyCustomization }, что немного лучше, потому что легче сказать, что настройка была сделана и где она была введена: "foo".method(:custom_method).owner покажет Это. Обычное исправление Monkeypatching сделает его так, как если бы метод был определен в самом String.

Utils Module

Обычно выполняется во всех языках программирования, модуль Util - это просто единое пространство имен, в котором класс методы / stati c методы сбрасываются. Это всегда вариант, чтобы избежать глобального загрязнения, но если Util все равно будет использоваться повсюду и будет заполнен до краев несвязанными методами, тогда значение пространства имен будет потеряно. Наличие метода в модуле Util обычно означает, что при организации кода было вложено недостаточно внимания, поскольку без обслуживания, в худшем случае, это не намного лучше, чем наличие глобальных методов.

Private Method

Предположим, он вам нужен только в одном классе - тогда его легко просто поместить в один частный метод. Что делать, если вам это нужно на многих занятиях? Следует ли сделать его частным методом в базовом классе? Если функциональность присуща классу, что-то связанное с идентичностью класса, тогда Да. При правильном использовании факт существования этого сообщения становится невидимым для компонентов за пределами этого класса.

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

Вспомогательный модуль

Многие разработчики Rails предложили бы разместить почти все эти служебные методы внутри модулей rails Helper . Вспомогательные модули представляют собой нечто среднее между опциями Utils Module и Private Method. Помощники включены и имеют доступ к частным членам, таким как частные методы, и предлагают независимость, как модули Utils (но не гарантируют это). Из-за этих свойств они имеют тенденцию появляться везде , теряя пространство имен, и в конечном итоге они получают доступ к закрытым членам друг друга, теряя независимость. Это означает, что он более мощный, но может легко стать намного хуже, чем отдельные методы class / stati c или частные методы.

Создайте класс

Если все вышеперечисленные случаи вырождаются в "глобальная область видимости", что, если мы принудительно создадим новую, меньшую область видимости посредством нового класса? Назначение нового класса будет заключаться только в том, чтобы принимать данные и преобразовывать их по запросу на выходе. Это общепринятая мудрость «создавать множество маленьких классов», так как маленькие классы будут иметь меньшую область действия и с ними будет легче работать. каждый из которых почти ничего не делает сам по себе. Вы избегаете комка грязи, но в итоге получаете кусочек супа, в котором каждая мелочь связана со всеми остальными мелочами. Это так же сложно, как иметь глобальные методы, все взаимосвязанные друг с другом, и вам не намного лучше. , вы можете подумать, что надежды нет, и все всегда в конечном итоге станет ужасно глобальным - Неправда! Важно понимать, что все они вырождают по-разному .

Возможно, функциональность 1, 2, 3, 4 ... 20, поскольку методы Util - это полный беспорядок, но они работают согласованно как функциональность A.1 ~ A.20 в пределах одного класса A. Возможно, класс B представляет собой полный беспорядок и лучше работает, разделив его на один метод Util и два частных метода в классе C.

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

Мой совет

У меня нет полного контекста вашего домена, и вы, вероятно, в любом случае не сможете так легко передать вопрос SO, поэтому я не могу быть уверен, что лучше всего подойдет вам.

Однако я отмечу, что, как правило, объединять вещи, чем разбивать их на части . Обычно я советую начинать с методов class / stati c. Поместите его в Util, а позже переместите в лучшее пространство имен (Printer?). Возможно, в будущем вы обнаружите, что многие из этих отдельных методов часто работают с одними и теми же входными данными, передавая одни и те же данные между ними - это может быть хорошим кандидатом для класса. Часто это проще, чем начать с одного класса или наследовать другой класс, а потом пытаться разбить функциональность на части.

...