RSS 2.0 Atom 1.0 CDF  
JASoft.org - Saturday, February 06, 2010
El blog de José Manuel Alarcón Aguín. Programación .NET y mucho más...
 

.NET 4.0 dispone de soporte para tiempo de ejecución de lenguajes dinámicos, el DLR (Dynamic Language Runtime). El propósito del DLR es permitir que los lenguajes de tipo dinámico -como PHP, JavaScript, Ruby, Python, Lisp o Groovy, por citar unos cuantos- puedan ejecutarse en la plataforma y además interactuar con código escrito en un lenguaje .NET -como C# o VB.

El DLR introduce en el framework una serie de clases dinámicas de comportamiento dinámico que ayudan mucho a la hora de interactuar con estos lenguajes o acceder a COM, pero que abren la puerta a crear monstruos de código si son mal utilizados. De hecho gurús de la plataforma como mi buen amigo Octavio Hernández, reniegan de esta característica ;-)

Lo cierto es que en general yo no recomendaría el uso de las clases dinámicas, pero sí que pueden llegar a ser útiles en algunas ocasiones. Por ello en este artículo voy a presentar la más útil y fácil de usar de todas, la clase ExpandoObject.

Añadiendo miembros dinámicamente

Este objeto es, en realidad, una colección genérica bien disfrazada con "azucar sintáctico" de manera que en lugar de andar escribiendo .Add y .Remove con el nombre de los miembros, se pueden escribir directamente en el código y el compilador hace caso omiso de ellos, posponiendo la comprobación de su existencia al tiempo de ejecución. Lo entenderemos mejor con un ejemplo:

//Creo el objeto
dynamic Persona1 = new System.Dynamic.ExpandoObject();
//le añado algunas propiedades
Persona1.Nombre = "JM";
Persona1.Apellidos = "Alarcón aguín";
Persona1.Edad = 37;

Fijémonos en lo que hemos hecho aquí: primero hemos declarado una nueva clase de tipo ExpandoObject, la cual está en el espacio de nombres System.Dynamic. Si hubiésemos escrito simplemente el nombre de la clase VS2010 nos da ya la opción de añadir el "using" correspondiente en la parte de arriba del código:

Hay que fijarse también en una cosa importante: en C# debemos declarar el tipo de la variable que va a contener el objeto como dynamic. Fíjate en que lo lleva delante. Este nuevo tipo de C# se puede considerar que es casi idéntico al tipo Object, pero su principal diferencia es que cuando declaramos una variable con dynamic, el compilador se salta la comprobación estática de tipos durante la compilación. De esta forma el compilador no "rompe" cuando compilamos si intentamos utilizar una propiedad o método de la clase dinámica aunque éstos no existan. En VB no es necesario un tipo especial porque este lenguaje soporta el enlazado de tipos postergado.

Bien, una vez creado el objeto dinámico podemos empezar a añadirle propiedades con sólo escribirlas, como se ve en las líneas anteriores, tras la declaración. Así, al nuevo objeto le añadimos una propiedad Nombre, otra Apellidos y otra Edad simplemente poniendo un punto y escribiéndola. Es decir, como si ya existiera de antemano, cosa que no es así. En la práctica lo que conseguimos es que si la propiedad existe que se asigne, pero si no existe se crea dinnámicamente y se asigna, es decir se van creando propiedades sobre la marcha.

Si ahora escribo:

Console.WriteLine("Persona: {0} {1}, Edad: {2}", Persona1.Nombre, Persona1.Apellidos, Persona1.Edad);

Obtendré por pantalla sin problemas el nombre y apellidos, seguidos de la edad anotadas en este nuevo objeto dinámico.

Los tipos apropiados para las propiedades se infieren del valor que se le pasa al asignarla. Así en el ejemplo, para el nombre y apellidos tendremos tipos string, y un int para le Edad. Además el tipo cambia también dinámicamente. Por ejemplo si asigno el valor 37 a la propiedad Edad su tipo será un Int. Sin embargo si acto seguido le asigno, por ejemplo, 10E10 (un número muy grande), automáticamente la propiedad cambia y ahora es de tipo double. Exactamente igual que pasaría en JavaScript u otro lenguaje dinámico tradicional.

Podemos crear propiedades de objetos dinámicos que a su vez son también objetos dinámicos. Por ejemplo:

Persona1.Domicilio = new ExpandoObject();
Persona1.Domicilio.Ciudad = "Vigo";

De este modo acabo de crear una propiedad Domicilio que es dinámica y le he creado a su vez una propiedad Ciudad. Así puede escribir Persona1.Domicilio.Ciudad para obtener el valor "Vigo".

Estos tipos dinámicos, aunque están soportados por el entorno de Visual Studio 2010, no nos ofrecen (al menos en la Beta2) soporte para Intellisense, en el sentido de que una vez definida la propiedad, esta no aparece en la ayuda contextual cuando volvemos a usar el objeto y ponemos un punto:

Como vemos, nos indica que lo que escribamos a continuación del punto será interpretado en tiempo de ejecución, no al compilar, y por tanto no nos muestra ayuda al respecto.

Con esto es muy facil, por ejemplo, crear un nuevo objeto dinámico dinámicamente (valga la redundancia) a partir de datos contenidos en algún lado. El ejemplo típico es cargar un archivo XML e ir recorriendo sus nodos e ir asignando a su vez propiedades alobjeto dinámico. Así podremos acceder más fácilmente a los datos desde el código pudiendo escribir notaciónn común de objetos (nombres y puntos) para acceder a ellas en lugar de estar escribiendo sintaxisd más complejas para leer valores de nodos o atributos XML. También nos valdría de modo similar para interpretar JSON.

Una aplicación especialmente interesante es a la hora de definir vistas de ASP.NET MVC 2.0 de manera dinámica, como explica Phil Haack en este post (inglés).

Además de propiedades es posible definir también métodos dinámicamente, si bien éstos son de menor utilidad ya que deberán ser estáticos y por lo tanto no pueden acceder al resto de propiedades del objeto.

Por ejemplo:

Persona1.Saludar = new Func<STRING, bool>((sSaludo) =>
{
    Console.WriteLine(sSaludo);
    return true;
});

Con esto creamos un nuevo método Saludar, y podemos escribir: Persona1.Saludar("Hola") para obtener ese mensaje por pantalla en este caso simple. El método se crea con una expresión Lambda por lo que siempre deve devolver algo. En este caso como no nos interesa para nada el valor devuelto he optado por devolver un booleano sin más. Ya digo que no tienen demasiada utilidad.

Si llamamos a la función sin pasarle el número de parámetros apropiado no se nos quejará el compilador y podremos generar el ejecutale. Sin embargo a la hora de ejecutar la aplicación romperá miserablemente:

Enumeración y eliminación de miembros

Hasta ahora hemos visto lo fácil que es crear un miembro, pero claro, nos será útil solamente si sabemos de antemano qué miembros están disponibles. ¿Cómo podemos averiguarlo?. Esto puede ser útil para, en el caso de crearlo a partir de un origen de datos arbitrario, poder enumerarlos y comprobar que existen un mínimo determinado de ellos, o simplemente para poder hacer introspección de los objetos. Siempre podríamos usar reflexión pero sin embargo no habríamos ganado demasiado ¿verdad?.

