web-dev-qa-db-fra.com

Jouer! le cadre utilise un <lot> de statique

Waaah, le jeu! le cadre a tellement de méthodes statiques. Où je vais à l'école, on nous a dit de ne jamais utiliser de statique, mais de jouer! l'utilise comme s'il n'y avait pas de lendemain. Est-ce que ça va? Si oui, pourquoi?

Nous (7 personnes et moi) prévoyons d'utiliser le jeu! cadre pour un projet impliquant une application web. Nous avons décidé de le faire avec Play! car cela semble assez amusant à faire, nous savons tous déjà Java et l'affectation est assez difficile, nous voulions donc nous concentrer sur l'affectation réelle plutôt que d'apprendre à programmer dans une autre langue.

On nous a toujours dit, cependant, JAMAIS JAMAIS d'utiliser des 'statiques dans n'importe quel programme Java Java que nous avons développé, mais quand je regardez Play! ... Eh bien ... environ la moitié des méthodes sont statiques. </exaggeration>

Je suppose, à tout le moins, que nous pourrions utiliser des objets singleton (en utilisant Scala, par exemple ^^) pour programmer notre projet, mais je suis très préoccupé par le nombre de statiques dans le framework lui-même.

Alors, dois-je m'inquiéter à ce sujet? A fait la façon dont le jeu! les développeurs l'ont programmé pour que toutes ces statiques ne posent pas de problème?

(Par exemple, ce fil a une diatribe sur les raisons pour lesquelles les membres statiques doivent être évités à tout prix.)

75
Saew

Le jeu utilise des méthodes statiques uniquement lorsque cela a du sens:

  • dans la couche contrôleur, car les contrôleurs ne sont pas orientés objet. Les contrôleurs agissent comme un mappeur entre le monde HTTP (qui est sans état et basé sur les requêtes/réponses) et la couche Model entièrement orientée objet.
  • dans la couche modèle pour les méthodes d'usine, comme findAll (), count (), create () qui bien sûr ne dépendent d'aucune instance particulière
  • dans certaines classes play.libs. * qui fournissent des fonctions purement utilitaires
95
Guillaume Bort

Le cadre de jeu n'est pas une bonne démonstration de l'utilisation de la statique, ni ne prouve que votre professeur avait tort. Le jeu est une sorte de triche, résout les problèmes de statique en dehors du langage Java.

Le problème clé est que vous devez traiter plusieurs requêtes HTTP en parallèle et que les champs statiques sont "globaux". Vous aurez donc besoin d'une instance par thread (ou mieux, d'une instance par requête HTTP) pour certaines choses, mais certaines de ces choses sont retournées par des méthodes statiques dans Play. Cela fonctionne parce que Play! utilise ThreadLocal- s, ce qui résout un problème de statique en dehors du langage Java. Mais ce n'est pas tout. Certains disent que les méthodes du contrôleur sont à juste titre statiques. Bien sûr, mais en clair Java ce serait gênant, car alors vous ne pouvez pas accéder aux données spécifiques à la demande sans une sorte de préfixe, comme req. dans req.session, puis vous devez toujours obtenir req quelque part, comme un paramètre de la méthode du contrôleur statique, ce qui est encore plus compliqué. Pourtant, dans Play, vous pouvez simplement écrire directement session et comme, ce ne sont que des champs statiques. C'est parce que Play utilise l'instrumentation bytecode pour changer toutes ces références de champ statique en quelque chose de plus intelligent. Encore une fois, une solution en dehors du langage Java. Ce ne sont pas des champs statiques à la fin.

Donc, en général, évitez la statique non finale. Le jeu fait la magie pour vous, alors n'ayez pas peur d'eux dans ce cas.

34
ddekany

D'un regard très bref, je dirais que cela a du sens: les requêtes Web sont sans état, donc il n'y a is aucun objet pour recevoir la requête (= la méthode). Ainsi, le mappage d'un URI tel que "/ articles/archive? Date = 08/01/08 & page = 2" à une méthode statique appelée archive() sur, je suppose, votre classe d'application est logique.

15
unwind

