Играть в! framework использует «много» статики

Ваааа, Игра! framework имеет так много статических методов. Там, где я хожу в школу, нам говорили никогда не использовать статику, но Play! использует его, как будто завтра не наступит. Это как-то нормально? Если да, то почему?

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

Однако нам всегда говорили НИКОГДА не использовать 'static' в любых разработанных нами Java-программах, но когда я смотрю на Play! ... Ну... около половины методов являются статическими. ‹/преувеличение›

Я полагаю, по крайней мере, мы могли бы использовать одноэлементные объекты (используя Scala, например ^^) для программирования нашего проекта, но меня очень беспокоит, сколько статики на самом деле есть в самом фреймворке.

Так стоит ли мне беспокоиться по этому поводу? Сделал так, чтобы Играть! разработчики запрограммировали так, чтобы вся эта статика не создавала проблем?

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


person Saew    schedule 04.03.2011    source источник
comment
Э... Вам, наверное, следует спросить своего профессора или кого-то еще. Кроме того, для остального мира естественно не разделять те же идеи о том, что такое хорошая и плохая практика программирования, как и у вас, так что привыкайте к этой идее. :)   -  person unwind    schedule 04.03.2011
comment
@Saew, хотя использование статики не рекомендуется, НИКОГДА не используйте статику - это преувеличение.   -  person Suraj Chandran    schedule 04.03.2011
comment
тег <exaggeration> не виден. :)   -  person Nishant    schedule 04.03.2011
comment
В том-то и дело, что наш профессор — ОО-пурист. Он всегда предупреждает нас об опасностях использования статики, и у него будут головы за использование статики, если мы не сможем дать достойное объяснение, почему мы все еще используем их и не боимся последствий.   -  person Saew    schedule 04.03.2011
comment
@Nishant @jensgram понятно, спасибо ;)   -  person Saew    schedule 04.03.2011


Ответы (14)


Play использует статические методы только тогда, когда это имеет смысл:

  • на уровне контроллера, поскольку контроллеры не являются объектно-ориентированными. Контроллеры действуют как сопоставитель между миром HTTP (который не имеет состояния и основан на запросах/ответах) и полностью объектно-ориентированным уровнем модели.
  • на уровне модели для фабричных методов, таких как findAll(), count(), create(), которые, конечно, не зависят от каких-либо конкретных экземпляров
  • в некоторых классах play.libs.*, предоставляющих чисто служебные функции
person Guillaume Bort    schedule 04.03.2011
comment
Кроме того, основной проблемой являются статические члены, а не статические методы. В игре в качестве статических членов используются только локальные потоки. - person niels; 05.03.2011
comment
Использование статического validation члена ( см. пример) в сочетании с ThreadLocal показывает, что статика не уместно во всех случаях. - person deamon; 15.09.2011
comment
Извините, демон, я не совсем понимаю, что вы имеете в виду, что не так с образцом, который вы предоставили? - person opensas; 03.10.2011
comment
Я привык иметь контроллеры, которые имеют зависимости, внедренные через структуру DI. Как бы вы реализовали DI, используя статические объекты? - person ripper234; 19.10.2011
comment
@ ripper234: DI - это просто передача параметров, частичное применение набора функций. - person Mauricio Scheffer; 20.10.2011
comment
да, если вы создаете статический класс DependencyInject с инжектором Guice, вы можете вызвать DependencyInject.create(), чтобы получить любой класс из любого из статических методов. В этом методе у вас все еще есть нужный DI;), поэтому, если вы взаимодействуете с другой системой, это может быть полезно, чтобы вы могли издеваться над ним. - person Dean Hiller; 10.02.2012
comment
Что, если бы мне понадобилось что-то вроде CRUD-контроллера для разных моделей. Если бы действия не были статичными, я мог бы использовать дженерики и наследование для достижения того же. Но теперь есть дублирование кода. - person smk; 28.12.2012
comment
Методы доступа к данным должны быть разделены, как мы можем этим управлять? Как я увидел, Играй! призвал разработчиков использовать средства поиска и фабрики вместо DI. - person Amir Karimi; 11.07.2013
comment
@Guillaume Гийом, я должен с вами сильно не согласиться, Play показывает худшие методы написания Java, и не должно быть никаких оправданий использованию static в коде Java, никогда. Статика не указывает на неизменность, напротив, статика указывает на общее состояние, что в значительной степени противоположно тому, что вы утверждаете. Затем, конечно, есть забавные вещи с отражением, такие как вызов статического метода для неправильного экземпляра, поскольку статические методы даже не связаны с классом, в котором они определены. Короче говоря, static в Java — это огромный запах кода, и его вообще не должно быть, если ваша цель - написать современную Java. - person Esko; 16.12.2013
comment
@Esko Я определенно согласен с вами, Play может быть ценным в scala, но в Java он суммирует список плохих практик. - person Snicolas; 06.02.2014
comment
Я не согласен или, по крайней мере, не понимаю. В идеале у вас должны быть UserMapperInterface и UserMapperImpl (вместо User.find). Контроллер (или действие, как бы вы его ни группировали) затем будет передан UserMapperInterface через конструктор (или преобразован в действие). Если бы я хотел переключить реализацию UserMapperInterface, используемую в моем коде, я бы просто изменил конфигурацию DI для контроллера. Или замените значение, возвращаемое ключом UserMapperInterface, в локаторе службы. Я не понимаю, как реализовать что-то подобное со статическими контроллерами и моделями. - person moteutsch; 06.02.2014

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

