Грай! framework використовує <lot> статики


75

Waaah, Гра! framework має стільки статичних методів. Там, де я ходжу в школу, нам казали ніколи не використовувати будь-яку статику, але грайте! використовує це так, ніби немає завтра. Це якось гаразд? Якщо так, то чому?

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

Однак нам завжди казали, НІКОЛИ НІКОЛИ не використовувати 'статичні елементи в будь-якій розробленій нами програмі Java, але коли я дивлюся на Play! ... Ну ... приблизно половина методів є статичними. </exaggeration>

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

Тож, чи мене це має турбувати? Зробив так, як грати! розробники запрограмували це зробити так, щоб усі ці статики не створювали проблем?

(Наприклад, у цьому ланцюжку йдеться про те, чому слід уникати статичних членів за будь-яку ціну.)


3
Е-е ... Вам, мабуть, слід запитати свого професора чи когось іншого. Крім того, для всього світу природно не підписуватись на ті самі ідеї щодо того, що є хорошою та поганою практикою програмування, як ви, тому звикайте до цієї ідеї. :)
розслабтесь

4
@Saew, хоча використання статики не рекомендується, "НІКОЛИ НІколи не використовуйте статику" - це завищення
Сурадж Чандран,

21
<exaggeration>тег непомітний. :)
Нішант,

Ось у чому річ, наш професор - ОО-пурист. Він завжди попереджає нас про небезпеку використання статики, і у нас будуть голови за використання статики, якщо ми не зможемо надати належного пояснення, чому ми все ще їх використовуємо, і не боїмося наслідків.
Saew

@Nishant @jensgram Я бачу, дякую;)
Saew

Відповіді:


95

Гра використовує статичні методи лише тоді, коли це має сенс:

  • на рівні контролера, оскільки контролери не є об’єктно-орієнтованими. Контролери виступають як перетворювач між HTTP-світом (тобто без громадянства та на основі запиту / відповіді) та рівнем моделі, який повністю орієнтований на об'єкти.
  • у шарі моделі для заводських методів, таких як findAll (), count (), create (), які, звичайно, не залежать від конкретних випадків
  • в деяких класах play.libs. *, що забезпечує суто корисні функції

1
Крім того, основною проблемою є статичні члени, а не статичні методи. У грі є лише локальні нитки як статичні члени.
niels

3
Використання статичного validationчлена (див. Приклад ) у поєднанні з ThreadLocalпоказом, що статичний не підходить у всіх випадках.
Дімон

9
Я звик мати контролери, у яких залежності вводяться через структуру DI. Як би ви реалізували DI, використовуючи статичні об'єкти?
ripper234

6
@Guillaume. Я повинен з вами серйозно не погодитися, Play показує найгірші практики написання Java, і ніколи не повинно бути виправдань за використання statics у коді Java. Незмінність не вказується статикою, а навпаки, статична вказує на загальний стан, який є майже протилежним тому, що ви заявляєте. Тоді, звичайно, є такі цікаві речі, як виклик статичного методу на неправильному екземплярі, оскільки статичні методи навіть не поєднані з класом, в якому вони визначені. Коротше кажучи, staticв Java є величезний запах коду, і він взагалі не повинен бути присутнім, якщо ви Мета - написати сучасну Java.
Еско,

2
@Esko Я безумовно погоджуюсь з вами, Play може бути цінним у Scala, але на Java це підсумовує список поганих практик.
Сніколас

34

Ігровий фреймворк не є гарною демонстрацією того, коли використання статики доречно, і це не доводить, що ваш вчитель помилявся. Гра - це свого роду обман, вирішує питання статики поза мовою Java.

Ключова проблема полягає в тому, що вам доведеться обробляти кілька запитів HTTP паралельно, а статичні поля є "глобальними". Отже, вам знадобиться один екземпляр на потік (або навіть краще, один екземпляр на HTTP-запит) для певних речей, проте деякі з цих речей повертаються статичними методами в Play. Це працює, тому що Play! ThreadLocalінтенсивно використовує -s, і тому він вирішує проблему статики поза мовою Java. Але це ще не все. Деякі кажуть, що методи контролера по праву статичні. Звичайно, але в звичайній Java було б незручно, так як тоді ви не можете отримати доступ запиту конкретних даних без будь - яких префікса, як req.в req.session, і тоді ви все ще повинні отримати reqзвідки - то, як в якості параметра методу статичного контролера , що ще більше клопоту. Однак у програмі Play ви можете просто писати безпосередньоsessionі, як, вони просто статичні поля. Це тому, що Play використовує прилади байт-коду, щоб змінити всі ці посилання на статичні поля на щось розумніше. Знову ж таки, рішення поза мовою Java. Це не статичні поля в кінці.

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


