¿Cómo puedo manejar los cambios de versiones al guardar activos?


9

Llevo un tiempo trabajando en un juego de rol y utilizo dos técnicas de serialización diferentes.

  • Los enemigos, las armas, los elementos se guardan como XML.
  • Los mapas y eventos se guardan como "binarios controlados" (cada clase obtiene un método de guardar / cargar y deciden qué quieren guardar / cargar).

Pero he comenzado a cuestionar mi elección de mapas y eventos. Mis preocupaciones:

  • He creado un editor de mapas, pero aún extraño poder cambiar cosas pequeñas con solo abrir el archivo.
  • Los cambios ensucian mucho. Digamos que quiero agregar una variable a una clase, si no cargo / guardo cada mapa nuevamente, se rompe más tarde.

La primera preocupación es difícil de resolver sin cambiar mi técnica. Pensé en cambiar a JSON, pero es mucho trabajo. También creo que se ve bastante feo con los atributos [DataContract] y [DataMember] en todas partes.

Eso me deja con mi segunda preocupación y me pregunto cómo puedo lidiar con eso. ¿Crea un pequeño programa que recorre todos los mapas y los vuelve a guardar con la nueva variable? Porque empiezo a obtener un par de mapas ahora y todavía lo hago manualmente. Me hace pensar dos veces cada vez que quiero hacer algunos cambios, ya que crea mucho trabajo extra.

Respuestas:


5

Hay muchas formas de manejar el problema de versiones; puede hacerlo teniendo una función de carga por versión, puede intentar automatizar el proceso describiendo (a través de los atributos usualmente) la transformación de la estructura del activo a lo largo del tiempo, puede hacer verificaciones específicas de la versión dentro de las funciones de carga / guardar, etc. .

Me gusta el enfoque de "describir los cambios" pero encuentro que tratar de hacerlo a través de atributos se vuelve incómodo rápidamente . Yo usaría funciones en su lugar; implementar una función que transforma los datos en la versiónN en datos en versión N + 1para toda su versión apropiada. En carga, verifique la versión con la última y, si no es así, ejecute los datos a través de todas las funciones de versiones apropiadas. Siempre guarde la última versión.

Esto funciona mejor si realiza la transformación cuando los datos todavía están en un formulario clave-valor en tiempo de ejecución. Esto significa que probablemente querrá implementar una representación para sus datos que sea un enfoque de "bolsa de propiedades de tiempo de ejecución", porque no puede usar la forma de valor clave subyacente de JSON o XML si tiene su propio formato binario. Si no hace esto, es posible que también deba mantener definiciones antiguas de clases, lo que se vuelve feo. Ser capaz de tener sus activos en este formato incorrecto de propiedad también es tremendamente útil para el desarrollo del editor de juegos.

Durante el desarrollo a medida que itera en sus datos, naturalmente se disparará a la última versión y eventualmente puede eliminar las funciones de versiones anteriores. Este es más o menos el mismo enfoque de alto nivel que usamos para la versión de los activos artísticos (como los mapas) en Guild Wars 2.


Ahora, dicho todo esto, creo que es útil admitir la serialización de texto y binaria para activos. Durante el desarrollo, mantenga todos sus datos en un formato legible por humanos basado en XML o JSON. Esto puede aumentar mucho su capacidad de iteración porque no necesita crear herramientas tan complejas para editar los datos. Puede volver a realizar ajustes rápidos y simples a mano.

En segundo lugar, suponiendo que aún desee un formato binario para enviar el juego (que puede mejorar el tamaño del archivo o los tiempos de E / S del archivo, por lo que es un deseo válido), diseñe sus API de serialización y deserialización para manejar el control de versiones. El control de versiones sigue siendo útil en un contexto de envío, porque en algún momento es posible que desee enviar actualizaciones o correcciones de errores. Hay algunos documentos que describen las capacidades de control de versiones de la serialización .NET y la serialización de Boost que pueden resultar interesantes. Si se va a apoyar el texto y formatos binarios, asegúrese de probar de vez en cuando (o pruebas de construcción automatizados para hacerlo, incluso mejor).


Gracias por el comentario, me dio algunas ideas sobre cómo continuar.
user1776562

1

Use un lenguaje de marcado con pares de atributos-valores como XML o JSON.

El analizador puede ignorar cualquier atributo que no entienda o usar valores predeterminados para cualquiera que no encuentre, lo que hace que la compatibilidad con versiones anteriores y posteriores sea bastante fácil. Además, el formato es legible para humanos, por lo que puede editarlo fácilmente con un editor de texto.

Cuando usa un lenguaje establecido como XML o JSON, también notará que muchos lenguajes de script lo admiten, por lo que cuando todavía necesite escribir un script para editar una gran cantidad de archivos, le resultará mucho más fácil hacerlo.

El inconveniente de la mayoría de estos idiomas es que son bastante detallados. Eso significa que los archivos resultantes son mucho más grandes de lo que deberían ser con un formato binario optimizado. Hoy en día, el tamaño del archivo no importa demasiado en la mayoría de las situaciones. Pero en aquellos en los que sí importa, el tamaño del archivo a menudo se puede reducir significativamente comprimiendo el archivo con un algoritmo estándar como zip.

Los lenguajes de marcado a menudo no permiten el acceso aleatorio a menos que todo el documento se lea desde el disco duro y se analice. Pero en la práctica esto no importa mucho, porque los discos duros son más rápidos con lecturas secuenciales. Buscar aleatoriamente varias veces en diferentes partes del mismo archivo a menudo puede ser mucho más lento que simplemente leer el archivo de una vez, incluso cuando significa que lee más datos de los que necesita.


1

puedes usar protobuf. https://code.google.com/p/protobuf/ Le brinda las ventajas de json / xml, que puede extender fácilmente mientras es compatible con versiones anteriores, además de la ventaja de ser binario. El flujo de trabajo consiste en crear una descripción del formato de datos en el lenguaje protobuf y luego generar el código fuente para la serialización y deserialización. La fuente se puede generar para varios idiomas. También es una gran ventaja que tenga una especificación clara de sus datos serializados, en contraste con json, donde la especificación se realiza implícitamente en la lectura / escritura.


Parece genial, pero uso C #, parece ser para C ++, Python y Java.
user1776562

Hay una versión de C #. No lo he probado personalmente, pero hay uno.
Arne
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.