Unos correos del 2001 interesantes sobre activex


Clases, Tipos fuertes y parámetros

Tipos fuertes

Uno de los detalles que hacen utilizable realmente a Visual, es una mezcla entre los tipos de datos fuertes y débiles. Que es esto? Bueno, a grandes rasgos, Turbo Pascal se distinguió en su momento por la capacidad de darle un tipo determinado a una variable, por ejemplo, byte, shortint, string, longint, char, text, por decir algunos. Aunque las versiones originales de Basic, QBASIC y BASICA permitían una declaración de tipos fuertes, Los que usamos BASIC en ese tiempo, estábamos acostumbrados a ordenes como DIM NOMBRE$, donde el $ era equivalente al actual as String.

Por razones de compatibilidad, y de sentido común estructurado, poco a poco Microsoft fue creando una gran variedad de tipos de datos, algunos utiles y otros no. Por ejemplo, estan String, Variant, Object, Integer, Boolean, Single, Double. Pero, debido a que muchos programadores estaban acostumbrados a hacer las cosas a la carrera, desde la primera versión de Visual Basic for Dos, se tuvo que permitir utilizar tipos debiles, que significa esto ?

Un programador poco experimentado podía no declarar una variable, o cambiarle de tipo sobre la marcha. Un programa podía ser, por ejemplo:

10 nombre = space(30)
20 input nombre
30 print nombre
40 nombre = 0
50 for nombre = 1 to 10
60 hazotracosa
70 next nombre
80 goto 10
El verdadero problema fue que BASIC no solamente empezó a usarse por estudiantes, como fue en su momento, sino por profesionales que no tenian a la mano un compilador de Fortran, Pascal, o C. Y como Basic venía incluido en el MSDOS, Microsoft se encontró con que los programadores «avanzados» necesitaban características que no existian; por lo mismo el compilador en si tuvo que adaptarse. Recuerdo que en un momento dado Borland sacó un compilador llamado Turbo Basic, que compilaba en base a tipos fuertes. Para evitar la perdida del mercado, cuando se empezó a Promocionar el QBASIC, ya permitia usar tipos fuertes o debiles, sin embargo, empezaron a suceder problemas porque algunos programas hechos en BASICA, no funcionaban con el nuevo compilador, porque estaban hechos con tipos debiles.

Microsoft creó entonces un tipo de datos similar a lo que es el «any» a Lenguaje C, y su problema básico quedó resuelto. Pero se crearon problemas nuevos, para variar, el nuevo tipo fue llamado VARIANT, y es el tipo de datos predefinido por Visual Basic en las versiones actuales.

Porqué se crearon problemas? Bueno.. Aqui debo regresar otra vez a los tiempos de TP y C. El principal inconveniente de Turbo Pascal era la limitación de un programa a 64 kb de código y 64 kb de «data»; esta era una limitación porque por ejemplo, definir una cadena como string[255], usaba 255 bytes de 64,000 disponibles. Empezó a ser obligatorio andar haciendo ajustes en TP para convertir longint a shortint, y demás. (Esto no es estrictamente cierto, pero si usabas punteros en Turbo Pascal no tienes nada que hacer leyendo esto).

Visual no tenía este problema. Lo unico malo es que su tipo de datos Variant ocupaba bastante mas memoria que un integer, por ejemplo. Y un Variant permitía al mismo tiempo hacer cosas que no se debían segun los puristas. Utilizando el ejemplo anterior, la versión VB sería

dim nombre as string
nombre = space(30)
nombre=inputbox(«Introduzca el nombre»,,nombre)
print nombre
nombre = 0
for nombre = 1 to 10
hazotracosa
next nombre
Que si bien es perfectamente válido, permite errores como sumar algo que no debería sumarse. Pero si cambiamos el Dim nombre, por un Dim nombre as string, ya no es posible compilar el programa. Usando la metodología de tipos fuertes, el código debería ser:

dim nombre as string
dim i as integer
nombre = space(30)
nombre=inputbox(«Introduzca el nombre»,,nombre)
print nombre
for i = 1 to 10
hazotracosa
next i
Esto tuvo una serie de efectos no apreciables a largo plazo. Realmente el principal problema fue que los programas que no definian el tipo, es decir, que decian dim variables sin decir el tipo ( as string por ejemplo ), ocupaban a veces 10 o doce veces mas memoria de la necesaria. Se ha hablado mucho de elegir los tipos de datos correctos al programar, usar en lo posible integer por ejemplo, que esta ligado al sistema operativo y ademas de usar menos memoria que un long, se ejecuta mas rapido.

Para fines prácticos, lo que necesitamos saber es que ademas de los tipos de datos tradicionales, existen dos tipos llamados comodines, que son Variant y Object. Mas adelante hablaremos sobre Object. Un ultimo detalle es que los tipos en Visual Basic, si no se define el tipo, quedan como variant por default, ejemplo:

dim a,b as string ‘ a es variant, b es string
dim c,d ‘ c y d son variant
dim e as string, f as string ‘ los dos son cadena.
Quiero destacar que no necesariamente usar Variant es malo, solo que tiene la desventaja de ser mas lento y usar más memoria, pero hay ocasiones en que voluntariamente a fuerzas la solución mas elegante es usar variant en algun proceso. Sin embargo, creo que un buen programador siempre debe de tratar de usar en lo posible tipos fuertes ( y se evita el problema de hacer «casting» como en lenguaje C ).

