Página principal  Página principalProgramación  ProgramaciónDelphi  DelphiVolver  Volver

PowerBuilder vs. Delphi


Vamos a ver qué nos ofrecen estas dos herramientas de programación, en principio orientadas hacia lo mismo, pero con filosofías muy distintas.



Todos sabemos qué es Delphi (lo sabemos ¿no?), pero si preguntamos a alguien qué es PowerBuilder ya empezaríamos a ver caras más raras.

Se trata de una herramienta de desarrollo orientada a aplicaciones de gestión contra bases de datos. Algo así como un Oracle Developer/2000 o el Access de Microsoft, pero profesional, multiplataforma, cliente/servidor, orientado a objetos y capaz de acceder homogéneamente a cualquier base de datos que soporte SQL (hoy en día el 99%).

PowerBuilder tiene bastante andadura a sus espaldas. Comenzó como un producto revolucionario de PowerSoft, y aunque las ideas que intentaba poner en práctica eran bastante buenas, se parecía más a una escopeta de feria que a una herramienta profesional.

Por aquella época no pasaba de ser una utilidad para crear pseudo-aplicaciones, que permitía ventanas, menús y poco más. No soportaba ni herencia, ni polimorfismo, y a duras penas hacía bien lo que se suponía que hacía. Vamos, un auténtico desastre.

Salió en 1990, allá cuando Windows 3.0 era un juguete, considerado sin futuro (confieso que yo también lo subestimaba) y aunque muy limitado en principio, la idea caló hondo y tuvo mucho éxito en EEUU, sobre todo debido a su especialización en el campo del desarrollo de bases de datos SQL (en aquella época había un gran vacío), su perfecta adaptación con Oracle y el éxito de uno de sus objetos: la DataWindow (por ahora, para hacernos una idea pensad que los formularios de Access se basan en este objeto).

No fue hasta la versión 4 (aún para Windows 16 bits) cuando se consolidó como una buena herramienta de programación, corrigiendo todos los errores y soportando (casi) complemente la orientación a objetos. En esta época estaba saliendo al mercado Delphi con su primera versión.

Cuando Delphi 1 iba a aparecer, la gente de Borland tenía un gran miedo: la popularidad de PowerBuilder en el campo de las bases de datos era muy importante, y quizá llegaban demasiado tarde, ya que los de PowerSoft llevaba 4 años depurando su herramienta (y la verdad es que lo consiguieron bastante bien). También se enfrentaban a Visual Basic, pero de este no hablaremos en nuestro artículo.

Una de las estrategias que utilizó Borland para convencer a sus posibles clientes, fue publicar distintos artículos y estudios comparativos de ambas herramientas. Lógicamente, los artículos los escribía gente de Borland, o consultores "independientes" a petición de ellos, y se puede decir que no era demasiado objetivos. En todos estos artículos se concluía con que PowerBuilder no era una herramienta válida, que su ejecución era demasiado lenta, y que la filosofía de programación de Delphi era infinitamente mejor que la de PowerBuilder.

La gente de PowerSoft, y varios sites dedicados a su herramienta, comenzaron a quejarse de la situación, enviando cartas de protesta e intentando hacer un boicot contra Borland, pero luchar con "el Borland de aquella época" era demasiado, sobre todo para una empresa pequeña. La batalla estaba perdida de antemano.

A partir de la versión 5 (la primera que compilaba en 32 bits), comenzaron a desarrollar DPB (Distributed PowerBuilder), un sistema de programación distribuida para aplicaciones multi-capa.

También a partir de esta versión, se incluyó un conjunto de librerías base (o FrameWork) denominado PFC, es decir: PowerBuilder Foundation Classes. Aunque estas librerías no son imprescindibles para desarrollar aplicaciones, su utilización está muy extendida, ya que nos ofrece un repositorio de objetos muy completo que nos ahorrará muchas horas de trabajo, además de una filosofía muy ingeniosa de diseño.

A la vez que salía al mercado la versión 5, Sybase realizó la compra de PowerSoft, absorbiendo así la herramienta PowerBuilder, la base de datos SQL Anyware y el compilador Watcom C++, entre otros productos. De este modo, Sybase se introducía en el mercado de las herramientas de desarrollo con una comunidad de programadores bastante amplia (sobre todo en EEUU). Según hemos visto después, Sybase tenía planeado orientar todas estas herramientas hacia su ya consolidada base de datos y hacia el entorno Unix. Sybase es un importante fabricante de bases de datos para Unix desde 1980, de hecho, SQLServer comenzó siendo un proyecto conjunto entre Microsoft y Sybase, pero al final se dividió en dos productos: uno para Windows (que se ha convertido en SQLServer) y otro para Unix (la base de datos Adaptative Server de Sybase).

En la versión 6 se consolidó la arquitectura del DPB, hasta el punto que la programación distribuida es una de las características por las que PowerBuilder es conocido y apreciado.

También se comenzó a orientar la programación de internet y fue en la versión 7 cuando salió la HTML-Datawindow, un objeto capaz de generar páginas HTML a partir de consultas SQL en cualquier formato, además de importantes cambios en el entorno de desarrollo.

Ahora mismo ya está la versión 8 en el mercado, que ha aportado cambios menores (gestión de excepciones, cambios en el IDE, etc.), y ya están en la fase final de desarrollo la versión 9 (que promete soportar código C++ para creación de componentes).

