Иногда я создаю классы 'Util', которые в первую очередь служат для хранения методов и значений, которые на самом деле не принадлежат никому другому. Но каждый раз, когда я создаю один из этих классов, я думаю: «О-о, я буду сожалеть об этом позже ...», потому что я где-то читал, что это плохо.
Но с другой стороны, кажется, есть два убедительных (по крайней мере для меня) случая для них:
- секреты реализации, которые используются в нескольких классах в пакете
- предоставляя полезную функциональность для расширения класса, не загромождая его интерфейс
Я на пути к уничтожению? Что вы скажете !! Должен ли я рефакторинг?
Util
в именах ваших классов. Проблема решена.SomethingUtil
немного лениво и просто затеняет истинное назначение класса - то же самое с классами с именемSomethingManager
илиSomethingService
. Если этот класс несет единственную ответственность, должно быть легко дать ему осмысленное имя. Если нет, то это реальная проблема для решения ...Util
, хотя, очевидно, я не ожидал, что это зафиксируется, а остальная часть вопроса проигнорирована ...Ответы:
Современный ОО дизайн допускает, что не все является объектом. Некоторые вещи являются поведением или формулами, а некоторые не имеют состояния. Это хорошо, чтобы смоделировать эти вещи как чистые функции, чтобы получить выгоду от этого дизайна.
Java и C # (и другие) требуют, чтобы вы создали класс util и перепрыгнули через этот обруч, чтобы сделать это. Раздражает, но не конец света; и не очень хлопотно с точки зрения дизайна.
источник
Никогда не говори никогда"
Я не думаю, что это обязательно плохо, это только плохо, если ты делаешь это плохо и злоупотребляешь этим.
Нам всем нужны инструменты и утилиты
Для начала, мы все используем некоторые библиотеки, которые иногда считаются почти повсеместными и обязательными. Например, в мире Java, Google Guava или некоторых из Apache Commons ( Apache Commons Lang , коллекции Apache Commons и т. Д.).
Так что в этом явно есть необходимость.
Избегайте грубых слов, дублирования и появления ошибок
Если вы думаете о них довольно много просто очень большой пучок этих
Util
классов вы описываете, за исключением кто - то прошел через большие длины , чтобы получить их (относительно) право, и они были раз - проверены и сильно глаза сжались другими.Поэтому я бы сказал, что первое эмпирическое правило, когда возникает желание написать
Util
класс, - проверить, чтоUtil
класс на самом деле еще не существует.Единственный контраргумент, который я видел для этого, - это когда вы хотите ограничить свои зависимости, потому что:
Но и то, и другое можно решить, переупаковав библиотеку с помощью ProGuard или ее эквивалента, или разобрав ее самостоятельно (для пользователей Maven , maven-shade-plugin предлагает несколько шаблонов фильтрации, чтобы интегрировать это как часть вашей сборки).
Так что, если он находится в lib и соответствует вашему варианту использования, и никакие тесты не говорят вам иначе, используйте его. Если это немного отличается от того, что вы, расширьте его (если возможно) или расширьте, или, в крайнем случае, перепишите его.
Соглашения об именах
Однако пока в этом ответе я назвал их
Util
такими же как ты. Не называй их так.Дайте им значимые имена. Возьмите Google Guava как (очень, очень) хороший пример того, что нужно делать, и просто представьте, что
com.google.guava
пространство имен на самом деле является вашимutil
корнем.Назовите свой пакет
util
, в худшем случае, но не классы. Если имеет дело сString
объектами и манипулированием строковыми конструкциями, называйте этоStrings
, а неStringUtils
(извините, Apache Commons Lang - я все еще люблю и использую вас!). Если это что-то конкретное, выберите конкретное имя класса (например,Splitter
илиJoiner
).Модульный тест
Если вам нужно прибегнуть к написанию этих утилит, обязательно протестируйте их. Преимущество утилит в том, что они, как правило, представляют собой автономные компоненты, которые принимают определенные входные данные и возвращают конкретные выходные данные. Это концепция. Так что нет никаких оснований не тестировать их.
Кроме того, модульное тестирование позволит вам определить и задокументировать контракт их API. Если тесты не работают, либо вы что-то изменили неправильно, либо это означает, что вы пытаетесь изменить контракт вашего API (или что ваши первоначальные тесты были дерьмовыми - учитесь на этом, и не делайте этого снова) .
API дизайн
Решение о дизайне, которое вы примете для этих API, будет следовать за вами, возможно, долгое время. Поэтому, не тратя часов на написание
Splitter
-clone, будьте осторожны с подходом к решению проблемы.Задайте себе несколько вопросов:
Вы хотите, чтобы эти утилиты охватывали широкий спектр вариантов использования, были надежными, стабильными, хорошо документированными, следовали принципу наименьшего удивления и были автономными. В идеале каждый подпакет ваших утилит, или, по крайней мере, весь ваш пакет утилит, должен быть экспортирован в пакет для простого повторного использования.
Как обычно, учитесь у гигантов здесь:
util
Пакет Java (который содержит библиотеку коллекций) и его эквивалент .Net ,Да, многие из них делают акцент на коллекциях и структурах данных, но не говорите мне, что это не то, где или для чего вы обычно реализуете большинство своих утилит, прямо или косвенно.
источник
If deals with String objects and manipulation of string constructs, call it Strings, not StringUtils
StringsCollectionTypeHere
если вы хотите конкретную реализацию. Или более конкретное имя, если эти строки имеют конкретное значение в контексте вашего приложения. В этом конкретном случае Гуава используетStrings
своих помощников, связанных со строками, в отличие отStringUtils
Commons Lang. Я нахожу это вполне приемлемым, для меня это просто означает, что классы обрабатываютString
объект или это класс общего назначения для управления строками.NameUtils
вещи не дают мне покоя, потому что, если они находятся под четко обозначенным именем пакета, я бы уже знал, что это служебный класс (а если нет, то быстро это выяснил бы, посмотрев на API). Это так раздражает меня , как люди объявляя вещи , какSomethingInterface
,ISomething
илиSomethingImpl
. Я был в порядке с такими артефактами, когда кодировал в C и не использовал IDE. Сегодня мне вообще не нужны такие вещи.Классы Util не являются связными и, как правило, имеют плохой дизайн, потому что у класса должна быть одна причина для изменения (принцип единой ответственности).
Тем не менее, я видел «Util» классов в самом Java API, как:
Math
,Collections
иArrays
.На самом деле это служебные классы, но все их методы связаны с одной темой, у одного есть математические операции, у одного есть методы для манипулирования коллекциями, а у другого - для манипулирования массивами.
Старайтесь не нет абсолютно не связанных методов в служебном классе. Если это так, скорее всего, вы можете поместить их в другое место, где они действительно принадлежат.
Если необходимо иметь классы утилит, попробуйте разделить их по темам, подобным Java
Math
,Collections
иArrays
. Это, по крайней мере, показывает некоторое намерение дизайна, даже когда они просто пространства имен.Я, например, всегда избегаю служебных классов и никогда не нуждался в их создании.
источник
Math
илиArrays
демонстрирующие хоть какое-то намерение дизайна.Вполне приемлемо иметь классы util , хотя я предпочитаю термин
ClassNameHelper
. .NET BCL даже содержит вспомогательные классы. Самая важная вещь, которую следует помнить, - это тщательно документировать назначение классов, а также каждого отдельного вспомогательного метода и сделать его высококачественным поддерживаемым кодом.И не увлекайтесь вспомогательными классами.
источник
Я использую двухуровневый подход. Класс "Globals" в пакете (папке) util. Чтобы что-то входило в класс «Globals» или пакет «util», оно должно быть:
Примеры, которые проходят эти тесты:
Вот пример очень маленького вспомогательного метода, полностью независимого от остальной части приложения:
Глядя на это, я вижу ошибку, согласно которой 21 должен быть «21-м», 22 - «22-м» и т. Д., Но это не относится к делу.
Если один из этих вспомогательных методов растет или усложняется, его следует переместить в его собственный класс в пакете util. Если два или более вспомогательных класса в пакете util связаны друг с другом, они должны быть перемещены в их собственный пакет. Если константный или вспомогательный метод оказывается связанным с определенной частью вашего приложения, его следует перенести туда.
Вы должны быть в состоянии объяснить, почему нет лучшего места для всего, что вы прикрепляете в классе Globals или в пакете утилит, и вам следует периодически очищать его, используя приведенные выше тесты. В противном случае вы просто создаете беспорядок.
источник