Основная проблема заключается в том, что вам приходится обрабатывать несколько HTTP-запросов параллельно, а статические поля являются «глобальными». Таким образом, вам понадобится один экземпляр на поток (или, что еще лучше, один экземпляр на HTTP-запрос) для определенных вещей, но некоторые из этих вещей возвращаются статическими методами в Play. Это работает, потому что Play! активно использует ThreadLocal, поэтому решает проблему статики за пределами языка Java. Но это еще не все. Некоторые говорят, что методы контроллера по праву являются статическими. Конечно, но в простой Java это было бы неудобно, так как тогда вы не можете получить доступ к данным, специфичным для запроса, без какого-либо префикса, например, req. в req.session, и тогда вам все равно нужно откуда-то получить req, например, в качестве параметра метод статического контроллера, что еще более хлопотно. Тем не менее, в Play вы можете просто написать session и так далее, это просто статические поля. Это потому, что Play использует инструментарий байт-кода, чтобы заменить все эти статические ссылки на поля чем-то более умным. Опять же, решение вне языка Java. Это не статические поля в конце.

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

person ddekany    schedule 04.08.2011

Из очень краткого взгляда я бы сказал, что это имеет смысл: веб-запросы не имеют состояния, поэтому нет объекта для получения запроса (= метода). Таким образом, сопоставление URI, такого как "/articles/archive?date=08/01/08&page=2", со статическим методом с именем archive(), я думаю, имеет смысл для вашего класса приложения.

person unwind    schedule 04.03.2011

ИЗМЕНИТЬ Теперь в Play 2.4 внедрение выполняется автоматически. Поэтому простое добавление @ в начале пути к контроллеру в файле routes поможет:

GET     /                  @controllers.Application.index()

Для более старых версий (от 2.1 до 2.3) вам придется переопределить getControllerInstance в классе Global, как описано в Документация.

person Didac Montero    schedule 14.12.2013

Как и во всем в программировании, никогда никогда никогда не является правильным ответом. Как всегда. Всегда есть исключения, и правильный ответ всегда «это зависит».

Это правда, что в чистом ОО (за что я полностью) очень мало места для статики. Но также верно и то, что иногда они просто имеют смысл.

Классический пример — служебные методы. Конечно, было бы лучше, если бы мы могли просто добавить наш метод abs() к Integer. Но мы не можем; так что мы застряли с Math.abs(int i).

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

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

Я никогда не видел Play!, но если вы говорите, что более 50 % из них статичны, то я предполагаю, что они были плохо спроектированы. Это не исключение; много фреймворков. Не позволяйте этому сломить вас. Определенно не учитесь на нем!
Но если он работает, вы все равно можете его использовать.

person Joeri Hendrickx    schedule 04.03.2011
comment
Play неплохо спроектирован, но он отличается от того, как спроектировано большинство библиотек Java. - person Marcus Downing; 05.03.2011

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

Отказ от ответственности: я мало что знаю о 'play!'

person Community    schedule 04.03.2011

Методы статического контроллера, безусловно, вызывают озабоченность в Play! framework, и после некоторого тестирования это основная причина, по которой я не запускаю Play! в проектах. Вы действительно можете увидеть это в проектах FOSS, где Play! используется. Существует мало или нет тестирования контроллера. Причина в том, что со статическими методами DI становится затруднительным. Именно здесь они должны были провести еще больше времени с ASP.NET MVC, откуда Play! уже требует немного вдохновения.

Обычно у вас есть такой конструктор:

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

Затем вы используете DI для внедрения реализации IService в контроллер. Дело в том, что в ваших тестах вы можете создать экземпляр IService непосредственно перед запуском контроллера, а затем проверить результат на основе только что созданного вами IService.