Fijémonos en la definición de la clase ExpandoObject (en C#):

public sealed class ExpandoObject : IDynamicMetaObjectProvider, 
    IDictionary<string, Object>, 
    ICollection<KeyValuePair<string, Object>>, 
    IEnumerable<KeyValuePair<string, Object>>, 
    IEnumerable, INotifyPropertyChanged

Como vemos implementa una interfaz IDictionary genérica y también una ICollection e IEnumerable. Es decir, en el fondo se trata ni más ni menos de una colección genérica capaz de albergar cualquier cosa. Los miembros que vamos añadiendo se incorporan a una colección interna. Por lo tanto para poder enumerarlos sólo hay que hacer uso del objeto como una colección o un diccionario:

IDictionary<String, Object> miembros = (IDictionary<string, Object>)Persona1;
foreach (System.Collections.Generic.KeyValuePair<String, Object> miembro in miembros)
{
    Console.WriteLine("{0}: {1}", miembro.Key, miembro.Value);
}

O de manera más directa y entendible:

foreach(var miembro in (IDictionary<string, Object>)Persona1)
{
    Console.WriteLine("{0}: {1}", miembro.Key, miembro.Value);
}

Como vemos simplemente hacemos un "cast" a la interfaz IDictionary y a partir de ese momento lo manejamos como cualquier otra colección de objetos cuya clave es de tipo texto. Gracias ello podemos añadir nuevos miembros usando el método Add del diccionario, pero, lo más importante, podemos eliminarlos usando el método Remove, por ejemplo:

((IDictionary)Persona1).Remove("Nombre");

En la que me he cargado la propiedad Nombre.

Detectando cambios en propiedades

Si nos fijamos en la definición de la clase vemos que implementa una interfaz INotifyPropertyChanged. Ésta define un evento llamado PropertyChanged que nos sirve para detectar el momento en que cambia una propiedad o se asigna por primera vez. Así, podemosdefinir una función como esta:

private static void DetectarCambios(object sender, PropertyChangedEventArgs e)
{
    Console.WriteLine("Se ha asignado la propiedad '{0}'", e.PropertyName);
}

y detectar los cambios en miembros simplemente estableciendo esa propiedad de la interfaz, así:

((INotifyPropertyChanged)Persona1).PropertyChanged += new PropertyChangedEventHandler(DetectarCambios);

No acaba de ser del todo útil porque no nos deja averiguar qué valor se ha asignado (aunque es fácil de determinar usando la colección interna como acabamos de ver hace un momento, pero puede ayudarnos en algunos casos. No obstante si queremos crear objetos dinámicos y tener control absoluto sobre cómo se crean sus miembros en lugar de ExpandoObject deberíamos usar la clase DynamicObject.

Colecciones de objetos dinámicos

Para terminar con este interesante tema me gustaría comentar cómo se crean colecciones de objetos dinámicos. Consideremos el siguiente código:

dynamic vecinitos = new List<dynamic>();

vecinitos.Add(new ExpandoObject());
vecinitos[0].Nombre = "Homer";
vecinitos[0].Apellidos = "Simpson";
vecinitos[0].Ropa = "Camisa blanca, pantalones azules";

//No son objetos iguales
vecinitos.Add(new ExpandoObject());
vecinitos[1].Nombre = "Ned";
vecinitos[1].Apellidos = "Flanders";

foreach (var vecinito in vecinitos)
{
    Console.WriteLine("{0} {1}", vecinito.Nombre, vecinito.Apellidos);
}

Vemos que la lista genérica se crea del tipo dynamic, y no del tipo ExpandoObject. Esto es normal ya que de esta forma estamos acogiendo objetos dinámicos de cualquier tipo y no sólo de esta clase particular. Aunque en este ejemplo concreto funcionaría perfectamente haberla definido con ExpandoObject, en general usaremos dynamic (u Object en VB) porque así nos aseguramos que vengan de donde vengan los objetos de la lista ésta funcionará sin problema.

A continuación definimos cada elemento añadido la lista de forma que creamos dinámicamente sus propiedades. Finalmente los recorremos en un bucle para mostrar sus propiedades.

Si en el bucle hubiésemos usado esta línea de código en ugar de la anterior:

Console.WriteLine("{0} {1}", vecinito.Nombre, vecinito.Apellidos, vecinito.Ropa);

Lo que hubiera pasado es que la primera vuelta (la de Homer) hubiera funcionado bien, pero como en el segundo elemento (Flanders) no hemos definido la propiedad ropa hubiésemos obtenido un error en tiempo de ejecución. Con esto quiero dejar claro que aunque se defina una propiedad para uno de los objetos, ésta no queda definida en los demás, ya que son objetos absolutamente independientes, así que hay que tener cuidado y no dar por hecho que una determinada propiedad va a existir para un objeto dinámico concreto.

En resumen

Los objetos dinámicos creados a partir de la clase ExpandoObject están pensados para trabajar con lenguajes dinámicos desde C# y VB. Ello además nos proporciona una nueva herramienta que podemos usar en otro tipo de desarrollos aunque no estén relacionados con los lenguajes dinámicos. Eso sí: debemos usarlos con sumo cuidado y sólo en situaciones que estén muy justificadas, porque de otra manera correremos el riesgo cierto de cometer muchos errores difíciles de detectar. De hecho una de las ventanas de los lenguajes tipados frente a los dinámicos es que es mucho más difícil meter la pata porque debes tener claro todo el rato qué tipo de información estás manejando. Así que ¡cuidado!.

Los objetos ExpandoObject son en realidad una forma fácil de acceder colecciones genéricas, por lo que debemos tener con ellos el mismo cuidado que con las colecciones. Así que cuando escribamos una propiedad con la notación del punto debes recordar que por debajo lo único que estás haciendo es añadir un elemento a una colección. Tenlo en mente todo el rato.

He dejado todo el código de este artículo en un ZIP para que puedas descargarlo y haer tus propios experimentos con estos objetos dinámicos y ver cómo se comportan.

¡Espero que te resulte útil!

Por: José Manuel Alarcon | Saturday, February 06, 2010 8:57:14 PM (Hora estándar romance, UTC+01:00)  #    Comments [0] - Trackback
Tags: Programación | Visual Studio


Sígueme en:

:: Twitter JM Alarcón: tecnología, marketing, este blog y frikadas varias
:: Twitter campusMVP: los mejores recursos sobre tecnología Microsoft: trucos, artículos, noticias, vídeos...
:: Facebook campusMVP: los mismos mejores recursos pero en directamente en Facebook.
:: Boletín campusMVP Nuestra publicación electrónica, una vez al mes en tu buzón de correo.
 
Banner

Si has utilizado en producción Windows azure, y en concreto su almacenamiento local para tablas, blobx y colas (Windows Azure Storage), habrás observado que cuando defines una cuenta de almacenamiento dispones de dos claves de seguridad para acceder a las mismas, una primaria y otra secundaria:

¿Por qué hay dos claves, para qué sirven y cómo se relacionan?

La verdad es que es un sistema interesante. Ambas claves son equivalentes y ambas sirven para acceder a la cuenta de almacenamiento, así que podemos utilizar una u otra indistintamente. Generalmente usaremos la primera y la desplegaremos en nuestra aplicación Azure, dentro de sus propiedades de configuración.

Al tener dos claves lo que conseguimos es que no exista ni un segundo de parada de nuestra aplicación si necesitamos cambiarla.

Supongamos que estamos usando la primera clave y alguien nos la roba y tiene acceso también al almacenamiento. ¿Cómo procederíamos para cambiarla y no parar el servicio?

El procedimiento sería el siguiente:

1.- Cambiamos el archivo de configuración de la aplicación Azure para que pasemos a utilizar la segunda de las claves. Este cambio es instantáneo y no es necesario desplegar de nuevo la aplicación. A partir de este momento se está usando la segunda clave y la primera no nos hace falta.

2.- Vamos a la pantalla anterior y pulsamos el botón de regenerar la primera clave. A partir de ese mismo instante la clave anterior queda invalidada y el que nos la haya robado no podrá utilizarla.

3.- Opcionalmente, volvemos a cambiar la configuración para usar la nueva clave primera, aunque no es necesario y podemos quedarnos con la segunda el tiempo que necesitemos, haciendo el procedimiento en sentido inverso si se viese comprometida.

Como vemos este pequeño truco es realmente útil para no interrumpir en ningún momento el funcionamiento de la aplicación Azure, cosa que sí tendríamos que hacer en caso de que sólo existiera una clave.

Espero que lo encuentres útil :-)

Por: José Manuel Alarcon | Thursday, January 28, 2010 9:37:10 PM (Hora estándar romance, UTC+01:00)  #    Comments [0] - Trackback
Tags: Azure


Sígueme en:

:: Twitter JM Alarcón: tecnología, marketing, este blog y frikadas varias
:: Twitter campusMVP: los mejores recursos sobre tecnología Microsoft: trucos, artículos, noticias, vídeos...
:: Facebook campusMVP: los mismos mejores recursos pero en directamente en Facebook.
:: Boletín campusMVP Nuestra publicación electrónica, una vez al mes en tu buzón de correo.
 
Banner

Una situación muy común en las empresas cuando les hablas de formación se produce cuando los responsables de RRHH/Equipos/Proyectos te dicen que no forman a su gente porque si lo hacen luego éstos se les marchan a la competencia. Pasa constantemente.

Es cierto que la formación mejora la empleabilidad de la gente. De eso no hay duda. Pero el que se vayan o se queden depende fundamentalmente de que la empresa ponga los medios y -sobre todo- las condiciones para "fidelizar" al empleado, y que por lo tanto éste desee permanecer en ella, porque está motivado, tiene posibilidades de mejorar y sobre todo se sienta realizado en el plano laboral.

Si un trabajador se marcha tras la formación es que ya deseaba irse antes de la formación. Es decir, no existe una relación de causalidad entre formar a una persona y que se quiera marchar de la empresa, como es obvio. Es más, el hecho de que la empresa no les brinde la oportunidad de formarse es una razón más para querer abandonarla, pues no se apuesta por esa persona. Claro que la persona también tiene que ser de una determinada forma, y es este tipo de trabajador al que se debiera apoyar.

En la actual sociedad competitiva y globalizada, donde las barreras de entrada a muchos negocios y actividades se han reducido o, directamente, han desaparecido, las empresas deben saber responder con celeridad a los cambios. Es más, deben en realidad tratar de adelantarse a los cambios y tendencias. En el ámbito tecnológico en el que nos movemos la audiencia de mi blog y yo, la única constante es el cambio.

La verdadera formación continua no sólo se trata del aprendizaje de una determinada disciplina técnica o competencia, sino que implica también "vivir en el mundo", comprender lo que te rodea, estar al tanto de los cambios y tendencias importantes que influyen o influirán a tu trabajo. Sólo de este modo podrán los trabajadores ayudar a su empresa a mejorar, a anticiparse, a ser diferente.

Obviamente esto implica no sólo que la empresa brinde la oportunidad de hacerlo, sino también trabajadores que tengan interés por ello. Estas personas son algo más que trabajadores, son profesionales.

Lo que expongo se aplica a cualquier trabajo que implique la realización de tareas que no sean mecánicas. En el caso de trabajadores de "cuello blanco" -los que se han dado en llamar "trabajadores del conocimiento"- son la práctica totalidad de los puestos.

En el caso concreto de los técnicos TIC esto último es especialmente cierto. El que se haya metido a programador, administrador de sistemas, etc.. pensando en que no se va a formar hasta el fin de sus días está muy equivocado. Sorprende entrevistar a recien titulados en informática que creen que por haber estudiado esta carrera ya saben todo lo que necesitan. También existe otra categoría de informáticos, muy común, cuya única formación es buscar en Internet la solución concreta al problema concreto que tienen en cada momento, pero sin ir más allá. ¿Cuántos programadores conoces que dicen que al terminar su jornada laboral no quieren tocar un ordenador?.

No son precisamente estos últimos aquellos que las empresas deben cuidar y apostar por su formación.

Pienso que las empresas, más que preocuparse porque si forman a los trabajadores éstos se les van a marchar, deberían preocuparse porque si no los forman, a lo mejor, se les quedan. Y esto sí que será un problema a largo plazo ;-)

