Abspielen! Framework verwendet eine <lot> Statik


75

Waaah, das Stück! Framework hat so viele statische Methoden. Wo ich zur Schule gehe, wurde uns nie gesagt verwenden, aber spielen! benutzt es, als gäbe es kein Morgen. Ist das irgendwie okay Wenn ja warum?

Wir (7 Personen und ich) planen, das Spiel zu nutzen! Rahmen für ein Projekt mit einer Web-App. Wir haben uns für Play entschieden! Da es ziemlich lustig aussieht, kennen wir alle bereits Java und die Aufgabe ist ziemlich schwierig. Deshalb wollten wir uns auf die eigentliche Aufgabe konzentrieren, anstatt auch zu lernen, wie man in einer anderen Sprache programmiert.

Uns wurde jedoch immer gesagt, NIEMALS in einem von uns entwickelten Java-Programm verwenden sollen, aber wenn ich mir Play anschaue! ... Nun ... ungefähr die Hälfte der Methoden ist statisch. </ Übertreibung>

Ich nehme an, wir könnten zumindest Singleton-Objekte verwenden (z. B. mit Scala ^^), um unser Projekt zu programmieren, aber ich bin ziemlich besorgt darüber, wie viele Statiken es tatsächlich im Framework selbst gibt.

Sollte ich mir darüber Sorgen machen? Hat den Weg gemacht das Spiel! Entwickler haben es so programmiert, dass all diese Statiken kein Problem darstellen?

(In diesem Thread wird beispielsweise darüber geschimpft, warum statische Elemente unter allen Umständen vermieden werden sollten.)


3
Äh ... Sie sollten wahrscheinlich Ihren Professor oder wen auch immer fragen. Außerdem ist es für den Rest der Welt selbstverständlich, nicht dieselben Ideen über gute und schlechte Programmierpraktiken wie Sie zu unterschreiben. Gewöhnen Sie sich also an die Idee. :)
Abroller

4
@Saew obwohl die Verwendung von Statik nicht empfohlen wird, ist "NIEMALS Statik verwenden" eine Übertreibung
Suraj Chandran

21
Das <exaggeration>Tag ist nicht sichtbar. :)
Nishant

Das ist die Sache, unser Professor ist ein OO-Purist. Er warnt uns immer vor den Gefahren der Verwendung von Statik und er wird unsere Köpfe für die Verwendung von Statik haben, es sei denn, wir können eine anständige Erklärung liefern, warum wir sie immer noch verwenden und haben keine Angst vor Konsequenzen.
Saew

@Nishant @jensgram Ich verstehe, danke;)
Saew

Antworten:


95

Das Spielen verwendet statische Methoden nur, wenn es sinnvoll ist:

  • in der Controller-Schicht, da Controller nicht objektorientiert sind. Controller fungieren als Mapper zwischen der HTTP-Welt (die zustandslos und anforderungs- / antwortbasiert ist) und der Modellebene, die vollständig objektorientiert ist.
  • in der Modellebene für Factory-Methoden wie findAll (), count (), create (), die natürlich nicht von bestimmten Instanzen abhängen
  • in einigen play.libs. * -Klassen, die reine Dienstprogrammfunktionen bereitstellen

1
Das Hauptproblem sind außerdem statische Elemente und keine statischen Methoden. Im Spiel sind das nur Threadlocals als statische Elemente.
Niels

3
Die Verwendung des statischen validationElements (siehe Beispiel ) in Kombination mit einem ThreadLocalzeigt, dass statisch nicht in allen Fällen geeignet ist.
Deamon

9
Ich bin es gewohnt, dass Controller mit Abhängigkeiten über ein DI-Framework injiziert werden. Wie würden Sie DI mit statischen Objekten implementieren?
Ripper234

6
@ Guillaume Ich muss Ihnen stark widersprechen. Play zeigt die schlechtesten Praktiken beim Schreiben von Java und es sollte keine Ausreden für die Verwendung von statics in Java-Code geben. Unveränderlichkeit wird nicht durch Statik angezeigt, ganz im Gegenteil Statik zeigt einen gemeinsamen Zustand an, der so ziemlich das Gegenteil von dem ist, was Sie behaupten. Dann gibt es natürlich lustige Dinge wie das Aufrufen einer statischen Methode auf einer falschen Instanz, da statische Methoden nicht einmal mit der Klasse gepaart sind, in der sie definiert sind. Kurz gesagt, staticin Java riecht es nach Code und sollte überhaupt nicht vorhanden sein, wenn Sie dies tun Ziel ist es, modernes Java zu schreiben.
Esko

2
@Esko Ich stimme dir definitiv zu. Spielen mag in Scala wertvoll sein, aber in Java summiert es eine Liste von schlechten Praktiken.
Snicolas