15

З дуже короткого огляду, я б сказав , що це свого роду має сенс: веб - запити є особами без громадянства, так що немає жодного об'єкту , щоб отримати запит (= метод). Таким чином, зіставлення URI, такого як "/ articles / archive? Date = 08/01/08 & page = 2", до статичного методу, викликаного archive(), я гадаю, ваш клас програми має сенс.


8

РЕДАГУВАТИ Зараз у програмі 2.4, ін’єкція робиться автоматично. Отже, просто додавши @ на початку шляху контролера у файл, routesце зробить фокус:

GET     /                  @controllers.Application.index()

Для старих версій (2.1–2.3) вам доведеться перевизначити getControllerInstance у глобальному класі, як це пояснюється в Documentantion .


5

Як і будь-що у програмуванні, ніколи ніколи не буває правильної відповіді. Як завжди . Завжди є винятки, і правильна відповідь - завжди "це залежить".

Це правда, що в чистому ОО (для чого я весь) дуже мало місця для статики. Але це також правда, що іноді вони просто мають сенс.

Класичний приклад - корисні методи. Звичайно, було б краще, якби ми могли просто додати наш abs()метод до Integer. Але ми не можемо; тож ми застрягли Math.abs(int i).

Я схильний вважати правильним робити метод статичним, коли він не має нічого спільного з самим екземпляром. Наприклад, у класі Personви можете мати метод, який бере список людей і повертає кількість людей, у яких сьогодні є день народження. Можливо, ви можете зробити це в самому класі, лише якщо дані, необхідні для обчислення, є приватними (щось, що зрозуміє пурист ОО;)), але метод, очевидно, не має відношення до одного екземпляра Person.

Інша справа - внутрішні заняття. Ви часто хочете зробити їх статичними, якщо вам не потрібне відношення до типу, що містить.

Я ніколи не бачив Play! але якщо ви кажете, що понад 50% цього елемента є статичним, то я здогадуюсь, що він, мабуть, був погано розроблений. Це не виняток; багато фреймворків. Нехай це вас не засмутить. Напевно, не вчись у цього!
Але якщо це працює, ви все одно можете ним скористатися.


22
Гра не погано розроблена, але це відступ від способу побудови більшості бібліотек Java.
Маркус Даунінг,

4

Основна проблема полягає в тому, що статичні методи мають доступ лише до інших статичних методів і полів, що призводить до `` статичного чіпляння '', в результаті чого статичні методи повинні зустрічатися з рештою програми (яка містить її співавторів) через загальні статичні поля (поля) , що призводить до негнучкості.

Застереження: Я не знаю багато про "грати!"


4

Методи статичного контролера, безумовно, викликають занепокоєння у програмі Play! фреймворк, і, провівши тестування, це головна причина того, що я не став грати! в проектах. Ви насправді це можете побачити у проектах FOSS, де Play! використовується. Тестування контролера мало або немає. Причина, за допомогою статичних методів, DI стає важкою. Саме тут їм слід було провести ще більше часу з ASP.NET MVC, звідки Грати! вже бере трохи натхнення.

Зазвичай у вас є такий конструктор:

public HomeController( IService service ) {
   _service = service;
}
public Index() {
   var data = _service.getData();
   return View( data );
}

Потім ви використовуєте DI для введення реалізації IService в контролер. Справа в тому, що у своїх тестах ви можете створити інстанцію IService безпосередньо перед запуском контролера, а потім протестувати результат на основі щойно створеної IService.

У Play це стає дуже важко. Таким чином, модульне тестування контролера стає важким. Це для мене суттєва проблема. Тому я, як правило, шукаю інші рамки, крім Play! у світі Java. Чорт возьми, чому б не піти з оригіналом і просто не скористатися JRuby?


3

Методи статики в грі в основному використовуються в методах дії контролерів. Ці методи призначені для просто отримання необхідних даних із моделі та виставлення їх на представлення.

Вони якимось чином відповідають кожному можливому http-запиту, і, як і ці http-запити, повністю відсутні.

У структурному програмуванні у вас є процедури, з одного боку, і змінні, з іншого, але в парадигмі ООП ви трактуєте процедури та змінні в цілому.

Тобто у вас є і об’єкт з методами екземпляра (процедурами) та змінними екземпляра.