En fin, esta es mi reflexión personal para una tarde domingo lluviosa, sin nada mejor que hacer, y espero que se me haya entendido :-)

Por: José Manuel Alarcon | Sunday, January 17, 2010 7:20:06 PM (Hora estándar romance, UTC+01:00)  #    Comments [6] - Trackback
Tags: Mundo TIC


Sígueme en:

:: Twitter JM Alarcón: tecnología, marketing, este blog y frikadas varias
:: Twitter campusMVP: los mejores recursos sobre tecnología Microsoft: trucos, artículos, noticias, vídeos...
:: Facebook campusMVP: los mismos mejores recursos pero en directamente en Facebook.
:: Boletín campusMVP Nuestra publicación electrónica, una vez al mes en tu buzón de correo.
 
Banner

Únete a nosotros

En Krasis estamos buscando personas motivadas para incorporarse a nuestro equipo de Marketing:

Técnico de Marketing Formación - Vigo - Enero 2010

El candidato se responsabilizará de las tareas de Marketing del área de Formación. Entre sus tareas estarán:

  • Identificación de posibles clientes
  • Ejecución y seguimiento de campañas de marketing.
  • Análisis de mercado y seguimiento de la competencia.
  • Coordinación de campañas de publicidad.
  • Relación con clientes.
  • Relación con Microsoft y partners.
  • Gestión del presupuesto de MK asignado.

Buscamos a una persona en el área de Vigo, de carácter resolutivo, con experiencia en marketing on-line, buen nivel de inglés y especial gusto por Internet y los medios digitales. Idealmente el candidato provendría del sector y conocería el ámbito de las certificaciones y formación en tecnología Microsoft, pero no es indispensable.

¡Incorporación inmediata!           Escríbenos un email con el asunto "TM_VGO_011309" a

Por: José Manuel Alarcon | Wednesday, January 13, 2010 1:58:09 PM (Hora estándar romance, UTC+01:00)  #    Comments [0] - Trackback
Tags: Off-Topic


Sígueme en:

:: Twitter JM Alarcón: tecnología, marketing, este blog y frikadas varias
:: Twitter campusMVP: los mejores recursos sobre tecnología Microsoft: trucos, artículos, noticias, vídeos...
:: Facebook campusMVP: los mismos mejores recursos pero en directamente en Facebook.
:: Boletín campusMVP Nuestra publicación electrónica, una vez al mes en tu buzón de correo.
 
Banner

Si llevas unos cuantos años en esto del desarrollo Web seguro que tienes todavía aplicaciones por ahí escritas en ASP 3.0, también conocido como "ASP Clásico". Este precursor del actual ASP era estupendo y funciona de maravilla aún hoy en día. A pesar de todas las virguerías técnicas existentes en la actualidad (que me encantan) me confieso un enamorado de esa antigua plataforma.

El caso es que aún hoy en día, si tienes que montar una aplicación de ASP 3.0 incluso en un moderno Windows Server 2008 R2 con IIS 7.5, podrás hacerlo sin problemas y funcionará todo de maravilla. O casi...

El otro día tuvimos que montar una de nuestras aplicaciones "legacy" en este entorno precisamente y todo parecía ir de maravilla. El caso es que nosotros instrumentamos todas nuestras aplicaciones, incluso  las antiguas, para llevar un registro automático de todos los eventos de interés que se producen: avisos, advertencias, operaciones importantes sobre los datos... y por supuesto los errores no gestionados y por tanto inesperados. Se trata de una buena práctica que deberías seguir en cualquier aplicación, y más en una para Internet y de la cual algunos ya me habréis oído hablar en ponencias por ahí.

En ASP clásico la forma de gestionar los errores inesperados pasa necesariamente por personalizar la página de error para el estátus 500 del servidor Web con una página .asp propia. En ésta se obtiene información sobre el error producido usando el método Server.GetLastError que devuelve un objeto ASPError con todos los detalles.