34

Das Spiel-Framework ist weder eine gute Demonstration dafür, wann die Verwendung von Statik angemessen ist, noch beweist es, dass Ihr Lehrer sich geirrt hat. Spielen ist eine Art Betrug, löst die Probleme der Statik außerhalb der Java-Sprache.

Das Hauptproblem besteht darin, dass Sie mehrere HTTP-Anforderungen parallel verarbeiten müssen und statische Felder "global" sind. Sie benötigen also eine Instanz pro Thread (oder noch besser eine Instanz pro HTTP-Anforderung) für bestimmte Dinge, doch einige dieser Dinge werden von statischen Methoden in Play zurückgegeben. Das funktioniert, weil Play! verwendet ThreadLocal-s stark und löst so ein Problem der Statik außerhalb der Java-Sprache. Das ist aber nicht alles. Einige sagen, dass Controller-Methoden zu Recht statisch sind. Sicher, aber in einfachem Java wäre es unpraktisch, da Sie dann ohne ein Präfix wie req.in nicht auf anforderungsspezifische Daten zugreifen könnenreq.session und dann noch abrufen müssenreq von irgendwoher kommen müssen, wie als Parameter der statischen Controller-Methode , was noch mühsamer ist. Im Spiel können Sie jedoch direkt schreibensessionund wie, sie sind nur statische Felder. Das liegt daran, dass Play die Bytecode-Instrumentierung verwendet, um all diese statischen Feldreferenzen in etwas Klügeres zu ändern. Wieder eine Lösung außerhalb der Java-Sprache. Das sind keine statischen Felder am Ende.

Vermeiden Sie daher im Allgemeinen nicht endgültige Statiken. Spielen macht die Magie für Sie, also haben Sie in diesem Fall keine Angst vor ihnen.


15

Auf einen kurzen Blick würde ich sagen, dass es irgendwie Sinn macht: Webanfragen sind zustandslos, daher gibt es kein Objekt, um die Anfrage zu empfangen (= die Methode). Wenn Sie also einen URI wie "/ articles / archive? Date = 08/01/08 & page = 2" einer statischen Methode archive()zuordnen, die aufgerufen wird , ist Ihre Anwendungsklasse wahrscheinlich sinnvoll.


8

BEARBEITEN Jetzt in Play 2.4 erfolgt die Injektion automatisch. Das Hinzufügen von @ am Anfang des Controller-Pfads in der Datei routesmacht also den Trick:

GET     /                  @controllers.Application.index()

Bei älteren Versionen (2.1 bis 2.3) müssen Sie getControllerInstance in der Global-Klasse überschreiben, wie in der Dokumentation erläutert .


5

Wie bei allem in der Programmierung ist niemals niemals die richtige Antwort. Genau wie immer . Es gibt immer Ausnahmen und die richtige Antwort lautet immer "es kommt darauf an".

Es ist wahr, dass in reinem OO (für das ich alles bin) sehr wenig Platz für Statik ist. Aber es ist auch wahr, dass sie manchmal einfach Sinn machen.

Das klassische Beispiel sind Dienstprogrammmethoden. Sicher, es wäre besser, wenn wir unsere abs()Methode einfach an Integer anhängen könnten . Aber wir können nicht; Also bleiben wir bei Math.abs(int i).

Ich neige dazu zu denken, dass es einfach richtig ist, eine Methode statisch zu machen, wenn sie nichts mit der Instanz selbst zu tun hat. Zum Beispiel in einer KlassePerson könnten Sie beispielsweise eine Methode haben, die eine Liste von Personen erstellt und die Anzahl der Personen zurückgibt, die heute Geburtstag haben. Vielleicht können Sie dies nur in der Klasse selbst tun, wenn die für die Berechnung benötigten Daten privat sind (etwas, das ein OO-Purist verstehen würde;)), aber die Methode hat eindeutig keine Beziehung zu einer einzelnen Personeninstanz.

Eine andere Sache sind interne Klassen. Sie möchten sie häufig statisch machen, wenn Sie die Beziehung zum enthaltenen Typ nicht benötigen.

Ich habe Play noch nie gesehen ! Aber wenn Sie sagen, dass über 50% davon statisch sind, dann wurde es wahrscheinlich schlecht entworfen. Das ist keine Ausnahme; viele Frameworks sind. Lass dich nicht unterkriegen. Lerne auf keinen Fall daraus!
Aber wenn es funktioniert, können Sie es trotzdem verwenden.


22
Play ist nicht schlecht gestaltet, aber es weicht von der Art und Weise ab, wie die meisten Java-Bibliotheken gestaltet sind.
Marcus Downing

4

