Подтвердить что ты не робот

Утилиты - это зло?

Я видел этот поток

Если "Утилиты" класс - это зло, где я помещаю свой общий код?

и подумал, почему классы полезности злые?

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

4b9b3361

Ответ 1

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

Однако есть моменты, когда вы можете использовать классы утилиты для группировки нескольких методов вместе - примером является класс java.util.Collections, который предоставляет ряд утилит, которые можно использовать в любой коллекции Java. Они не относятся к конкретному типу коллекции, но вместо этого реализуют алгоритмы, которые могут использоваться в любой коллекции.

На самом деле, вам нужно подумать о своем дизайне и определить, где именно смысл использовать методы. Обычно это как операции внутри класса. Однако иногда это действительно как класс полезности. Однако, когда вы используете класс утилиты, не просто бросайте в него случайные методы - организуйте методы по назначению и функциональности.

Ответ 2

Я думаю, что общий консенсус в том, что классы полезности сами по себе не являются злом. Вам просто нужно использовать их разумно:

  • Создайте статические методы утилиты для общего и многоразового использования. Убедитесь, что они не имеют гражданства; т.е. нет статических переменных.

  • Если у вас много полезных методов, разделите их на классы таким образом, чтобы разработчикам было легко найти их.

  • Не используйте классы утилиты, где статические методы или методы экземпляра в классе домена будут лучшим решением. Например, рассмотрите, было бы лучшим решением решение в абстрактном базовом классе или экземпляре вспомогательного класса.

  • Для Java 8, "методы по умолчанию" в интерфейсе могут быть лучшим вариантом, чем классы утилиты.


Другой способ взглянуть на этот вопрос - заметить, что в цитируемом Вопросе "Если классы полезности являются" злыми ", это аргумент соломона. Его, как я спрашиваю:

"Если свиньи могут летать, я должен носить зонтик?".

В вышеупомянутом вопросе я на самом деле не говорю, что свиньи могут летать... или что я согласен с предложением, что они могут летать.

Типичные утверждения "xyz is evil" - это риторические устройства, которые призваны заставить вас думать, создавая экстремальную точку зрения. Они редко (если вообще когда-либо) предназначены как утверждения буквального факта.

Ответ 3

Классы полезности являются проблематичными, поскольку они не могут группировать обязанности с данными, которые их поддерживают.

Они, однако, чрезвычайно полезны, и я все время их строю как постоянные структуры или как ступеньки во время более тщательного рефакторинга.

Из классов Clean Code перспективы нарушают Единую Ответственность и Открытый Принцип Закрытия. У них есть много причин для изменения и по дизайну не расширяемость. Они действительно должны существовать только во время рефакторинга в качестве промежуточного рывка.

Ответ 4

Я полагаю, что он начинает злиться, когда

1) Он становится слишком большим (просто группируйте их в значимые категории в этом случае).
2) Существуют методы, которые не должны быть статическими.

Но пока эти условия не выполняются, я думаю, что они очень полезны.

Ответ 5

Классы полезности плохо, потому что они означают, что вы слишком ленились, чтобы придумать лучшее имя для класса:)

Говоря, я ленив. Иногда вам просто нужно выполнить задание, а ваш ум - пустое, что когда классы "Утилиты" начнут ползать.

Ответ 6

Очень легко создать что-то полезное просто потому, что дизайнер не мог придумать подходящее место для размещения кода. Часто бывает мало настоящих "утилит".

Как правило, я обычно храню код в пакете, где он впервые используется, а затем рефакторинг только в более общем месте, если я нахожу, что позже он действительно нужен в другом месте. Единственное исключение - если у меня уже есть пакет, который выполняет аналогичные/связанные функции, и код лучше всего подходит там.

Ответ 7

Я не совсем согласен, что классы полезности являются злыми.

В то время как класс утилиты может в какой-то мере нарушать принципы OO, они не всегда плохие.

Например, представьте, что вам нужна функция, которая очистит строку всех подстрок, соответствующих значению x.

stl С++ (на данный момент) напрямую не поддерживает это.

Вы можете создать полиморфное расширение std::string.

Но проблема в том, действительно ли вы хотите, чтобы каждая строка, которую вы используете в своем проекте, была вашим расширенным классом строк?