La configuración en IIS 7.0 o IIS 7.5 se hace de la siguiente forma:

1.- En las propiedades del servidor virtual se va a la sección de páginas de error:

2.- Una vez dentro de ésta aparecen la lista de códigos de estátus HTTP estándar, como por ejemplo el 404 para páginas no encontradas (muy recomendable gestionarlo), el 302 (acceso denegado), o el que nos interesa: 50, error interno del servidor. Sustituimos la página por defecto de IIS para el error 500 y colocamos una página .asp propia. Utilizando el mencionado objeto ASPError podemos obtener información sobre errores que se produzcan, anotar información sobre lo que ha pasado con todo lujo de detalles (error, tipo, ubicación, página, usuario, tipo de navegador...) para luego poder hacer un diagnóstico y detectar problemas. También devolveremos una página más bonita y adecuada para los usuarios, lo cual es muy importante también, y además es una buena práctica de seguridad el no mostrar mensajes detallados de error al usuario final.

No funciona en IIS 7.x

La idea es estupenda y funciona muy bien si lo hacemos en IIS 5.0 o 6.0, ¡pero en IIS 7.x no funcionará!. Es decir, sí que se llamará a nuestra página personalizada, y ésta funcionará. El problema es que el método Server.GetLastError devolverá un objeto con todas sus propiedades vacías, por lo que sabremos que se produce un error pero no tendremos ni un sólo detalle del mismo :-(

Se trata de un bug reconocido por Microsoft desde IIS 7.0, pero que no ha sido corregido en ninguno de los Service Pack ni tampoco en la versión R2 del sistema operativo (nueva versión 7.5 de IIS). Son los riesgos de usar una tecnología antigua para la que Microsoft no tiene la menor intención de seguir invirtiendo ni un segundo.

¿Cómo lo solucionamos?

Como casi siempre hay una vía de escape para solventar el problema. IIS 7.x dispone de un gestor global de códigos de estado HTTP que se usa cuando no hay uno específicamente designado en la configuración. Resulta que en este gestor global de errores el objeto ASPError sí que se rellena correctamente.

Por lo tanto lo que tenemos que hacer es eliminar el estátus HTTP 500 de la lista de errores gestionados por IIS, para que no tenga asignada ni siquiera la página por defecto. Si editamos la configuración general de este módulo de gestión global de errores:

Nos aparece un diálogo en el que podremos ajustar nuestra página de gestión global:

Allí deberemos introducir una ruta relativa a la raíz de nuestra aplicación (por ejemplo "/Logevents/logerr.asp" como en la figura), y usar en el PathType la opción de "Ejecutar una URL".

De este modo se recibirán perfectamente las propiedades del error y podremos trabajar como siempre :-)

¡Uppps! IIS me da un error de "violación de bloqueo" (Lock Violation)

Vaya. Cuando ya pensábamos que lo teníamos controlado y podríamos tener nuestra aplicación ASP Clásico funcionando a pleno rendimiento, al pulsar "OK" en el diálogo de la figura anterior nos sale este mensaje:

¿Qué demonios es esto? La verdad es que el mensaje no proporciona demasiada información al respecto. He de confesar que cuando nos salio la primera vez pensé que era un bug de la interfaz de gestión de IIS 7.5, que tenía interbloqueos mal hechos ;-P

A base de indagar y probar, ya que no había información en Internet al respecto y la poca que hay no está bien, llegué a la solución del problema.

Por defecto, hay ciertas secciones de la configuración global de IIS 7.x que están protegidas para impedir la modifiación en sub-ramas del servidor. Esto está diseñado de esta forma pensando en las empresas de hosting, ya que de esta manera pueden bloquear ciertas secciones peligrosas para que los administradores de los sitios web que venden no puedan cambiar ajustes que puedan comprometer la seguridad global del servidor. ¡Bien hecho Microsoft!. Lo malo es que no está nada claro en ningún sitio (o al menos a mi eso me parece), y a más de uno que gestiona sus propios servidores le puede traer por la calle de la amargura. ¡Mal hecho Microsoft! ;-)

En nuestro caso lo que debemos hacer es desbloquear este ajuste en la configuración global del servidor para que nos permita cambiarlo en la configuración secundaria de los sitios Web.

Para ello debes ir, como administrador, a la carpeta "C:\Windows\System32\Inetsrv" o equivalente (está ahí incluso en versiones de 64 bits de Windows). Dentro de ésta encontrarás el archivo applicationHost.config. Sácale una copia por si acaso te cargas algo que no debes, y ábrelo con el bloc de notas, ya que es un simple archivo de texto XML.

Una vez abierto busca el nodo "<httpErrors>". Encontrarás una rama que pondrá algo similar a esto:

<httpErrors defaultPath="" defaultResponseMode="ExecuteURL"
lockAttributes="allowAbsolutePathsWhenDelegated,defaultPath">

La parte importante aquí es el atributo lockAttributes. Como puedes observar, por defecto, tiene bloqueada la modificación de la ruta por defecto para los errores, que es precisamente lo que pretendemos modificar en nuestro sitio web.

Elimina la palabra "defaultPath" del atributo lockAttributes, graba el archivo y ciérralo. Ahora vuelve a IIS y cambia d enuevo la configuración en el diálgoo que hemos visto. Esta vez, al cerrarlo, no te generará la violación de bloqueo, y todos felices.

Este último consejo te valdrá para IIS en general, y por lo tanto para ASP.NET o incluso PHP, y no se restringe sólo a esta sección de la configuración.

Espero que si llegas hasta aquí a través de un búsqueda, desesperado/a por el problema, todo esto te haya servido. Si me lo quieres agradecer puedes dejar un comentario, y también ya sabes ;-)

Por: José Manuel Alarcon | Saturday, January 09, 2010 12:38:42 PM (Hora estándar romance, UTC+01:00)  #    Comments [0] - Trackback
Tags: ASP.NET | Sistemas operativos


Sígueme en:

:: Twitter JM Alarcón: tecnología, marketing, este blog y frikadas varias
:: Twitter campusMVP: los mejores recursos sobre tecnología Microsoft: trucos, artículos, noticias, vídeos...
:: Facebook campusMVP: los mismos mejores recursos pero en directamente en Facebook.
:: Boletín campusMVP Nuestra publicación electrónica, una vez al mes en tu buzón de correo.
 
Banner

Generalmente, lo que más nos interesa a la hora de realizar copias de seguridad es hacerlas hacia alguna máquina o dispositivo especializado de la red local, distintos a la máquina en la que se ejecuta nuestra aplicación o -en nuestro caso concreto- el servidor de datos. Así podremos recuperarlos desde cualquier otra máquina ante cualquier contingencia que surja. En los Data Center (y en muchas oficinas) suelen existir sistemas NAS (Network Attached Storage, almacenamiento en red) cuyo propósito es precisamente albergar las copias de seguridad.

SQL Server, sin embargo, sólo ofrece soporte nativo para realizar copias de seguridad en unidades de disco o dispositvos de backup hardware locales. Esto siempre me ha parecido una seria limitación, ya que hacer copias de seguridad en local no me resulta útil en absoluto. Y tiene muchas limitaciones más (como no comprimir o cifrar las copias), aunque esto es bueno para las empresas que venden herramientas especializadas en ello, como la excelente SQL Backup de Red Gate Software.

