Неплохо ли иметь класс MiscUtilities?

Наша компания хранит класс MiscUtilities, который состоит исключительно из публичных статических методов, которые часто выполняют несвязанные задачи, такие как преобразование дат из String в Calendar и запись ArrayLists в файлы. Мы ссылаемся на него в других классах и находим, что это довольно удобно. Тем не менее, я видел, что класс Утилитов высмеивался на TheDailyWTF. Мне просто интересно, есть ли какой-либо фактический недостаток этого класса, и каковы альтернативы.

Ответы

Ответ 1

Для языков, которые поддерживают функции, это своего рода класс, несомненно, плохой форме.

Для языков, которые этого не делают, этот класс не является и, вероятно, превосходит другие классы со случайными методами полезности. Статические методы утилиты, потому что они находятся в каком-то другом классе, могут использовать только открытый интерфейс объектов, которые они обрабатывают, что уменьшает вероятность некоторых видов ошибок. И этот подход также позволяет избежать загрязнений публичных интерфейсов со случайным пакетом захвата того, что люди находили полезным в то время.

Конечно, существует определенное количество личного стиля. Я не очень верю в классы, которые обеспечивают все под солнцем (даже С++ std::string является чуть-чуть более склонным к моему вкусу) и, как правило, предпочитают иметь вспомогательную функциональность в качестве отдельных функций. Упрощает обслуживание класса, заставляет общественный интерфейс быть полезным и эффективным, а с помощью механизмов стиля "утиная печать" внешние функции могут использоваться в широком диапазоне типов без дублирования исходного текста или совместного использования базовых классов и т.д. (Неодуманные алгоритмы в стандартной библиотеке С++ являются хорошей демонстрацией этого, несовершенного и подробного, как они есть.)

Тем не менее, я работал со многими, кто жалуется на строки, которые не знают, как интерпретировать себя как имена файлов, или разделяться на слова или то, что у вас есть, и так далее. (Я выбираю строки, потому что они кажутся главной мишенью для функций полезности...) Мне кажется, что существуют невидимые затраты на обслуживание и надежность, связанные с наличием таких больших классов, совершенно не относящихся к уродливости номинально простого класса что на самом деле огромный нелогичный мишмар не связанных между собой проблем, чьи грязные пальцы в конце концов выкалывают себя в каждый последний угол, потому что ваша самоарквинирующая строка нуждается в каком-то контейнере для ввода жетонов, верно?! - но это балансирующий акт, даже если моя формулировка подсказывает его более чистое, чем это.

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

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

Я предполагаю, что исполнительное резюме: no.

Ответ 2

Вместо того, чтобы давать личное мнение, я приведу цитату из авторитетного источника в сообществе Java и примеры из 2 очень уважаемых сторонних библиотек.

Цитата из Effective Java 2nd Edition, пункт 4: Обеспечьте неинтуитивность с помощью частного конструктора:

Иногда вам нужно написать класс, который представляет собой просто группировку методов static и static. Такие классы приобрели плохую репутацию, потому что некоторые люди злоупотребляют ими, чтобы не думать об объектах, но они действительно имеют применение. Их можно использовать для группировки связанных методов по примитивным значениям или массивам в виде java.lang.Math или java.util.Arrays. Их также можно использовать для группировки методов static, включая методы factory, для объектов, реализующих конкретный интерфейс, в виде java.util.Collections. Наконец, их можно использовать для группировки методов в классе final вместо расширения класса.

В библиотеках Java есть много примеров таких классов полезности.


Краткое описание

  • Предпочитайте хороший дизайн ООП, всегда
  • static классы полезности имеют правильное применение для группировки связанных методов:
    • Примитивы (поскольку они не являются объектами)
    • Интерфейсы (поскольку они не могут иметь ничего конкретного)
    • final классы (поскольку они не расширяемы)
  • Предпочитаю хорошую организацию, всегда
    • Методы групповой утилиты для SomeType - SomeType Utils или SomeType s
    • Избегайте одного большого класса утилиты, который содержит различные несвязанные задачи для разных типов/понятий.

Ответ 3

Удобно, скорее всего.

Можно превратиться в страшную, трудную для поддержания швейцарско-армейской ракетно-бензопилой и полировочную машину, также наиболее вероятно.

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

Риск здесь состоит в том, что класс становится запутанным беспорядком, которого никто не понимает, и никто не осмеливается прикоснуться - или заменить. Если вы считаете, что это приемлемый риск и/или избегаемый в ваших обстоятельствах, ничто не мешает вам использовать его.

Ответ 4

Я никогда не был поклонником класса MiscUtilities. Моя самая большая проблема в том, что я никогда не знаю, что в ней. Все, что подано по разному, невозможно обнаружить. Вместо этого я предпочитаю использовать общую DLL, которую я могу импортировать в свои проекты, которые содержат хорошо названные, разделенные классы для разных целей. Разница тонкая, но я считаю, что это облегчает мою жизнь.

Ответ 5

