martes, 18 de enero de 2011

Snippet Designer

En una entrada anterior, “Mis extensiones favoritas”, mencioné el complemento Snippet Designer , http://snippetdesigner.codeplex.com/. En este post, trataremos sobre cómo crear snippets con este plug-in y sobre cómo sacarle el máximo provecho.

Para instalarlo basta con ir al menú Herramientas > Administrador de extensiones… y localizarlo por ejemplo con la palabra snippet en el cuadro de búsqueda.

clip_image002

Para crear un snippet, tendremos que seleccionar el código en el editor de VS y en el menú contextual, seleccionar la opción “Export as Snippet”.

Para nuestro ejemplo crearemos un snippet que saluda al basto mundo que nos rodea… vale, es una chorrada, pero para ilustrar como crear un snippet y configurarlo es suficiente.

Nuestro código es el siguiente:

clip_image003

Así, nuestro siguiente paso será seleccionar el texto y pulsar “Export as Snippet” en el menú contextual.

clip_image004

Después de esto aparentemente no pasa nada y aún no está disponible nuestro snippet. Para terminar de completar la operación, tenemos que pulsar el menú Archivo > Nuevo > Archivo… y seleccionar un archivo de tipo “Code Snippet” en la categoría “Snippet Designer”.

clip_image006

Automáticamente se abrirá un nuevo archivo con el código que exportamos anteriormente.

clip_image008

Además, en cuanto a la configuración del snippet es muy importante la ventana propiedades que expone las principales características del snippet.

clip_image010

Antes de configurar el código de nuestro snippet (para que admite variables de reemplazo), configuraremos el snippet en lo relativo a la ventana de propiedades.

·        File Path muestra el fichero temporal donde se creó el snippet cuando pulsamos “Export as Snippet”.

·        Author y Description son informativos.

·        Help Url.

·        Imports es una colección de instrucciones Import que agregará el snippet.

·        Keywords es una lista de palabras clave para la posterior localización del snippet en la nueva ventana que incorpora el Snippet Designer.

·        References es una colección de referencias que agregará automáticamente el snippet.

·        Shorcut será el atajo por el que llamaremos a nuestro snippet. Es importante señalar que no debe contener espacios.

·        Snippet Kind. Puede ser MethodBody, MethodDecl, TypeDecl.

·        Snippet Type. Puede ser Expansion o SurroundsWith.

En nuestro ejemplo, hemos configurado nuestro snippet de saludo de la siguiente forma:

Author

Sergio León

Description

Saludo básico en Visual Basic

Help Url

http://panicoenlaxbox.blogspot.com

Imports

System.Web.UI.WebControls

Keywords

Saludo

References

System.Web

Shortcut

misaludo

Snippet Kind

MethodBody

Snippet Type

Expansion

 

Otra cosa a tener en cuenta es el que es necesario dar un nombre al snippet en la caja que aparecer en la parte superior del editor. Nosotros lo llamaremos miprimersnippet. De hecho, al guardar el documento, se propone este nombre como nombre del fichero .xml donde se va a guardar el snippet.

clip_image012

Pues bien, al pulsar Guardar habrá acabado nuestro trabajo y ya tendremos nuestro snippet disponible.

clip_image014

Como vemos nos informa que el acceso directo es “misaludo” (propiedad Shortcut), que su descripción es “Saludo básico en Visual Basic” (propiedad Description) y que el snippet se llama “miprimersnippet”

También podemos ver nuestro snippet recién creado en el menú Herramientas > Administrador de fragmentos de código

clip_image015

Como vemos, aquí también nos informa del tipo del snippet (propiedad Snippet Type, en nuestro caso Expansion) y del Autor (propiedad Author).

Además, el plug-in Snippet Designer ha agregado a VS una nueva ventana accesible desde el menú Ver > Otras ventanas > Snippet Explorer

clip_image016

Como vemos desde esta nueva ventana podemos buscar por las palabras clave que especificamos anteriormente (propiedad Keywords). Además de ver el código, también podemos abrir el snippet para editarlo de nuevo o bien eliminarlo.

Antes de continuar con la edición del snippet quisiera explicar la propiedad Snippet Type.

Snippet Type puede ser Expansion o SurroundWith. Surround significa rodear. De este modo, esta propiedad nos indica cómo se va insertar nuestro snippet en el código.  Expansion significa que nuestro snippet se insertará donde esté colocado el cursor, mientras que SurroundWith coloca el snippet alrededor de una parte de código seleccionada.

Si editamos el fichero .xml que guarda el snippet veremos que tiene el siguiente código que es bastante autoexplicativo.

<?xml version="1.0" encoding="utf-8"?>

