Escribir, comprobar y depurar Comercial Tasmania
Durante su escritura, se ha ido probando y depurando el código de los productos almacenados en bases de datos, métodos de clase, métodos de formulario, menús y programas.
Este tema abarca la escritura, la comprobación y la depuración de la aplicación Comercial Tasmania en las siguientes áreas:
- Formularios
- Informes
- Menús y barras de herramientas
- Tratamiento de errores
- Probar y depurar
En este tema también se ofrece un resumen de lo que ocurre cuando se ejecuta inicialmente el programa principal. Al final del tema, también encontrará información adicional en Comentarios sobre el código.
Formularios
Tastrade incluye clases Form (almacenadas en archivos .vcx) y formularios (almacenados en archivos .scx) basados en clases Form. Vea la sección "Diseño y creación de las clases de Comercial Tasmania" para obtener más información acerca de las clases Form. En la siguiente lista figuran todos los formularios (archivos .scx ) de Comercial Tasmania [las clases primarias aparecen entre corchetes].
Nombre del formulario | Descripción |
---|---|
BehindSc.scx [tsBaseForm] | Formulario Información técnica. |
ViewCode [tsTextForm] | Muestra el código de Información técnica. |
Category [tsMaintForm] | Formulario de mantenimiento para Category.dbf. |
ChngPswd [tsBaseForm] | Permite que el usuario modifique la contraseña. |
CustAdd [tsBaseForm] | Permite que el usuario introduzca información acerca de un cliente nuevo. |
Customer [tsMaintForm] | Formulario de mantenimiento para Customer.dbf. |
Employee [tsMaintForm] | Formulario de mantenimiento para Customer.dbf. |
GetInv [form] | Permite al usuario especificar un intervalo de fechas en el informe Pedidos. |
GetTitle [form] | Permite que el usuario filtre los empleados que se van a mostrar en el informe ListEmpl. GetInv y GetTitle están basados en la clase de formulario base de Visual FoxPro, por lo que se pueden ejecutar en informes procedentes del Administrador de proyectos sin que sea necesario abrir bibliotecas. |
OrdEntry [OrderEntry] | Formulario Entrada de pedidos. |
OrdHist [OrderEntry] | Formulario Historial de pedidos. |
Product [tsMaintForm] | Formulario de mantenimiento para Products.dbf. |
Rebuild [tsBaseForm] | Permite al usuario administrativo reindizar y comprobar la validez de la base de datos. |
Reports [tsBaseForm] | Permite que el usuario especifique el informe que se debe ejecutar. |
Shipper [tsMaintForm] | Formulario de mantenimiento para Shipper.dbf. |
Supplier [tsMaintForm] | Formulario de mantenimiento para Supplier.dbf. |
La mayoría de los formularios con controles que no están enlazados a datos (por ejemplo, IntroForm y About) se guardan como clases en archivos .vcx y se crean con la función CREATEOBJECT( ). A veces un formulario enlazado a datos se llama directamente como si fuera una clase. Por ejemplo, la clase Login expone propiedades para establecer los datos para sus controles. Los valores predeterminados de dichas propiedades se establecen en las tablas y los campos de Comercial Tasmania. La subclase, LoginPicture, se utiliza directamente en la aplicación, no hay ningún archivo .scx para estos formularios.
La ventaja de ejecutar directamente una clase Form es que se puede crear el formulario y mostrarlo en dos operaciones independientes:
- Form = CREATEOBJECT("IntroForm")
- Form.Show
Si hace esto, podrá definir los valores de la propiedad después de crear el objeto, pero antes de mostrarlo.
La ventaja de crear un formulario en el Diseñador de formularios es el acceso al entorno de datos y a las propiedades, eventos y métodos asociados con el objeto del entorno de datos. También es recomendable diseñar y probar formularios de esta forma porque se pueden ejecutar directamente desde el Diseñador de formularios o desde el Administrador de proyectos.
La mayoría de los formularios dependientes de datos incluidos en la aplicación contienen tablas en sus entornos de datos. Si la aplicación hubiera incluido un formulario que permitiera al usuario actualizar simultáneamente varias tablas, se habría creado una vista con este propósito.
Informes
Se pueden crear informes en cualquier momento cuando la base de datos esté en su ubicación. Comercial Tasmania no es una aplicación intensiva de informes, por lo que los informes se crearon bastante tarde respecto al proceso de programación. Cada informe contiene una vista local en su entorno de datos. Dos de los informes permiten al usuario especificar parámetros para el informe:
- El informe Pedidos imprime facturas para intervalos de fechas especificados.
- El informe ListEmpl permite al usuario filtrar la lista de empleados mediante la descripción del trabajo.
Las vistas de los entornos de datos de dichos informes se han creado con parámetros. Cuando el informe de entornos de datos abre las vistas, Visual FoxPro, de forma predeterminada, presenta al usuario un cuadro de diálogo genérico que le pregunta acerca de los parámetros. Para personalizar este comportamiento para Comercial Tasmania, las propiedades AutoOpenTables de los entornos de datos se han establecido como falso (.F.). En el evento Init del entorno de datos, se ejecutan los formularios personalizados para obtener variables de parámetros. Después se llama al método OpenTables del entorno de datos.
Se ha considerado a las consultas como orígenes para los informes, pero no se han utilizado porque para eso eran necesarios archivos adicionales (archivos .qpr) para su mantenimiento y seguimiento. Por otra parte, el archivo (.dbc) de base de datos contiene las vistas, que se pueden mostrar y modificar a voluntad en el Diseñador de bases de datos y también se pueden agregar directamente al entorno de datos. No obstante, las instrucciones SQL SELECT se utilizan cuando sea necesario, como en el procedimiento almacenado RemainingCredit.
Menús y barras de herramientas
El menú principal de la aplicación está definido en Main.mnx. La única barra de herramientas utilizada en la aplicación se basa en la clase tsToolbar de Tsbase.vcx.
El postprograma del menú comprueba el nivel de usuario de la persona que ha iniciado una sesión en la aplicación, y libera títulos y barras a las que el usuario no debería tener acceso. El código del procedimiento asociado con la opción Volver a Visual FoxPro del menú Archivo llama al método Cleanup( ) del objeto Application, que ejecuta CLEAR EVENTS y restaura el sistema de menús de Visual FoxPro.
El código asociado al evento Click de los botones de la barra de herramientas llama a métodos del formulario activo para obtener funcionalidad. De esta forma, la funcionalidad asociada con un formulario está encapsulada en el formulario.
Para coordinar los menús y las barras de herramientas de la aplicación, el código de los elementos de menú llama al código del evento Click de los botones de comandos de las barras de herramientas. Una expresión en la cláusula Skip For activa o desactiva los elementos de menú basados en el estado del botón de comando correspondiente de la barra de herramientas. Si desea obtener una descripción detallada de cómo coordinar menús y barras de herramientas, busque en la Ayuda cómo "coordinar barras de herramientas y menús".
Tratamiento de errores
El objetivo del tratamiento de errores es prevenirlos e impedir, en lo posible, que aparezcan en código. Por ejemplo, el código de Main.prg se incluye para ajustar el valor de ruta de acceso relativa si se ejecuta Main.prg (en …\Samples\Tastrade\Progs) en lugar de Tastrade.app. Antes de que el código de un método establezca o lea propiedades del objeto Application desde fuera del objeto, primero confirma la existencia del objeto Application:
IF TYPE('oApp') == 'O'
* do some code
ENDIF
Si existe la posibilidad de que la elección de un control produzca un error en una situación en particular, dicho control se desactiva.
Sin embargo, no se pueden prever todos los errores en el código. El tratamiento de errores, cuando sea necesario, se administra en el código asociado al evento Error de un objeto.
Cuando se produce un error en el código de método, Visual FoxPro buscará el código de tratamiento de errores asociado al evento Error del objeto. Si no se ha escrito ningún código a nivel de objeto para el evento Error, se ejecutará el código del evento Error heredado de la clase primaria o de otra clase superior dentro de la jerarquía de clases.
Si no se ha escrito código para el evento Error en ninguna clase de la jerarquía, Visual FoxPro comprueba la existencia de una rutina ON ERROR. Si no existe ninguna rutina ON ERROR, Visual FoxPro muestra el mensaje de error predeterminado de Visual FoxPro. Para ver los mensajes de error predeterminados de Visual FoxPro, vea Mensajes de error.
Comercial Tasmania buscará tres tipos de errores que podrían haberse producido en el nivel de la base de datos: infracción de la regla de campo, infracción de la clave principal y fallo del desencadenador. Dado que los formularios de Comercial Tasmania tienen un valor de BufferMode de 2 - Optimista, estos errores sólo podrían producirse cuando el usuario se desplace a un registro distinto (lo que causaría la eliminación del búfer) o cuando guarde cambios realizados en el registro en uso. Ambas tareas se realizan mediante métodos a nivel de formulario (métodos heredados de tsBaseForm), por lo que Visual FoxPro primero comprueba el código de tratamiento de errores del evento Error del formulario. Por ejemplo, el siguiente código está asociado con el evento Error del formulario Clientes:
DO CASE
CASE nError = 1884 && Primary key violated
THISFORM.pageframe1.page1.cntCustomerInfo.Error(nError, cMethod, nLine)
CASE nError = 1582 && Field rule violated
THISFORM.pageframe1.page1.cntCustomerInfo.Error(nError, cMethod, nLine)
OTHERWISE
tsMaintForm::Error(nError, cMethod, nLine)
ENDCASE
Si se ha infringido la clave principal o una regla de campo, la información acerca del error se pasa al control relacionado, cntCustomerInfo, de forma que el código de error del control pueda presentar un mensaje de error más específico que el mensaje de error predeterminado de Visual FoxPro, restaurar los valores antiguos como sea conveniente y establecer el enfoque en el control adecuado.
Si se produce otro error, el formulario Clientes pasará el error a la clase primaria, tsMaintForm, la cual hereda el código de tratamiento de errores de la clase tsBaseForm respectiva. Si el error indica un desencadenador fallido, el código asociado al evento Error de tsBaseForm mostrará el mensaje de error correspondiente almacenado en la propiedad aErrorMsg[ ] del formulario Clientes: "Error del desencadenador Insert", "Error del desencadenador Update" o "Error del desencadenador Delete". (Se puede crear un mensaje de error único para cada formulario al inicializar el elemento apropiado de la matriz aErrorMsg[ ] en el evento Init de dicho formulario.) Cualquier otro error se trata ofreciendo al usuario la opción de anular, reintentar o pasar por alto.
Hay un valor ON ERROR en Comercial Tasmania en el método RestoreWindowPos( ) de tsBaseForm:
ON ERROR llError = .T.
El código que restaura la posición de la ventana comprueba el valor de llError. Si se produce un error durante la lectura de las posiciones de ventana guardadas procedentes del archivo .INI, serán las propiedades predeterminadas Top y Left del formulario las que determinarán la posición del formulario.
Probar y depurar
Las operaciones de prueba y depuración forman parte de todos los pasos en la implementación del proceso de programación. Cualquier componente de Comercial Tasmania que pudiera considerarse, de algún modo, funcional, se sometía a prueba. En cuanto se encontraba algún fallo, se aislaba mediante las herramientas de depuración de Visual FoxPro y se arreglaba.
Se ha utilizado una constante a nivel de aplicación definida en Tastrade.h en la programación de Comercial Tasmania para facilitar las pruebas y la depuración:
#DEFINE DEBUGMODE .T.
El código condicional conecta automáticamente a cualquier usuario como el Programador de aplicaciones (Leverling) si DEBUGMODE es verdadero (.T.) de forma que los programadores no tuvieron que realizar todo el proceso cada vez que ejecutaban la aplicación para someterla a pruebas.
El menú Utilidades de la barra principal de menús de Comercial Tasmania está activo cuando un usuario o un profesional inicia la sesión como Programador de aplicaciones. Este menú ofrece acceso a las ventanas Seguimiento, Vista y Depuración, así como la capacidad de cancelar, reanudar y suspender el código.
El programa principal
El código de Main.prg es el programa principal de la aplicación. Cuando se ejecuta la aplicación, se ejecuta en primer lugar el código de Main.prg. Este código:
Declara las funciones de API utilizadas en la lectura y la escritura en el archivo .ini de la aplicación.
Guarda parte de la configuración del entorno. Es necesario establecer antes dichos valores de configuración (CURDIR( ), PATH y CLASSLIB) para poder crear el objeto de la aplicación.
Adapta la ruta de acceso en el caso de que un usuario ejecute Main.fxp en lugar de Tastrade.app.
Establece las bibliotecas de clases como MAIN y TSGEN.
Crea un objeto Application basado en Tastrade de Main.vcx:
oApp = CREATEOBJECT('TasTrade')
Las siguientes acciones tienen lugar como consecuencia de la creación de este objeto:
Se invoca al evento Init de la clase primaria (APPLICATION). El código asociado con este evento crea un objeto de entorno y guarda el resto de la configuración del entorno:
THIS.AddObject("oEnvironment", "Environment")
THIS.oEnvironment.Set( )
La sección predeterminada del archivo Tastrade.ini se lee con GetPrivString para determinar si se tiene que mostrar la Pantalla de introducción.
Si así se ha especificado en el archivo .INI, se mostrará IntroForm (Pantalla de introducción).
Se llama al método Login( ) de la clase en el evento Init de Tastrade.
El método Login( ) llama al método DoFormRetVal( ) de la clase.
DoFormRetVal( ) toma el parámetro de Login, y crea y muestra una instancia de la clase LogInPicture.
Cuando el usuario inicia una sesión, se devuelve el nivel de acceso del usuario y se almacena como una propiedad, cUserLevel, del objeto Application.
Llama al método Do( ) del objeto Application:
oApp.Do( )
El código del método Do( ) realiza las siguientes acciones:
Ejecuta el programa de menús para la aplicación:
THIS.DoMenu( )
Determina, basándose inicialmente en el nivel de acceso del usuario, el componente de la aplicación que se va a ejecutar:
lcAction = THIS.GetStartupAction( ) * The GetStartupAction method returns * the value in the Action field of the User
Ejecuta el componente, por ejemplo Entrada de pedidos:
IF !EMPTY(lcAction) &lcAction ENDIF
Establece el estado de espera del evento con READ EVENTS.
Comentarios sobre el código
Para facilitar la localización, es necesario definir todas las cadenas que se van a traducir a varios idiomas con la directiva de preprocesador #DEFINE. Las constantes definidas tienen que terminar en _LOC para que las herramientas de localización puedan identificarlas como traducibles. Éstas se definen en el archivo de inclusión Strings.h.
La mayor parte del código de la aplicación se escribe en métodos de formularios o de clases para que se pueda encapsular con los objetos adecuados. Los procedimientos almacenados permiten que se almacene en la base de datos el código específicamente utilizado en el mantenimiento o la validación de datos.
UTILITY.prg, la biblioteca de procedimientos para la aplicación, incluye cuatro funciones:
- IsTag( ) para asegurarse de que existe una etiqueta de índice antes de hacer referencia a la misma.
- NotYet( ) se utiliza durante la programación mientras se agregan características.
- FileSize( ) para devolver el tamaño de un archivo pasado como un parámetro.
- FormIsObject( ) que devuelve .T. si el formulario activo es un objeto basado en la clase de base Form.
Se podría crear una clase para ocuparse de estas utilidades, pero crear un objeto sólo para proporcionar acceso a estos procedimientos agregaría un nivel de abstracción innecesario.
Vea también
Ejemplos de soluciones | Ejemplo Comercial Tasmania | Creación de la especificación para Comercial Tasmania | Diseño y creación de las clases de Comercial Tasmania | Bibliotecas de clases de Comercial Tasmania | Diseño de la base de datos Tastrade