Lo que muchos hemos hecho toda la vida ha sido lo siguiente: haces el backup en una carpeta local y programas, un tiempo prudencial después, la ejecución de un archivo .bat que mueva la copia a una unidad de red usando comandos del sistema operativo. Esto funciona pero añade complejidad ya que hay que coordinar ambas acciones y hay más puntos de fallo. Además hay una cuestión adicional que a mi ya me ha ocurrido en servidores viejos: si el disco local no tiene espacio suficiente no puedes hacer copias de seguridad (no te caben), cuando a lo mejor tienes cientos de GB libres en el NAS que no puedes aprovechar :-(

Lo ideal sería hacer la copia directamente en el NAS sin pasar por el disco local. En este post voy a contar cómo podemos conseguir precisamente esto: hacer backups de SQL Server directamente a la red. Además cuento cómo conseguir un backup diario, con un archivo para día de la semana, que se van sobrescribiendo automáticamente, por lo que conseguimos de manera sencilla una retención de 7 días.

Las instrucciones que doy a continuación funcionan con SQL Server 2005 y 2008, y las he sacado a base de prueba y fallo durante bastante tiempo. No he encontrado en Internet instrucciones algunas que contemplen esta operación por completo, sobre todo en lo referente a los pequeños detalles (como la seguridad) que hacen que llegue a funcionar.

1.- Cuenta de ejecución de SQL Server

Lo primero que tenemos que hacer es asegurarnos de que nuestro sistema SQL Server va a tener acceso a la red local. Tanto el motor de bases de datos como el agente de SQL Server se ejecutan suplantando a un determinado usuario del sistema operativo. Mucha gente instala SQL Server para que sus servicios se ejecuten bajo la cuenta de sistema, ya que ésta tiene acceso a cualquier recurso del sistema local, y simplifica la gestión. Esto, aparte de un posible problema de seguridad (en el que no voy a entrar), no es necesario en absoluto. Además hay una cuestión fundamental: la cuenta de sistema no tiene capacidades para acceder a la red. Por lo tanto si nuestro servidor de datos se ejecuta bajo System no podremos realizar copias de seguridad a unidades de red.

La cuenta recomendada para ejecutar SQL Server y conseguir acceso a la red es "Servico de Red" (o, en inglés, "Network Service"). Esta cuenta tiene los permisos suficientes para ejecutar SQL Server sin problema y además nos sirve para nuestro propósito. Lo podemos cambiar desde la configuración de Servicios de SQL Server, en las propiedades de cada servicio:

Si las copias de seguridad las vamos a hacer escribiendo el comando desde el SQL Management Studio, esta cuenta debemos asignarla al motor de SQL Server. Si, como es más común, las copias de seguridad serán automatizadas con el agente de SQL Server, es este servicio el que debe ejecutarse con esta cuenta. En cualquier caso (y sin ser especialista en absoluto en SQL Server), mi recomendación sería que pusiésemos ambos servicios a ejecutarse bajo esta cuenta.

2.- Creación de la cuenta para acceso a la red

Una cosa es la cuenta bajo la que se ejecuta el servidor y otra es la cuenta que usaremos para acceder al recurso de red. Tendrá que ser un usuario que tenga permisos de lectura y escritura en la carpeta compartida en la que queremos escribir el backup. Si no estamos bajo un mismo dominio de Directorio Activo -es decir, utilizamos usuarios diferentes para cada máquina- debemos crear en nuestra máquina local (en la que se ejecuta SQL Server) una cuenta de usuario con el mismo nombre y clave que el que usaremos para acceder a dicho recurso. Por ejemplo, si el NAS tiene un usuario llamado "NAS\Backup" con clave "backup", deberemos crear también en local este mismo usuario. Cuando accedemos interactivamente desde el explorador de Windows al recurso remoto podemos escribir el usuario y la clave en la ventan que aparece, pero con el Script SQL que usaremos aquí, o disponemos del usuario también en local, o no funcionará. El motivo no lo tengo muy claro, pero es así :-(

3.-Habilitar el comando xp_cmdshell

Este comando permite ejecutar comandos del sistema operativo desde scripts T-SQL. Vamos a necesitarlo para habilitar el acceso a los recursos remotos. Por defecto viene desactivado y no podremos usarlo, ya que reviste bastante peligro, puesto que otorga acceso a comandos del sistema que pueden ser muy peligrosos (como formatear el disco duro, por ejemplo). En SQL Serevr 2000 venía habilitado por defecto y las aplicaciones con problemas de seguridad debidas a inyeción SQL y ejecutadas bajo cuentas con demasiados privilegios eran una coladera, por eso en la versión 2005 y posteriores se ha deshabilitado por omisión.

En nuestro caso lo necesitaremos, así que tenemos que habilitarlo. Para ello debemos lanzar las siguientes instrucciones T-SQL desde SQL Management Studio:

-- Permitir el cambio de opciones avanzadas de SQL Server
EXEC sp_configure 'show advanced options', 1
GO
-- Reconfigurar para que permita modificarlas.
RECONFIGURE
GO
-- Habilitar la característica xp_cmdshell
EXEC sp_configure 'xp_cmdshell', 1
GO
-- Refrescar para que el cambio surta efecto
RECONFIGURE
GO

Ya está.

4.- Programar la copia de seguridad

Ahora ya tenemos las bases necesarias para que esto funcione, así que lo único que nos resta es crear una nueva tarea del agente SQL que se encargue de realizar la copia de seguridad. En el apartado de "pasos de la tarea" crearemos un nuevo paso con las siguientes instrucciones T-SQL:

SET LANGUAGE us_english
exec xp_cmdshell 'net use \\192.168.1.1\backups\SQL clave /user:backup'
DECLARE @Archivo AS nvarchar(100)
SET @Archivo = N'\\192.168.1.1\Backups\SQL\MiBaseDeDatos_' + DATENAME(WEEKDAY, GETDATE()) + '.bak'
BACKUP DATABASE [MiBaseDeDatos] TO  DISK = @Archivo WITH NOFORMAT, INIT, 
NAME = N'MiBaseDeDatos-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10; exec xp_cmdshell 'net use \\192.168.1.1\Backups\SQL /D'

Lo que estamos haciendo es poner el lenguaje actual en inglés. Yo suelo usar siempre el inglés para todo y tengo los sistemas en este idioma porque considero que tiene muchas ventajas pero tú, claro está, puedes usar el idioma que prefieras. El hecho de establecer el idioma es para asegurarnos de que si transportamos el Script a otro servidor diferente los nombres de los archivos de copia de seguridad van a tener nombres consistentes, ya que usaremos el nombre del día de la semana para crear un archivo .bak cada día (lunes, martes, y así sucesivamente).

El comando xp_cmdshell de la segunda línea habilita la conexión a la carpeta de red \backups\SQL que está en nuestro NAS, con dirección IP 192.168.1.1. Podríamos haber usado el nombre de red (por ejemplo \\NAS o similar), pero con la IP nos aseguramos de que siempre va a funcionar, pues lo otro a veces he detectado que da problemas. En esta línea, por tanto, debes poner la ruta de red que queires usar e indicar la clave y nombre de usuario que usaremos para acceder (ver paso 2).

Las dos siguientes líneas declaran el nombre y la ruta del archivo de backup que vamos a crear. Lo que yo hago aquí es ponerle como sufijo el nombre del día de la semana en inglés, de forma que se me crean copias de seguridad diarias con el nombre "MiBaseDeDatos_Monday.bak", "MiBaseDeDatos_Tuesday.bak", y así sucesivamente. Con esto consigo tener una copia completa cada día de la semana, con una retención de 7 días, que se va sobrescribiendo automáticamente cuando pasa una semana. Para mi esto es más que suficiente, pero si quisieras más retención o más de una copia diaria al día tendrías que buscar una forma alternativa para nombrar los archivos.

La siguiente línea es una instrucción T-SQL normal y corriente para crear una copia de seguridad, sólo que en este caso ya se hará directamente sobre la carpeta de red, y no en local, que es lo que deseábamos.

Finalmente con xp_cmdshell, nos desconectamos del recurso de red. Esto es necesario para que no queden conexiones abiertas y nos impidan volver a reconectar en sucesivas ocasiones.

Espero que te resulte útil y que mis horas de prueba y error te ahorren a ti mucho tiempo. Si me loquieres agradecedr, ya sabes, matricúlate en alguno de nuestros cursos o compra alguno de nuestros libros ;-)

Por: José Manuel Alarcon | Wednesday, January 06, 2010 7:27:11 PM (Hora estándar romance, UTC+01:00)  #    Comments [2] - Trackback
Tags: SQL Server


Sígueme en:

:: Twitter JM Alarcón: tecnología, marketing, este blog y frikadas varias
:: Twitter campusMVP: los mejores recursos sobre tecnología Microsoft: trucos, artículos, noticias, vídeos...
:: Facebook campusMVP: los mismos mejores recursos pero en directamente en Facebook.
:: Boletín campusMVP Nuestra publicación electrónica, una vez al mes en tu buzón de correo.
 
Banner

Hace unos meses (en mayo) hice 5 años con este blog, es decir que llevo ya más de 5 años y medio con él. Si eres de los que lleva siguiendo mis posts desde hace tiempo habrás notado que últimamente mi frecuencia de publicación ha bajado un poco. El motivo principal es que cada vez tengo menos tiempo disponible y además, como puedes comprobar si ves lo que escribo, me suelo "currar" bastante los posts, es decir, que me lleva bastante tiempo escribirlos.

Otro de los motivos es bien diferente: en los últimos meses utilizo mucho más las redes sociales y eso me quita tiempo para el blog. En realidad el uso que hago de éstas es tanto personal como profesional, pero en cualquiera de los dos casos lo que hago en ellas tiene relación directa con la temática de este blog: programación en general, tecnología, Microsoft, desarrollo Web, frikadas varias...

Con esto no estoy diciendo en absoluto que vaya a dejar de lado el blog. De hecho tengo intención de seguir metiendo muchas cosas interesantes en el futuro. Simplemente te sugiero que si tienes interés en todas estas cosas y quieres tener mucha más información interesante y con más frecuencia, lo mejor es que me sigas a mi y a mi empresa en el medio social que uses habitualmente:

· Twitter JM Alarcón: mi twitter personal con enlaces, comentarios personales, y también avisos de cuando hay nuevos posts en este blog.
· Facebook campusMVP: noticias, artículos, enlaces, videos... todo sobre .NET y Microsoft. Al menos un par de ellas al día. Nada de publicidad.
· Twitter campusMVP: Idem que el anterior pero a través de twitter, para los que os va más ese servicio.
· Scribd de Krasis Press: Aqui publicamos de vez en cuando artículos interesantes, fragmentos de libros e, incluso a veces, libros completos, como mi último libro de ASP.NET 4.0 y AJAX. La disponibilidad de nuevos artículos se anuncian en Facebook y Twitter.
· Boletín de campusMVP: boletín por e-mail mensual de campusMVP sobre tecnologías Microsoft. Todo interesante, nada de publicidad y sólo se envía una vez al mes, hacia el día 15.

Otros recursos relacionados en los que estoy involucrado de lleno y que te pueden interesar también son estos:

· Blog de e-mail marketing de Krasis: trucos, consejos, comentarios sobre el trabajo con correo electrónico y el e-mail marketing. Lo hacemos también en inglés.
· Boletín BECK: boletín mensual de Krasis (día 1 de cada mes). Poco técnico pero totalmente centrado en la actualidad de las TI.

En fin, espero que sigas siendo fiel al blog, pero ten en cuenta también todas estas otras fuentes de información para estar mejor informado :-)