Ahora vamos a ver qué decían de cierto todas aquellas comparativas...


La gente de Sybase vende su producto diciendo que "es un entorno de propósito general". Lo siento, pero discrepo.

Es cierto que con PowerBuilder se puede hacer casi de todo, y eso les permite asegurar que es de propósito general, pero por esa regla de tres, el Ensamblador también es de propósito general, porque con él se puede hacer de todo (¿o acaso miento?). Así que por mucho que digan, no nos dejaremos engañar: no es de propósito general.

PowerBuilder está orientado al 100% para aplicaciones de gestión, con uso intensivo de base de datos.

No está pensado, ni diseñado, para aplicaciones de cálculo intensivo, ni para programar drivers, ni rutinas a tiempo real, ni aplicaciones de dibujo... PowerBuilder está pensado para bases de datos, y es ahí donde es fuerte.

En cambio, con Delphi sí que podemos presumir de que es de propósito general, es mucho más genérico, y se puede programar tanto a muy bajo nivel (más bajo que el ensamblador, pocas cosas hay), como a muy alto nivel (simplemente pinchando controles y ajustando propiedades, sin escribir ni una letra de código), tiene buenas capacidades gráficas y su soporte de base de datos es bastante completo. Podemos ir tranquilamente por la vida diciendo que Delphi sí es de propósito general.

Otro dato interesante: Delphi está hecho en Delphi, es decir, la versión 3 de Delphi, está programada con la versión 2, la versión 4 con la 3, y así sucesivamente (¿alguien sabe con qué hicieron las versión 1? ¿con Delphi 0?). Esto nos demuestra hasta donde podemos llegar con Delphi, hasta el programa de los programas: el compilador.

Sin embargo PowerBuilder no está hecho en PowerBuilder, sino en Visual C++.

Este dato nos puede despistar, y al final acabar diciendo: "cuantas más posibilidades tenga un lenguaje, mejor". Pues no siempre, eso depende de muchos factores.

Aplicando el mismo razonamiento, podemos decir que cuanto más corra un vehículo mejor. Pero... ¿qué pasa si nosotros lo queremos para arar nuestro campo de patatas? Creo que con nuestro flamante Ferrari F- 40, no íbamos a llegar muy lejos, y si nuestro sustento viene de las patatas... pues mal vamos.

De igual modo no podemos decir que Delphi sea mejor que PowerBuilder. ¿Qué pasa si nuestra empresa o departamento sólo desarrolla aplicaciones de gestión (contabilidad, facturación, financieras, etc.)? ¿Las desarrollaríamos en Ensamblador? ¿Y en C? Pues no.

Todos sabemos que cuanto más alto sea el nivel y más especializado esté el entorno, más productivos (léase rápidos) seremos. Y al fin y al cabo eso es lo que quieren todos los jefes: que trabajemos rápido y bien.


PowerBuilder cuenta con un lenguaje propio de alto nivel llamado PowerScript, que soporta todas las características de la orientación a objetos (encapsulación, herencia, y polimorfismo), SQL incrustado, excepciones (a partir de la versión 8), y otras características propias de este tipo de lenguajes.

El "estilillo" se puede decir que nos recuerda a Clipper, aunque la filosofía de programación es más al estilo Java (con punteros ocultos y referencias).

Durante la etapa de desarrollo, es un lenguaje interpretado, y tras un (largo) proceso de compilación, genera un código pseudo compilado (llamado PCode) que puede ser leído por una máquina Virtual llamada PBVM (PowerBuilder Virtual Machine). Esta máquina virtual traduce las instrucciones del PCode a instrucciones propias de la plataforma, estando disponibles máquinas virtuales para Windows 3.1, Windows 95/NT/2000, MacOS (hasta la versión 6) y Unix-Solaris. También es posible compilar en código nativo, evitando así el PCode, pero atándonos a una de las plataformas.

Gracias a la máquina virtual, PowerBuilder puede presumir de ser multiplataforma, permitiendo, con una única compilación, ejecutarse en cualquiera de las plataformas anteriores, al puro estilo Java. La parte negativa es que esta máquina virtual es imprescindible para ejecutar cualquier aplicación, por lo que debe incluirse en la distribución de nuestros ejecutables (lo cual limita mucho para cierto tipo de proyectos). La máquina virtual también es necesaria si hemos compilado nuestro proyecto en modo nativo (sin PCode), aunque no para interpretar el código, sino para utilizar muchos de los recursos que están contenidos dentro de ella, por lo que no hay ninguna manera de hacer nuestra aplicación completamente independiente, y no podremos distribuir solamente el ejecutable.

Ya tenemos más diferencias: para empezar, PowerBuilder utiliza un intérprete para ejecutar el código neutro (PCode), y Delphi directamente ejecuta el código compilado. La eterna batalla: Interpretado vs. Compilado.

Todos sabemos que un lenguaje compilado es infinitamente más rápido y eficiente que un lenguaje interpretado, pero aquí también hay casos en los que la tortilla se nos da la vuelta ella solita. Un lenguaje interpretado puede implementar muy fácilmente la multiplataforma, simplemente con generar un código "neutro", independiente de la plataforma, y después, programar un intérprete de ese código para cada arquitectura que queremos dar soporte.

