Я видел эту ветку
Если класс «Утилиты» злой, где мне разместить свой общий код?
и подумал, почему классы утилит злые?
Допустим, у меня есть модель предметной области, состоящая из десятков классов. Мне нужно иметь возможность использовать экземпляры xml-ify. Могу ли я создать метод toXml для родительского элемента? Могу ли я создать вспомогательный класс MyDomainXmlUtility.toXml? Это тот случай, когда бизнес-потребность охватывает всю модель предметной области - действительно ли она относится к методу экземпляра? А что, если есть куча вспомогательных методов по xml-функциональности приложения?
design-patterns
software-design
hvgotcodes
источник
источник
Ответы:
Служебные классы - это не совсем зло, но они могут нарушать принципы, составляющие хороший объектно-ориентированный дизайн. В хорошем объектно-ориентированном дизайне большинство классов должно представлять одну вещь и все ее атрибуты и операции. Если вы работаете с чем-то, этот метод, вероятно, должен быть его членом.
Однако бывают случаи, когда вы можете использовать служебные классы для группировки нескольких методов вместе - примером является
java.util.Collections
класс, который предоставляет ряд служебных программ, которые можно использовать в любой коллекции Java. Они не относятся к одному конкретному типу Коллекции, а вместо этого реализуют алгоритмы, которые можно использовать в любой Коллекции.На самом деле, что вам нужно сделать, это подумать о своем дизайне и определить, где лучше всего разместить методы. Обычно это операции внутри класса. Однако иногда это действительно служебный класс. Однако, когда вы используете служебный класс, не просто добавляйте в него случайные методы, вместо этого организуйте методы по назначению и функциональности.
источник
Я думаю , что общее мнение состоит в том , что вспомогательные классы не являются злом сами по себе . Вам просто нужно разумно их использовать:
Разработайте статические служебные методы так, чтобы они были общими и могли использоваться повторно. Убедитесь, что они не имеют гражданства; т.е. нет статических переменных.
Если у вас много служебных методов, разделите их на классы таким образом, чтобы разработчикам было проще их найти.
Не используйте служебные классы, где статические методы или методы экземпляра в доменном классе были бы лучшим решением. Например, подумайте, будут ли методы в абстрактном базовом классе или создаваемом экземпляре вспомогательного класса лучшим решением.
Для Java 8 и новее "методы по умолчанию" в интерфейсе могут быть лучшим вариантом, чем служебные классы. (См., Например, интерфейс с методами по умолчанию и абстрактный класс в Java 8. )
Другой способ взглянуть на этот Вопрос - это заметить, что в процитированном Вопросе «Если классы полезности являются« злыми »» - это соломенный аргумент. Это как я спрашиваю:
В приведенном выше вопросе я на самом деле не говорю, что свиньи умеют летать ... или что я согласен с утверждением, что они могут летать.
Типичные утверждения «xyz - зло» - это риторические приемы, которые предназначены для того, чтобы заставить вас задуматься, излагая крайнюю точку зрения. Они редко (если вообще когда-либо) задумываются как констатация буквального факта.
источник
Служебные классы проблематичны, потому что они не могут сгруппировать обязанности с данными, которые их поддерживают.
Однако они чрезвычайно полезны, и я все время строю их либо как постоянные конструкции, либо как ступеньки во время более тщательного рефакторинга.
С точки зрения чистого кода служебные классы нарушают принцип единой ответственности и принцип открытого-закрытого. У них есть множество причин для изменения, и они по замыслу не расширяются. Они действительно должны существовать только во время рефакторинга как промежуточный мусор.
источник
class
ключевое слово. Он крякает, как пространство имен, он ходит как пространство имен - это одно ...x.equals(y)
потому что 1) тот факт, что это действительно не должно изменять какое-либо состояние, не передается (и я не могу полагаться на это, не зная реализации) 2) Я никогда не собирался вставлятьx
" предпочтительная позиция или позиция, в которой «действовали» по сравнению сy
3) Я не хочу рассматривать «идентичности»x
илиy
просто интересуюсь их ценностями.Я полагаю, это становится злым, когда
1) Он становится слишком большим (в этом случае просто сгруппируйте их по значимым категориям).
2) Присутствуют методы, которые не должны быть статическими.
Но пока эти условия не выполняются, я считаю, что они очень полезны.
источник
Widget.compareTo(Widget widget)
сравнении со статикойWidgetUtils.compare(Widget widgetOne, Widget widgetTwo)
. Сравнение - это пример того, что нельзя делать статически.Практическое правило
Вы можете посмотреть на эту проблему с двух точек зрения:
*Util
методы часто предполагают плохой дизайн кода или ленивое соглашение об именах.Пример 1. Правильное использование
util
классов / модулей. Пример внешней библиотекиПредположим, вы пишете приложение, которое управляет ссудами и кредитными картами. Данные из этих модулей предоставляются через веб-службы в
json
формате. Теоретически вы можете вручную преобразовать объекты в строки, которые будут внутриjson
, но для этого придется изобретать колесо. Правильным решением было бы включить в оба модуля внешнюю библиотеку, используемую для преобразования java-объектов в желаемый формат. (в примере изображения я показал gson )Пример 2. Правильное использование
util
классов / модулей. Написание своего собственногоutil
без извинений перед другими членами командыВ качестве варианта использования предположим, что нам нужно выполнить некоторые вычисления в двух модулях приложения, но оба из них должны знать, когда в Польше есть государственные праздники. Теоретически вы можете производить эти вычисления внутри модулей, но было бы лучше выделить эту функциональность в отдельный модуль.
Вот небольшая, но важная деталь. Написанный вами класс / модуль не называется
HolidayUtil
, ноPolishHolidayCalculator
. Функционально этоutil
класс, но нам удалось избежать общего слова.источник
Служебные классы плохи, потому что означают, что вам было лень придумать лучшее название для класса :)
При этом я ленив. Иногда вам просто нужно выполнить работу, и ваш ум пуст ... вот тогда-то и начинают появляться "служебные" классы.
источник
Оглядываясь назад на этот вопрос, я бы сказал, что методы расширения C # полностью устраняют потребность в служебных классах. Но не во всех языках есть такая гениальная конструкция.
У вас также есть JavaScript, где вы можете просто добавить новую функцию прямо к существующему объекту.
Но я не уверен, что действительно есть элегантный способ решить эту проблему на более старом языке, таком как C ++ ...
Хороший объектно-ориентированный код довольно сложно написать, и его трудно найти, поскольку для написания хорошего объектно-ориентированного кода требуется гораздо больше времени / знаний, чем для написания приличного функционального кода.
А когда у вас ограниченный бюджет, ваш босс не всегда рад видеть, что вы весь день пишете кучу уроков ...
источник
Я не совсем согласен с тем, что служебные классы - это зло.
Хотя служебный класс может некоторым образом нарушать принципы объектно-ориентированного программирования, это не всегда плохо.
Например, представьте, что вам нужна функция, которая очистит строку от всех подстрок, соответствующих значению
x
.stl c ++ (на данный момент) не поддерживает это напрямую.
Вы можете создать полиморфное расширение
std::string
.Но проблема в том, действительно ли вы хотите, чтобы КАЖДАЯ строка, которую вы используете в своем проекте, была вашим расширенным строковым классом?
Бывают случаи, когда объектно-ориентированный подход не имеет смысла, и это один из них. Мы хотим, чтобы наша программа была совместима с другими программами, поэтому мы будем придерживаться
std::string
и создать классStringUtil_
(или что-то еще).Я бы сказал, что лучше всего использовать одну утилиту на класс. Я бы сказал, что глупо иметь одну утилиту для всех классов или несколько утилит для одного класса.
источник
Очень легко назвать что-то утилитарным просто потому, что дизайнер не мог придумать подходящего места для размещения кода. Настоящих «утилит» часто бывает мало.
Как правило, я обычно сохраняю код в пакете, в котором он используется впервые, а затем выполняю рефакторинг только в более общее место, если обнаруживаю, что позже он действительно понадобится в другом месте. Единственное исключение - если у меня уже есть пакет, который выполняет аналогичные / связанные функции, и код лучше всего подходит для него.
источник
Могут быть полезны служебные классы, содержащие статические методы без сохранения состояния. Часто их очень легко протестировать.
источник
С Java 8 вы можете использовать статические методы в интерфейсах ... проблема решена.
источник
Большинство классов Util плохи, потому что:
Есть некоторые аналогии статических и динамических библиотек.
источник
Когда я не могу добавить метод к классу (скажем,
Account
заблокирован от изменений младшими разработчиками), я просто добавляю несколько статических методов в свой класс Utilities, например:источник
Account
файл. Или лучше использовать неблокирующие системы управления версиями.Account
файл был заблокирован так, что разработчики-младшие не могут вносить в него изменения. Как младший разработчик, чтобы обойти это, он сделал то, что описано выше. Тем не менее, все же лучше просто получить доступ на запись к файлу и сделать это правильно.Классы полезности не всегда зло. Но они должны содержать только те методы, которые являются общими для широкого диапазона функций. Если есть методы, которые можно использовать только среди ограниченного числа классов, подумайте о создании абстрактного класса в качестве общего родителя и поместите в него методы.
источник