Ответы на ваш вопрос обязательно будут субъективными, потому что всегда есть много ответов на вопрос «где разместить функциональность?», В соответствии с предпочтениями, принципами, привычками, обычаями и т. Д. 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
?). Возможно, в будущем вы обнаружите, что многие из этих отдельных методов часто работают с одними и теми же входными данными, передавая одни и те же данные между ними - это может быть хорошим кандидатом для класса. Часто это проще, чем начать с одного класса или наследовать другой класс, а потом пытаться разбить функциональность на части.