Esto es lo que hace PowerBuilder con su máquina virtual, al igual que Java y últimamente Microsoft, que está poniendo toda la carne en el asador con la plataforma NET, y su lenguaje neutral IL (Intermediate Language). Y la gente de M$ nos quieren hacer creen que están inventando la rueda.

Según evolucionan estos locos tiempos, se tiende más a que el software se desliguen del hardware, es decir, que cada vez se introducen más capas intermedias (llamadas capas de abstracción) que interpretan los lenguajes neutrales y los convierten en códigos ejecutables. Cada vez está más de moda la multiplataforma, las máquinas virtuales y la abstracción del hardware.

Al igual que ocurrió en su día con las capas intermedias para acceder a bases de datos (BDE, ODBC, DAO, ADO, etc.), hoy está ocurriendo con los lenguajes de programación, y me aventuro a decir que ocurrirá con los sistemas operativos, y tendremos un mismo sistema operativo que acabará funcionando en distintas plataformas, bueno NT ya lo hace con su HAL (Hardware Abstraction Layer).

Una de las consecuencias más obvias entre un lenguaje interpretado y otro compilado es el tiempo de ejecución. En este aspecto Delphi arrasa literalmente con PowerBuilder (como era de esperar). Este fue el principal argumento que utilizaron los buenazos de Borland para descalificar a su oponente (lógicamente el F-40 corría más que el tractor, pero... ¿quien cultiva mejor las patatas?)


Toda aplicación PowerBuilder cuenta con un objeto global llamado Objeto Transacción (o SQLCA) que representa la conexión a base de datos. Algo así como que en Delphi hay un objeto global Screen, porque se supone que toda aplicación va a utilizar una pantalla (tiene su lógica). Pues toda aplicación PowerBuilder, supone que va a utilizar una base de datos (esto no tiene tanta lógica, aunque si partimos de esa premisa...). Esto demuestra la especialización que desde un principio se ha pretendido dar a esta herramienta.

A la hora de conectar a la base de datos hay que decidir el tipo de conexión a utilizar (nativa, ODBC, OLEDB, etc.), el usuario y password, y otro parámetros necesarios.

Este es el único punto en que hay que tener en cuenta qué base de datos queremos utilizar. El resto lo hace PowerBuilder con los datos que aquí le proporcionemos.

Aunque PowerBuilder crea un objeto de este tipo por defecto, nosotros podemos crear tantos objetos (es decir, conexiones) como queramos, simplemente creando un nuevo objeto, asignándole las propiedades y ejecutando la instrucción:

CONNECT USING ObjetoTransaccion

Estos objetos podrán ser locales (si necesitamos una conexión adicional en un momento determinado) o globales (una conexión durante toda la vida de la aplicación).

Una característica interesante de este objeto es que permite conexiones asíncronas (dependiendo de la base de datos a la que nos conectemos). De este modo podremos lanzar una consulta y continuar con nuestra aplicación mientras la consulta retorna un resultado, o bien cancelarla si no queremos esperar el resultado.

Delphi también tiene un objeto parecido con su componente TDatabase y realiza las conexiones del mismo modo con capas intermedias como BDE, ODBC u otras.


La principal arma de que dispone PowerBuilder es un objeto, llamado DataWindow, que se encarga de realizar todas las operaciones de acceso a base de datos.

La DataWindow es un objeto que encapsula una sentencia SQL, un conjunto de resultados y reglas de negocio en el cliente y una interfaz gráfica para representar todo esto, ya sea en forma de rejilla, como formulario, un gráfico, etiquetas, listado para imprimir, árbol jerárquico, o cualquier otro formato.

Algo así como si juntamos un TQuery, un TDataSource, un TCtrlGrid, un QuickReport, un TTreeView y un TeeChar, todo junto en un mismo componente.

El objeto DataWindow es la piedra angular de PowerBuilder, todo gira en torno a este objeto, cualquier ventana contendrá una o varias DataWindows en la que mostraremos datos, ya sean a partir de una sentencia SQL, datos estáticos (definidos en tiempo de compilación), o bien a partir de un array en memoria.

Con una Datawindow, se pueden hacer tanto ventanas de mantenimiento, como de opciones, listados, gráficos, árboles jerárquicos, listados de etiquetas, componentes avanzados (¡he visto hasta una calculadora hecha con una Datawindow!) y cualquier objeto que se nos ocurra. Me atrevería a decir que se puede hacer una aplicación completa, con el nivel de complejidad que se quiera, sólo con Datawindows y ventanas para mostrarlas.

Esto facilita bastante la programación, sobretodo en proyectos grandes, en los que toda la programación es muy homogénea (siempre se utiliza el mismo componente y 4 ó 5 más, así que no hay dudas de qué utilizar).

Pero claro, saber utilizar bien el objeto Datawindow no es fácil.

Cuenta con un conjunto muy extenso de métodos (para hacer todo lo que hace, es normal que necesite muchos), una lista bastante larga de eventos, otro conjunto de funciones internas para los campos calculados (más o menos unas 10 veces las que ofrece QuickReport), y un sistema de atributos dinámicos que quita el hipo "al más pintao".

El conjunto de funciones internas incluye las funciones típicas (max, min, avg, sum, if, etc.), incluso cualquier función normal escrita en PowerScript se puede utilizar como si fuera una función interna. Es decir, podemos escribir nuestras propias funciones normales, y utilizarlas desde los campos calculados, desde un evento, o desde cualquier lugar del programa. Un uso típico a esto suele ser escribir una función que acceda a base de datos para obtener un dato (por ejemplo un saldo, o un total de una tabla) y utilizar esta función dentro de nuestros listados. Muy útil para listados muy enrevesados, que tienen forma de cualquier cosa menos de listado.