Por: José Manuel Alarcon | Friday, December 18, 2009 6:24:25 PM (Hora estándar romance, UTC+01:00)  #    Comments [2] - Trackback
Tags: Off-Topic


Sígueme en:

:: Twitter JM Alarcón: tecnología, marketing, este blog y frikadas varias
:: Twitter campusMVP: los mejores recursos sobre tecnología Microsoft: trucos, artículos, noticias, vídeos...
:: Facebook campusMVP: los mismos mejores recursos pero en directamente en Facebook.
:: Boletín campusMVP Nuestra publicación electrónica, una vez al mes en tu buzón de correo.
 
Banner

El otro día un alumno del curso de preparación del examen 70-536 en campusMVP me hizo la siguiente (interesante) pregunta:

"He revisando el tema de las coleciones y me han surgido las siguentes dudas: Al leer en el MSDN información sobre distintas colecciones a veces aparece la siguiente frase: 'La recuperación del valor de esta propiedad es una operación O(1); el establecimiento de la propiedad también es una operación O(1).' ¿exactamente a que se refiere con operación O(1)? El ejemplo que he puesto pertenece a ArrayList.Item (Propiedad) http://msdn.microsoft.com/es-es/library/system.collections.arraylist.item.aspx"

¿Y esto qué es?

Lo de 0(1) es una notación matemática usada en algoritmia que indica el comportamiento límite de una función. A este tipo de notación se le llama "notación asintótica", "notación Landau" o "notación Big O".

En la wikipedia hay un artículo muy completo sobre esta notación, pero básicamente lo que hay que saber para "andar por casa" es que lo que significa que un algoritmo 0(1) es que éste tarda lo mismo en ejecutarse para cualquiera de sus elementos. Bueno, en realidad lo exacto no sería decir que "tarda lo mismo", sino más bien que "en términos computacionales el esfuerzo necesario para procesarlo es el mismo", lo cual en muchos casos se traduce en el mismo tiempo.

Así por ejemplo en el caso de la pregunta, la extracción de un elemento de la lista especializada ArrayList a través de su indexador (propiedad item), lo que te indica la notación 0(1) de la documentación de MSDN es que se tarda lo mismo en obtener el primer elemento de la colección que el último o que otro cualquiera. Es decir, que da igual que la lista tenga 10 o 10.000 elementos: el tiempo que tardas en obtener una referencia a cualquiera de ellos es el mismo. ¡Lo cual es estupendo!

Sin embargo si coges otro tipo de lista (por ejemplo un SortedList) y ves alguno de sus métodos para manipular elementos (por ejemplo RemoveAt) verás que la documentación te dice que es una operación 0(n). En este caso, aunque no lo indica, 'n' se refiere al número total de elementos de la lista. Esto quiere decir que el esfuerzo algorítmico -que luego se traduce en tiempo- para eliminar un elemento de la lista es una proporción lineal directamente proporcional al número de elementos de la lista. Es decir, que cuanto más al final de la lista esté el elemento más cuesta obtenerlo.

Si nos encontraramos algún algoritmo que indicara que es, por ejemplo, 0(n^3), querría decir que el esfuerzo es exponencial (al cubo) al número de elementos.

Esto es muy importante a la hora de seleccioanr uno u otro algoritmo según la cantidad de elementos que deba procesar. En el caso de las listas que nos ocupa gracias a estas indicaciones sabemos que si vamos a manejar una colección con muchos elementos será mejor utilizar un ArrayList que una SortedList, ya que cualquier acceso a los elementos para su procesamiento nos costará mucho más en el segundo caso que en el primero.

Espero que a otras personas les pueda resultar útil.

Por: José Manuel Alarcon | Saturday, December 12, 2009 7:28:30 PM (Hora estándar romance, UTC+01:00)  #    Comments [3] - Trackback
Tags: Programación


Sígueme en:

:: Twitter JM Alarcón: tecnología, marketing, este blog y frikadas varias
:: Twitter campusMVP: los mejores recursos sobre tecnología Microsoft: trucos, artículos, noticias, vídeos...
:: Facebook campusMVP: los mismos mejores recursos pero en directamente en Facebook.
:: Boletín campusMVP Nuestra publicación electrónica, una vez al mes en tu buzón de correo.
 
Banner