<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">

  <CodeSnippet Format="1.0.0">

    <Header>

      <Keywords>

        <Keyword>Saludo</Keyword>

        <Keyword>Mundo</Keyword>

      </Keywords>

      <SnippetTypes>

        <SnippetType>Expansion</SnippetType>

      </SnippetTypes>

      <Title>miprimersnippet</Title>

      <Author>Sergio León</Author>

      <Description>Saludo básico en Visual Basic</Description>

      <HelpUrl>http://panicoenlaxbox.blogspot.com</HelpUrl>

      <Shortcut>misaludo</Shortcut>

    </Header>

    <Snippet>

      <References>

        <Reference>

          <Assembly>System.Web</Assembly>

        </Reference>

      </References>

      <Imports>

        <Import>

          <Namespace>System.Web.UI.WebControls</Namespace>

        </Import>

      </Imports>

      <Code Language="vb" Kind="method body"><![CDATA[        Dim saludo As String

        saludo = "Hola Mundo!"

        Console.WriteLine(saludo)

        Console.ReadLine()]]></Code>

    </Snippet>

  </CodeSnippet>

</CodeSnippets>

Una de las características que me maravilla de los snippets son las variables de reemplazo. Pues bien, ha llegado el momento de ver cómo crear estas variables con Snippet Designer.

Basta con escribir algo que tenga el formato $literal$ y se agregará automáticamente una variable de reemplazo. Yo por mi parte he cambiado los valores predeterminados que agrega automáticamente Snippet Designer (como Tooltip, Defaults to…) para ver cómo se comporta después en ejecución.

clip_image018

Ahora insertaremos de nuevo el snippet en nuestro módulo de código:

clip_image019

Como vemos ahora nuestro snippet es mejor y más utilizable y además la propiedad Tooltip y Defaults to han funcionado… bien!

Si volvemos a ver el fichero .xml ahora ha agregado la sección Declarations y ha cambiado la sección Code.

      <Declarations>

        <Literal Editable="true">

          <ID>tusaludo</ID>

          <ToolTip>Tu saludo</ToolTip>

          <Default>Tu saludo va aquí</Default>

          <Function>

          </Function>

        </Literal>

      </Declarations>

      <Code Language="vb" Kind="method body"><![CDATA[        Dim saludo As String

        saludo = "$tusaludo$"

        Console.WriteLine(saludo)

        Console.ReadLine()]]></Code>

Si quieres el manual oficial del complemento, aunque el mío es mejor, te aviso ;-), está en este dirección http://snippetdesigner.codeplex.com/wikipage?title=createFromScratch&referringTitle=Documentation

Un saludo y a snipear se ha dicho!.

lunes, 10 de enero de 2011

Borrar todos los índices del asistente de optimización de base de datos de Sql Server

Si eres como yo y utilizas el asistente para optimización de base de datos de Sql Server sin mucho criterio (ya sé que tengo que mejorar pero a veces la prisa apremia), te paso este script que deja la base de datos limpia de esos índices que a veces se descontrolan y ocupan más de lo necesario.

DECLARE @stmt NVARCHAR(4000)

DECLARE c_dta_index CURSOR

READ_ONLY

FOR

       SELECT 

                    OBJECT_NAME(i.object_id) AS tableName,

                    i.name AS indexName

       FROM    sys.indexes AS i

                    INNER JOIN sys.partitions AS p ON i.object_id = p.object_id AND i.index_id = p.index_id

                    INNER JOIN sys.allocation_units AS a ON p.partition_id = a.container_id

       WHERE   i.name LIKE '[_]dta[_]%'

OPEN c_dta_index

DECLARE @tableName NVARCHAR(4000)

DECLARE @indexName NVARCHAR(4000)

FETCH NEXT FROM c_dta_index INTO @tableName, @indexName

WHILE (@@fetch_status <> -1)

BEGIN

       IF (@@fetch_status <> -2)

       BEGIN

             SET @stmt = 'DROP INDEX ' + @tableName + '.' + @indexName

             EXECUTE(@stmt)

       END

       FETCH NEXT FROM c_dta_index INTO @tableName, @indexName

END

CLOSE c_dta_index

DEALLOCATE c_dta_index

Un saludo!

lunes, 3 de enero de 2011

POO en Javascript con ASP.NET AJAX

En anteriores post, POO en Javacript I, II y III, expusimos los principios de la programación orientada a objetos en Javascript y además también vimos como ASP.NET AJAX nos proporciona un marco de trabajo que extiende la funcionalidad de Javascript, tanto en sus objetos básicos como a través de un conjunto de librerías que nos proporcionan funcionalidades avanzadas. Ahora ha llegado el momento de dar el salto a la POO en Javascript ayudándonos de ASP.NET AJAX y sus extensiones.

En nuestro primero ejemplo registraremos un espacio de nombres, después crearemos un clase y finalmente registraremos la clase en el espacio de nombres creado.

            //Registrar espacios de nombres.

            Type.registerNamespace("Alimentos.Frutas");

 

            //Constructor de la clase Tropical.

            Alimentos.Frutas.Tropical = function (color) {

                //Por convención, las propiedades y métodos que comiencen con _ son privados.

                this._color = color;

            };

 

            //Definición de la clase Tropical.

            Alimentos.Frutas.Tropical.prototype = {

                getColor: function () {

                    return this._color;

                },

                setColor: function (color) {

                    this._color = color

                },

                toString: function () {

                    return "color: " + this.getColor();

                }

            };

 

            //Registrar la clase Tropical.            Alimentos.Frutas.Tropical.registerClass("Alimentos.Frutas.Tropical");

 

            var kiwi = new Alimentos.Frutas.Tropical("verde");

            alert(kiwi.getColor()); //verde

            alert(kiwi.toString()); //color: verde

 