El conjunto de funciones internas incluye las funciones típicas (max, min, avg, sum, if, etc.), incluso cualquier función normal escrita en PowerScript se puede utilizar como si fuera una función interna. Es decir, podemos escribir nuestras propias funciones normales, y utilizarlas desde los campos calculados, desde un evento, o desde cualquier lugar del programa. Un uso típico a esto suele ser escribir una función que acceda a base de datos para obtener un dato (por ejemplo un saldo, o un total de una tabla) y utilizar esta función dentro de nuestros listados. Muy útil para listados muy enrevesados, que tienen forma de cualquier cosa menos de listado.

Imaginemos que queremos que un botón (Button1) se sitúe 50 pixels por debajo de una etiqueta (Label1). En PowerBuilder podríamos asignar a la propiedad "Top" el valor:

Button1.Top = "Label1.top + Label1.height + 50"

Y esta expresión se irá recalculando dinámicamente, cada vez que sea necesario. De este modo, cada vez que la posición de Label1 cambia, la posición del botón también, independientemente del origen del primer cambio (ya sea por programa, por cambio de la resolución de pantalla, o porque a su vez es otra expresión calculada dinámicamente). Incluso se pueden incluir cualquier función interna, o nuestras funciones dentro de estas expresiones.

Si ahora, lo que queremos es que el color del texto de un Edit aparezca en rojo si el saldo global es negativo, y que el texto de un botón cambie de "Calcular" a "Cálculo imposible", y además, dicho botón se desactive, codificaremos del siguiente modo:

      // cambiar el color.
      EditValor.Font.Color = "if( IntToStr(ObtenerSaldoGlobal()) > 0,
                                  clBack,
                                  clRed)"
      // cambiar el texto
      BotonCalcular.Text = "if( IntToStr(ObtenerSaldoGlobal()) > 0,
                                '&Calcular',
                                '&Calculo imposible')"
      // desactivar si procede
      BotonCalcular.Enabled = "IntToStr(ObtenerSaldoGlobal()) > 0"
    
ObtenerSaldoGlobal es una función escrita en PowerScript que hace una consulta SELECT a base de datos y obtiene un número.
if e IntToStr son funciones internas de Datawindow.

NOTA: He utilizado una mezcla entre Pascal y PowerScript para que los Pascaleros entiendan bien el código.

Como podemos ver, esto es una gran ventaja, que nos hace olvidarnos qué mensaje nos enviará Windows cada vez que cambie la posición de un componente, o cualquier otro cambio en cascada. Además podemos construir listados todo lo complejos que se nos ocurra, simplemente introduciendo campos calculados que llamen a funciones con acceso a base de datos. Esto ahorra mucho tiempo, incluso diría que hay tareas que sólo son posibles a través de este sistema. De hecho, yo todavía no estoy seguro cómo plantearía en Delphi problemas como este.

Otra de las características de la Datawindow, es que cada uno de objetos contenidos dentro de ella (etiquetas, cuadros combinados, listas, campos, botones de radio, botones de chequeo, etc.), tiene su propias reglas de validación, aplicando para esto otra expresión de DataWindow (que como ya hemos visto, nos permitirá tanto funciones internas o externas).

Estos objetos, tienen la capacidad de ser recolocados y modificados por el usuario final, pudiendo así crearse sus propios listados a partir de los que nosotros programemos. Y sólo poniendo a true una de las propiedades del objeto.

También permite que el usuario final guarde una Datawindow a disco (en un formato propietario con extensión PSR), pudiendo consultarla en otro momento. En general: que con dos propiedades ya tenemos hecho un editor de listados, para que los usuarios ajusten los informes, gráficos o incluso mantenimientos, a sus necesidades.

Es posible definir un filtro en el cliente (como la propiedad Filter de los Datasets de Delphi) utilizando expresiones de Datawindow, y un orden en el cliente, que también puede hacerse a través de estas expresiones o simplemente indicando los campos de ordenación.

También cuenta con un buen número de eventos en los que se puede codificar en PowerScript aquello que no podamos hacer a través de funciones internas.

El objeto Datawindow, incluye una consulta SQL a partir de la que tomará los datos (si así lo queremos, o bien utilizar datos definidos en diseño).

El SQL utilizado es un dialecto portable, que la gente de PowerSoft llamó en su día PBSQL. La sentencia SQL se podrá escribir en modo texto (escribiendo nosotros mismos con la sintaxis adecuada) o bien dibujar en modo gráfico con una herramienta especial, pudiendo pasarse de un modo a otro en cualquier momento. El dialecto SQL, se utiliza internamente para permitir que una consulta SQL se adapte a las peculiaridades de las distintas bases de datos. No es que tengamos que limitarnos al ANSI-SQL, sino que a partir de la sentencia que nosotros escribamos (o dibujemos), el entorno la traducirá internamente a un SQL neutro (el PBSQL), y luego, dependiendo de la base de datos donde se esté ejecutando dicha consulta, la volverá a traducir a la sintaxis requerida por la base de datos destino. Esta característica funciona realmente bien... he visto con mis propios ojos como la migración de Oracle a SQLServer de una aplicación bastante grande se hacía en ¡¡1 día!! simplemente corrigiendo pequeños errores con los formatos de fecha.

