martes, mayo 31, 2005

Obteniendo valores por QueryString

En el post anterior hablamos de zonas de riesgo y de que debemos verificar los datos que nuestra aplicación recibe de los usuarios. También mencionamos que es mucho el código adicional que debemos escribir si necesitamos verificar muchos datos y que deberíamos abstraer esa problemática. Pues bien, ahora vamos a ver un ejemplo de cómo hacer esto.

El problema que intentamos resolver es el siguiente. Nuestra aplicación presenta un listado en varias páginas y obtiene el número de página que debe mostrar a través del parámetro “pagina” pasado por QueryString. En un punto del código, necesito obtener un valor entero y en caso de no conseguirlo, el valor debe ser “1”, es decir, la primera página.


using System;
using System.Web;

namespace DWP.Web
{
/// Definimos la clase como sellada
/// para impedir la herencia

public sealed class Requester
{
/// Constructor privado para impedir
/// la creación de instancias.

private Requester(){}

/// Método estático para obtener
/// parámetros por QueryString

public static object FromQueryString(string key, object defaulValue)
{
/// Obtenemos el objeto Request actual
HttpRequest Request = HttpContext.Current.Request;
object o;
string val = "";

/// Verificamos si el valor existe
/// en el QueryString. Si no, devolvemos
/// el valor por default

if (Request.QueryString[key]!=null && Request.QueryString[key].ToString()!="") {
val = Request.QueryString[key].ToString();
} else {
return defaulValue;
}

/// Intentamos convertir el valor obtenido
/// al tipo de dato del valor default.
/// Si esto da error, devolvemos el
/// valor default.

try {
o = Convert.ChangeType(val, defaulValue.GetType());
} catch {
o = defaulValue;
}
return o;
}
}
}


Como podemos ver, el método “FromQueryString” tiene como tipo de retorno un object. Necesitamos que sea así porque vamos a devolver un objeto de tipo similar al valor por default. De esta forma, si estamos esperando un entero y por QueryString nos llegó un texto, el método devuelve el valor predeterminado, es decir, garantiza el tipo de dato devuelto.

Las siguientes son formas válidas de utilizar nuestra función:
///Esperamos un entero, si no, devuelve el valor 1.
int currPage = (int)Requester.FromQueryString("pagina",1);

///Esperamos una fecha, si no, 1 de enero de 2005.
DateTime currDate = (DateTime)Requester.FromQueryString("fecha", new DateTime(2005,01,01));


Les dejo a ustedes la tarea de crear los métodos que obtienen valores por Form y Cookies.

lunes, marzo 21, 2005

Zonas de riesgo

Todas las aplicaciones tienen zonas en las que la probabilidad de que se produzca un error es más alta que en otras partes de del desarrollo. En general son zonas de riesgo los límites de nuestra aplicación. Aquel código que interactúa con el "exterior".

Si analizamos una aplicación de Internet basada en formularios que almacena la información ingresada por los usuarios en una base de datos, entonces, rápidamente identificamos dos zonas de riesgo:

La captura de datos
Recordemos que la información que proviene de los usuarios (esto incluye formularios, querystrings y cookies) no es confiable, puede venir con un formato erróneo o puede no llegar en absoluto. Debemos verificar los datos que recibimos y no confiar en que siempre llegarán correctamente.
Un caso muy común es cuando enviamos, por querystring, el número de página que debemos mostrar. Entonces redirigimos a los usuarios a URLs parecidas a esta:
listado.aspx?pagina=3
Luego en nuestro código escribimos algo así:
int pagina = int.Parse(Request.QueryString["pagina"].ToString());
Los desafío a que busquen páginas de este tipo en Internet y vean lo que sucede si modifican el valor de "pagina" a "abc".
Para que no sucedan estas cosas (las páginas de error no son muy agradables) deberíamos preguntar: "si vino el dato que estoy esperando, y si el dato no es vacío, y si puedo crear un entero, entonces tomar el dato, si no, debo asignar un valor predeterminado". En nuestro ejemplo, ante cualquier problema, pagina valdría "1".
Es cierto que, si por cada dato que queremos obtener debemos escribir tanto código, nuestro programa sería muy extenso, pero también es cierto que, si creamos un objeto que se encargue de obtener estos valores, habremos resuelto el problema para los próximos desarrollos que hagamos.

El almacenamiento de datos
Ya hemos obtenido la información y ahora necesitamos guardarla en una base de datos. Aquí también podemos encontrarnos con errores inesperados ya que existen factores que no podemos controlar. Pueden aparecer errores por clave principal repetida, valores incorrectos, conexiones agotadas, comunicación con la base interrumpida, etc. Otra vez, las páginas de error no son muy amigables. Tenemos que estar preparados y saber que estas cosas, y otras tantas, pueden suceder.

Existen otras zonas de riesgo dependiendo del tipo de aplicación que estemos desarrollando. Debemos identificarlas y tomar los recaudos necesarios para que nuestros desarrollos sean cada vez más robustos.

martes, marzo 15, 2005

Caching

La llegada de .NET hizo que muchos programadores comenzaran a agregar caching en sus aplicaciones.

ASP.NET nos brinda dos opciones para aplicar cache en nuestros sitios:
Output cache: con este mecanismo se mantiene una copia de la respuesta que produce una página, de modo tal que, mientras dura el cache, el código de la página se habrá ejecutado una sola vez.
Objeto cache: a través del cual podemos almacenar datos para no tener que ir a buscarlos cada vez al repositorio original

Todo muy útil, pero no debemos olvidar que el cache es una solución para cuando nuestro sitio tiene un nivel de uso que se hace necesario "proteger" al servidor web y al repositorio de datos del uso intensivo que generan los usuarios que ingresan al sitio. No tiene sentido utilizar output cache si la página es solicitada una vez cada 5 minutos y la información que muestra la página es válida por más o menos por el mismo tiempo.

Pero lo más importante es que no debemos diseñar una aplicación en función de que vamos a usar cache. En otras palabras, no debemos hacer aplicaciones que no funcionen sin cache siendo que tienen un uso moderado.

Por último, todos nuestros desarrollos que usan cache deberían poder activarlo y desactivarlo fácilmente. Salvo alguna excepción en particular, nuestros desarrollos no deben ser dependientes del caching, deben poder usarlo cuando lo necesitan.

lunes, marzo 07, 2005

Criterio

Conocer en profundidad las características de un lenguaje de programación es muy importante. Esto se consigue leyendo, estudiando, practicando y trabajando. De esta forma nos convertiremos en expertos. Es probable que, con tiempo, logremos ser expertos en varios lenguajes y tecnologías.

Pero lo que nos diferencia, lo que nos convierte en verdaderos profesionales es el criterio. Necesitamos criterio para definir la mejor solución. Necesitamos criterio para decidir cual es la tecnología más apropiada para cada caso. Para conocer los riesgos que estamos tomando.

El criterio no se estudia, no está escrito. Se desarrolla en base a la experiencia.
Es necesario analizar, luego de cada desarrollo, que cosas hicimos bien y cuales podríamos haberlas hecho mejor. Es fundamental que cada trabajo que hagamos amplíe nuestro criterio y, también, aprender de la experiencia de quien eventualmente tengamos al lado.