clip_image001

Un siguiente ejemplo tratará sobre clases base y clases hija y sobre como ASP.NET AJAX nos ayuda en este concepto.

            //Registrar espacios de nombres.

            Type.registerNamespace("Alimentos.Frutas");

 

            //Constructor de la clase Tropical.

            Alimentos.Frutas.Tropical = function (color) {

                //Por convención, las propiedades y métodos que comiencen con _ son privados.

                this._color = color;

            };

 

            //Definición de la clase Tropical.

            Alimentos.Frutas.Tropical.prototype = {

                getColor: function () {

                    return this._color;

                },

                setColor: function (color) {

                    this._color = color;

                },

                toString: function () {

                    return "color: " + this.getColor();

                }

            };

 

            //Registrar la clase Tropical.            Alimentos.Frutas.Tropical.registerClass("Alimentos.Frutas.Tropical");

 

            //Constructor de clase Mango.

            Alimentos.Frutas.Mango = function (color, estado) {

                //En la clase hija se llama al método initializeBase.

                Alimentos.Frutas.Mango.initializeBase(this, [color]);

                this._estado = estado;

            }

 

            //Definición de clase Mango.

            Alimentos.Frutas.Mango.prototype = {

                getEstado: function () {

                    return this._estado;

                },

                setEstado: function (estado) {

                    this._estado = estado;

                },

                toString: function () {

                    //Desde una clase hija se llama a métodos de la clase base con el método callBaseMethod.

                    return Alimentos.Frutas.Mango.callBaseMethod(this, 'toString') + ", estado: " + this.getEstado();

                }

            }

 

            //Registrar una clase hija, especificando la clase base.            Alimentos.Frutas.Mango.registerClass("Alimentos.Frutas.Mango", Alimentos.Frutas.Tropical);

 

            var mango = new Alimentos.Frutas.Mango("verde", "bien");

            alert(mango.getColor()); //llamada a un método heredado, verde.

            alert(mango.getEstado()); //bien.           

            alert(mango.toString()); //color: verde, estado: bien.

 

Por último, algo que utilizo muchísimo en VB.NET y que echo en falta en Javascript son las enumeraciones.

            //Registrar espacios de nombres.

            Type.registerNamespace("Alimentos.Frutas");

 

            //Constructor de la clase Tropical.

            Alimentos.Frutas.Tropical = function (color) {

                //Por convención, las propiedades y métodos que comiencen con _ son privados.

                this._color = color;

            };

 

            //Definición de la clase Tropical.

            Alimentos.Frutas.Tropical.prototype = {

                getColor: function () {

                    return this._color;

                },

                setColor: function (color) {

                    this._color = color;

                },

                toString: function () {

                    return "color: " + this.getColor();

                }

            };

 

            //Registrar la clase Tropical.            Alimentos.Frutas.Tropical.registerClass("Alimentos.Frutas.Tropical");

 

            //Enumeración.

            Alimentos.Frutas.Estado = function () { };

            Alimentos.Frutas.Estado.prototype = {

                Bien: 1,

                Mal: 2,

                Regular: 3

            };

 

            //Registrar enumeración.            Alimentos.Frutas.Estado.registerEnum("Alimentos.Frutas.Estado");

 

            //Constructor de clase Mango.

            Alimentos.Frutas.Mango = function (color, estado) {

                //En la clase hija se llama al método initializeBase.

                Alimentos.Frutas.Mango.initializeBase(this, [color]);

                this._estado = estado;

            }

 

            //Definición de clase Mango.

            Alimentos.Frutas.Mango.prototype = {

                getEstado: function () {

                    return this._estado;

                },

                setEstado: function (estado) {

                    this._estado = estado;

                },

                toString: function () {

                    //Desde una clase hija se llama a métodos de la clase base con el método callBaseMethod.

                    var text = Alimentos.Frutas.Mango.callBaseMethod(this, 'toString') + ", estado: ";

                    switch (this.getEstado()) {

                        case Alimentos.Frutas.Estado.Bien:

                            text += "bien.";

                            break;

                        case Alimentos.Frutas.Estado.Mal:

                            text += "mal.";

                            break;

                        case Alimentos.Frutas.Estado.Regular:

                            text += "regular.";

                            break;

                    }

                    return text;

                }

            }

 

            //Registrar una clase hija, especificando la clase base.

            Alimentos.Frutas.Mango.registerClass("Alimentos.Frutas.Mango", Alimentos.Frutas.Tropical);

 

            var mango = new Alimentos.Frutas.Mango("verde", Alimentos.Frutas.Estado.Regular);

            alert(mango.toString()); //color: verde, estado: regular.

 

Como vemos, ya no hay excusa para no mantener organizados nuestras clase Javascript y para hacer un buen uso de POO de Javascript en el cliente.

Un saludo!