Muy acertada la idea de Antonio de que el uso de tecnologías como XML son obligatorias. Con ese criterio mismo no habría que dejar de lado
a la POO. Se me ocurre que el modelo solución será que el IDE producirá código XML, que contendrá la información que hasta ahora
producimos con editores de recursos, y a esto se añadirá la información propia de los aspectos propios de nuestra aplicación,
incluyendo detalles respecto de los controles, variables y las acciones asociadas a los eventos que se producen en el diálogo.
Si el IDE producirá codigo XML, habrá un procesador que transforme ese XML en código xBase o C, y que se vinculará de alguna manera
con el código que nosotros escribamos en el PRG.
Este modelo coincide bastante con lo que plantea Vladimir, a lo que propondría algunos agregados que me parece que ayudarían a controlar mejor el código.
Mirando los IDEs actuales, todos manejan más o menos los mismos conceptos, es decir, una parte del código sobre la que actúa el IDE y otra independiente con el código que escribimos, normalmente asociado a los eventos que se producen en el dialogo/ventana/formulario.
Si a partir del XML generamos una clase, subclase de Dialog/Windows/Form, que implementa los aspectos visuales, podemos
escribir una sublase con nuestro propio código implementando los eventos.
Esto es lo que hacen muchos IDEs, desde Visual Objects hasta Delphi, y es bastante simple de implementar y usar. Tiene la ventaja de que las variables tanto de los controles como de buffers de edición son declaradas en la clase, por lo que nuestros métodos siempre tienen acceso a ellas ( como se dice, "siempre están en ámbito" ) y no hay que declarar variables ni cosas extrañas, ni es necesaria andar haciendo búsquedas de controles por nombre ni cosas parecidas.
En la misma superclase el compilador de XML generará el codigo de la clase, incluyendo no solo las DATAs sino tambien declarará los métodos, aunque los declare de manera virtual. Eso ayuda en el prototipado rápido, y permitiría testear la clase sin haber escrito una sola línea de código.
Por ejemplo, supongamos que el IDE produce el siguiente código XML:
prueba.xml
- Code: Select all Expand view
<FORM>
</NAME:TIPOIVA>
</NTOP:6>
</NLEFT:18>
</NHEIGHT:212>
</NWIDTH:140>
</STYLE: WS_POPUP|DS_MODALFRAME|DS_3DLOOK|WS_CAPTION|WS_SYSMENU|WS_VISIBLE >
</CAPTION: "Tipos de IVA" >
<CONTROLS>
<STATIC>
</NAME: oSayCodigo >
</TEXT:"Código">
</STYLE: WS_GROUP>
</NTOP:10>
</NLEFT:12>
</NHEIGHT:8>
</NWIDTH:44>
</STATIC>
<STATIC>
</NAME: oSayDescrip >
</TEXT:"Descripción">
</STYLE: WS_GROUP>
</NTOP:25>
</NLEFT:12>
</NHEIGHT:8>
</NWIDTH:44>
</STATIC>
<TGET>
</NAME:oGetTipo>
</VAR:TIPO>
</INIT: 0 >
</PICTURE:"99">
</STYLE: ES_RIGHT|WS_BORDER|WS_TABSTOP>
</NTOP:8>
</NLEFT:68>
</NHEIGHT:12>
</NWIDTH:36>
</VALID:ValidaTipo>
</TGET>
<TGET>
</NAME:oGetDescrip>
</VAR:DESCRIP>
</INIT: " " >
</STYLE: WS_BORDER|WS_TABSTOP>
</NTOP:23>
</NLEFT:68>
</NHEIGHT:12>
</NWIDTH:132>
</VALID:ValidaDescrip>
</TGET>
<TBUTTON>
</NAME:oBtnAceptar>
</TEXT:"&Aceptar">
</NTOP:117>
</NLEFT:101>
</NHEIGHT:15>
</NWIDTH:45>
</ACTION:Aceptar>
</TBUTTON>
<TBUTTON>
</NAME:oBtnCancel>
</TEXT:"&Cancelar">
</NTOP:154>
</NLEFT:101>
</NHEIGHT:15>
</NWIDTH:45>
</ACTION:Cancel>
</TBUTTON>
</CONTROLS>
</FORM>
Con esto un programa debería generar un código parecido a:
prueba.frm
- Code: Select all Expand view
CLASS _TIPOIVA // FROM ¿TFORM?
DATA Form
DATA oSayCodigo
DATA oSayDescrip
DATA oGetCodigo
DATA TIPO
DATA oGetDescrip
DATA DESCRIP
DATA oBtnAceptar
DATA oBtnCancel
METHOD New()
METHOD ValidaTipo() VIRTUAL // Valida un control
METHOD ValidaDescrip() VIRTUAL // Valida otro control
METHOD Aceptar() VIRTUAL // Accion asociada a un boton
METHOD Cancel() VIRTUAL // idem
END CLASS
METHOD New() CLASS _TIPOIVA
/*
</NTOP:6>
</NLEFT:18>
</NHEIGHT:212>
</NWIDTH:140>
</STYLE: WS_POPUP|DS_MODALFRAME|DS_3DLOOK|WS_CAPTION|WS_SYSMENU|WS_VISIBLE >
</CAPTION: "Tipos de IVA" >
*/
@ 6, 18 DIALOG ::Form SIZE 140, 212 CAPTION "Tipos de IVA" STYLE WS_POPUP|DS_MODALFRAME|DS_3DLOOK|WS_CAPTION|WS_SYSMENU|WS_VISIBLE
/*
<STATIC>
</NAME: oSayCodigo >
</TEXT:"Código">
</STYLE: WS_GROUP>
</NTOP:10>
</NLEFT:12>
</NHEIGHT:8>
</NWIDTH:44>
</STATIC>
*/
@ 10, 12 SAY ::oSayCodigo PROMPT "Código" ...
.... más controles
/*
<TGET>
</NAME:oGetTipo>
</VAR:TIPO>
</INIT: 0 >
</PICTURE:"99">
</STYLE: ES_RIGHT|WS_BORDER|WS_TABSTOP>
</NTOP:8>
</NLEFT:68>
</NHEIGHT:12>
</NWIDTH:36>
</VALID:ValidaTipo>
</TGET>
*/
@ 8, 68 GET ::oGetTipo VAR ::TIPO PICTURE "99" STYLE ES_RIGHT|WS_BORDER|WS_TABSTOP VALID ::ValidaTipo()
... mas controles
/*
<TBUTTON>
</NAME:oBtnAceptar>
</TEXT:"&Aceptar">
</NTOP:117>
</NLEFT:101>
</NHEIGHT:15>
</NWIDTH:45>
</ACTION:Aceptar>
</TBUTTON>
*/
@ 117, 101 BUTTON ::oBtnAceptar SIZE 45, 15 ACTION ::Aceptar()
RETURN Self
Además, si no existe prueba.prg lo crea con el siguiente código
prueba.prg
- Code: Select all Expand view
CLASS TIPOIVA FROM _TIPOIVA
METHOD ValidaTipo()
METHOD ValidaDescrip()
METHOD Aceptar()
METHOD Cancel()
ENDCLASS
METHOD ValidaTipo() CLASS TIPOIVA
RETURN .T.
METHOD ValidaDescrip() CLASS TIPOIVA
RETURN .T.
METHOD Aceptar() CLASS TIPOIVA
RETURN NIL
METHOD Cancel() CLASS TIPOIVA
RETURN NIL
Dejándonos el código listo para seguir programando.
Algo interesante es que desde dentro de los métodos podemos acceder a cualquier control o variable, ya que son DATAs del método que se está ejecutando. Y seguimos teniendo la independencia que ya tenemos con los recursos, entre los aspectos visuales del form y el código de la aplicacion propiamente dicho.
Tambien hasta se podría ejecutar el código de la clase _ que no hará nada, pero sería como la funcion de test que tiene el PellesC para los dialogos.
Esto se corresponde con un patron de programación GRASP, variaciones protegidas, que tiene muchos usos en temas visuales de la programación.
Un saludo,
Carlos.