Creo que Delphi no puede presumir de esto. Si nos limitásemos a utilizar el ANSI-SQL en los TQuery, no podríamos aprovecharnos de muchas características que todas las bases de datos implementan, aunque cada una a su modo. Eso sin contar que utilicemos componentes ADO (pensados para SQLServer/Access), o IBX (para Interbase), o Zeos (para MySQL), o los NCOCI8 (para Oracle), o DBExpress, o quien sabe que saldrá mañana.

Las Datawindows también permiten anidamiento, es decir, dentro de una Datawindow, meto otra, y dentro de esa, otra, y otra, y otra, y... ¡¡Catapún!!... hasta que salte un "Access Violation" (que suele ocurrir cuando nos pasamos de listos). Es algo así como una mezcla de los TFrame (a partir de Delphi 5) y los CompositeReport (del QuickReport), que utilizado con moderación (y cabeza) nos permitirá hacer ese listado que no hay por donde cojerlo (y que tanto les gusta a los jefes).

Desde la versión 6 se incluye un plug-in para Internet Explorer y "Nescafé" Navigator que permite la visualización de Datawindows dentro del navegador. Esta característica abre más aún el abanico de posibilidades, ya que podremos portar fácilmente un aplicación de escritorio, a aplicación web, ya que el 90% de los objetos de una aplicación son datawindows y estos están soportados por el navegador. Además, las posibilidades de representación dentro de un navegador se amplían, ya que no hay que limitarse a lo que el HTML es capaz de hacer, o intentar hacer con ActiveX lo que no conseguimos con HTML. Esta tecnología no es muy recomendable para internet, ya que muy poca gente tendrá instalado el plug-in de Datawindows, y la verdad es que la descarga es bastante “gorda” (unos 3 megas). Sí que puede ser un buen entorno para su utilización una intranet, en la que nos aseguramos que todos los equipos cumplen unas características mínimas, y el ancho de banda es lo suficientemente ancho para no tener problemas.

Delphi soluciona esta faceta utilizando las ActiveForms, que no son más que componentes ActiveX para visualizar desde el navegador. Para estos no es necesario ningún plug-in especial, sino que un navegador que soporte ActiveX será suficiente.

A todo esto que hemos mencionado, hay que agregarle los distintos servicios que nos ofrece la librería de clases PFC, como un servicio de filtrado, de ordenación de registros, grabación de datos, impresión, sincronización de maestros-detalles, de previsualización de listados y un largo etc. Estos servicios, al residir en objetos distintos, sólo estarán en memoria mientras el servicio esté activo, por lo que se reduce la carga de la Datawindow. Más tarde hablaremos del PFC y su arquitectura basada en servicios.

En contra del objeto Datawindow hay que decir que mezcla demasiado todo: el interfaz gráfico, la consulta SQL, las reglas de negocio y el comportamiento a través de sus funciones internas. El resultado final es un objeto "monstruoso" que tiene que ser gestionado a través de una única DLL de la máquina virtual. Esta DLL ocupa más de un mega. ¡¡Un componente que ocupa un mega!! En realidad este código se carga una vez y se reutiliza desde todas las Datawindows de la aplicación (cientos y cientos), pero la carga inicial es bastante lenta. Esto se ha intentado mejorar a través de la arquitectura basasa en servicios, aunque no se ha conseguido un objeto lo suficientemente “ligero”.

Al estar tan ligado el aspecto gráfico con el funcionamiento interno nos encontramos con bastantes problemas, y uno de los más habituales es que nos suele aparecer la misma consulta SQL repartida por varias Datawindows. Esto se soluciona en parte con un objeto Query (que hace las veces del TQuery de Delphi, encapsulando solamente la consulta SELECT) del cual podrán hacer uso en distintas Datawindows, aunque la solución es bastante rústica y deja mucho que desear.

Otro problema al que se están enfrentando, es la separación de las aplicaciones en capas, ya que en los últimos años está proliferando mucho la arquitectura distribuida en 3 niveles. Esto requiere se que separe la interfaz gráfica (capa de interfaz o cliente), las reglas de negocio (capa intermedia, de negocio o servidor de aplicaciones) y los datos (capa servidora o servidor de datos). La Datawindow tiene graves problemas en este aspecto, ya que desde un principio se diseño como un objeto "monolítico", intentando integrar todo dentro de ella (y vemos que la tendencia es justo lo contrario). Quizá por este motivo, la filosofía que están aplicando a DPB se considera bastante forzada, en la que "con calzador" tienen que conseguir que un objeto "que sabe hacer de todo" derive sus responsabilidades a otros objetos, incluso remotos.El intento que hacen se basa en dos herramientas llamadas PowerDynamo (un servidor web) y Jaguar CTS (algo así como el VisiBroker de Delphi), que ambas forman la capa intermedia, a través de un producto llamado EAServer (Enterprise Application Server). Es decir, PowerBuilder y su Datawindow no son capaces de crear arquitecturas en 3 capas y han creado herramientas y aplicaciones adicionales para este tipo de proyectos.