Das Hauptproblem besteht darin, dass statische Methoden nur Zugriff auf andere statische Methoden und Felder haben, was zu einem "statischen Festhalten" führt, wobei sich die statischen Methoden über gemeinsame statische Felder mit dem Rest der Anwendung (die ihre Mitarbeiter enthält) treffen müssen. , was zu Inflexibilität führt.

Haftungsausschluss: Ich weiß nicht viel über "Spielen!"


4

Statische Controller-Methoden sind sicherlich ein Bereich, der bei Play! Framework, und nachdem ich einige Tests durchgeführt habe, ist es der Hauptgrund für mich, nicht zu spielen! in Projekten. Sie können dies tatsächlich in FOSS-Projekten sehen, in denen Play! wird eingesetzt. Es gibt nur wenige oder keine Controller-Tests. Der Grund, warum DI mit statischen Methoden schwierig wird. Hier hätten sie noch mehr Zeit mit ASP.NET MVC verbringen sollen, von wo aus Play! braucht schon ein bisschen Inspiration.

Normalerweise haben Sie einen Konstruktor wie diesen:

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

Anschließend verwenden Sie DI, um die IService-Implementierung in den Controller einzufügen. Der Punkt ist, dass Sie in Ihren Tests den IService unmittelbar vor dem Ausführen des Controllers instanziieren und dann das Ergebnis basierend auf dem gerade erstellten IService testen können.

Im Spiel wird dies sehr schwierig. Somit wird das Testen der Controller-Einheit schwierig. Das ist für mich ein erhebliches Problem. Ich würde daher eher nach anderen Frameworks als Play suchen! in der Java-Welt. Heck, warum nicht mit dem Original gehen und nur JRuby verwenden?


3

Statische Methoden im Spiel werden hauptsächlich in Steuerungsaktionsmethoden verwendet. Diese Methoden sollen nur die erforderlichen Daten aus dem Modell abrufen und für Ansichten verfügbar machen.

Sie entsprechen irgendwie jeder möglichen http-Anfrage und sind genau wie diese http-Anfragen völlig zustandslos.

Bei der strukturellen Programmierung haben Sie einerseits Prozeduren und andererseits Variablen, aber beim OOP-Paradigma behandeln Sie Prozeduren und Variablen als Ganzes.

Das heißt, Sie haben und widersprechen Instanzmethoden (Prozeduren) und Instanzvariablen.

Controller-Aktionen sind jedoch zustandslos, dh sie erhalten alle vorhandenen Variablen aus der Anforderung (möglicherweise auch aus dem Cache, aber in diesem Fall benötigen Sie eine Sitzungs-ID, die schließlich aus der Anforderung stammt). Controller-Aktionen sind also genau wie Stateles-Prozeduren, und deshalb passen sie nicht besonders in das OOP-Paradigma, wie dies Modelle tun.


2

Ich nehme an, wir könnten zumindest Singleton-Objekte verwenden

Singleton in Java macht keinen großen Unterschied als die Verwendung aller statischen. Es gibt auch nicht viel als Staat zu speichern. Ich denke, du solltest dir darüber keine Sorgen machen.

Sollte ich mir darüber Sorgen machen? Hat den Weg gemacht das Spiel! Entwickler haben es so programmiert, dass all diese Statiken kein Problem darstellen?

Es würde nicht. In der Tat ist es in Ordnung.


1
Okay, denke ich. Mein Gewissen nervt mich immer noch, weil ich Statik benutze, aber ich werde es diesmal ignorieren :)
Saew

1
-1, weil wir in Singleton mit nicht statischen Methoden Vererbung und Polymorphismus anwenden können, aber in der statischen Welt können wir diese Vorteile von OOP NICHT nutzen. Also ist es fast nicht dasselbe.
ses

Statik statt gute Sprachunterstützung für Singletons zu haben, ist wohl der größte Fehler in der Java-Sprache. Das Begleitobjektsystem von Scala ist eine Fallstudie darüber, wie diese kleine Änderung enorme Vorteile haben kann. Selbst wenn Sie die Implementierung in der realen Welt niemals austauschen würden, ist es fast immer nützlich, eine Implementierung beim Testen austauschen zu können. Ich stimme dem Professor mit wenigen Ausnahmen sehr zu. Es ist einfach nicht so schwer, einen Singleton zu machen.
Sarah G

1

Ich bin auch überrascht von der Anzahl der statischen Methoden im Spiel, aber warum nicht, wenn es gut funktioniert ...

Eigentlich stimme ich deinem Lehrer nicht zu.

Wenn ein Objekt keinen Status hat (dh globale Variablen), sondern nur Methoden enthält, bietet es Ihnen keine Vorteile, ein Objekt anstelle statischer Methoden zu verwenden. Außer wenn Sie planen, später einen Status hinzuzufügen (Status, der nicht freigegeben werden sollte) oder wenn Sie eine Schnittstelle verwenden und die Implementierung einfach wechseln möchten, ist es einfacher, statische Methoden zu verwenden ...

