2009-12-29 27 views
10

En el proyecto en el que trabajo, gestionamos la facturación médica.Versiones de clase para admitir la compatibilidad con versiones anteriores

Cada vez que el estado realiza un cambio en la forma oficial (que representan nuestras clases de datos), para mantener la compatibilidad con versiones anteriores, agregamos las nuevas propiedades pero dejamos las antiguas intactas y tenemos una versión de documento propiedad que se utiliza para determinar qué validación se realiza y las acciones de UI para mostrarla.

Esto ha llevado a clases infladas durante la vida del proyecto (casi 5 años de cambios ordenados por el estado), y simplemente no es compatible con los formatos de documentos antiguos.

Me gustaría intentar crear una nueva clase para cada versión del documento, pero incluso así tendremos varias copias de código muy similar (aunque ligeramente modificado). Y los nombres de clase como ProgressNoteV16, ProgressNoteV17 tienen un aspecto horrible.

No se puede usar la herencia, porque de todos modos se produciría el mismo problema (las clases tienen propiedades que ya no se necesitan). Las interfaces harían que la interfaz estuviera tan hinchada que no resolvería el problema.

¿Cuáles son las soluciones y las mejores prácticas para resolver este problema?

Respuesta

7

Este es un problema bastante clásico para cualquier agencia que trabaje con el público en cualquier capacidad, especialmente si se trata de una agencia supervisada por el gobierno o el gobierno.La solución no es trivial, y probablemente requerirá mucho trabajo de creación y mantenimiento posterior.

Esto ha funcionado para mí en el pasado cuando se trata de problemas similares para los clientes, aunque podría no funcionar para ti, necesitarás redactar lo que intentas lograr y si tiene sentido hacerlo.

Hay un par de patrones que estar familiarizado con (si ya enviaban):

  1. Factory que ya ha sido anteriormente mencionado
  2. Composition que se espera que salir de algunos de la problemas de herencia feas
  3. Template para la separación de la lógica de lo que la forma hace de las versiones

Hay dos libros que son bastante buenos para explicar estos (y otros pocos útiles):

  1. Head First Design Patterns (no puedo recordar la parte superior de la cabeza)
  2. Patrones de Arquitectura de Aplicaciones Empresariales (Fowler)

Ahora que el proceso que he utilizado en el pasado:

  1. de inicio mediante la adopción de todas las versiones actuales de la formularios, sepárelos en diferentes clases y busque una superposición común. Puede hacer esto en modo borrador o como su plan actual para tener diferentes clases para cada versión
  2. Derive de esta estructura de clase una cantidad de objetos "base" que puede usar para ser la raíz de herencia de cada conjunto significativo de versiones para una forma. Puede tener varios de estos, pero deben ser menos de los que tiene objetos de forma total.
  3. Ahora en cada uno de estos objetos base, agrupe la funcionalidad común (es decir, las estructuras de nombre y dirección, etc.) y abstraiga esta en su propia jerarquía de clases, inyecte esta jerarquía en sus clases base mediante la inyección del constructor.
  4. Aplique el patrón de composición a su jerarquía de clases base ahora y trabaje para obtener la mayor estructura de clases común posible. Idealmente, sus formularios en este momento serían la funcionalidad mínima que ha cambiado en cada formulario y tienen un constructor que toma todas las funcionalidades comunes (y tal vez ligeramente variables).
  5. Aplica el patrón de Plantilla ahora para abstraer toda la "funcionalidad" común de tus clases, como la validación común y la lógica de persistencia, usa la inyección de constructor nuevamente para volver a esta funcionalidad en tus clases base.
  6. Extraiga las definiciones del adaptador de interfaz de sus clases base y úselas como base para que su aplicación funcione con sus formularios
  7. Cree sus clases de fábrica para manejar todo el trabajo sucio de configurar esto.

Espero que te dé algunas ideas de qué hacer.

+0

Gracias, tenemos la capacidad de repensar nuestro diseño debido a una posible revisión en la forma en que el gobierno federal está haciendo las cosas. Este esquema ayudará enormemente a explorar las posibilidades. –

+0

NP. Y buena suerte. tener la capacidad de llegar a algunos otras agencias como DHS (Servicios Humanos) o DIS (Servicios de Inmigración) tienen este problema a gran escala y podrían brindarle buena información. – GrayWizardx

+0

Me encontré con esto porque empecé a ver 'fechas' aparecen en nuestros nombres de clase, es decir, ClassA, ClassA20100901, ClassA20101201. Me fue explicado como: ClassA es válido/usado hasta el 1 de septiembre, luego se usaría Class20100901, luego, el 1 de diciembre, la última clase se activará. Este es un GRAN olor que algo está mal. Voy a digerir esto y proponer esto al equipo. Proporcionaré una respuesta si encontramos algún consejo. ¡Gracias! –

2

Si la herencia no se puede usar "porque los campos en el documento se pueden eliminar", ¿cómo se maneja eso en este momento?

Dependiendo de los detalles de su diseño, debe poder anular los campos no utilizados por la versión actual del documento (es decir, anular en una subclase para ese documento) y lanzar una NotSupportedException o similar en la implementación de ese método si el formulario intenta asignar un valor. Con una lógica similar, puede (y probablemente debería) usar interfaces ... simplemente sabiendo que una implementación concreta puede arrojar una excepción para una propiedad que implementa pero que no está definida para esa versión de la UI.

Puede usar el Factory Pattern para devolver una instancia apropiada del objeto para la versión de formulario dada.

Si hay algo en común entre el código que ha cambiado ligeramente pero casi el mismo, es posible que pueda refactorizar algunas de esas características comunes en un método privado/protegido que sea utilizado por múltiples métodos públicos.

En cuanto a la denominación de clases, si utiliza el patrón de fábrica puede hacer referencia a la clase en la mayoría de su código utilizando la interfaz. Solo la fábrica necesitaría lidiar con nombres de clases que parezcan "extraños".

+0

"Si la herencia no se puede usar" porque los campos en el documento se pueden eliminar ", ¿cómo se maneja eso en este momento?" Eso no resolvería el problema de las clases que tienen demasiadas propiedades (de versiones anteriores que quedan para compatibilidad con versiones anteriores) –

+0

El patrón de fábrica parece una solución plausible, y dado que las cadenas de datos de aceptación no tendrán una escritura fuerte errores del compilador ... –

+0

@Aequitarum: la versión específica de la IU probablemente no se vincularía a los campos que son inapropiados para esa versión. Tener la subclase específica de la versión arrojar una NotImplementedException si una de esas propiedades está vinculada a la IU después de todo ayuda atrape tales problemas al principio. –

0

Implementaré esto de una manera mucho más flexible, una clase que contiene dos campos: una versión y un diccionario. Cuando los datos cambian tanto, es muy tedioso tratar de realizar un seguimiento de las propiedades que se pierden y agregan. Con un diccionario puedes simplemente probar para ver si la clave existe.

Cuestiones relacionadas