Otra de las capacidades que nos proporciona PowerBuilder, es la de soportar SQL incrustado dentro del código, sin necesidad de componentes adicionales, sino que el propio PowerScript reconoce tanto SQL estático (con todos los datos conocidos en tiempo de compilación) como dinámico (construido en tiempo de ejecución a partir, por ejemplo, de una variable string).

Dentro de una función podemos realizar un SELECT y retornar el resultado en una variable, comprobar si cierto registro existe, recuperar la descripción asociada a un código o cualquier cosa. Esto es muy cómodo, ya que nos permite realizar consultas sencillas sin tener que insertar (o crear en tiempo de ejecución) componentes adicionales.

También es posible ejecutar consultas a partir de una cadena de texto, ya sea completamente o parcialmente dinámicas. Es decir, podemos tener una cadena con la sentencia a ejecutar, o bien, una cadena con el objeto, con las columnas, etc.

Instrucción parcialmente dinámica (“tabla” es una variable string que contiene el nombre de una tabla):

      SELECT *
      FROM   :tabla;
    

Intrucción completamente dinámica (“sentencia” es una variable string que contiene la sentencia):

    sentencia = "DELETE FROM FACTURAS"
    EXECUTE :sentencia;
    

Una de las utilidades de esto es, en vez de incrustar la sentencia directamente en el código, podemos almacenarla en una cadena (que leemos de fichero, o de la propia base de datos) y después ejecutar esta sentencia. De este modo se independiza más el programa de la base de datos, ya que un cambio en el esquema no requeriría una nueva compilación.

Desde mi punto de vista, el SQL incrustado es bastante útil y cómodo, aunque también tengo que decir que los lenguajes modernos huyen de esta técnica, ya que ata demasiado la aplicación a la base de datos (algo similar es el Pro*C de Oracle, que es una tecnología que ya tiene sus añitos y empieza a estar en desuso).

Otra objeto disponible es el Pipeline, que representa una “tubería” de datos entre una base de datos y otra, pudiendo ser estas de cualquier tipo dentro de los soportados por PowerBuilder. Es muy útil para hacer migraciones de bases de datos, ya que, simplemente indicando el origen y el destino, el proceso nos hará la copia de todos los objetos y datos (o aquellos que seleccionemos), ajustando aquellas sentencias que no sean compatibles en la base de datos destino.


PowerBuilder permite también la creación de objetos de usuario, un concepto muy extenso que va desde los Frame de Delphi a las clases de cualquier lenguaje OO.

Básicamente, se pueden crear objetos de usuario de los siguientes tipos:


Todos los objetos, ventanas, componentes y código en PowerBuilder, se almacenan en librerías con extensión PBL que contienen tanto el código fuente, como la versión compilada. Esto provoca más de un quebradero de cabeza, ya que cuando el código compilado se corrompe, también perdemos nuestro código fuente. Esto en versiones antiguas era bastante habitual, y aunque cada vez funciona mejor, siempre existe ese riesgo.

Existe un proceso de exportación que nos extrae un objeto concreto de la librería y lo almacena en un archivo de texto, algo así como el archivo .pas de Delphi. Este archivo podemos modificarlo, y volver a importarlo para la compilación, pero esto es una tarea bastante pesada y perdemos las ventajas que nos ofrece el entorno de desarrollo.


La librería PFC se compone de un conjunto de objetos de propósito general (je, je, no se lo creen ni ellos) que nos permiten hacer las tareas más habituales de dos ratonazos.

No se puede decir que el PFC sea el equivalente a la VCL de Delphi, ya que este último se trata de una librería de componentes visuales (Botones, Listas, etc.) y en PowerBuilder estos vienen “de fábrica” y son inamovibles.

Los objetos incluidos en el PFC son de más alto nivel y se basan en los componentes visuales para construir interfaces (ventanas de opciones, de listados, mantenimientos maestro-detalle a N niveles, opciones de impresión, etc.), objetos auxiliares (pilas, colas, algoritmos de ordenación, parsers de SQL, soporte para multi-idioma, etc.), componentes compuestos (calculadoras, calendarios, barras de progreso...) u otro tipo de objetos (hasta un total de unos 300 objetos listos para ser utilizados).

La principal característica que introduce es un nuevo concepto de programación: la arquitectura basada en servicios. Es una técnica de diseño para programación orientada a objetos y se basa en que cada objeto tendrá disponibles distintos servicios que pueden ser activados en un momento dado para proporcionar una funcionalidad concreta.

Pongamos un ejemplo para analizar: necesitamos un objeto reutilizable que presente un árbol jerárquico. Este árbol, además debe:

Un primer diseño de la clase que haga esto podría ser crear una nueva clase heredada de TTreeview en la que iremos añadiendo los métodos para cada una de las acciones requeridas (LeerBD, GrabarBD, Imprimir, EnviarMail, AceptarDrop y IniciarDrag), además de algunos métodos para configurar estas acciones (ConectarBD, DesconectarBD, ConfigurarBD, ConfigurarImpresion, AniadirAdjuntoMail, ConfigurarMail, y ConfigurarDragDrop). Como podemos ver, la clase ya está creciendo considerablemente, y se puede apreciar como las funciones se pueden dividir en cuatro grupos, según las requisitos pedidos: Base de datos, Impresión, Correo y Arrastre.

En notación UML podríamos representar esta clase según aparece en la Figura 1.

