Для языков, поддерживающих функции, такой класс, несомненно, является плохим тоном.
Для языков, которые этого не делают, такого класса нет и, вероятно, он лучше, чем расширение других классов с помощью случайных служебных методов. Статические служебные методы, поскольку они принадлежат к другому классу, могут использовать только открытый интерфейс обрабатываемых ими объектов, что снижает вероятность определенных видов ошибок. И этот подход также позволяет избежать загрязнения общедоступных интерфейсов случайным набором всего, что люди сочли полезным в то время.
Конечно, здесь присутствует определенная доля личного стиля. Я не очень-то верю в классы, которые предоставляют все необходимое (даже C ++ std :: string
, на мой вкус, немного перегружен) и предпочитаю иметь вспомогательные функции как отдельные функции. Облегчает обслуживание класса, заставляет общедоступный интерфейс быть полезным и эффективным, а с механизмами стиля утиной печати внешние функции могут использоваться в широком диапазоне типов без необходимости дублировать исходный текст или совместно использовать базовые классы и т. Д. (Часто высмеиваемые алгоритмы в стандартной библиотеке C ++ являются хорошей демонстрацией этого, хотя они и несовершенны и многословны.)
Тем не менее, я работал со многими, кто жалуется на строки, которые не знают, как интерпретировать сами как имена файлов, или разбиваются на слова, или что у вас, и так далее. (Я выбираю строки, потому что они кажутся основной целью служебных функций ...Я думаю, что наличие таких больших классов сопряжено с невидимыми затратами на обслуживание и надежность, совершенно не считая уродства номинально простого класса, который на самом деле представляет собой огромную нелогичную мешанину не связанных между собой проблем, чьи грязные пальцы в конечном итоге проникают в каждую секунду. угол - потому что вашей самотокенизирующейся строке нужен какой-то контейнер для размещения токенов, верно ?! - но это балансирующий акт, даже если моя формулировка предполагает более четкую формулировку, чем это.
Я не очень верю в понятие "догмы ОО", но, возможно, параноик увидит здесь это в действии. Нет веских причин, по которым все функции должны быть привязаны к определенному классу, и многих веских причин, почему этого не следует делать. Но некоторые языки по-прежнему не позволяют создавать функции, что ничего не делает для устранения необходимости в них и заставляет людей обходить ограничение, создавая классы, состоящие только из статических методов. На мой взгляд, это, скорее, перегружает смысл концепции класса, и это не очень хорошо.
Это хороший повод возразить против этой практики, но это бесполезно, если только язык не изменится, чтобы приспособиться к тому, что люди должны делать. И языки не обходятся без функций, если у их разработчиков нет проблем, которые нужно заткнуть, или для этого есть технические причины, поэтому я думаю, что изменение в любом случае маловероятно.
Я полагаю, что краткое изложение: нет.
Скорее всего, удобно.
Скорее всего, он может вырасти в страшного и сложного в обслуживании швейцарского армейского ракетопила и полировщика полов.
Я бы рекомендовал разделить различные задачи на отдельные классы, с некоторой логической группировкой, кроме «больше нигде не поместится».
Риск здесь состоит в том, что класс превращается в запутанный беспорядок, который никто полностью не понимает, и никто не осмеливается трогать - или заменять. Если вы считаете, что это приемлемый риск и / или которого можно избежать в ваших обстоятельствах, ничто не мешает вам его использовать.
Я храню отдельный класс misc для каждого проекта и копирую / вставляю код из других проектов по мере необходимости. Возможно, это не лучший подход, но я предпочитаю избегать межпроектных зависимостей.
Примеры вещей в моем вспомогательном классе:
Многие из них полезны только при работе с двоичными данными, но ни один из них на самом деле не зависит от предметной области. Возможно, первые шесть могли бы войти в модуль BinaryHelpers, но я не уверен, куда должен идти Zap, кроме как в классе утилит разного назначения.
Ну, плохие служебные классы высмеиваются на TheDailyWTF :)
На самом деле нет ничего плохого в том, чтобы иметь общий служебный класс для различных статических бизнес-функций. Я имею в виду, вы могли бы попытаться поместить все это в более объектно-ориентированный подход, но какой ценой времени и усилий для бизнеса и какого компромисса с ремонтопригодностью? Если последнее перевешивает первое, дерзайте.
Один из подходов, который вы можете принять в зависимости от языка и т. Д., - это, возможно, переместить часть логики в расширения существующих объектов. Например, расширение класса String (здесь мы думаем на C #) с помощью метода, который пытается преобразовать строку в DateTime. Собственная библиотека расширений просто улучшает язык с помощью собственных небольших DSL вашего бизнеса.
В своих личных проектах я держу разную библиотеку, но вместо того, чтобы добавлять ссылку в свои проекты, я вставляю соответствующие фрагменты кода в соответствующие места. Технически это дублируется, но не в рамках единого решения, и это важно. Однако я не думаю, что это сработает в большем масштабе, слишком беспорядочно.
Обычно у меня нет проблем с ними, хотя, как и со всеми вещами, ими можно злоупотреблять:
В зависимости от того, что действительно делают и возвращают ваши статические служебные функции, это может вызывать проблемы при модульном тестировании. Я наткнулся на метод в классе, который вызывает статическую функцию статического класса, которая возвращает то, что мне не нужно в моем модульном тесте, делая весь метод непроверяемым ...
Компания, в которой я работаю, имеет такой класс в своем репозитории. Лично меня это раздражает, потому что вы должны быть действительно близки с классом, чтобы знать, для чего он полезен. Следовательно, я обнаружил, что переписываю методы, которые уже охватывает этот класс! Вдвойне раздражает, потому что я зря потратил время.
Я бы предпочел более объектно-ориентированный подход, который привел бы к расширяемости. Обязательно имейте класс Utilities, но внутри него поместите другие классы, которые расширяются до определенной функциональности. Например, Utilities.XML, Utilities.DataFunctions, Utilities.WhateverYouWant. Таким образом, вы можете расширить и в конечном итоге взять свой класс MiscUtilities из 20 функций и превратить его в библиотеку классов функций из 500.
Подобная библиотека классов может быть использована кем угодно и добавлена кем угодно (с привилегиями) логически организованным способом.
Раньше в каждом проекте у меня был модуль MiscStuffAndJunk. Это было место, где можно было хранить все, что не было четкого места, либо потому, что функциональность была разовой, либо потому, что я не хотел менять свой фокус, чтобы создать правильный дизайн для функции. это было необходимо, но вне зависимости от того, на чем я сейчас концентрировался.
Тем не менее, эти модули явно нарушают принципы объектно-ориентированного проектирования.
Итак, в настоящее время я называю модуль StuffIHaventRefactored, и все же с миром все в порядке.
Вместо того, чтобы высказывать личное мнение, я процитирую авторитетный источник в сообществе Java и примеры из двух очень уважаемых сторонних библиотек.
Цитата из Эффективное 2-е издание Java, пункт 4: Обеспечьте неэкземплярность с помощью частного конструктора :
Иногда вы захотите написать класс, который представляет собой просто группу
static
истатические
поля. Такие классы приобрели плохую репутацию, потому что некоторые люди злоупотребляют ими, чтобы не мыслить категориями объектов, но у них действительно есть допустимое использование . Их можно использовать для группировки связанных методов по примитивным значениям или массивам, какjava.lang.Math
илиjava.util.Arrays
.Их также можно использовать для группировкистатических
методов, включая фабричные методы, для объектов, реализующих определенный интерфейс, в видеjava.util.Collections
. Наконец, их можно использовать для группировки методов в классеfinal
вместо расширения класса.
В библиотеках Java есть много примеров таких служебных классов.
Type
Utils
.
ArrayUtils
, StringUtils
, ObjectUtils
, BooleanUtils
и т. Д.
s
соглашение об именах
Объекты
, Строки
, Throwables
, Коллекции2
, Итераторы
, Итераторы
, Списки
, Карты
и т. Д. статических
служебных методов Ints
, Floats
, Booleans
и т. Д. статические
служебные классы имеют допустимое применение для групповых связанных методов на:
final
классы (поскольку они не расширяемы) SomeType
- SomeType
Utils
или SomeType
s
Я никогда не был поклонником класса MiscUtilities. Моя главная проблема в том, что я никогда не знаю, что в нем находится. Все, что находится в разделе miscellaneous, невозможно обнаружить. Вместо этого я предпочитаю использовать общую dll, которую я могу импортировать в свои проекты и которая содержит хорошо названные, разделенные классы для различных целей. Разница едва заметна, но я нахожу, что это делает мою жизнь немного проще.
Утилитарные классы сами по себе неплохи. Иногда их можно (неправильно|ab|over)использовать, но у них есть свое место. Если у вас есть утилитарные методы для типов, которыми вы владеете, подумайте о переносе статических методов в соответствующие типы. Или создайте методы расширения.
Старайтесь избегать монолитного класса утилит - они могут быть статическими методами, но у них будет плохая связность. Разбейте большой набор несвязанных функций на более мелкие группы связанной функциональности, точно так же, как вы делаете это с "обычными" классами. Назовите их *Helper или *Utils, или как вам больше нравится. Но будьте последовательны и группируйте их вместе, возможно, в папке внутри проекта.
Когда классы-утилиты разбиты, как описано выше, вы можете создавать методы для работы с определенными типами - примитивами или классами, такими как массивы, строки, даты и время, и так далее. Разумеется, они не могут быть использованы где-либо еще, поэтому утилитарный класс - это то, что нужно.
Я думаю, что неправильный недостаток такого класса состоит в том, что он нарушает принцип разделения ответственности . Обычно я создаю несколько классов «Helpers», содержащих широко используемые общедоступные статические методы, например ArrayHelpers для записи списков ArrayLists в файлы и DatesHelper для преобразования дат из String в Calendar. Более того, если класс действительно содержит сложные методы, лучше попытаться реорганизовать их, используя более объектно-ориентированные методы. Вы всегда можете переключиться с вашего класса «Помощники» на использование различных объектно-ориентированных шаблонов, оставив старые статические методы функционировать как Фасад . Юо будет получать огромные преимущества каждый раз, когда ты сможешь это сделать.
Лично я часто нахожу такой класс удобным - пусть даже в краткосрочной перспективе. Тем не менее, я стараюсь не разделять их между проектами. Я бы не стал хранить глобальную версию, а написал бы по одной для каждого проекта - в противном случае вы получите лишний груз, который может вызвать проблемы с безопасностью или архитектурой.