Бывают случаи, когда ОО не имеет смысла, и это один из них. Мы хотим, чтобы наша программа была совместима с другими программами, поэтому мы будем придерживаться std::string и создадим класс StringUtil_ (или что-то еще).

Я бы сказал, что лучше всего, если вы придерживаетесь одного использования для каждого класса. Я бы сказал, что глупо иметь один утилит для всех классов или много utils для одного класса.

Ответ 8

Полезные классы, содержащие статичные статичные методы, могут быть полезны. Они часто очень легки для unit test.

Ответ 9

Утилиты - это зло, хотя они могут выглядеть очень полезными и удобными. Этот пост объясняет это более подробно: http://www.yegor256.com/2014/05/05/oop-alternative-to-utility-classes.html Если вы пишете истинное объектно-ориентированное программное обеспечение, вы должны использовать объекты вместо этого, независимо от того, сколько из них вы создадите.

Ответ 10

С Java 8 вы можете использовать статические методы в интерфейсах... проблема решена.

Ответ 11

Большинство классов Util являются плохими, потому что:

  • Они расширяют возможности методов. Они делают общедоступным код, который в противном случае был бы приватным. Если метод утилиты стабилен (т.е. Не нуждается в обновлении), лучше, на мой взгляд, копировать и вставлять частные вспомогательные методы, чем раскрывать его как API и затруднять понимание того, что точка входа в общедоступный компонент (вы поддерживать иерархическую иерархию дерева с одним родителем на один метод, который легче мысленно разделять на компоненты, которые сложнее, когда вы вызываете методы из нескольких родительских методов).
  • Они приводят к мертвому коду. Утилитные методы со временем становятся неиспользованными, так как ваше приложение развивается, и вы получаете неиспользуемый код, загрязняющий вашу базу кода. Если бы он оставался конфиденциальным, ваш компилятор скажет вам, что метод не используется, и вы можете просто удалить его (лучший код вообще не является кодом).

Есть несколько аналогий с статическими или динамическими библиотеками.

Ответ 12

Правило большого пальца

Вы можете посмотреть эту проблему с двух сторон:

  • В целом методы *Util часто представляют собой идею плохого проектирования кода или ленивого соглашения об именах.
  • Это законное дизайнерское решение для многократных межсекторальных функций без гражданства. Обратите внимание, что для почти всех распространенных проблем существуют существующие решения.

Пример 1. Правильное использование классов/модулей util. Пример внешней библиотеки

Предположим, вы пишете приложение, которое управляет кредитами и кредитными картами. Данные из этих модулей отображаются через веб-службы в формате json. В теории вы можете вручную преобразовать объекты в строки, которые будут в json, но это будет изобретать колесо. Правильным решением было бы включить в оба модуля внешнюю библиотеку, используемую для преобразования объектов Java в желаемый формат. (в примере изображение, которое я показал gson)

введите описание изображения здесь


Пример 2. Правильное использование классов/модулей util. Написание собственных util без оправданий другим членам команды

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

Вот небольшая, но важная деталь. Класс/модуль, который вы написали, не называется HolidayUtil, но PolishHolidayCalculator. Функционально это класс util, но нам удалось избежать родового слова.

введите описание изображения здесь

Ответ 13

Оглядываясь назад на этот вопрос, я бы сказал, что методы расширения С# полностью уничтожают необходимость в служебных классах. Но не все языки имеют такую ​​гениальную конструкцию.

У вас также есть JavaScript, где вы можете просто добавить новую функцию прямо к существующему объекту.

Но я не уверен, что действительно есть элегантный способ решить эту проблему на более старом языке, таком как С++...

Хороший код OO очень трудно писать, и его трудно найти, поскольку для написания Good OO требуется гораздо больше времени/знаний, чем написания достойного функционального кода.

И когда вы находитесь в бюджете, ваш босс не всегда рад видеть, что вы целый день написали кучу классов...

Ответ 14

Когда я не могу добавить метод в класс (скажем, Account заблокирован от изменений разработчиками Jr.), я просто добавляю несколько статических методов в мой класс Utilities, например:

public static int method01_Account(Object o, String... args) {
    Account acc = (Account)o;
    ...
    return acc.getInt();
}