Java - Un antipattern de los gordos?

 
Vista:

Un antipattern de los gordos?

Publicado por Rakan (9 intervenciones) el 29/04/2019 14:00:59
Llevo dos semanas buscando una solución a un problema, al final la he encontrado, pero creo que es un antipatrón de esos que cuando los ves dices: pues se ha quedado a gusto el que ha escrito este codigo ehhh...

Lo que quiero hacer es ir cargando objetos en memoria usando los datos que tengo en un archivo (entidades de un mapa de un juego).
Tras pensar mucho, he tomado la siguiente estructura:

Una clase raiz BasicEntity

AxisEntity extiende BasicEntity y permite tener X e Y junto a algunas funcionalidades para el plano.

VisualizableEntity extiende BasicEntity e implementa la interfaz Visualizable, que tiene los métodos para obtener el frame a renderizar.
VisualizableEntity va a ir siendo extendida, para hacer una clase NPC por ejemplo, una clase Enemigo, jugador, pared, plataforma, etc...

Problema?¿

Pues que al cargar el mapa, usaré reflection para instanciar los objetos según la clase a la que pertenezcan.

Por ejemplo, si el mapa tiene 4 muros de la clase Muro, y 1 personaje de la clase Personaje, crearé las instancias de Muro y de Personaje usando reflection y las voy a guardar en una List<VisualizableEntity>.

Con esto, obligo a tener ciertos constructores en las subclases para que el objeto pueda crearse sin problemas, y esto huele bastante mal.

Escribiendo el post, he tratado de poner alguna de las alternativas que se me ocurrian, pero incluso las alternativas llevan al mismo problema:
que reflection + constructores no se llevan demasiado bien con la herencia (o almenos eso creo por lo que estoy viendo)
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
-1
Responder

Un antipattern de los gordos?

Publicado por Rakan (9 intervenciones) el 29/04/2019 20:53:18
Esta estructura de clases esta estructura me parece un poco inviable, ya que para cada nueva extensión de la clase raíz hay que actualizar el creador de objetos... Pero con anotaciones, y usando la Class.getClassName() como identificador de que quiere crearse podría llegarse a algo...
Pero como digo en el post, acabamos llegando al mismo punto: las clases que extiendan la raíz se verán obligadas a tener un constructor específico para que el sistema funcione bien. Esto será confuso para los diseñadores de juegos que usen el motor, por no decir a ver como se documenta esto de forma coherente con diagramas UML haha...
Creo que voy a buscar algun motor de juegos Open Source en Java para ver como solventan este problema, si es que lo hacen, porque no sería la primera vez que me encuentro con cosas que no tienen forma de hacerse correctamente por limitaciones del lenguaje
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
-2
Comentar
sin imagen de perfil
Val: 48
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Un antipattern de los gordos?

Publicado por José (16 intervenciones) el 29/04/2019 22:40:05
Parece que tienes ganas de buscar tres pies al gato usando reflection pero allá tú.
No defines muy claro lo que pretendes hacer, pero tampoco hay tanto problema:

1
2
3
4
5
6
7
8
public class TestReflection {
 
	public static void main(String args[]) throws Exception {
		Class<?> ts = Class.forName("Sub1");
		Constructor[] cdef = ts.getDeclaredConstructors();
		Object obj = cdef[0].newInstance(1, 2);
	}
}
1
2
3
4
5
6
7
8
class Base1 {
	int noop1;
 
	Base1(Integer v) {
		noop1 = v;
		System.out.printf("New Base1(%d)\n", v);
	}
}
1
2
3
4
5
6
7
8
9
class Sub1 extends Base1 {
	int noop2;
 
	Sub1(Integer v0, Integer v1) {
		super(v0);
		this.noop2 = v1;
		System.out.printf("New Sub1(%d, %d)\n", v0, v1);
	}
}
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
2
Comentar

Un antipattern de los gordos?

Publicado por Rakan (43 intervenciones) el 30/04/2019 15:49:44
El mapa se cargará usando una clase que irá creando objetos de los distintos tipos que vaya encontrando en el archivo. Todos los tipos tendrán la misma clase base, pero pueden no implementar el mismo constructor, lo que es un problema.
Creo que habrá que hacer clases compuestas y muy ricas, en las que en lugar de extender, se introducen distintos componentes.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Un antipattern de los gordos?

Publicado por Tom (1831 intervenciones) el 29/04/2019 14:53:40
¿ Qué constructores son esos ?
¿ Por qué usas reflection si ya has diseñado las clases que vas a usar ?
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Un antipattern de los gordos?

