setborder - titledborder java
¡Jugar! framework usa un<lote> de estática (14)
Supongo que, al menos, podríamos usar objetos únicos
Singleton en Java no hace mucha diferencia que usar todo estático. No hay mucho para almacenar como estado también. Creo que no deberías preocuparte por eso.
Entonces, ¿debería preocuparme por esto? ¡Hizo la forma en que juega! los programadores programados lo hacen de modo que todas estas estáticas no representen un problema?
No debería. De hecho, está bien.
Waaah, el juego! marco tiene tantos métodos estáticos. Donde voy a la escuela, nos dijeron que nunca utilizáramos estáticas, ¡pero jugamos! lo usa como si no hubiera un mañana. ¿De alguna manera está bien? Si es así, ¿por qué?
Nosotros (7 personas y yo) estamos planeando usar Play! marco para un proyecto que involucra una aplicación web. ¡Decidimos hacerlo con Play! porque parece bastante divertido de hacer, todos nosotros ya conocemos Java y la tarea es bastante difícil, así que queríamos centrarnos en la tarea real en lugar de aprender a programar en un idioma diferente.
Sin embargo, siempre nos dijeron que NUNCA DEBEMOS usar ''estáticos'' en ningún programa Java que desarrollamos, ¡pero cuando miro Play! ... Bueno ... aproximadamente la mitad de los métodos son estáticos. </ exageración>
Supongo que, como mínimo, podríamos usar objetos singleton (usando Scala, por ejemplo ^^) para programar nuestro proyecto, pero estoy bastante preocupado por la cantidad de estáticas que realmente hay en el marco mismo.
Entonces, ¿debería preocuparme por esto? ¡Hizo la forma en que juega! los programadores programados lo hacen de modo que todas estas estáticas no representen un problema?
(Por ejemplo, este hilo tiene una diatriba sobre por qué los miembros estáticos deben evitarse a toda costa).
¡Los métodos de control estáticos son ciertamente un área de preocupación con Play! marco, y después de haber hecho algunas pruebas, ¡es la razón principal por la que no estoy jugando! en proyectos ¡De hecho, puedes ver esto en los proyectos de FOSS donde Play! es usado. Hay poca o ninguna prueba de controlador. La razón, con métodos estáticos, DI se vuelve difícil. Aquí es donde deberían haber pasado aún más tiempo con ASP.NET MVC, ¡desde donde jugar! ya toma un poco de inspiración.
Por lo general, tienes un constructor como este:
public HomeController( IService service ) {
_service = service;
}
public Index() {
var data = _service.getData();
return View( data );
}
Luego usa DI para inyectar la implementación IService en el Controlador. El punto es que en sus pruebas, puede instanciar el IService justo antes de ejecutar el Controlador, y luego probar el resultado en función del IService que acaba de producir.
En Play esto se vuelve muy difícil. Por lo tanto, la prueba de la unidad del controlador se vuelve difícil Eso es, para mí, un problema significativo. ¡Por lo tanto, tendía a buscar otros marcos que Play! en el mundo de Java Diablos, ¿por qué no ir con el original y solo usar JRuby?
Ahora puede usar Spring DI dentro de Play, consulte https://.com/a/16552598/10433 . Lo estoy usando y funciona bien hasta ahora.
Como con cualquier cosa en la programación, nunca nunca es la respuesta correcta. Como siempre . Siempre hay excepciones y la respuesta correcta siempre es ''depende''.
Es cierto que en OO puro (para lo que estoy de acuerdo) hay muy poco espacio para la estática. Pero también es cierto que a veces tienen sentido.
El ejemplo clásico es métodos de utilidad. Claro, sería mejor si pudiéramos agregar nuestro método abs()
a Entero. Pero no podemos; entonces estamos atrapados con Math.abs(int i)
.
Tiendo a pensar que es correcto hacer un método estático cuando no tiene nada que ver con la instancia en sí. Por ejemplo, en una Person
clase, podría tener un método que tome una lista de personas, y devuelva el número de personas que tienen un cumpleaños hoy. Quizás solo puedas hacer esto en la clase si los datos necesarios para hacer el cálculo son privados (algo que un purista de OO entendería;)) pero aún así el método claramente no tiene relación con una sola instancia de Persona.
Otra cosa son las clases internas. A menudo quiere hacer que sean estáticos si no necesita la relación con el tipo contenedor.
¡Nunca he visto Play! pero si dices que más del 50% es estático, entonces supongo que probablemente fue mal diseñado. Esa no es una excepción; muchos marcos son No dejes que te deprima. ¡Definitivamente no aprendes de eso!
Pero si funciona, puedes usarlo.
Desde una perspectiva muy breve, diría que tiene sentido: las solicitudes web son sin estado, por lo que no hay ningún objeto para recibir la solicitud (= el método). Por lo tanto, la asignación de un URI como "/ articles / archive? Date = 08/01/08 & page = 2" a un método estático llamado archive()
en, supongo, su clase de aplicación tiene sentido.
El método estático en juego se usa principalmente en los métodos de acción de los controladores. Estos métodos tienen la finalidad de obtener los datos necesarios del modelo y exponerlos a las vistas.
Corresponden de alguna manera a cada solicitud HTTP posible, y, al igual que las solicitudes http son completamente apátridas.
En la programación estructural, usted tiene procedimientos, por un lado, y variables, por el otro, pero en el paradigma de OOP, trata los procedimientos y las variables como un todo.
Es decir, tiene y objeta con métodos de instancia (procedimientos) y variables de instancia.
Pero las acciones del controlador son sin estado, es decir, obtienen todas las variables de la solicitud (quizás también de la memoria caché, pero en ese caso necesita algún tipo de identificación de sesión que finalmente proviene de la solicitud). Entonces, las acciones de los controladores son como los procedimientos de stateles, y es por eso que no encajan particularmente en el paradigma de OOP, como lo hacen los modelos.
El marco de juego no es una buena demostración de cuando usar la estática es apropiado, ni prueba de que tu maestro estaba equivocado. Jugar es una especie de trampa, resuelve los problemas de estática fuera del lenguaje Java.
El problema clave es que debe procesar varias solicitudes HTTP en paralelo, y los campos estáticos son "globales". Por lo tanto, necesitará una instancia por hilo (o incluso mejor, una instancia por solicitud HTTP) para ciertas cosas, pero algunas de esas cosas son devueltas por métodos estáticos en Play. Eso funciona porque Play! usa mucho ThreadLocal
-s, por lo que resuelve un problema de estática fuera del lenguaje Java. Pero eso no es todo. Algunos dicen que los métodos del controlador son legalmente estáticos. Claro, pero en Java simple sería inconveniente, ya que entonces no se puede acceder a los datos específicos de la solicitud sin algún tipo de prefijo, como req.
en req.session
, y luego todavía tiene que obtener req
desde alguna parte, como un parámetro del método de controlador estático, que es aún más complicado. Sin embargo, en Play puedes simplemente escribir session
directamente y me gusta, solo son campos estáticos. Eso es porque Play usa la instrumentación bytecode para cambiar todas las referencias de campo estático a algo más inteligente. De nuevo, una solución fuera del lenguaje Java. Esos no son campos estáticos al final.
Por lo tanto, en general, evite la estática no final. Sin embargo, Play hace la magia por ti, así que no temas en este caso.
El principal problema es que los métodos estáticos solo tienen acceso a otros métodos y campos estáticos, lo que resulta en un "bloqueo estático" por el cual los métodos estáticos tienen que encontrarse con el resto de la aplicación (que contiene sus colaboradores) a través de campos estáticos comunes. , lo que conduce a la inflexibilidad.
Descargo de responsabilidad: no sé mucho sobre ''jugar!''
Jugar usa métodos estáticos solo cuando tiene sentido:
- en la capa de controlador, porque los controladores no están orientados a objetos. Los controladores actúan como asignador entre el mundo HTTP (que es sin estado, y basado en solicitud / respuesta) y la capa del Modelo que está completamente orientada a objetos.
- en la capa modelo para métodos de fábrica, como findAll (), count (), create () que por supuesto no dependen de ninguna instancia en particular
- en algunas clases play.libs. * que proporciona funciones puramente de utilidad
Play tiene un enfoque funcional, como node.js por ejemplo, y podría decirse que tiene más sentido en Scala que en Java, como la pila Typesafe está presionando, por ejemplo. Como han señalado otros carteles, Java se está incrementando usando la instrumentación bytecode (a la Aspect J) para comportarse de una manera más sin estado / funcional; Scala hace esto por defecto.
Si usted es un purista de programación orientada a objetos, no debe utilizar métodos / campos static
, sin embargo, pueden usarse de manera segura y no deben ser motivo de preocupación en mi humilde opinión.
También estoy sorprendido por la cantidad de métodos estáticos en juego, pero ¿por qué no si funciona bien ...?
En realidad, no estoy de acuerdo con tu profesor.
Si un objeto no tiene ningún estado (es decir, variables globales) pero solo contiene métodos para ejemplificar, no le proporciona ningún beneficio utilizar un objeto en lugar de métodos estáticos. Excepto si planea agregar un estado más tarde (indicar que no se debe compartir), o si está utilizando una interfaz y desea poder cambiar fácilmente la implementación, es más fácil usar métodos estáticos ...
JDK en sí, apache commons o muchos frameworks incluyen métodos estáticos:
- StringUtils
- Pattern.matches (regex, entrada)
----------
En realidad, supongo que te preguntas acerca de las clases como JPA.java: https://github.com/playframework/play/blob/master/framework/src/play/db/jpa/JPA.java
Usan solo métodos estáticos y mantienen un estado estático. Esto podría ser extraño, pero en realidad para mí es como usar un singleton, excepto que los métodos se usan en un contexto estático en lugar de en un objeto. La principal diferencia es que no tiene que llamar a getInstance () cada vez.
Creo que esto fue diseñado así para facilidad de uso, porque no es fácil de usar para llamar a "getInstance" y es genial poder obtener fácilmente una sesión en todas partes (vinculada al hilo) en lugar de inyectar el sessionFactory en todas partes con xml o autowiring. ..
Su profesor quizás le diga que evite usar estática porque puede ser peligroso para su diseño si no los usa correctamente. Pero observe que en muchos casos, reemplazar los métodos estáticos por un singleton no mejora su diseño. Incluso si ahora llama a los métodos en un método de instancia, los objetos aún estarán estrechamente acoplados ...
Entonces, tal vez una regla debería ser evitar el uso de estática, excepto cuando realmente no te importa un acoplamiento cerrado.
En este caso, cuando llama a métodos JPA.xxx (), su código está estrechamente vinculado a la clase de JPA del framework. Pero no creo que el juego esté diseñado para que puedas cambiar fácilmente de un marco a otro sin al menos alguna modificación ...
Es una gran diferencia con las especificaciones de EJB3 o cosas por el estilo: si los métodos del administrador de entidades EJB3 son estáticos, se vería forzado a acoplar estrechamente su código a la implementación llamando a HibernateEntityManager.xxx () o ToplinkEntityManager.xxx (). En este caso, hay una interfaz común (y no podemos agregar métodos estáticos en las interfaces).
----------
- Esa clase no es parte de una especificación utilizada en otros marcos.
- La clase JPA tiene una sola implementación: la que se realiza por juego. Y probablemente no estén planeando hacer una segunda.
- Por lo tanto, un acoplamiento estrecho a esta clase de Juego, mientras está usando Play Framework, parece estar bien para mí.
Una de las razones para utilizar métodos estáticos son las importaciones estáticas que le permiten acortar la notación y hacer que el código sea más legible. Esto es especialmente cierto cuando se utilizan bibliotecas de utilidades como Guava o Apache Commons en las que puede tener muchas llamadas estáticas.
Los métodos de controlador no estáticos ahora son supported con Play 2.1 mediante el uso de la inyección de controlador, por lo que no está muy claro por qué no estaban allí desde el principio.
EDITAR ahora en Play 2.4, la inyección se realiza automáticamente. Así que solo agregar @ al comienzo de la ruta del controlador en las routes
archivos hará el truco:
GET / @controllers.Application.index()
Para versiones anteriores (2.1 a 2.3), deberá anular getControllerInstance en la clase Global, como se explica en la Documentantion .