В игре это становится очень сложно. Таким образом, модульное тестирование контроллера становится сложным. Для меня это существенная проблема. Поэтому я бы предпочел искать другие фреймворки, кроме Play! в мире Явы. Черт возьми, почему бы не пойти с оригиналом и просто использовать JRuby?

person Terje    schedule 29.10.2012

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

Они каким-то образом соответствуют каждому возможному http-запросу и, как и эти http-запросы, полностью не имеют состояния.

В структурном программировании у вас есть процедуры, с одной стороны, и переменные, с другой, но в парадигме ООП вы рассматриваете процедуры и переменные как единое целое.

То есть у вас есть и объект с методами экземпляра (процедурами) и переменными экземпляра.

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

person opensas    schedule 05.03.2011

Я полагаю, по крайней мере, мы могли бы использовать одноэлементные объекты

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

Так стоит ли мне беспокоиться по этому поводу? Сделал так, чтобы Играть! разработчики запрограммировали так, чтобы вся эта статика не создавала проблем?

Это не так. На самом деле все в порядке.

person Nishant    schedule 04.03.2011
comment
Хорошо.. Я думаю. Совесть все еще грызет меня за использование статики, но на этот раз я ее проигнорирую :) - person Saew; 04.03.2011
comment
-1, потому что в синглтоне с нестатическими методами мы МОЖЕМ применять наследование и полиморфизм, но в мире статики мы НЕ можем использовать эти преимущества ООП. Так что это не почти то же самое. - person ses; 12.05.2011
comment
Наличие статики вместо хорошей языковой поддержки синглтонов, возможно, является самым большим недостатком языка Java. Система сопутствующих объектов Scala — пример того, как это небольшое изменение может иметь огромные преимущества. Даже если вы никогда не поменяли бы реализацию в реальном мире, почти всегда полезно иметь возможность поменять реализацию при тестировании. Полностью согласен с профессором, за некоторыми исключениями. Просто сделать синглтон не так сложно. - person Sarah G; 02.11.2013

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

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

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

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

  • StringUtils
  • Pattern.matches (регулярное выражение, ввод)

----------

На самом деле, я думаю, вам интересно, что насчет таких классов, как JPA.java: https://github.com/playframework/play/blob/master/framework/src/play/db/jpa/JPA.java

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

Я думаю, что это было разработано таким образом для удобства использования, потому что вызывать «getInstance» неудобно для пользователя, и здорово иметь возможность легко получить сеанс везде (связанный с потоком) вместо того, чтобы везде внедрять sessionFactory с помощью xml или autowiring. ..

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

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

  • В этом случае, когда вы вызываете методы JPA.xxx(), ваш код тесно связан с классом JPA фреймворка. Но я не думаю, что игра разработана таким образом, чтобы вы могли легко переключаться с одного фреймворка на другой без каких-либо переделок...

  • Это большая разница со спецификацией EJB3 или чем-то подобным: если бы методы менеджера сущностей EJB3 были статическими, вы были бы вынуждены тесно связать свой код с реализацией, вызывая HibernateEntityManager.xxx() или ToplinkEntityManager.xxx(). В этом случае есть общий интерфейс (и мы не можем добавлять статические методы на интерфейсы).

----------

  • Этот класс не является частью спецификации, используемой в других платформах.
  • У класса JPA есть только одна реализация: та, что выполняется с помощью play. И, вероятно, они не планируют делать второй.
  • Таким образом, тесная связь с этим классом Play, пока вы используете платформу Play, кажется мне приемлемой.
person Sebastien Lorber    schedule 25.05.2011

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

person spume    schedule 17.05.2012

Если вы являетесь пуристом объектно-ориентированного программирования, вам не следует использовать методы/поля static, однако их можно использовать безопасно, и они не должны вызывать беспокойства, ИМХО.

person Peter Lawrey    schedule 04.03.2011
comment
Я не уверен. Необдуманное использование полей static может привести к неприятным утечкам загрузчика классов в некоторых средах. - person skaffman; 04.03.2011
comment
См. предыдущий комментарий :) По словам моего профессора, статика является причиной для беспокойства.. - person Saew; 04.03.2011

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

Нестатические методы контроллера теперь поддерживаются в Play 2.1. с помощью инъекции контроллера, поэтому не очень понятно, почему их не было с самого начала.

person Andrey Chaschev    schedule 20.09.2013

Теперь вы можете использовать Spring DI в Play, см. https://stackoverflow.com/a/16552598/10433. Я использую его, и пока он работает нормально.

person Andrew Swan    schedule 04.10.2013