Publicado por Rakan (43 intervenciones) el 29/04/2019 15:26:00
VisualizableEntity tiene un constructor que recibe un objeto Visualizable y un objeto EntityBounds.
Reflection se usa para cargar en memoria los mapas del juego.
En los archivos que guardan el mapa, tengo la clase que hay que usar para cada entidad de este.
Por ejemplo: Muro, 100w, 100h, 50x, 50y. Jugador, 100w, 100h, 100x, 100y.
La primera línea carga un objeto Muro con los datos que le específico.
La segunda lo misno con un objeto Jugador.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 973
Bronce
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Un antipattern de los gordos?

Publicado por Agustin (170 intervenciones) el 29/04/2019 15:09:07
Estas tomando datos de una fuente de texto y pasandolos a objetos en memoria. Esto se conoce como deserialización.

Dicho esto, si estuvieras usando un lenguaje moderno, el modelo que planteás se podría realizar con un Discriminated Union. En lugar de una jerarquía de clases interminable y tediosa para construir y mantener.

Además de esto, no me parece un buen diseño atar los objetos de tu modelo a la capa de presentación, con esta idea de que cada tipo de entidad "renderice" su propia GUI. Creo que la renderización del frontend NO es una responsabilidad del model.

Lamentablemente ninguno de los frameworks de java soporta una adecuada separación entre las vistas y la lógica de presentación, como la que se logra con paradigmas reactivos o MVVM y DataBinding en frameworks modernos.

Conclusión: yo te diría que te olvides de java y empieces a utlizar tecnología moderna y decente, con lo cual vas a poder realizar tu idea con mucho menos esfuerzo, mucho menos código, y de una forma mucho más mantenible y extensible en general.