Este fin de semana largo que tenemos en España he aprovechado para releer el clásico de la literatura del Open Source, "The cathedral and the bazaar" (PDF, 145KB) de Eric S. Raymond. Este ensayo -cuya primera versión data de 1997- se convirtió enseguida en una pieza de referencia para el movimiento Open Source ya que en él Eric analizaba las diferencias existentes entre el desarrollo tradicional de software en las grandes empresas, a las que comparaba con una catedral, con el desarrollo de aplicaciones Open Source a través de Internet con voluntarios, que comparaba con un bazar. Lo que lo inspiró a escribirlo fue la tremenda efectividad del desarrollo de Linux a principios de los años 90, que luego puso en marcha él mismo con el desarrollo de su conocido servidor de correo Fetchmail. En los últimos años Eric ha tenido sonadas disputas con el Free sSoftware Foundation y en especial con el grillado de Richard Stallman.

Por si alguien lo dudaba las "catedrales" son empresas como Microsoft (especialmente) y otros gigantes, que tienen una política de ocultar el código incluso internamente,  mientras que los "bazares", donde hay mucho ruido y confusión pero se hacen muchos tratos todo el tiempo, son los grandes proyectos Open Source como los mencionados.

He decidido resumir aquí los puntos principales del documento (y traducirlos) tal cual él los expone, con algún comentario propio, por si le pueden servir a alguien y para tenerlos yo mismo resumidos para futura referencia. Espero que te gusten y te resulten útiles.

Ahora bien, aunque coincido con muchas de las cosas que dice Eric en su artículo, pienso que muchas de sus premisas no son aplicables en proyectos comerciales y menos en empresas pequeñas. Además estoy convencido de que Microsoft y otras grandes empresas han aprendido mucho del Open Source y, aparte de tener muchos proyectos OS propios, han modificado sus técnicas de trabajo y han abierto mucho sus productos y el código para ser más ágiles. ¿El mercado les ha obligado? Seguro, pero eso no quita que sea así.

-----
LA CATEDRAL Y EL BAZAR - PUNTOS IMPORTANTES

  1. Todo buen trabajo de software comienza por rascar el "picor" de un buen programador ---> Motivación
  2. Los buenos programadores saben qué código escribir. Los grandes programadores saben qué código rescribir ---> Reutilización de código y no reinventar la rueda
  3. Planea tirar al menos una vez el trabajo. Lo harás de todos modos ---> Las cosas no salen bien a la primera generalmente
  4. Si tienes la actitud correcta, los problemas interesantes te encontrarán ---> La curiosidad es buena y te llevará a crear proyectos interesantes
  5. Cuando pierdes el interés en un programa, tu última obligación para con él es cedérselo a un sucesor competente ---> No tires el trabajo, dáselo a alguien que le interese y lo pueda seguir llevando
  6. Tratar a tus usuarios como co-desarrolladores es el camino con menos obstáculos hacia la mejora del código y la depuración efectiva ---> Involucra a otra gente en el desarrollo
  7. Libera pronto, libera a menudo y escucha a tus clientes ---> mejor liberar código que no sea perfecto muy a menudo que código muy probado de muy tarde en tarde (en un mundo donde los que lo reciben son programadores, claro)
  8. Dada una base suficientemente grande de beta-testers y co-desarrolladores, casi cualquier problema será determinado rápido y la solución será obvia para alguien ---> Esta la clásica teoría de que muchos ojos pueden ver cualquier error, lo cual ya he comentado en otras ocasiones que no me convence nada. Para muestra un botón, pero hay muchos ejemplos en el mundo Linux y OS engeneral. Está claro que cuatro ojos ven mejor que dos y así sucesivamente pero basar la calidad y seguridad del Open Source en que hay muchos ojos mirando es una falacia. Me gusta un corolario que sale de aquí, y que dice: "The total cost of maintaining a widely used program is typically 40 percent or more of the cost of developing it. Surprisingly this cost is strongly affected by the number of users. More users find more bugs". Está claro: cuánto más lo use la gente más errores van a aparecer.
  9. Es mejor tener estructuras de datos  bien pensadas y mal código que al revés ---> Piensa bien antes de desarrollar. serás más efectivo.
  10. Si tratas a tus beta-testers como si fueran tu recurso más valioso, responderán convirtiéndose en tu recurso más valioso ---> Esto lo lleva haciendo Microsoft muchos años aunque sin cóigo fuente la mayor parte de las veces.
  11. Lo segundo mejor después de tener buenas ideas es reconocer las buenas ideas de tus usuarios. A veces esto último es incluso mejor ---> No comments.
  12. A menudo las soluciones más impactantes e innovadoras vienen al darte cuenta de que tu concepto del problema estaba equivocado ---> Rectificar es de sabios.
  13. La perfección (en diseño) se consigue no cuando no hay nada más que añadir, sino más bien cuando ya no hay nada más que quitar ---> Totalmente de acuerdo. Es el principio KISS.
  14. Una herramienta debe ser útil en el modo esperado, pero una herramienta realmente buena suele dar usos que nunca habías esperado.
  15. Cuando escribas software de pasarela del tipo que sea, esfuérzate por entorpecer el flujo de datos lo menos posible, y nunca deseches ninguna información a menos que el destinatario te fuerce a ello ---> De esto poco tengo que decir, está relacionado con su programa de e-mail, y como dice un amiguete: "Cuando tienes un martillo todo te parecen clavos" ;-)
  16. Cuando tu lenguaje no es ni de lejos Turing-completo, el azucar sintáctico puede ser tu amigo ---> vamos que justifica la exitencia de construcciones en los lenguajes que faciliten el trabajo.
  17. Un sistema de seguridad es sólo tan seguro como sus secretos. Ten cuidado con los pseudo-secretos ---> con esto estoy totalmente de acuerdo: no bases la seguridad de tus sistemas en la ofuscación o el que no se conozca tus algoritmos. Esto es ley en programación.
  18. Para resolver un problema interesante, comienza por buscar un problema que te interese ---> nuevamente la cuestión de la motivación y que los grandes programadores suelen trabajar en cosas que les interesan y motivan. Muy bonito y está bien participar en ello en un proyecto Open Source, pero en la cruda realidad hay que comer y el trabajo no siempre es tan interesante o motivador. De esta parte me gusta un párrafo en el que compara la catedral y el bazar con las leyes físicas Newtonianas y de la relatividad especial respectivamente, y dice: "This resembles the relationship between Newtonian and Einsteinian physics-the older system is still valid at low energies, but if you push mass and velocity high enough you get surprises like nuclear explosions or Linux."
  19. Partiendo de la base de que el coordinador del desarrollo (Open Source) tiene a su disposición un medio de comunicación al menos tan bueno como Internet y que sabe como dirigir sin coerción, muchas cabezas son inevitablemente mejores que una sola ---> Amén.

-----

El ensayo es todo un clásico y, a pesar de lo que pueda parecer por mi resumen, es bastante interesante y cualquier programador debería leerlo, sobre todo si debe coordinar equipos de desarrolladores. Eric tiene otros ensayos interesantes sobre Open Source que quizá comente en otra ocasión.

En fin, cada uno que saque sus conclusiones...

Por: José Manuel Alarcon | Monday, December 07, 2009 1:21:51 PM (Hora estándar romance, UTC+01:00)  #    Comments [0] - Trackback
Tags: Artículos


Sígueme en:

:: Twitter JM Alarcón: tecnología, marketing, este blog y frikadas varias
:: Twitter campusMVP: los mejores recursos sobre tecnología Microsoft: trucos, artículos, noticias, vídeos...
:: Facebook campusMVP: los mismos mejores recursos pero en directamente en Facebook.
:: Boletín campusMVP Nuestra publicación electrónica, una vez al mes en tu buzón de correo.
 
Banner

