Inicio
He creado este espacio para compartirlo con familiares y amigos, aunque no descarto la posibilidad de que otros visitantes se encuntren a gusto y lo puedan disfrutar tambien...

InicioMapa del sitioDescargasColaboradoresEnlacesAutor    
Buscar :

Ideas


Y encima del sofá... un televisor

¿Realmente merece el televisor ese papel protagónico que solemos darle?


¿Un flat panel sobre mi buró?

¿Y por qué no... "debajo" del buró?


Web site de una sola página

Un sitio web típico, aún tratándose de una aplicación web (escrita en PHP, por ejemplo), se compone de varias "páginas" entrelazadas mediante "links" y/o redireccionamientos automáticos. Desde hace algún tiempo, sin embargo, he estado experimentando con una técnica diferente: escribir todo el site en una sola página, llamada: index.php.




Armando Acosta  (09-10-2008)

Mi motivación ha sido el acercarme a un estilo de programación más "tradicional", el mismo que he utilizado por años para desarrollar aplicaciones de escritorio en lenguajes como C y Visual Basic. En aquel entonces me sentía libre de organizar mis ficheros de código fuente de acuerdo a mi propio criterio de organización y no, como ahora, por imposición del concepto de "páginas" cuyos URLs hay que visitar como parte del flujo del programa.

¿Existirá alguna manera de librarnos de tal imposición? Por supuesto, y no soy el primero en utilizar estas técnicas. Solo que en lugar de dedicar tiempo a investigar, me lancé a generar código y ganar experiencia por mi propia cuenta —cosa esta poco aconsejable; es mejor investigar que arriesgarse a reinventar el agua caliente, pero así soy.

Lo que sigue es, pues, el producto de mis propias aventuras, las cuales, gracias a mi buena suerte, me han traído resultados muy gratificantes.

Include en vez de link

Según mi nuevo estilo de programación web, una aplicación consta de una página de presentación (index.php) y una o más bibliotecas en las cuales reside el peso del código. El enlace entre unas y otras se realiza mediante instrucciones include.

Comencemos con una sola biblioteca llamada my_lib.php. He aquí la estructura que tomaría index.php.

       include("my_lib.php");

       HTMLayout_Open();

       $action = $_GET["act"];

       switch($action){

              case "value_1":

                     CallFunctionOne();

                     break;

              case "value_2":

                     CallFunctionTwo();

                     break;

              /** etc... **/

       }

       HTMLayout_Close();

?>

Todas las funciones invocadas en este script están definidas en my_lib.php. La primera comienza a dibujar la página (HTML layout). La ejecución continúa con la lectura del único parámetro GET que le interesa a index.php: "act"; en dependencia de su valor, invocará a la función encargada de darle atención, la cual retornará indefectiblemente al mismo sitio. Finalmente, invoca HTMLayout_Close para culminar el trazado de la presentación.

Toda presentación intermedia correrá a cargo de las funciones involucradas. Todo parámetro GET o POST necesario para la aplicación (aparte de "act"), será generado y leído allí donde es pertinente, no en index.php.

De inmediato notamos las siguientes consecuencias:

1) Todos los links y redireccionamientos apuntarán al mismo script: index.php, aunque los parámetros pasados vía GET o POST ("act" y otros) serán diferentes en cada caso.

2) El código fuente quedará distribuido en diferentes ficheros, pero será a criterio del programador y no impuesto por el enjambre de links que suele armarse en una aplicación web típica.

Hasta aquí hemos logrado el primer objetivo: la organización. Pero eso es solo el principio.

La vida en un "hit"

La Web es un entorno fascinante, pero carece de algo a que los programadores "tradicionales" no tardan mucho en extrañar: el "estado".

Imagínese por un momento en presencia de una aplicación web más o menos compleja. Por aquí se crea un objeto de una cierta clase cuyo código llenaría seis páginas si se le imprimiese en papel de oficina. Más allá se establece una variable global cuyo primera asignación se efectúa en las primeras líneas del script y cuya primera lectura se realiza ya casi al final. Por el camino se invocan varias funciones pasándoles argumentos y retornando valores que luego se pasan vía GET a otros scripts, los cuales se ocupan de presentar resultados no sin antes consultar la base de datos.

Típico ¿verdad? Pues bien, lo que no deja de asombrarme —si no ya, confundirme, como al principio— es que todo esto ocurre en el breve lapso en que el usuario visita un link y obtiene una respuesta visual en su browser. Apenas un segundo.

Pero lo más asombros es que, una vez consumido el lapso, la aplicación regresa a su estado inicial, como si nada de aquello hubiese ocurrido jamás. En el próximo hit se volverán a crear los mismos objetos desde las mismas clases y volverán a iniciarse las variables globales como si nunca hubieran albergado esos mismos valores. Y es que entre un hit y otro no hay recuerdo.

Con cada hit, la ejecución comienza y termina; su vida entera transcurre en un solo hit, tras lo cual "muere" para volver a la vida en el hit siguiente.

Esto no es nuevo, por supuesto. Se le conoce como la naturaleza "state less" (sin estado) de la web. Y el culpable es el protocolo HTTP, el cual no fue diseñado para mantener una conexión (como lo hacen TELNET y FTP, por ejemplo). Tecnologías recientes como Microsoft .NET enmascaran esta limitación a los ojos del programador, pero no la eliminan; la web (sobre HTTP) sigue siendo "state less".

Por la parte que nos corresponde (como programadores), hay dos maneras de lidiar con esta limitación. Una es, asumiendo "la vida en un hit". La otra, haciendo uso extensivo y sistemático de las variables de sesión.