[~ # ~] modifier [~ # ~] Maintenant dans Play 2.4, l'injection se fait automatiquement. Donc, ajouter simplement @ au début du chemin du contrôleur dans le fichier routes fera l'affaire:

GET     /                  @controllers.Application.index()

Pour les versions plus anciennes (2.1 à 2.3), vous devrez remplacer getControllerInstance dans la classe Global, comme expliqué dans le Documentantion .

8
Didac Montero

Comme pour tout ce qui concerne la programmation, jamais jamais n'est jamais la bonne réponse. Tout comme toujours. Il y a toujours des exceptions et la bonne réponse est toujours "ça dépend".

Il est vrai qu'en pur OO (pour lequel je suis tout à fait), il y a très peu de place pour la statique. Mais il est également vrai que parfois ils ont juste un sens.

L'exemple classique est celui des méthodes utilitaires. Bien sûr, il serait préférable que nous puissions simplement ajouter notre méthode abs() à Integer. Mais nous ne pouvons pas; nous sommes donc coincés avec Math.abs(int i).

J'ai tendance à penser qu'il est juste de rendre une méthode statique lorsqu'elle n'a rien à voir avec l'instance elle-même. Par exemple, dans une classe Person, vous pourriez avoir une méthode qui prend une liste de personnes et renvoie le nombre de personnes qui ont un anniversaire aujourd'hui. Peut-être que vous ne pouvez le faire dans la classe elle-même que si les données nécessaires pour effectuer le calcul sont privées (quelque chose qu'un OO comprendrait;)) mais la méthode n'a clairement aucun lien avec un seul Instance de personne.

Une autre chose est les classes internes. Vous voulez souvent les rendre statiques si vous n'avez pas besoin de la relation avec le type conteneur.

Je n'ai jamais vu Play! mais si vous dites que plus de 50% de celui-ci est statique, alors je suppose qu'il était probablement mal conçu. Ce n'est pas une exception; beaucoup de cadres sont. Ne vous laissez pas abattre. Certainement ne pas en apprendre!
Mais si cela fonctionne, vous pouvez toujours l'utiliser.

5
Joeri Hendrickx

Le problème principal est que les méthodes statiques n'ont accès qu'à d'autres méthodes et champs statiques, ce qui se traduit par un "accrochage statique", les méthodes statiques devant se retrouver avec le reste de l'application (qui contient ses collaborateurs) via des champs statiques communs. , ce qui conduit à l'inflexibilité.

Avertissement: je ne connais pas grand-chose au jeu!

4
user638455

Les méthodes de contrôleur statique sont certainement un sujet de préoccupation avec le jeu! et après avoir fait quelques tests, c'est la principale raison pour laquelle je ne fais pas Play! dans les projets. Vous pouvez voir cela dans les projets FOSS où Play! est utilisé. Il y a peu ou pas de tests de contrôleur. La raison, avec des méthodes statiques, DI devient difficile. C'est là qu'ils auraient dû passer encore plus de temps avec ASP.NET MVC, d'où Play! prend déjà un peu d'inspiration.

En règle générale, vous avez un constructeur comme celui-ci:

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

Ensuite, vous utilisez DI pour injecter l'implémentation IService dans le contrôleur. Le fait étant que dans vos tests, vous pouvez instancier l'IService juste avant d'exécuter le contrôleur, puis tester le résultat en fonction de l'IService que vous venez de produire.

Dans Play, cela devient très difficile. Ainsi, les tests unitaires du contrôleur deviennent difficiles. C'est, pour moi, un problème important. J'aurais donc tendance à chercher d'autres frameworks que Play! dans le monde Java. Heck, pourquoi ne pas aller avec l'original et utiliser simplement JRuby?

4
Terje

Les méthodes statiques en jeu sont principalement utilisées dans les méthodes d'action des contrôleurs. Ces méthodes sont destinées à extraire simplement les données nécessaires du modèle et à les exposer à des vues.

Ils correspondent d'une manière ou d'une autre à chaque requête http possible et, tout comme ces requêtes http sont complètement sans état.

Sur la programmation structurelle, vous avez des procédures d'une part et des variables de l'autre, mais sur le paradigme OOP vous traitez les procédures et les variables dans leur ensemble.

C'est-à-dire que vous avez et objectez avec des méthodes d'instance (procédures) et des variables d'instance.

Mais les actions du contrôleur sont sans état, c'est-à-dire qu'elles obtiennent toutes les variables de la demande (peut-être aussi du cache, mais dans ce cas, vous avez besoin d'une sorte d'ID de session qui vient finalement de la demande). Les actions du contrôleur sont donc comme les procédures stateles, et c'est pourquoi elles ne rentrent pas particulièrement dans le paradigme OOP, comme le font les modèles.

3
opensas

Je suppose que nous pourrions au moins utiliser des objets singleton

Singleton in Java ne fait pas beaucoup de différence que d'utiliser tous les statiques. Il n'y a pas non plus grand chose à stocker comme état. Je pense que vous ne devriez pas vous en soucier.

Alors, dois-je m'inquiéter à ce sujet? A fait la façon dont le jeu! les développeurs l'ont programmé pour que toutes ces statiques ne posent pas de problème?

Ce ne serait pas le cas. En fait, ça va.

2
Nishant

Le jeu adopte une approche fonctionnelle, comme node.js par exemple, et a sans doute plus de sens dans Scala qu'en Java, comme le Typesafe Stack pousse, par exemple. Comme d'autres affiches l'ont souligné, Java est augmenté en utilisant l'instrumentation de bytecode (à la Aspect J) pour se comporter de manière plus apatride/fonctionnelle; Scala fait cela par défaut.

1
spume

Je suis également surpris par le nombre de méthodes statiques en jeu, mais pourquoi pas si cela fonctionne bien ...

En fait, je ne suis pas d'accord avec votre professeur.

Si un objet n'a pas d'état (c'est-à-dire des variables globales) mais contient simplement des méthodes par exemple, cela ne vous donne aucun avantage d'utiliser un objet plutôt que des méthodes statiques. Sauf si vous prévoyez d'ajouter un état ultérieurement (état qui ne doit pas être partagé), ou si vous utilisez une interface et que vous souhaitez pouvoir basculer facilement l'implémentation, il est plus facile d'utiliser des méthodes statiques ...

JDK lui-même, les communs Apache ou de nombreux frameworks incluent des méthodes statiques:

  • StringUtils
  • Pattern.matches (regex, entrée)

----------

En fait, je suppose que vous vous demandez ce que sont les classes comme JPA.Java: https://github.com/playframework/play/blob/master/framework/src/play/db/jpa/JPA.Java

Ils utilisent uniquement des méthodes statiques et conservent un état statique. Cela peut être étrange, mais en fait pour moi, c'est un peu comme utiliser un singleton, sauf que les méthodes sont utilisées sur un contexte statique au lieu d'un objet. La principale différence est que vous n'avez pas besoin d'appeler getInstance () à chaque fois.

Je pense que cela a été conçu comme ça pour la convivialité, car il n'est pas convivial d'appeler "getInstance" et c'est cool de pouvoir obtenir facilement une session partout (liée au thread) au lieu d'injecter partout la sessionFactory avec du xml ou du câblage automatique. ..

Votre professeur vous dit peut-être d'éviter d'utiliser la statique, car cela peut être dangereux pour votre conception si vous ne les utilisez pas correctement. Mais remarquez dans de nombreux cas, le remplacement des méthodes statiques par un singleton n'améliore pas votre conception. Même si vous appelez maintenant les méthodes sur une méthode d'instance, les objets seront toujours étroitement couplés ...

Donc, peut-être qu'une règle devrait être d'éviter d'utiliser la statique, sauf lorsque vous ne vous souciez pas vraiment d'un couplage serré.

  • Dans ce cas, lorsque vous appelez les méthodes JPA.xxx (), votre code est étroitement couplé à la classe JPA du framework. Mais je ne pense pas que le jeu soit conçu pour que vous puissiez facilement passer d'un framework à un autre sans au moins quelques retouches ...

  • C'est une grande différence avec les spécifications EJB3 ou des trucs comme ça: si les méthodes du gestionnaire d'entités EJB3 étaient statiques, vous seriez forcé de coupler étroitement votre code à l'implémentation en appelant HibernateEntityManager.xxx () ou ToplinkEntityManager.xxx (). Dans ce cas, il existe une interface commune (et nous ne pouvons pas ajouter de méthodes statiques sur les interfaces).

----------

  • Cette classe ne fait pas partie d'une spécification utilisée sur d'autres frameworks.
  • La classe JPA n'a qu'une seule implémentation: celle réalisée par le jeu. Et ils n'envisagent probablement pas d'en faire un deuxième.
  • Ainsi, un couplage étroit avec cette classe Play, pendant que vous utilisez le framework Play, me semble correct.
1
Sebastien Lorber

Vous pouvez maintenant utiliser Spring DI dans Play, voir https://stackoverflow.com/a/16552598/104 . Je l'utilise et cela fonctionne bien jusqu'à présent.

0
Andrew Swan

L'une des raisons d'utiliser des méthodes statiques est les importations statiques qui vous permettent de raccourcir la notation et de rendre le code plus lisible. Cela est particulièrement vrai lorsque vous utilisez des bibliothèques d'utilitaires comme Guava ou Apache Commons dans lesquelles vous pouvez avoir beaucoup d'appels statiques.

Les méthodes de contrôleur non statiques sont désormais prises en charge dans Play 2.1 via l'utilisation de l'injection de contrôleur, il n'est donc pas très clair pourquoi elles n'étaient pas là depuis le début.

0
Andrey Chaschev

Si vous êtes un puriste de la programmation orientée objet, vous ne devez pas utiliser les méthodes/champs static, mais ils peuvent être utilisés en toute sécurité et ne doivent pas être une source de préoccupation à mon humble avis.

0
Peter Lawrey