Otra cosa: los "patrones de diseño" (de los cuales los programadores java son fanaticos) son simples parches para compensar la deficiencia del lenguaje. En la medida que empieces a utilizar cualquier lenguaje estático moderno (C#, F#, TypeScript, Swift, Kotlin, etc), te vas a dar cuenta que el 80% de los "patrones de diseño" que se usan en java son irrelevantes y obsoletos, al igual que el lenguaje java.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
-4
Comentar

Un antipattern de los gordos?

Publicado por Rakan (43 intervenciones) el 29/04/2019 19:42:11
Buenas tardes y muchas gracias por una respuesta tan completa!

Sobre lo que comentas de mi estructura de clases, tú qué harías en mi lugar?
La cosa es que el motor tiene un reloj que en cada tick realiza una serie de operaciones. Cuando quiere añadirse algo a ejecutar por el juego, como una animación, físicas o detectar eventos del teclado, se registra la clase que lo ejecuta en el reloj para que corra cada x ticks.

Sobre las animaciones, texturas y acciones que una entidad puede realizar, se te ocurre alguna forma de programarlo sin tenerlo todo en una clase?
La verdad es que tienes mucha razón sobre que tenerlo centralizado no es buena idea, pues algunas entidades como la cámara, no van a tener textura, o van a ser especiales. Esto sí el programa es simple no se notará, pero a la hora de expandir será un dolor de cabeza!
Algo que se me ocurre (y ahora que pienso en ello, recuerdo que lo hice para la librería de detección de eventos del teclado), es en vez de poner directamente la textura a la entidad, hacer que la entidad tenga un administrador de texturas.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
-1
Comentar
sin imagen de perfil
Val: 973
Bronce
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Un antipattern de los gordos?

Publicado por Agustin (170 intervenciones) el 30/04/2019 00:35:02
> tú qué harías en mi lugar?

Yo empezaría por no usar java nunca más en la vida, para nada.

¿Por qué? pues porque java es el Reino de los Sustantivos y su increíblemente limitado umbral de abstracción te limita a pensar en los términos en los que se puede pensar en java, y por lo tanto terminás pensando en sustantivos que muchas veces deberían ser verbos.

Dicho esto, parece que estás tratando de reinventar Unity2D. Si la intención es esa, adelante. Pero si tu intención es simplemente crear un juego te diría que hagas uso de alguno de los múltiples game engines que ya existen.

respecto de las distintas capas, se me ocurre rapidamente un mecanismo de messaging para que cada entidad de señales de sus ciclos de vida y las distintas capas los manejan, independientemente del resto de las capas. Despues si puedo te armo un ejemplo, por supuesto no en java.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
-4
Comentar

Un antipattern de los gordos?

Publicado por Rakan (9 intervenciones) el 30/04/2019 03:38:40
Pues la verdad es que un pequeño ejemplo me vendría genial, sobretodo ahora que estoy a punto de empezar con partes del motorcito que dependen en gran medida de la estructura que sigan las entidades.

Y sobre lo de dejar de lado Java, estoy en proceso de hacer cambio en mi tiempo de estudio hacia C++.
Este motor es un proyecto de grupo donde, yo que soy el que más se apaña con el tema de estructurar los programas (y aún así mira la de marrones en los que me he metido con la estructura), voy a hacer lo principal, otro seguirá mi trabajo, terminando de pulir cosas y expandir el motor para que lo puedan usar los dos que se encargarán de hacer un juego simple con este.
Hemos sido ambiciosos para el trabajo, y sabemos que el juego irá lento por el tema de que como comentas, Java no es el lenguaje indicado, pero por otro lado, haciendo esto, vamos a toparnos de frente con las limitaciones del lenguaje, y tendremos que trabajar alrededor de estas, entendiendo así de primera mano lo que tiene de bueno y malo, sin basarnos exclusivamente de opiniones leídas en foros y artículos.

>se me ocurre rapidamente un mecanismo de messaging para que cada entidad de señales de sus ciclos de vida
Tiene buena pinta, estaré atento al hilo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
-2
Comentar
sin imagen de perfil
Val: 973
Bronce
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Un antipattern de los gordos?

Publicado por Agustin (170 intervenciones) el 30/04/2019 06:17:34
Bueno, acá esta: https://github.com/agleiva/Ejemplos/tree/master/EjemploGame2D

Mejor que cualquier cosa que puedas siquiera soñar con hacer en java, en tan pocas lineas de código.

Te lo explico brevemente:

la MainWindow define un ListBox, cuyo panel es un Canvas, el canvas permite definir las propiedades X (Canvas.Left) e Y (Canvas.Top) de los elementos.

Cada Entidad tiene 4 propiedades basicas: X, Y, Width, Heigth. Estas estan bindeadas a las propiedades visuales. Fijate que no hay codigo en ningun lugar que manipule ningun elemento visual. Esto es la separacion de la que te hablaba antes. La capa de presentacion cumple su funcion de actualizarse a si misma de manera reactiva cuando una propiedad del modelo cambia.

El CsvEntityLoader carga las entidades definidas en el archivo Entities.csv, y setea las 4 propiedades basicas. Para eso usa reflection, solo la primera vez, para crear un diccionario con los tipos de entidad, mapeados segun su respectivo nombre. Despues en todos los casos utiliza este mismo diccionario.

El GameBoard simplemente actua como un contenedor para la lista de entidades. Eventualmente esta clase tendra mas funcionalidad.

Decime si te sirve y lo seguimos elaborando.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
-4
Comentar
Imágen de perfil de joel
Val: 194
Ha aumentado su posición en 4 puestos en Java (en relación al último mes)
Gráfica de Java

Un antipattern de los gordos?

Publicado por joel (59 intervenciones) el 30/04/2019 11:13:13
Augstin siempre estas en el foro de Java maldiciéndolo... como si tuvieras algún resquemor con Java... estas seguro que no te gusta Java??? o simplemente entras en los foros de Java para hacer de troll??
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
2
Comentar
sin imagen de perfil
Val: 973
Bronce
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Un antipattern de los gordos?

Publicado por Agustin (170 intervenciones) el 30/04/2019 17:01:15
Yo no "maldije" nada maestro. Si te fijas, cada uno de mis posts aportan información técnica valiosa. Cosa que tu post claramente no hace.

Y si fuera un "troll", debería ser fácil rebatir algo de lo que digo, no? En lugar de llamarme troll, te pido que demuestres qué parte de lo que dije es falaz o incorrecta, con argumentos técnicos y ejemplos de código.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
-5
Comentar
sin imagen de perfil
Val: 166
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Un antipattern de los gordos?

Publicado por Cesar (52 intervenciones) el 30/04/2019 21:00:39
Hola.

El que si parece troll, es Joel. Seguimos esperando el "ejemplo" para usar C# sin .Net
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
-4
Comentar
sin imagen de perfil
Val: 973
Bronce
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Un antipattern de los gordos?

Publicado por Agustin (170 intervenciones) el 01/05/2019 15:07:50
Error. Como todo programador java, te quedaste en el siglo pasado.

Hoy en día, el término .NET engloba las plataformas .NET Framework, Xamarin (Mono), Unity, .NET Core y UWP. Con lo cuál, usando cualquiera de estas tecnologías en realidad estas usando .NET.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
-4
Comentar

Un antipattern de los gordos?

Publicado por Tom (1831 intervenciones) el 30/04/2019 22:23:17
Esto sí es información técnica:
Agustin técnicamente hablando, eres imbécil (y el trol oficial del foro, si eso alimenta tu ego).
Te enlazo una definicón bastante técnica, por si acaso:
https://www.cun.es/diccionario-medico/terminos/imbecilidad

Y, como dicen que está en desuso (en medicina) pongo una más actualizada, la de cretino, para que te revises los síntomas, a ver si coinciden:
https://es.wikipedia.org/wiki/Cretinismo

Precisamente la característica de los trols de la web ("oficio" tan viejo como los mismos foros públicos) es que os importan un pito las razones técnicas y que os "rebatan" o no (Esto es muy informativo, los más jóvenes pueden no estar aún familiarizados con el término) , cualquier cosa vale con el fin de crear cadenas de respuestas interminables y reflotarlas constantemente.

Hay trols mejores que tú. No hay que tener muchos conocimientos, solo un poco de experiencia, para darse cuenta de que en general solamente sueltas latinajos vacíos de significado real.

Es probable que alguien, razonablemente, borre este post, así que me permitiré el efímero capricho de enlazar otra definición de tu actitud trolesca:

https://forum.wordreference.com/threads/mosca-cojonera.1973637/
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
4
Comentar

Un antipattern de los gordos?

Publicado por Rakan (43 intervenciones) el 30/04/2019 20:57:44
Con lo de separar vista, también te refieres a que el objeto Animation (que maneja los frames de una animación) esté fuera de Entity?
Lo que tengo ahora mismo en cuanto a gráficos, es una interfaz Visualizable con el método getSprite (un Sprite es un fotograma de animación).
VisualizableEntity extiende XYEntity y contiene un objeto de tipo Visualizable, y a la vez, esta clase implementa Visualizable, con lo que delega el trabajo de calcular que Sprite toca mostrar a el objeto Visualizable que he nombrado antes que tiene, mediante getSprite.
Me suena haber leído esta estructura en algún libro de programación.

Cómo lo ves?

Ahora releyendo lo que he dicho, me doy cuenta que se me olvidó comentar que gracias a esto, a FrameMaker.makeFrame(Visualizable) puedo pasarle directamente las entidades a renderizar para hacer un fotograma.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
-2
Comentar
sin imagen de perfil
Val: 973
Bronce
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Un antipattern de los gordos?

Publicado por Agustin (170 intervenciones) el 30/04/2019 21:50:07
> Con lo de separar vista, también te refieres a que el objeto Animation (que maneja los frames de una animación) esté fuera de Entity?

Si.

> VisualizableEntity extiende XYEntity y contiene un objeto de tipo Visualizable, y a la vez, esta clase implementa Visualizable, con lo que delega el trabajo de calcular que Sprite toca mostrar a el objeto Visualizable que he nombrado antes que tiene, mediante getSprite.

No está mal, dadas las limitaciones de java.

Comentame si viste mi ejemplo, y que te parece.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
-3
Comentar

Un antipattern de los gordos?

Publicado por Rakan (9 intervenciones) el 01/05/2019 01:41:39
He visto tu ejemplo y creo que mas o menos entiendo por donde quieres ir con ello.
Las entidades hacen exclusivamente su trabajo de ir cambiando de estado según los eventos que sucedan en el mapa, e independientemente de esto, se va renderizando el estado de todo.
Duda que tengo:
Supongamos que quiero añadir luciernagas a mi juego. Estas luciernagas, de noche, tienen que hacer un pequeño efecto de luz a su alrededor.
Pues nada, extiendo de la clase Entity y me las ingenio para que estas se vayan moviendo en circulo en bucle.
Ahora como le hago saber al encargado de renderizar el frame que alrededor de esa luciernaga hay que hacer un difuminado de color amarillo, esto sin estar haciendo trabajo que tiene que ver con graficos?

Escribiendo esta pregunta, me doy cuenta que Visualizable no debería ofrecer acceso a una textura, sinó que debería ofrecer cierto "apoyo" para dibujar en el frame, para casos en los que una entidad que quiera hacer un efecto visual que no sea una textura.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
-3
Comentar