Ну, на TheDailyWTF высмеиваются плохие классы полезности:)

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

Один подход, который вы можете предпринять, в зависимости от языка и т.д., - это, возможно, переместить часть логики в расширения существующих объектов. Например, расширение класса String (мышление на С# здесь) с помощью метода, который пытается проанализировать строку в DateTime. Внутренняя библиотека расширений просто расширяет язык с помощью собственных небольших DSL-приложений.

Ответ 6

В компании, в которой я работаю, есть такой класс в своем репозитории. Лично я нахожу это раздражающим, потому что вы должны быть очень близки к классу, чтобы знать, для чего это полезно. Следовательно, я обнаружил, что переписываю методы, которые уже охватывает этот класс! Двойное раздражение, потому что я сейчас теряю время.

Я предпочел бы более объектно-ориентированный подход, который привел бы к расширяемости. У вас есть класс Utilities, но внутри него добавляются другие классы, которые расширяются до определенной функциональности. Как Utilities.XML, Utilities.DataFunctions, Utilities.WhateverYouWant. Таким образом, вы можете расширить и, в конечном счете, взять свой 20-разрядный класс MiscUtilities и превратить его в библиотеку классов функций 500.

Библиотека классов, подобная этой, может затем использоваться кем угодно и добавляться кем-либо (с привилегиями) логически организованным способом.

Ответ 7

Я считаю, что неправильный дефект такого класса заключается в том, что он нарушает принцип Разделение проблем. Обычно я создаю несколько классов "Помощники", которые содержат широко используемые общедоступные статические методы, например ArrayHelpers, для записи ArrayLists в файлы, а DatesHelper - для преобразования дат из String в Calendar. Более того, если класс содержит сложные методы, лучше попытаться реорганизовать их с помощью более объектно-ориентированного tecnique. Вы всегда можете переключиться с вашего класса "Помощники" на использование различного шаблона OO, в результате чего ваши старые статические методы будут функционировать как Facade, Yuo'll найдет отличные преимущества каждый раз, когда вы сможете это сделать.

Ответ 8

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

Примеры вещей в моем классе-помощнике:

  • hex2, hex4 и hex8 (принимают целочисленные параметры, за исключением hex8, который имеет целые и uinteger вариации, все версии игнорируют биты более высокого порядка)
  • byt (преобразование 8 lsb аргумента в байт)
  • getSI, getUI, getSL, getUL (каждый принимает байтовый массив и смещение и возвращает малознаковое подписанное слово, неподписанное слово, подписанное 32-битное слово или 32-битное слово без знака при этом смещении
  • putSI, putUI, putSL, putUL (принимает байтовый массив, смещение и значение, чтобы положить его в формате little-endian)
  • hexArr (преобразует байтовый массив или его часть в шестую строку)
  • hexToArr (преобразует шестнадцатеричную строку в массив байтов)
  • Zap (из T как iDisposable) (принимает byref iDisposable, если не Nothing, распоряжается им и устанавливает его в Nothing)

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

Ответ 9

Утилиты не плохие, сами по себе. Они могут быть (mis | ab | over) использованы время от времени, но у них есть свое место. Если у вас есть методы утилиты для ваших собственных типов, рассмотрите возможность перемещения статических методов к соответствующим типам. Или создайте методы расширения.

Постарайтесь избежать монолитного класса утилит - они могут быть статическими методами, но они будут иметь слабую связность. Разбейте большой набор несвязанных функций на более мелкие группы связанных функций, как и ваши "нормальные" классы. Назовите их * Помощник или * Утилиты или любые ваши предпочтения. Но будьте последовательны и объедините их вместе, возможно, в папку внутри проекта.

Когда классы утилиты разбиваются, как описано, вы можете создавать методы для работы с определенными типами - примитивами или классами, такими как массивы, строки, даты и время и т.д. По общему признанию, они не будут принадлежать нигде, поэтому класс утилиты - это место, куда можно пойти.

Ответ 10

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

Ответ 11

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

Ответ 12

У меня вообще нет проблем с ними, хотя, как и все вещи, их можно злоупотреблять:

  • Они растут очень большими, так что большинство проблем, которые используют класс, не используют 99% функций.
  • Они растут невероятно большими, так что 90% функций не используются какой-либо используемой программой.
  • Часто они являются свалкой для функций, специфичных для одного домена. Они должны быть направлены на использование подобного класса только по программе в этом домене. Часто эти функции были бы лучше включены в соответствующие классы.

Ответ 13

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

Тем не менее, эти модули явно нарушают принципы проектирования OO.

Итак, в настоящее время я называю модуль StuffIHaventRefactoredYet, и все правильно с миром.

Ответ 14

В зависимости от того, что на самом деле выполняются и возвращаются ваши статические функции полезности, это может быть причиной тестирования модулей. Я столкнулся с методом в классе, который вызывает статическую функцию в статическом классе, который возвращает те вещи, которые мне не нужны в моем unit test, что делает весь метод untestable...