Sin embargo la arquitectura basada en servicios ofrece otra solución muy distinta: se separan las distintas funcionalidades en clases distintas (llamadas Servicios), teniendo como atributo la clase “madre” en cada uno de los servicios. Estos servicios se crearán sólo cuando se requiera la funcionalidad, y no estarán continuamente en memoria.

El diagrama en UML podemos verlo en la Figura 2: el objeto Treeview (de la clase TTreeview) puede activar su servicio de base de datos para leer/grabar datos a una base de datos (activar el servicio sería crear un objeto de la clase TTreeviewSrvBD a través de la función ActivarSrvBD), el servicio de impresión, para imprimir su contenido (crear un objeto de la clase TTreeviewSrvPrint llamando a la función ActivarSrvPrint), el servicio de envío por correo electrónico de sus datos (TTreeviewSrvMail con la función ActivarSrvMail) o bien el servicio de “arrastrar y soltar” (TTreeviewSrvDragDrop a través del a función ActivarSrvDragDrop).

Figura 1

Figura 2

De este modo, el programador sólo irá activando (creando) los distintos servicios cuando se requiera su funcionalidad, y no residirá continuamente en memoria todo el código (ya que la mayoría de las veces no se utilizan todas las funcionalidades). Otra ventaja es que se separa la implementación de las distintas funcionalidades en distintas clases, creándose varias clases pequeñas, en vez de una gran clase que lo hace todo. A priori puede parecer que se complica demasiado la programación, pero para proyectos grandes es una gran ventana, ya que el código queda muy organizado.

La librería PFC está creada sobre un árbol de herencia muy ingenioso, que permite introducir nuestras modificaciones y objetos en medio de este árbol. Es decir, en Delphi siempre tenemos que heredar por debajo de la VCL, no es posible crear una especialización de TWinControl (llamada por ejemplo TjmWinControl) y que todos los objetos de Delphi (el TButton, el TForm y demás) se aprovechen de la nueva definición de TWinControl, o que el TSaveDialog muestre una ventana personalizada en vez de la ventana de Windows. PFC sí que permite esto, a través de lo que denominan extensiones, algo así como puertas de entrada al árbol de herencia. Inicialmente PFC vienen con dos niveles de extensión (cada nivel sería un punto por donde se “entrar” al árbol), aunque es posible incluir todos los niveles que queramos a través de una herramienta especial que viene incluida (PFC Library Extender).


El entorno de desarrollo de PowerBuilder se basa en la arquitectura MDI, en la que van apareciendo las distintas ventanas, llamadas painters: un painter de ventanas, otro de Datawindows, otro de menús, otro de objetos de usuario, de funciones, de SQL, de bases de datos, de librerías, de Pipelines, etc., hasta un total de 15.

Podemos ver una vista de algunos painters (de librerías, de bases de datos y el editor de código) en la siguiente figura:
Hacer click para ver a tamaño real

El entorno de desarrollo es radicalmente distinto al de Delphi, ya que este último se basa en que todo esté continuamente visible, y el de PowerBuilder se basa en que sólo habrá un painter visible en cada momento (aunque se puede organizar como “cascada” o “mosaico” al ser una aplicación MDI).

De todas estas ventanas MDI hay una principal llamada Library Painter que nos muestra todas las librerías (archivos PBL) de nuestro programa pudiendo abrir los distintos objetos, exportar, copiar, eliminar, buscar y cualquier tarea que sea necesaria hacer con un objeto. Una vez que hemos decidido el objeto que queremos modificar (y lo hemos encontrado), haciendo doble clic (o Enter) abrimos el painter en cuestión (otra ventana MDI), lo modificamos, lo guardamos y volvemos al Library Painter. También es posible dejar una ventana continuamente abierta, si la vamos a utilizar con frecuencia (el pintor de SQL, por ejemplo).

En la versión 7 se introdujeron cambios importantes en el IDE, y en la 8 se continuó con esa tendencia , incluyendo la posibilidad de dockar cualquier ventana dentro de otra, algo así como en Delphi, pero con alguna característica añadida. Estos cambios tan frecuentes en el IDE despistan bastante, ya que lo que hoy se hace con doble clic, mañana se hace con el Intro... ¡así no hay quien se aprenda los atajos de teclado!

El editor de código de PowerBuilder también sigue otra filosofía al de Delphi: sólo tendremos en pantalla el código de una función o evento. Esto a priori puede parecer muy incómodo, ya que para ver otra función tenemos que cerrar la ventana del editor de código y abrir otra ventana con la del nuevo código. Sin embargo, una vez que nos acostumbramos, esto se hace muy rápidamente, simplemente con un par de atajos de teclado ya tendremos nuestra nueva función preparada en pantalla, sin tener que utilizar el razón en ningún momento. En Delphi tenemos que hacer un uso intensivo de la función "Buscar", o bien el Code Explorer (sólo a partir de la versión 4), para ir localizando nuestros distintos eventos o funciones.

Se puede decir que el entorno es muy ágil, sin grandes avances (el MDI está bastante visto), pero funcional al 100%. Hasta la versión 6.5 (la última que he tenido el gusto de “sufrir” profesionalmente) se pueden hacer prácticamente todas las tareas a través de atajos de teclado, con lo que se acelera mucho la programación. Por mis años de experiencia en ambos entornos, puedo decir sin ningún reparo que es menos ágil y rápido el entorno de Delphi, ya que para muchas tareas tenemos que hacer uso del ratón (y esto relentiza mucho el desarrollo).