En mi anterior post hablé sobre el concepto de clausuras en Java_Script (JS a partir de ahora), y de cómo les podíamos sacar partido en programación avanzada en este lenguaje. En esta ocasión voy a rematar aquello comentando la existencia de auto-clausuras, un concepto muy interesante al que se le puede sacar partido para conseguir algo a priori imposible en este lenguaje: miembros privados en clases JS.

En JS podemos definir una clase de la manera convencional, tratando al mismo tiempo de encapsular el acceso a las variables privadas simulando la existencia de propiedades con funciones 'get' y 'set', por ejemplo así:

function coche() {
  var modelo = "NINGUNO";
  this.getModelo = function () {
    return modelo;
  };
  this.setModelo = function (sModelo) {
    modelo = sModelo.toUpperCase();
  };
}

var miCoche = new coche;
miCoche.setModelo("Ferrari");
alert(miCoche.getModelo());  //Muestra FERRARI

En este caso hemos definido una clase coche que tiene un miembro interno llamado modelo. Para intentar encapsular el acceso a este miembro y poder tener control sobre lo que se hace (que no sea una lectura o escritura directas, vamos) hemos definido dos funciones -que son clausuras- que harán las veces de los métodos getter y setter de una propiedad. De este modo para leer el valor del miembro "privado" usamos getModelo, y para escribirlo setModelo, que en este caso además se ocupa de que el nombre del modelo siempre vaya en letras mayúsculas (por poner un ejemplo de regla de negocio simple y no despistarnos del verdadero objetivo del ejemplo).

Así, si el programador usa estos dos métodos para leer y escribir los miembros privados, como en el ejemplo anterior, todo irá bien. Lo que ocurre es que nadie impide al programador ir directamente a la variable supuestamente privada y hacer esto:

miCoche.modelo = "Ferrari";
alert(miCoche.modelo);  //Muestra Ferrari en minúsculas

Con lo cual todo nuestro esfuerzo no vale absolutamente de nada.

Es posible hacer esto porque en realidad en las clases de JS no existen los miembros privados, ya que no hay modificadores de ámbito (public o private, por ejemplo) que nos permitan controlarlo.

¿Cómo podemos solucionar esto gracias a las clausuras?

Antes de continuar vamos a considerar un ejemplo de código muy sencillo como el siguiente:

  (function (){
    var interno = "Valor Interno";
    alert(interno);
    }
  )();

En este ejemplo hemos definido una función que se llama a si misma, y por lo tanto sólo existe durante el instante en que se ejecuta. No queda rastro de ella una vez que se ejecuta. Sí, es raro y aparentemente no tiene utilidad alguna, pero ten un poco de paciencia.

Lo que estamos definiendo en el fragmento anterior es una función anónima y también una auto-clausura. Es una función que se define, se ejecuta, y luego desaparece sin que pueda volver a ser usada. En realidad no desaparece sino que al no haber una referencia a la misma en ningún lugar de nuestro código no tenemos forma de usarla de nuevo ni de acceder a sus miembros. O sea, en cuanto se ejecuta la variable interna deja de ser accesible en nuestro código pues no hay una referencia a la función en ningún lugar.

¿Qué pasaría si de algún modo pudiésemos definir una función como esta que desaparezca pero quedarnos con una refencia a algo que esté en su interior (una clausura interna de esta función efímera)? Pues pasaría que, de repente, tendríamos acceso a los miembros de esta función efímera pero sólo de manera indirecta, nunca directa como en el caso anterior ya que no tenemos ninuna variable que apunte a la propia función.

Este es el concepto que usaron por primera vez los chicos de Yahoo y que ha permitido definir clases con miembros privados en JS.

Vamos a verlo con un ejemplo práctico reproduciendo la clase anterior que representa a un coche, pero esta vez que sólo sea accesible a través de los métodos getter y setter que hayamos definido:

var coche = function() { 
  var modelo= "NINGUNO";
  return {
    getModelo : function () {
      return modelo;
    },
    setModelo : function (sModelo) {
      modelo = sModelo.toUpperCase();
    }
  };
}();

alert(coche.modelo);  //Undefined
alert(coche.getModelo()); //NINGUNO
coche.setModelo("Smart Fortwo");
alert(coche.getModelo()); //SMART FORTWO

Fíjate bien en este código como se define una función que se ejecuta inmediatamente poniéndole un (); al final (línea 11), y almacena el resultado de su ejecución en una variable llamada coche. El código interno de esta función define una variable modelo que al igual que antes contendrá el nombre del modelo de coche que estamos manejando. Además como resultado de ejecutar la función se devuelve un nuevo objeto interno que tiene dos métodos que leen o fijan el valor de la variable interna. Como están dentro de la función son dos clausuras que tienen acceso a sus miembros (en este caso la variable modelo), pero como n queda referencia a la función, pues la estamos ejecutanod inmediatamente, entonces la única forma de acceso a la variable modelo que nos queda es a través de esas clausuras. ¡¡Lo que tenemos en la práctica es una variable privada!!. Algo imposible de conseguir a priori. Los alert del final del código anterior nos demuestran que así es. El primero de ellos intenta acceder a la variable modelo pero no puede, porque realmente tiene una refefencia a un objeto interno de la función, no a ésta, así que no puede y devuelve un valor "undefined" ya que no existe dicho miembro para el objeto coche. En las otras tres líneas usamos los métodos "legales" para acceder a la variable y todo funciona correctamente.

Instancias únicas de clase: Singleton

En la práctica ademas obtenemos una clase de instancia única (Singleton), ya que sólo existe una referencia a la misma y no es posible crear nuevas instancias. Esto es muy útil cuando estamos definiendo marcos de trabajo como el mencionado antes de Yahoo, y esta técnica ha sido usada desde entonces por otros frameworks como los mencionados en el post anterior.

Sin embargo nos impide crear clases con miembros privados y que podamos utilizar varias veces. Es decir, tal y como está el código anterior sólo podemos tener un único coche, no varios.

Si quitamos el doble paréntesis de antes (de la línea 11) que fuerza la ejecución, podemos trabajar con ella como si de una clase normal se tratara y seguimos teniendo acceso limitado a los miembros privados:

var Coche = function() { 
  var modelo= "Ninguno";
  return {
    getModelo : function () {
      return modelo;
    },
    setModelo : function (sModelo) {
      modelo = sModelo.toUpperCase();
    }
  };
};

var coche1= new Coche();
var coche2= new Coche();
alert(coche1.modelo);  //Undefined
coche1.setModelo("Porsche");
coche2.setModelo("Smart");
alert(coche1.getModelo()); //PORSCHE
alert(coche2.getModelo()); //SMART

Ahora creamos dos objetos de la clase Coche y les asignamos valores a través de su método setter. Si te fijas en la línea 15, intentamos acceder a su variable privada modelo sin éxito, pues se devuelve un indefinido, así que estamos consiguiendo en la práctica clases con miembros privados y que además podemos instanciar tantas veces como queramos.

Una vuelta de tuerca más al lenguaje de script más popular que tiene una gran utilidad práctica y que espero que te resulte útil :-)

Por: José Manuel Alarcon | Sunday, November 29, 2009 11:48:15 AM (Hora estándar romance, UTC+01:00)  #    Comments [2] - Trackback
Tags: JavaScript


Sígueme en:

:: Twitter JM Alarcón: tecnología, marketing, este blog y frikadas varias
:: Twitter campusMVP: los mejores recursos sobre tecnología Microsoft: trucos, artículos, noticias, vídeos...
:: Facebook campusMVP: los mismos mejores recursos pero en directamente en Facebook.
:: Boletín campusMVP Nuestra publicación electrónica, una vez al mes en tu buzón de correo.
 
Banner
Copyright © 2010 José Manuel Alarcón Aguín. All rights reserved.