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

Я видел эту нить

Если class «Утилиты» является злым, где я могу поместить свой общий код?

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

    Занятия полезны, потому что они означают, что вы слишком ленивы, чтобы придумать лучшее название для classа 🙂

    Сказав это, я ленив. Иногда вам просто нужно выполнить задание, а ваш ум пуст. Вот когда начнут ползать уроки «Утилиты».

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    Практическое правило

    Вы можете рассмотреть эту проблему с двух точек зрения:

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

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

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

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


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

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

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

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

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

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

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

    Stream Live Android Audio на сервер

    Что означает «Использование неназначенной локальной переменной»?

    Как заставить Сасса работать?

    Как можно отключить веб-поиск в обновлении Windows 10 Anniversary Update (Build 1607)?

    Почему статические методы не используются в качестве веб-служб в веб-службах ASMX?

    Какую версию Windows 7 купить для юридического использования в Ubuntu VirtualBox?

    System.BadImageFormatException Была сделана попытка загрузить программу с неправильным форматом

    java-файл с возможностью перемотки назад () / reset ()

    Hashcode и Equals для Hashset

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

    Шифровать специальную папку в жестком жестком диске

    Значение изменения JavaFX ComboBox вызывает IndexOutOfBoundsException

    Каким будет самый простой способ быстрой рассылки файла через GMail?

    Почему полезен указатель «точка-volatile», например «volatile int * p»?

    Как показать эллипсы в моем TextView, если он больше, чем 1 строка?

    Давайте будем гением компьютера.