Variables de sesión globales y... ¡Locales!

Desde luego, existen las variables de sesión, y no hay programador hoy en día que no las use. Pero si nos limitamos a utilizar las ofrecidas por PHP, nos parecerá haber regresado a los tiempos de FORTRAN. Porque las variables de sesión solo tienen alcance global.

¿No sería maravillo poder crear un objeto cuyo estado persistiera indefinidamente —más allá de un hit— sin perder la privacidad?

Porque las variables de sesión no son privadas. Digamos que creo un objeto llamado my_obj con una propiedad llamada prop, y me tomo el trabajo —dentro de la clase— de almacenar su valor en la variable de sesión "prop_value".

Desde código cliente, siempre podré leer mi propiedad usando la sintaxis tradicional:

       $p = $my_obj -> prop;

Pero también podré hacerlo de este modo:

       $p = $_SESION["prop_value"];

Lo cual viola el propósito mismo de la programación orientada a objeto que es, entre otros, el de encapsular tanto el código como los datos que hay detrás (o "dentro") de un objeto.

Mi solución a este problema ha sido el implementar mi propio mecanismo para manejar variables de sesión, utilizando la base de datos para almacenarlas. La tabla que utilizo para tal menester presenta las siguientes columnas:

       session_id

       context_id

       var_name

       var_value

La primera contiene el identificador de sesión, fabricado aleatoreamente como es costumbre. Las dos últimas guardan el nombre y valor de cada variable, respectivamente. Lo verdaderamente interesante está en la columna context_id.

Mis variables de sesión pueden ser globales o locales. Cuando son globales, la columna context_id = 0. Cuando son locales, esa columna almacena el "contexto" (un entero) dentro del cual dicha variable tiene validez.

El mecanismo también provee funciones para crear, asignar y leer variables. Estas funciones son:

       SetVarGlobal( name, value)

       GetVarGlobal( name)

       SetVarLocal ( context, name, value)

       GetVarLocal( context, name)

Veamos un ejemplo donde se utilizan variables locales. El uso de variables globales es obvio, así que no perderemos tiempo en ello.

define ("CTX_ONE", 1);

define("CTX_TWO", 2);

///////////////////////////////////////////////////////

//       CLASS

///////////////////////////////////////////////////////

class My_Class {

       var prop = "";

       /** Constructor **/

       function My_Class (){

              $this->prop = GetVarLocal (CTX_ONE, "prop");

       }

       function SetProp($value){

              SetVarLocal (CTX_ONE, "prop", $value);

       }

}

///////////////////////////////////////////////////////

//       CLIENT CODE

///////////////////////////////////////////////////////

$my_obj = new My_Class;

switch($_GET["act"]){

       case "set_name":

              $my_obj->SetProp($_GET["name"]);

              break;

       case "show_name":

              echo ("El nombre es: " . $my_obj->prop);

}

echo ("Probando encapsulamiento: " . GetVarLocal(CTX_TWO, "prop"));

?>

Visitemos este script en dos hits consecutivos. Comencemos por:

       index.php?act=set_name&name=pepe

El código cliente del script creará el objeto my_obj; invocará luego el método SetProp pasándole el valor del GET ("pepe", en este caso) como argumento, el cual quedará almacenado en la variable local se sesión "prop".

Finalmente, la instrucción echo de la última línea nos mostrará el contenido de una cierta variable de sesión también llamada "prop". Solo que al leerla, utilizó un contexto diferente (CTX_TWO en lugar de CTX_ONE), por lo cual retornará vació en lugar de "pepe".

Hagamos el segundo hit, esta vez:

       index.php?act=show_name

Ahora el código cliente volverá a crear el objeto my_obj, cuyo constructor rescatará el valor de la propiedad prop a partir de la variable de sesión local "prop". Cuando el echo lea dicha propiedad (usando la sintaxis tradicional) obtendrá el nombre de "pepe" y este nos será mostrado, como era de esperar.

El echo de la última línea, sin embargo, volverá a fallar en leer una variable de sesión de igual nombre pero de contexto diferente.

Con esta técnica hemos conseguido dos cosas:

1) Persistir el estado de un objeto por tiempo indefinido.

2) Respetar el encapsulamiento de la clase mediante el uso de variables locales de sesión.

Lo único incómodo que encuentro en esta técnica es la necesidad de definir y utilizar constantes de contexto. Y otra peculiaridad —no sé se considerarla ventaja o desventaja— es el hecho de que el "contexto" se puede establecer a criterio del programador, no teniendo que responder forzosamente al sentido tradicional de localidad.

De cualquier manera, la implementación de variables locales nos libera del tener que establecer un riguroso convenio de nombres para nuestras variables de sesión y nos estimula, consecuentemente, a utilizarlas de manera extensiva y sistemática. Podríamos, cómodamente, proveer un "estado" persistente a todas nuestras variables si así lo deseáramos.

Conclusiones

En este artículo no he dicho cómo crear el tal mecanismo para manejar variables de sesión con respaldo en la base de datos, pero el lector se asombraría de ver lo sencillo que resulta, así que ahí os lo dejo de tarea.

En cuanto a mi web site de una sola página, estoy dando mis primeros pasos con un proyecto en el que vengo trabajando desde hace algunas semanas. Los resultados han sido gratificantes; por primera vez en años siento que programo de forma organizada... ¡como en los buenos tiempos!


  • Otros articulos técnicos


  • Imprimir   Enviar a un amigo   
                                                    

    Miami / USAmail@armandoacosta.comInicio