Але дії контролера не мають стану, тобто вони отримують усі змінні із запиту (можливо, і з кешу, але в такому випадку вам потрібен якийсь ідентифікатор сеансу, який нарешті надходить із запиту). Отже, дії контролера подібні до процедур stateles, і тому вони особливо не вписуються в парадигму ООП, як це роблять моделі.


2

Я припускаю, щонайменше, ми могли б використовувати одиничні об'єкти

Синглтон в Java не має великої різниці, ніж використання всіх статичних. Існує не так багато для зберігання як держава, а також. Думаю, вам не слід про це турбуватися.

Тож, чи мене це має турбувати? Зробив так, як грати! розробники запрограмували це зробити так, щоб усі ці статики не створювали проблем?

Не було б. Насправді це добре.


1
Гаразд .. Гадаю. Моя совість досі набридає на мене за використання статики, але цього разу я її проігнорую :)
Saew

1
-1, оскільки в синглтоні з нестатичними методами ми МОЖЕМО застосувати успадкування та поліморфізм, але в світі статики ми НЕ можемо використовувати ці переваги ООП. Тож це не майже однаково.
ses

Наявність статики замість хорошої мовної підтримки для одиноких є, мабуть, найбільшим недоліком мови Java. Система супутникових об’єктів Scala - це тематичне дослідження того, як ця невелика зміна може мати величезні переваги. Навіть якщо ви ніколи не поміняєте місцями реалізацію в реальному світі, майже завжди корисно мати можливість поміняти місцями реалізацію під час тестування. Я погоджуюся з професором, за кількома винятками. Просто не так важко зробити синглтона.
Sarah G

1

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

Насправді я не згоден з вашим учителем.

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

Сам JDK, apache commons або багато фреймворків включають статичні методи:

  • StringUtils
  • Pattern.matches (регулярний вираз, введення)

----------

Насправді, я думаю, вам цікаво, що з класами, такими як JPA.java: https://github.com/playframework/play/blob/master/framework/src/play/db/jpa/JPA.java

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

Я думаю, це було розроблено так для зручності використання, оскільки не зручно викликати "getInstance", і це здорово, коли ви можете легко отримати сеанс скрізь (пов'язаний з потоком), замість того, щоб вводити sessionFactory скрізь за допомогою xml або автоматичного підключення. ..

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

Тож, можливо, правилом повинно бути уникати використання статики, за винятком випадків, коли ви насправді не піклуєтесь про щільне зчеплення.

  • У цьому випадку, коли ви викликаєте методи JPA.xxx (), ваш код тісно пов'язаний з класом JPA фреймворка. Але я не думаю, що гра розроблена таким чином, щоб ви могли легко переходити з одного фреймворку без будь-якої переробки ...

  • Це велика різниця зі специфікацією EJB3 або подібними речами: якщо методи менеджера сутності EJB3 є статичними, ви будете змушені щільно з'єднати свій код із реалізацією, зателефонувавши HibernateEntityManager.xxx () або ToplinkEntityManager.xxx (). У цьому випадку існує загальний інтерфейс (і ми не можемо додавати статичні методи до інтерфейсів).

----------

  • Цей клас не є частиною специфікації, яка використовується для інших фреймворків.
  • Клас JPA має лише одну реалізацію: таку, яку виконує гра. І вони, ймовірно, не планують робити другий.
  • Таким чином, тісна зв'язок із цим класом Play, поки ви використовуєте фреймворк Play, здається мені нормальною.

1

Служба Play застосовує функціональний підхід, наприклад, node.js , і, можливо, має більше сенсу в Scala, ніж у Java, наприклад, під час натискання стеку Typesafe . Як зазначали інші плакати, Java доповнюється за допомогою інструментальних засобів байт-коду (а-ля Aspect J), щоб вести себе більш бездержавно / функціонально; Scala робить це за замовчуванням.


0

Якщо ви є пуристом об’єктно-орієнтованого програмування, вам не слід використовувати staticметоди / поля, однак їх можна використовувати безпечно і не повинно викликати занепокоєння IMHO.


2
Я не настільки впевнений. Безкоштовне використання staticполів може спричинити неприємні витоки навантажувача класів у деяких середовищах.
skaffman

1
Див раніше коментар :) На мою професору, статика є причиною занепокоєння ..
Saew

0

Однією з причин використання статичних методів є статичний імпорт, який дозволяє скоротити позначення та зробити код більш читабельним. Це особливо вірно при використанні таких службових бібліотек, як Guava або Apache Commons, в яких може бути багато статичних викликів.

Нестатичні методи контролера тепер підтримуються в Play 2.1 за допомогою введення контролера, тому не зовсім зрозуміло, чому вони не були там із самого початку.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.