Vamos a ver una pequeña comparativa de tiempos en algunas operaciones de programación básicas. La comparativa se hace entre la ejecución de código en Delphi, PowerBuider interpretado y PowerBuilder compilado.

Como os podéis imaginar, los tiempos variarán de una máquina a otra, así que deben tomarse como datos relativos y no absolutos.

Los algoritmos que he utilizado y los tiempos de ejecución se pueden ver en la siguiente tabla:.

IteracionesDelphiPowerBuilder
Interpretado
PowerBuilder
Compilado
Compilación111,95-97,3
Bucle vacío1.000.0000,047,910,03
Operaciones de punto flotante1.000.0002,2636,946,76
Algoritmo TAK - Benchmark500,56520,526,29
Ordenación burbuja5.0001,4734,25129,78
Creación/visualización de ventana502,467,57,73

También he realizado una comparativa sobre acceso a base de datos. Las pruebas las he realizado contra un Oracle 7, utilizando una conexión nativa a través del BDE y los componentes básicos (TDatabase y TQuery) ya que para Oracle no hay ningún componente oficial (sí los hay de terceros). Además este es el método más estándar, y el más utilizado por la mayoría de los programadores.

En PowerBuilder he utilizado un objeto Datawindow para las consultas SELECT y SQL incrustado para las demás.

Las pruebas y los tiempos obtenidos pueden verse en la siguiente tabla:

IteracionesDelphiPowerBuilder
Interpretado
PowerBuilder
Compilado
Compilación111,95-97,3
Bucle vacío1.000.0000,047,910,03
Operaciones de punto flotante1.000.0002,2636,946,76
Algoritmo TAK - Benchmark500,56520,526,29
Ordenación burbuja5.0001,4734,25129,78
Creación/visualización de ventana502,467,57,73

La última prueba consiste en una comparativa de tráfico de red en instrucciones SQL. He utilizado un servidor Oracle 7 y consultas y actualizaciones con una tabla con 3 columnas y 50 filas.
Los resultados pueden verse a continuación:

DelphiPowerBuilder
Nº de accesos a red57279
Nº de bytes procesados por el servidor68.6489.180
Tamaño del paquete (en bytes)105.80617.878

Todos estos resultados no deben tomarse al pie de la letra, sino discriminando aquella operaciones que tengan menos importancia en nuestros proyectos. Por ejemplo, el tiempo de compilación no debe ser un factor decisivo a la hora de elegir una u otra herramienta (sobre todo en PowerBuilder, ya que este proceso sólo se realiza al finalizar el proyecto). Otra tareas, como las operaciones con número flotantes, el test TAK (que mide el rendimiento en algoritmos recursivos) puede que tampoco sean importantes en proyectos de ámbito no-científico.

Y por último incluimos en la siguiente tabla, un pequeño resumen indicando el soporte de ambas herramientas a distintas características y tecnologías:

DelphiPowerBuilder
Orientación a objetos
Arquitectura basada en serviciosNo
Gestión de excepciones
PunterosNo
Referencias
Acceso a DLLs externas (sólo estático)
Código nativo compiladoNo
Código interpretado - máquina virtualNo
Código ensamblador en líneaNo
Código SQL en línea (SQL incrustado)No
Acceso homogéneo a distintas bases de datos
MultiplataformaNo
Cliente/Servidor
Programación distribuída
Programación de librerías DLLNo
IDE programable (expertos, editores de propiedades, etc.)No
Debugger gráfico
Librería de componentes (nº de componentes) (150) (30)
Librería de clases o Framework (VCL) (PFC)
Herramientas de generación de SQL
Programación CGI/ISAPINo
Applets del Panel de ControlNo
Servidores WebNo
Servicios NTNo

Como conclusión podemos decir que, aunque en principio ambas herramientas se orientaban a lo mismo, hoy en día PowerBuilder se ha especializado mucho más a fondo en la programación sobre bases de datos que Delphi, hasta el punto en que prácticamente es lo que mejor podemos hacer. Delphi tiene un abanico mucho más amplio de posibilidades, tecnologías, y una filosofía de programación más abierta, lo cual puede ser bueno, o puede no ser necesario si no vamos a aprovecharlo al completo o nuestro departamento sólo se dedica "a hacer selects".

Desde mi punto de vista (completamente subjetivo y parcial) puedo decir que PowerBuilder es una herramienta muy válida para desarrollos profesionales orientados exclusivamente a bases de datos, en entornos cliente/servidor, sin grandes pretensiones fuera del SQL y las aplicaciones de gestión (aunque es posible hacer cualquier cosa, no está pensado para ir más allá de las bases de datos). Sin embargo, Delphi nos permitirá otros muchos tipos de aplicaciones, aún siendo menos productivos en las aplicaciones de gestión.

http://community.borland.com/article/0,1410,10326,00.html
http://www.sphere-data.com/docs/del1_pb4.html
http://www.justpbinfo.com/nodelphi.asp
http://www.justpbinfo.com/delphireply2.asp
http://www.justpbinfo.com/delphireply3.asp
http://www.justpbinfo.com/delphiletters1.asp
http://www.justpbinfo.com/delphiletters2.asp
http://www.consist.it/DE_PB.htm



Autor: JM


Página principal  Página principalProgramación  ProgramaciónDelphi  DelphiVolver  VolverCreative Commons License 2003 by JM