Чи використання *** Helper або *** Util класів, що містять лише статичні методи, AntiPattern


19

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

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

Моє запитання, що ви думаєте про такий вид статичних класів helper / util, оскільки перевага, звичайно, полягає в швидкому виклику з використанням лише назви класу.

І на якому рівні абстрагування ви б уникали використання таких класів?

На мою думку, ключове слово "статичний" повинно бути дозволено в межах декларації класу (Java), а не для методів. На мою думку, використання цього способу може бути хорошою альтернативою для того, щоб можна було комбінувати Procuedural- і OO-Paradigms на Java та уникати зловживання ключовим словом.

Доповнення завдяки відповідям:

Спочатку я вважаю, що цілком законно можна поєднувати різні парадигми і навіть використовувати мови інтерпретації сценаріїв виконання, виконані в машинному або vm-компільованому коді.

Мій досвід полягає в тому, що під час розробки проекту подібні помічники та утиліти, або як би це не було, зростають і ростуть і використовуються в кожному забутому куточку кодової бази, яка спочатку була розроблена як модульна та флексибельна. А через брак часу для виготовлення реконструкцій або продумування дизайну ви просто з часом зробите це набагато гірше.

Я думаю, що staticслід видалити з Java. Особливо зараз, де можна використовувати ще більш складні функціональні мовні елементи.



Я думаю, якщо помічнику не потрібно інстанціювати клас, це добре. Проблема полягає в тому, коли помічник створює конкретну реалізацію класу, і тоді ви не в змозі знущатися над цим інтерфейсом. Якщо помічник проходить інтерфейс або абстрактний клас, я думаю, це нормально.
bobek

Це добре, якщо ви вимагаєте робити процедурне програмування. Це не якщо ви вимагаєте робити об’єктне (орієнтоване) програмування.
Виявлено

1
@Spotted: і як немає жодної цінності для бізнесу, якщо ви заявляєте, що займаєтесь виключно об'єктно-орієнтованим програмуванням, просто завжди робіть змішане програмування парадигми і будьте лайно.
RemcoGerlich

@RemcoGerlich Рівно. Моя думка полягала в тому, що відповідь в основному є "філософською", пов'язаною з такою парадигмою програмування, яку ви вважаєте.
Виявлено

Відповіді:


20

Ну, у Java бракує вільних функцій, тому ви змушені ставити їх як статичні функції в якийсь клас проформа. Необхідна робота навколо ніколи не є анти-візерунком, хоча вона може бракувати елегантності.

Далі, з безкоштовними функціями немає нічого поганого. Насправді використання безкоштовних функцій зменшує з'єднання, оскільки вони мають доступ лише до загальнодоступного інтерфейсу замість всіх деталей.

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


2
@TimothyTruckle Або вони статичні, або вони мають зайве this, і вимагають, щоб щось було встановлено належним чином
Caleth

6
@TimothyTruckle Тому що це Java. Інші мови можуть мати вільні функції без накладних витрат, щоб їх класти в клас лише для того, щоб оголосити, що це не метод екземпляра. І в якийсь момент у вас повинна бути щільна муфта. Є чи це добре чи ні, повністю залежить від того , що розглянута функція робить .
nvoigt

5
@TimothyTruckle Абсолютно, підтримання стану було б головною причиною того, що "не добре".
nvoigt

2
@nvoigt, я вважаю, що ця відповідь буде значно покращена, якщо явно зазначити цю точку. Державна статистика погана; особи без громадянства - це добре. Дійсно досить просто.
Девід Арно

3
@TimothyTruckle Це не міцна муфта. Ви описуєте сипучу муфту. Жорстке з'єднання в цьому контексті означало б певну взаємозалежність. Одностороння залежність не відповідає цій вимозі.
JimmyJames

18

Статичні функції утиліти або помічники не є анти-зразком, якщо вони дотримуються деяких вказівок:

  1. Вони повинні бути позбавлені побічних ефектів

  2. Вони використовуються для специфічної поведінки програми, яка не належить до класу чи класів, на яких ці функції функціонують

  3. Вони не потребують загального стану

Загальні випадки використання:

  • Форматування дат конкретним способом
  • Функції, які приймають один тип як вхідний і повертають інший тип.

Наприклад, у програмі, яку я працював над користувачами, зберігати записи журналів про свою діяльність. Вони можуть вказати дату спостереження та завантажити нагадування про подію. Ми створили статичний клас корисних програм для того, щоб зробити запис у журналі та повернути необроблений текст для файлу .ics.

Це не вимагало жодного спільного стану. Це не мутувало жодного стану, і створення події iCal, безумовно, було специфічним для програми та не належало до класу входу в журнал.

Якщо статичні функції або класи утиліти мають побічні ефекти або потребують спільного стану, я рекомендую переоцінити цей код, оскільки він вводить з'єднання, яке може бути важким для макетування для тестування одиниць.


4

Це буде залежати від вашого підходу. Багато додатків написані більш функціонально, на відміну від класичного мислення (включаючи більшу частину набору сайтів, на яких ви перебуваєте).

При такому мисленні на класах робітників буде багато корисних методів, які можна поєднати як статичні. Їх подають / використовують ближче до звичайних об'єктів, які зберігають лише дані та передаються навколо.

Це дійсний підхід і може працювати дуже добре, особливо в масштабах.