Parámetros

En el correo anterior mencionamos algunas cosas sobre los sub y function, pero hay que hacer de una vez una aclaración importante. Los Function o funciones, pueden ( y en casos ideales deben ) regresar un tipo fuerte. Si nosotros no especificamos el tipo, obtendremos un variant. Veamos un ejemplo:

private function nombre_empresa
dim pass as string
pass=»www.laempresa.com»
nombre_empresa=pass
end function
Fuera de toda lógica aparente, el resultado será un variant y no un string. Lo correcto sería:

private function nombre_empresa as String
Muchas personas se preguntan que es un parámetro y para que nos sirve. Nos sirve para modificar nuestro código sin tener que hacer gran cambio. Por ejemplo, supongamos que hemos hecho un programa que usan nuestras diez sucursales, pero no queremos hacer una funcion diferente para cada una. Vamos a suponer que de un lugar determinado, leimos el numero de la sucursal o empresa y lo guardamos como la variable numcons. Y mas adelante queremos hacer un reporte que de un encabezado diferente para cada sucursal. Podríamos usar algo similar a:

private function nombre_empresa (num_empresa) as String
dim pass as string
select case num_empresa
case 1: pass= «www.laempresa.com»
case 2: pass= «www.laempresa2.com»
case 3: pass= «www.laempresa3.com»
case else
pass = «Empresa desconocida !!!!»
end select
nombre_emperesa=pass
end function
Este código nos permite de manera muy simple usar en la cabecera del reporte un print nombre_empresa(numcons), que hace el código mas legible.

Es importante destacar que podemos usar también tipos fuertes en los parámetros, e igual que dijimos antes, si no especificamos el tipo por default tomará variant, por lo que si queremos tipos fuertes, deberíamos declararlo así:

private function nombre_empresa (num_empresa as integer) as String
Parámetros por referencia y por valor

Otro de los detalles que nos heredó BASIC / BASICA, fue que cuando empezaron a usarse los procedimientos en la versiones mas avanzadas, los procesos a veces cambiaban el valor de una variable. Por ejemplo, supongamos un sub que genera el cuadrado de un numero:

numero=4
msgbox numero
call cuadrado(nume)
msgbox numero

private sub cuadrado(nume as integer)
nume=(nume*nume)
end sub
Nos da una desagradable sorpresa. Numero ahora vale 16, aunque no debía ser. Esto se debe a que por default, Visual Basic toma los parámetros por referencia, es decir, considera el parámetro como el NOMBRE de lo que debe cambiar. Una aproximación mas razonable, y menos propensa a errores, sería declarar lo anterior como una función o function, ya que obviamente regresa un valor, asi que por principio de cuentas no tiene nada que hacer como sub.

numero=4
msgbox numero
msgbox cuadrado(nume)
msgbox numero

private function cuadrado(BYVAL nume as integer)
nume=(nume*nume)
cuadrado=nume
end function
Esto nos permite evitar efectos secundarios en el código. La palabra Clave BYVAL es un indicador que le dice a Visual Basic, que solo tome el VALOR del parámetro, sin alterarlo. Los que han seguido las lecciones desde el principio, recordarán que dije que usar parámetros byval nos quita muchos quebraderos de cabeza. Ahora es posible entender de manera mas completa el ejemplo que puse en el correo anterior:

Public Function Padl(ByVal cadena As String, ByVal largo As Byte) As String
If Left(cadena, 5) = «- » Then cadena = Trim(Right(cadena, Len(cadena) – 5))
If largo >= Len(cadena) Then ‘ no simplificar
Padl = String(largo – Len(cadena), » «) & cadena
Else
Padl = cadena
End If
End Function
La regla es usar siempre BYVAL en los parámetros, y si necesitamos el modo standard , usar en su lugar la palabra clave BYREF, aunque esto no es obligatorio puede hacernos la vida bastante mas sencilla. Finalmente nuestra función quedaría:

private function nombre_empresa (byval num_empresa as integer) as String
Además nos protege si por error cambiamos el valor de num_empresa dentro del proceso, y al ser byval, un beneficio adicional es que el código se ejecuta mas rápido.

Clases

En la lección anterior decíamos que una unidad de Turbo Pascal nos permitía procesos publicos y privados. Una clase de Visual Basic, disponible desde la versión 4, nos permite lo mismo, sin embargo, para fines prácticos vamos a referirnos solamente de VB 5 en adelante. Un detalle interesante, es que una clase de Visual Basic NO es algo orientado a objetos, por lo menos en su forma pura. Los que han manejado OOP conocen terminos como herencia, polimorfismo, etc, pero VB no permite algunas de las características distintivas de los objetos, por lo menos en la forma tradicional.

El tema de las clases es muy extenso, y lo tomaremos en las siguientes lecciones. Por mientras , sugiero que hagan un pequeño experimento. El archivo Bas que generamos en el correo anterior, desde windows o sistema operativo cambienle la extensión de BAS a CLS