sueldos sii juradas jurada declaraciones declaracion c++ templates switch-statement chain-of-responsibility

c++ - sii - ¿Reemplazar la declaración del interruptor gigante con qué?



dj 1946 (6)

Tengo un código que analiza algunos archivos de plantilla y cuando encuentra un marcador de posición, lo reemplaza con un valor. Algo como:

<html> <head> <title>%title%</title> </head> <body bgcolor="%color%"> ...etc.

En el código, el analizador encuentra esos, llama a esta función:

string getContent(const string& name) { if (name == "title") return page->getTitle(); else if (name == "color") return getBodyColor(); ...etc. }

y luego reemplaza el marcador de posición original con el valor devuelto.

En el caso real, no es una página web ficticia, y hay muchos (50+) marcadores de posición diferentes que pueden ocurrir.

Mi código es C ++, pero creo que este problema existe con cualquier idioma. Se trata más de algoritmos y diseño OO, supongo. Lo único importante es que esto debe compilarse, incluso si quisiera no podría tener ningún código dinámico / eval.

Pensé en implementar un patrón de Cadena de Responsabilidad, pero no parece que mejore mucho la situación.

ACTUALIZACIÓN: y también me preocupa este comentario en otro hilo. ¿Debería importarme?


¿Has considerado XSLT? Es muy adecuado para este tipo de cosas. Desarrollé un sistema de administración de contenido que hizo exactamente lo mismo y descubrí que XSLT es muy efectivo. El analizador hace mucho del trabajo por ti.

ACTUALIZACIÓN: El comentario de Steven plantea un punto importante: querrá que sus plantillas sean XHTML válidas si decide ir por la ruta XSLT. Además, usaría un delimitador diferente para tus fichas de reemplazo. Algo menos probable que ocurra naturalmente. Utilicé #! PLACEHOLDER #! en mi CMS.


Combinaré 3 ideas:

  1. (de Steven Hugig): usa un método de fábrica que te da una clase diferente para cada selector.
    • (de Neil Butterworth): dentro de la fábrica, use un diccionario para deshacerse del switch(){} grande switch(){} .
    • (mío): agregue un método setup() a cada clase de controlador, que se agregue a sí mismo (o una nueva instancia de clase) al diccionario.

explicando un poco

  • cree una clase abstracta que tenga un dict static y métodos para registrar una instancia con una cadena de selección.
  • en cada subclase, el método setup() se registra con el dictado de la superclase
  • El método de fábrica es poco más que un diccionario leído.

Como "tío" Bob Martin mencionó en un podacast anterior con Joel y Jeff , casi cualquier cosa que se le ocurra reproducirá la declaración del gran cambio.

Si te sientes mejor implementando una de las soluciones seleccionadas anteriormente, está bien. Puede hacer que su código sea más bonito, pero debajo de las cubiertas, es esencialmente equivalente.

Lo importante es asegurarse de que solo haya una instancia de su declaración de cambio grande. Su declaración de cambio o diccionario debe determinar qué clase maneja esta etiqueta, y luego las determinaciones subsiguientes deben manejarse usando polimorfismo.


En lugar de analizar, han intentado simplemente leer la plantilla en una cadena y luego realizar reemplazos.

fileContents = fileContents.Replace("%title%", page->getTitle()); fileContents = fileContents.Replace("%color%", getBodyColor());


Quieres reemplazar condicional con polimorfismo . Aproximadamente:

string getContent(const string& name) { myType obj = factory.getObjForName(name); obj.doStuff(); }

donde se sobrecarga doStuff.


Use un diccionario que asigne nombres de etiquetas a un controlador de etiquetas.