"може працювати дуже добре, особливо в масштабі". Ні. Приблизька причина з'єднання статичним доступом незабаром стане на вашому шляху в міру зростання проекту.
Тімоті Вікторле

@TimothyTruckle Чи не могли б ви пояснити, як Agent.Save (obj) набагато міцніше пов'язаний, ніж obj.Save ()? Агент настільки ж здатний отримати посилання DI / IoC, навіть для статичних методів, як екземпляр класу aa. Для довідки, сам стек-бірж написаний у такому режимі мислення, і він масштабується краще, ніж будь-який інший додаток ASP.Net з меншими ресурсами, ніж будь-який інший, про який я знаю.
Tracker1

"Не могли б ви пояснити, як Agent.Save (obj) настільки міцніше пов'язаний, ніж obj.Save ()?" Це неправильний приклад. Правильний приклад був би Agent.Save(obj)проти agentInstance.Save(obj). За допомогою останнього ви маєте можливість ввести agentInstance код, що використовує. В результаті ви можете надати будь-дочірній клас від Agentзанадто який дозволяє повторно використовувати О.Г. з допомогою коду з різними «типами» Agentбез перекомпіляції. Це низька муфта .
Тімоті Тріклер

Я думаю, що це дійсно зводиться до пари речей. Чи потрібна держава, наскільки вона повинна бути гнучкою, і чи нормально мати глобальний / екземплярний стан? Це вирішує кожен розробник / архітектор. Я вважаю за краще простішу кодову базу над додаванням складності для сценаріїв, які роблять все складніше для розуміння в цілому. Однією з речей, які мені подобається у node / js, є те, що я можу писати простий / чистий код і все-таки вводити його для тестування без коду, записаного в специфікації DI / IoC.
Tracker1

2

Я особисто вважаю, що єдиною важливою частиною таких занять для помічників є те, що вони мають бути приватними. Крім того - вони суворо хороша ідея (застосовуються скупо).

Як я думаю про це - якщо у впровадженні класу (або функції) - щось подібне є корисним і робить цю реалізацію зрозумілішою, то як це може бути поганим? І OFTEN важливо визначити такі приватні класи помічників, щоб дозволити інтеграцію та використання інших алгоритмів, які залежать від даних, що знаходяться у певній формі.

Чи називати його "помічником" - це справа особистого смаку, але це означає, що це допомагає в реалізації та не представляє інтересу / використання для широкої аудиторії. Якщо в цьому є сенс - ідіть до цього!


1
Класи комунальних послуг все ще можуть бути корисними. Prime приклад: java.lang.Math.
амон

1

Поширеність staticкласів помічників на основі помилкового уявлення. Тільки тому, що ми називаємо класи лише staticметодами "корисні класи", це не означає, що заборонено писати загальну поведінку в POJO.

static Допоміжні класи - це анти-шаблон з трьох причин:

  1. Статичний доступ до цих помічників приховує залежності . Якщо ці "утилітні класи" були POJO, ви можете ввести їх int до залежного класу як конструкторських параметрів, що зробить залежність очевидною для будь-якого користувача залежного класу.

  2. Статичний доступ до цих хелперних методів викликає тісне з'єднання . Це означає, що код за допомогою хелперних методів важко повторно використати і (як побічний ефект) перевірити.

  3. Особливо, якщо вони підтримують стан, це просто глобальні змінні . І, сподіваємось, ніхто не заперечує, що глобальні змінні є корисними ...

Статичні класи помічників є частиною антитілевого коду STUPID .


Глобальний стан не пов'язаний з питанням, - max630

ОП написала:

Але здебільшого це дійсно залежно від контексту та держави.

Статичні державніповні конструкції - це глобальні держави.

будь-який код може використовувати його. - max630

Так, від причини. І майже всі програми потребують якогось глобального стану .

Але глобальна держава ! = Глобальна змінна .

Ви можете створити глобальний стан за допомогою методів OO за допомогою введення залежності, але ви не можете уникнути глобального стану зі стаціонарними статичними структурами, що є глобальними змінними внизу.


2
Глобальний стан не пов'язаний з питанням, будь-який код може використовувати його.
max630

@ max630, будь ласка, дивіться моє оновлення
Timothy Truckle

1
Ви можете використовувати статичні вільні функції без з’єднання. Ви проходите навколо Func<Result, Args>об'єктів, які інстанціровані в іншому місці.
Калет

1
1) Я взагалі вважаю, що приховувати реалізацію - це добре, де це підходить. 2) Якщо все, що вводиться аргументами / залежностями, також створює певну схему дизайну та часу, ви можете відчути це, коли вам доведеться витратити багато часу на зміну підписів у довгих ланцюгах залежностей. І, як, будь-яка функція, що вимагає вашого Logger або інших наскрізних проблем, як аргумент, урх ... (Але так, це може зробити складніше тестування на низькому рівні) 3) Звичайно, статичні функції повинні бути без стану.
Алекс

1
@ Алекс Тоді дозвольте сказати це навпаки: одиниця - це будь-яка купа коду (включаючи статичні методи "утиліти"), які мають ті самі причини, що потрібно змінювати . Все, що знаходиться всередині цього підрозділу, є деталізацією реалізації . Все інше є залежністю , і пристрій не повинен мати статичний доступ до нього.
Тімоті Тріклер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.