JDK selbst, Apache Commons oder viele Frameworks enthalten statische Methoden:

  • StringUtils
  • Pattern.matches (Regex, Eingabe)

----------

Eigentlich fragst du dich, was ist mit Klassen wie JPA.java: https://github.com/playframework/play/blob/master/framework/src/play/db/jpa/JPA.java

Sie verwenden nur statische Methoden und behalten einen statischen Zustand bei. Das könnte seltsam sein, aber für mich ist es ein bisschen wie mit einem Singleton, nur dass die Methoden in einem statischen Kontext anstelle eines Objekts verwendet werden. Der Hauptunterschied besteht darin, dass Sie getInstance () nicht jedes Mal aufrufen müssen.

Ich denke, dies wurde aus Gründen der Benutzerfreundlichkeit so konzipiert, da es nicht benutzerfreundlich ist, "getInstance" aufzurufen, und es cool ist, einfach überall eine Sitzung zu erhalten (mit dem Thread verknüpft), anstatt die sessionFactory überall mit XML oder Autowiring zu injizieren. ..

Ihr Professor fordert Sie möglicherweise auf, die Verwendung von Statik zu vermeiden, da dies für Ihr Design gefährlich sein kann, wenn Sie sie nicht richtig verwenden. Beachten Sie jedoch, dass das Ersetzen statischer Methoden durch einen Singleton in vielen Fällen Ihr Design nicht verbessert. Selbst wenn Sie jetzt die Methoden für eine Instanzmethode aufrufen, werden Objekte immer noch eng miteinander verbunden ...

Vielleicht sollte eine Regel darin bestehen, die Verwendung von Statik zu vermeiden, es sei denn, Sie kümmern sich nicht wirklich um eine enge Kopplung.

  • In diesem Fall ist Ihr Code beim Aufrufen der Methoden JPA.xxx () eng an die JPA-Klasse des Frameworks gekoppelt. Aber ich denke nicht, dass Play so konzipiert ist, dass Sie ohne zumindest einige Nacharbeiten problemlos von einem Framework zu einem anderen wechseln können ...

  • Es ist ein großer Unterschied zu EJB3-Spezifikationen oder Ähnlichem: Wenn die Methoden des EJB3-Entitätsmanagers statisch sind, müssen Sie Ihren Code eng an die Implementierung koppeln, indem Sie HibernateEntityManager.xxx () oder ToplinkEntityManager.xxx () aufrufen. In diesem Fall gibt es eine gemeinsame Schnittstelle (und wir können keine statischen Methoden für Schnittstellen hinzufügen).

----------

  • Diese Klasse ist nicht Teil einer Spezifikation, die in anderen Frameworks verwendet wird.
  • Die JPA-Klasse hat nur eine Implementierung: die spielerische. Und sie planen wahrscheinlich nicht, einen zweiten zu machen.
  • Daher scheint mir eine enge Kopplung an diese Play-Klasse, während Sie das Play-Framework verwenden, in Ordnung zu sein.

1

Play verfolgt einen funktionalen Ansatz, wie zum Beispiel node.js , und ist in Scala wohl sinnvoller als in Java, da der Typesafe Stack zum Beispiel Druck macht. Wie andere Poster bereits betont haben, wird Java mithilfe von Bytecode-Instrumenten (a la Aspect J) erweitert, um sich zustandsloser / funktionaler zu verhalten. Scala macht dies standardmäßig.


0

Wenn Sie ein Purist der objektorientierten Programmierung sind, sollten Sie keine staticMethoden / Felder verwenden, diese können jedoch sicher verwendet werden und müssen meiner Meinung nach kein Grund zur Sorge sein.


2
Ich bin mir nicht sicher. Die unentgeltliche Verwendung von staticFeldern kann in einigen Umgebungen zu unangenehmen Klassenladerlecks führen.
Skaffman

1
Siehe früheren Kommentar :) Nach meinem Professor, Statik ist ein Grund zur Besorgnis ..
Saew

0

Einer der Gründe für die Verwendung statischer Methoden sind die statischen Importe, mit denen Sie die Notation verkürzen und den Code besser lesbar machen können. Dies gilt insbesondere dann, wenn Sie Dienstprogrammbibliotheken wie Guava oder Apache Commons verwenden, in denen möglicherweise viele statische Aufrufe ausgeführt werden.

Nicht-statische Controller - Methoden werden nun unterstützt im Play 2.1 über mit Controller Injektion, es ist so nicht ganz klar , warum sie von Anfang an nicht da war.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.