Friday, November 30, 2007

y LinQ?...

Hola de nuevo.

Esta ves demos cabida a un tema que me llama mucho la atención, y ha de ser del gusto de muchos porque es una nueva herramienta sobre el tapete, para consultar y manipular información, pero no al estilo SQL, no señores, un estilo más c#, con muchas características interesantes que quiero describir en breve:

  • Dicen por ahi que LinQ, es el lenguaje de consultas integrado para el Framework de .NET. Es un conjunto de extensiones de C# y VB.NET, con un modelo de programación unificado que extiende el Framework de .NET para ofrecer consulta integrada de objetos, bases de datos, y XML.
  • Cualquier colección que soporte la interfaz System.Collections.Generic.IEnumerable, o la interfaz genérica IEnumerable<T>, es considerada una secuencia y puede ser operada utilizando los nuevos operadores de consulta de LINQ.
  • Vale la pena mencionar la característica de inferencia de tipos, entre lo nuevo de C#, ya que le permite a las variables locales ser automáticamente tipadas por su expresión de inicialización.

Y viendo código en acción, simplemente creen un proyecto de consola y escriban lo siguiente, para que ejecuten su primer ejemplo utilizando LINQ, sobre colecciones en memoria.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LinQ1
{
  class Program
  {
    static void Main(string[] args)
   { 
     NumQuery(); 
   }
   static void NumQuery()
   {
   var numbers = new int[] { 1, 4, 9,  16,25, 36 };
   var evenNumbers = from p in numbers where (p % 2) == 0  select p; Console.WriteLine("Result:");
    foreach (var val in evenNumbers)
      Console.WriteLine(val);
   }
  }
}

Si notaron el uso de la expresión var, aqui es donde el compilador de C# hace inferencia, y determina el tipo de dato correcto sobre la variable. Cabe notar también como la expresión foreach ha sido extendida para utilizar la inferencia de tipos también.

Por ahora esto es solo el inicio, ya iremos viendo cosas mucho más sofisticadas y entendiendo otros temas importantes alrededor de LINQ.

Feliz consulta!!

Monday, November 12, 2007

Eventos Noviembre 8, 9 y 10 de 2007

Hola de nuevo.

En esta entrada quiero dedicar un poco a los eventos de Office System 2007 y metodologia para desarrollo de aplicaciones, que tuve el placer de dictar en Barranquilla y Popayán.
Comencemos por Barranquilla, ciudad calurosa para alguien que ya lleva 2 años en Bogotá, con un calor humano estupendo, gente linda que te recibe sin prevenciones y te hacen sentir como en casa. Estuve exactamente en un evento de la Coporación Universitaria de la Costa, rodeado de estudiantes y expositores de talla internacional. Estos personajes tocaron temas de alta investigación, que me hicieron regresar a tiempos atras cuando estudiaba ingeniería física. Pero entre todo esto, yo entré con una charla de solo 30 minutos sobre programación para Office System 2007. Creo que la gente se llevó lo que iban buscando, ya que el auditorio estaba lleno, a la expectativa del representante de Microsoft. En fin un dia sensacional en el Hotel Dann Carlton, girando al rededor del hermozo mar y el impresionante rio Magdalena. Un abrazo hermanos barranquilleros y ojala pueda volver por allá.

DSC00163
Antes del suculento pescado en salsa de coco y camarones!!

Con pocas horas de sueño, partí hacía mi linda Popayán, donde me esperaban en el Colegio Mayor, con la charla sobre metodologías para deasrrollo de software. Sin palabras, auditorio lleno, y gente muy entusiasmada por escuchar unos cuantos tips e ideas nuevas que les permitan seguir adelante, desarrollandose en sus carreras. Un abrazo a todos los que me recibieron tan amablemente, Mr JD/C gracias Totales!!

Mis hermanos, amigos, en fin super heroes de la Célula UNICAUCA.NET, un recibiemiento como ningun otro. Que nostálgia pero que alegria, saber que dejé ese camino abierto que han continuado abriendo alrededor de la tecnología .NET. Pero más que tecnología se siente un gran calor humano, aunque bastante frio mi Popayán, todo estuvo de maravilla. Gracias por la pizza muchachos. Al dia siguiente una maratón de programación sin muchos ganadores, pero nuevamente viendo gente comprometida, y unos super premios que no pudieron ser entregados por falta de ganadores, pero para la próxima muchachos. A ver si no ponen ejercicios tan díficiles, jejeje, no mentira!!

DSC00217
Hablando de Office System 2007

En fin, una maratón de eventos, sensacional, donde creo todos quedaron satisfechos, y ojala podamos seguir unidos alrededor de la tecnología .NET, un abrazo a todos!!

DSC00233
De izquierda a derecha, heroés de .NET!!

Solo me resta decirle a INETA y a Microsoft gracias por esta oportunidad, y ojala sigamos difundiendo la tecnología .NET para que el nuevo año sea lleno de satisfacciones. Nilda, Sergio, Zulma, muchas gracias!!

Sunday, October 28, 2007

Más y más novedades

Comenzaré por indicarles los sitios específicos para acceder a todo lo referente con Silverlight 1.0 y 1.1. Descargas, ejemplos, y más recursos para acomodarse en primera fila, y poder aprender una tecnología que muy pronto estaré compitiendo fuertemente con el ya conocido Flash y demás engendros!!
http://www.microsoft.com/silverlight/halo3.aspx
http://weblogs.asp.net/scottgu/
http://silverlight.net/
http://silverlight.net/learn/learnvideos.aspx
Ayuda intellisense para Silverlight aqui:
http://weblogs.asp.net/scottgu/archive/2007/08/01/vs-2008-javascript-intellisense-for-silverlight.aspx
Y si quiere un alfa de Silverlight 1.1 para trabajrlo desde VS.NET
http://silverlight.net/getstarted/

El señor Miguel de Icaza y Su Moonlight, el Silverlight para Linux, mmm.
http://mono-project.com/Moonlight
Yo le sugeriria a los de Mono que primero organicen mejor esta página.

Y esto si para comprar palomitas. Microsoft libera el Service Pack I de Microsoft .NET Micro Framework SDX 2.0, para todo lo referente con Hardware Miniatura, ofreciendo las siguientes características:

  • Integración con VS
  • Librerias y drivers de código manejado
  • Emulador extensible
  • Protecciónde memoria flash
  • Herramienta de gestión de la memoeria flash
  • Herramienta de generación de fuentes

Para mayor información:
http://www.microsoft.com/downloads/details.aspx?FamilyID=32f5df20-6c95-4fe8-a76c-0ed56a839ad2&DisplayLang=en

Friday, October 19, 2007

ListBox Multiselect

Hola de nuevo

Hace unos dias, adicioné un control ListBox a una de mis páginas. El control debería utilizar la propiedad SelectionMode = Multiple, permitiendome seleccionar varias opciones del control.  Para mi sorpresa, cuando intentaba hacer esto, y en mi código detectar las opciones seleccionadas, sencillamente solo me retornaba como seleccionada, la primera opción.
Supongamos que cargo mi control en el primer postback de este modo:

if

(!Page.IsPostBack)
{
  ListBox1.Items.Add(
new ListItem("Rock and Roll","1"));
  ListBox1.Items.Add(
new ListItem("Country","1"));
  ListBox1.Items.Add(
new ListItem("Salsa", "1"));
}

Diganme que notan algo peculiar, porque a mí me tomó medio dia darme cuenta del causante de este problema. Si señores, el código asociado a cada opción es el mismo, ese es el "problema". No es cuestión de fijarle AutoPostback=true al control, como sugieren algunos foros, no es fijar la propiedad SmartNavigation=true en VS.NET 2003, no es la forma de recorrer el control para saber qué opciones están seleccionadas, no señores, deben es evitar que el código se repita, y de este modo el problema desaparace. Por ejemplo cuando tengan esto en un botón que me permita imprimir los items seleccionados, el programa debe funcionar sin ningun problema, y sin mostrar como seleccionada solo la primera opción de su listado.

foreach
(ListItem miItem in ListBox1.Items)
{
  if (miItem.Selected)
    Response.Write(miItem.Text);
}

Dos moralejas, primera hay foros alimentados por personas realmente perversas que terminan confundiendo a sus usuarios y segunda, a mí modo de ver aqui hay o un bug o algo que a mí parecer no debería tener este comportamiento.

Feliz solución!!

Saturday, October 13, 2007

Escribiendo buen código parte I

Hola de nuevo

En esta ocasión quiero comenzar con una serie de ejemplos que muestren cómo se debe escribir buen código en las aplicaciones. Es decir, tener en cuenta los recursos de la máquina en la que se van a ejecutar nuestras aplicaciones, ya que aunque hoy en dia el hardware nos favorece en gran medida nuestras metidas de pata con el software, en cualquier momento nuestras aplicaciones se van a ver seriamente afectadas en rendimiento, y por lo tanto llegar a causar errores o el serio aburrimiento de nuestros usuarios.

Utilizar propiedades en nuestras aplicaciones es mi primer recomendado:

1. No más variables públicas, no más métodos al estilo get y set.
2. Las propiedades son el mejor remedio para la encapsulación, si señores ellas exponen nuestros miembros de datos como parte de una interfaz pública.
3. Las propiedades nos permiten acceder nuestras variables y al mismo tiempo manipular su comportamiento, ya que las propiedades utilizan métodos.
4. Escribiendo propiedades tenemos acceso en un solo punto, para cambiar, o agregar funcionalidad según lo necesitemos. Por ejemplo, si decidimos que nuestro cliente no deberá aceptar nombres en blanco podemos hacer lo siguiente:

public class Customer
{
  private string _name;
  public string Name
  {
    get
    {
      return _name;
    }
    set
    {
      if (( value == null ) ||
        ( value.Length == 0 ))
        throw new ArgumentException( "Name cannot be blank",
          "Name" );
      _name = value;
    }
  }

  // ...
}

Con esto ya no tenemos el problema causado por las variables públicas, donde tendríamos que buscar en cada lugar de nuestro mar de código, donde esa variable se utilizó para hacer algo similar en muchas partes del código.

5. Adicionar manejo de hilos es mucho más sencillo, o si no que lo diga el ejemplo:

public string Name
{
  get
  {
    lock( this )
    {
      return _name;
    }
  }
  set
  {
    lock( this )
    {
      _name = value;
    }
  }
}

6. Ya que técnicamente las propiedades son métodos, estas heredan todas sus características, por ejemplo poder ser virtuales:
public class Customer
{
  private string _name;
  public virtual string Name
  {
    get
    {
      return _name;
    }
    set
    {
      _name = value;
    }
  }

  // remaining implementation omitted
}

Propiedades abstractas, o quiza ser parte de una definición de interfaces:

public interface INameValuePair
{
  object Name
  {
    get;
  }
  object Value
  {
    get;
    set;
  }
}

7. En C# 2.0 podemos establecer diferentes modificadores de acceso para los métodos get y set de nuestras propiedades. Por ejmplo, esto es válido:

// Legal C# 2.0:
public class Customer
{
  private string _name;
  public virtual string Name
  {
    get
    {
      return _name;
    }
    protected set
    {
      _name = value;
    }
  }

  // remaining implementation omitted
}

8. Igualmente el uso de indexadores en las propiedades es permitido, haciendo de esto algo muy poderoso:

public int this [ int index ]
{
  get
  {
    return _theValues [ index ] ;
  }
  set
  {
    _theValues[ index ] = value;
  }
}

// Accessing an indexer:
int val = MyObject[ i ];

9. La legibilidadd del código es una ventaja más, ya que accedemos a nuestros miembros de clases utilizando nombres significativos y fáciles de entender para asignar u obtener la data.
string name = customerOne.Name;
customerOne.Name = "This Company, Inc.";

Esto y otras consideraciones son muy importantes, y nos pueden ahorrar dolores de cabeza más adelante. Les queda de tarea analizar por ejemplo qué ocurre con el MSIL generado para nuestras propiedades. Y finalmente decilres que a nivel de desempeño, entre propiedades y métodos normales que accedan campos públicos, aunque estos últimos pudieran en algun momento dado ser más rápidos, la verdad es que el comportamiento inline de los métodos definidos para las propiedades, hace que el JIT o el compilador justo a tiempo del Framework, ponga a la par en rendimiento las diferentes técnicas. No olviden, los miembros deben ser privados y nuestras propiedades serán los puntos por los cuales accedemos y modificamos la información de dichos miembros.

Feliz buena práctica!!

Saturday, September 08, 2007

WPF Video

Es la 1:30 am, y el sueño ya no me venció. Así que decidí escribir esta entrada sobre WPF y una tonta comparación con GDI+.

Supongamos que quiero dibujar un cubo con algo de pintura en un windows form.

private void Form1_Paint(object sender, PaintEventArgs e)
{
GraphicsPath miPath = new GraphicsPath();LinearGradientBrush miBrochaGradiente = new LinearGradientBrush(new Rectangle(20, 20, 200, 150),Color.Blue,Color.Black,LinearGradientMode.ForwardDiagonal);Graphics miGrafico = this.CreateGraphics();//Iniciar una figuramiPath.StartFigure();miPath.AddRectangle(new Rectangle(20, 20, 200, 150));miGrafico.FillRectangle(miBrochaGradiente,20,20,200,150);miPath.AddRectangle(new Rectangle(50, 50, 200, 150));miPath.AddLine(20, 20, 50, 50);miPath.StartFigure();miPath.AddLine(220, 20, 250, 50);miPath.StartFigure();miPath.AddLine(220, 170, 250, 200);miPath.StartFigure();miPath.AddLine(20, 170, 50, 200);//Dibujando el pathPen miLapiz = new Pen(Color.Red, 3);miGrafico.DrawPath(miLapiz, miPath);miPath.Dispose();miLapiz.Dispose();miBrochaGradiente.Dispose();
}


Sencillo cierto? un path, que me permite construir una figura a partir de figuras primitivas, las cuales pueden ser: líneas, arcos, rectángulos, elipses, polígonos, y cuantas más figuras se les puedan ocurrir como clases trae el framework para esto. Bien la cosa es que todo esto forma una sola entidad, y en mi sencillo ejemplo, es cuestión de rectángulos y líneas. Oh claro no olviden hacerle Dispose a cada una de sus instancias gráficas, en este caso al objeto que permite hacer el dibujado sobre la forma (miGrafico), el objeto (miPath) quien representa los rectángulos y líneas, y los objetos encargados de ponerle color al asunto (miLapiz y miBrochaGradiente).
Bueno hasta este punto esto ya se pone aburridor y me comienza a dar sueño. Pero se me ocurre que puedo rotar mi cubo. Qué!! Rotar este cubo a estas horas de la madrugada, no señor, y con GDI+, esto no lo acepto. Y que tal si además de rotarlo, en cada una de sus caras muestro un video. Pues yo creo que esto es una pesadilla. Pues no señores es aquí cuando WPF (Windows presentation foundation) llega al rescate.
Dejando la tontería atrás quiero mostrarles como se puede lograr esto. Qué necesitan? Framework 3.0 o 3.5 y de ahí en adelante mucha pero mucha creatividad. Aquí va y que tengan lindos sueños.

<Window
  x:Class="RichContent.Window1" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="RichContent">
  <Grid MouseLeftButtonDown="Evento">
  <Viewport3D>
    <Viewport3D.Camera>
      <PerspectiveCamera
        FarPlaneDistance="20"
        LookDirection="0,-0.65,-1"
        UpDirection="0,1,0"
        NearPlaneDistance="1"
        Position="0,2,3" FieldOfView="40" x:Name="Camara" />
    </Viewport3D.Camera>
    <ModelVisual3D>
      <ModelVisual3D.Content>
        <Model3DGroup>
          <AmbientLight Color="White" />
          <GeometryModel3D>
            <GeometryModel3D.Geometry>
              <MeshGeometry3D
              TriangleIndices="0,1,2 3,4,5 6,7,8 9,10,11 12,13,14 15,16,17 18,19,20 21,22,23 24,25,26 27,28,29 30,31,32 33,34,35 "
              Normals="0,0,-1 0,0,-1 0,0,-1 0,0,-1 0,0,-1 0,0,-1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,-1,0 0,-1,0 0,-1,0 0,-1,0 0,-1,0 0,-1,0 1,0,0 1,0,0 1,0,0 1,0,0 1,0,0 1,0,0 0,1,0 0,1,0 0,1,0 0,1,0 0,1,0 0,1,0 -1,0,0 -1,0,0 -1,0,0 -1,0,0 -1,0,0 -1,0,0 "
              TextureCoordinates="1,1 1,0 0,0 0,0 0,1 1,1 0,1 1,1 1,0 1,0 0,0 0,1 0,1 1,1 1,0 1,0 0,0 0,1 1,1 1,0 0,0 0,0 0,1 1,1 1,0 0,0 0,1 0,1 1,1 1,0 0,0 0,1 1,1 1,1 1,0 0,0 "
              Positions="-0.5,-0.5,-0.5 -0.5,0.5,-0.5 0.5,0.5,-0.5 0.5,0.5,-0.5 0.5,-0.5,-0.5 -0.5,-0.5,-0.5 -0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5 -0.5,-0.5,-0.5 0.5,-0.5,-0.5 0.5,-0.5,0.5 0.5,-0.5,0.5 -0.5,-0.5,0.5 -0.5,-0.5,-0.5 0.5,-0.5,-0.5 0.5,0.5,-0.5 0.5,0.5,0.5 0.5,0.5,0.5 0.5,-0.5,0.5 0.5,-0.5,-0.5 0.5,0.5,-0.5 -0.5,0.5,-0.5 -0.5,0.5,0.5 -0.5,0.5,0.5 0.5,0.5,0.5 0.5,0.5,-0.5 -0.5,0.5,-0.5 -0.5,-0.5,-0.5 -0.5,-0.5,0.5 -0.5,-0.5,0.5 -0.5,0.5,0.5 -0.5,0.5,-0.5 "/>
            </GeometryModel3D.Geometry>
            <GeometryModel3D.Transform>
              <RotateTransform3D>
                <RotateTransform3D.Rotation>
                  <AxisAngleRotation3D
             x:Name="MyRotation3D" Angle="45" Axis="0 1 0"/>
                </RotateTransform3D.Rotation>
              </RotateTransform3D>
            </GeometryModel3D.Transform>
            <GeometryModel3D.Material>
              <DiffuseMaterial>
                <DiffuseMaterial.Brush>
                  <VisualBrush>
                    <VisualBrush.Visual>
                      <MediaElement LoadedBehavior="Play" UnloadedBehavior="Close" Source = "D:\Música\Radiohead\Radiohead live at Glastonbury 2003.avi" Name="Media" />
                    </VisualBrush.Visual>
                  </VisualBrush>
                </DiffuseMaterial.Brush>
              </DiffuseMaterial>
            </GeometryModel3D.Material>
          </GeometryModel3D>
        </Model3DGroup>
      </ModelVisual3D.Content>
    </ModelVisual3D>

    <Viewport3D.Triggers>
      <EventTrigger RoutedEvent="Viewport3D.Loaded">
        <EventTrigger.Actions>
          <BeginStoryboard>
            <Storyboard>
              <DoubleAnimation From="0" To="360" Duration="0:0:5"
              Storyboard.TargetName="MyRotation3D"
              Storyboard.TargetProperty="Angle" RepeatBehavior="Forever" Name="Animacion"/>
            </Storyboard>
          </BeginStoryboard>           
        </EventTrigger.Actions>
      </EventTrigger>
    </Viewport3D.Triggers>

  </Viewport3D>
    <Button HorizontalAlignment="Left" Margin="7,10,0,236" Name="button1" Width="58"  Click="Evento" >Button</Button>
    <TextBox Height="20" Margin="11,42,0,0" Name="textBox1"  VerticalAlignment="Top" HorizontalAlignment="Left" Width="20" TextChanged="Cambio"></TextBox>
    <TextBox Height="20" Margin="11,72,0,0" Name="textBox2" VerticalAlignment="Top" HorizontalAlignment="Left" Width="20" TextChanged="Cambio"></TextBox>
    <TextBox Height="20" Margin="11,102,0,0" Name="textBox3"  VerticalAlignment="Top" HorizontalAlignment="Left" Width="20" TextChanged="Cambio"></TextBox>
    <TextBox Height="20" Margin="11,132,0,0" Name="textBox4"  VerticalAlignment="Top" HorizontalAlignment="Left" Width="20" TextChanged="Cambio"></TextBox>
    <Slider Height="23" Margin="78,9,83,0" Name="slider1" VerticalAlignment="Top" Maximum="59" ValueChanged="Cambio" />
    <Label Height="24.2766666666667" HorizontalAlignment="Right" Margin="0,2.72333333333333,7,0" Name="label1" VerticalAlignment="Top" Width="72.63">Label</Label>
  </Grid>
</Window>



Lo anterior damas y caballeros, es el pequeño fragmento de código XAML que hace toda la tarea que yo quise hacer con GDI+. La verdad es para mí un fragmento de código muy corto, comparado con todo lo que esto hace por nosotros, clases muy potentes que nos proporcionan estos lujos.

Hay unos pocos controles que adicioné para controlar la rotación del cubo, lo cual es otra característica más, además de producir XAML (si créanme, producir, y a cargo de diseñadores gráficos), nosotros como desarrolladores C#, seguimos escribiendo nuestro code behind como veníamos haciéndolo. Y al ritmo de Radio Head aquí está:

// Sample event handler:
private void Evento(object sender, EventArgs e)
{
// Media.Source = new Uri("D:\\Música\\James Morrison - The Last Goodbye.mp3");
}

private void Cambio(object sender, EventArgs e)
{

if (textBox1.Text.Length > 0 && textBox2.Text.Length > 0 && textBox3.Text.Length > 0)
{
Vector3D miV3D = new Vector3D(Double.Parse(textBox1.Text), Double.Parse(textBox2.Text), Double.Parse(textBox3.Text)); MyRotation3D.Axis = miV3D; } if (textBox4.Text.Length > 0) MyRotation3D.Angle = Double.Parse(textBox4.Text); TimeSpan miTs = new TimeSpan(0,0,Convert.ToInt32(slider1.Value)); Duration miDuracion = new Duration(miTs); Animacion.Duration = miDuracion; label1.Content = miTs.Hours.ToString() + ":" + miTs.Minutes.ToString() + ":" + miTs.Seconds.ToString(); Camara.UpDirection = new Vector3D(0, 1, slider1.Value);
}
}

Bueno recueden, deberan apuntar a su propio video, tengo comentada la línea del manejador Evento(), porque ahí muestro cómo puedo cargar por ejemplo un archivo de audio. Claro señores, no solo de video vive el hombre.

Bueno solo dejo a su imaginación todo lo que puede llegar hacer con esto, no siendo más… WPF los mató a todos!!

La imaginación es más importante que el conocimiento
Albert Einstein

Saturday, September 01, 2007

The .NET Show: The Final Episode - Silverlight

Es tiempo de decirle adiós a una de las mejores iniciativas de Microsoft, en pro de los desarrolladores. Lastimosamente veo anunciado el episodio final del .NET Show, que lástima pero bueno sus razones tendrán.

http://blogs.msdn.com/theshow/archive/2007/08/14/the-net-show-the-final-episode-silverlight.aspx

Thursday, August 23, 2007

Digame Patrón

Hola de nuevo

Esta ves quiero regresar a bloguear con un tema que definitivamente es de mucha importancia para todos los que tratamos de desarrollar software. Todos ya nos conocemos el tema aquel de análizar, diseñar, construir, probar... Y en cada una de estas etapas, algunos consagrados y juiciosos personajes han encontrado soluciones generales a problemas bastante específicos. Soluciones que no están restringidas a ningún lenguaje, tecnología o herramienta. Si señores, son los patrones, que nos contextualizan, nos emprobleman, pero al final nos dan una solución.
Y espero de aqui en adelante, basado en el documento "Enterprise Solution Patterns Using Microsoft .NET v2.0" de lo señores de Patterns & Practices, regalarles algunos tips de lo que encuentro ahi como lo más relevante. Acerca de esto no se ha dicho la última palabra, pero los patrones aqui expuestos son la base filosofica y metafisica de miles de aplicaciones ejecutandose en el mundo, por qué? porque nos facilitan la vida, cuando esta se vuelve un ocho en aplicaciones de clase empresarial. No siendo más espero sea de su utilidad.

Patrones para soluciones empresariales utilizando Microsoft .NET

Lo primero es pensar en que todo sistema empresarial debe concebirse simple y crecerá con el tiempo. Esto radica en que cualquier cosa simple trabaja mientras necesite ser reemplazada. La idea es encontrar patrones que sirvan a lo simple y a lo complejo en tiempos distintos. No significa que un patrón lo haga mal y el otro lo haga correctamente, significa que cada patrón se acomoda a un momento dado del proyecto. Muchos objetos en .NET ya implementan varios patrones, así que la idea es utilizarlos y no implementar el patrón desde el principio.

La idea es presentar 32 patrones que expandan varios puntos de vista, y mostrar como pueden ser integrados en una aplicación empresarial. Visualizar los patrones como un lenguaje para expresar experiencias de diseño. Los patrones proporcionan un lenguaje común a arquitectos y desarrolladores para acortar la brecha entre las dos disciplinas.

Las soluciones de negocio de clase empresarial, son a menudo extremadamente complejas y deben ejecutarse bien frente a las altas expectativas. No solo deben ser altamente disponibles y escalables de cara a lo impredecible, sino también medibles y predecibles en respuesta a requerimientos de negocio que cambian rápidamente.

Los patrones son útiles para arquitectos y desarrolladores porque:
· Documentan mecanismos simples que trabajan
· Proveen un vocabulario y una taxonomía común para desarrolladores y arquitectos
· Habilitan a las soluciones para ser descritas como combinaciones de patrones.
· Habilitan el rehúso de arquitectura, diseño, e implementación de decisiones.

Mecanismo para documentar patrones

Un patrón describe un problema recurrente que ocurre en un contexto dado y, basado en un conjunto de lineamientos, recomienda una solución. La solución es usualmente un mecanismo simple, una colaboración entre dos o más clases, objetos, servicios, procesos, hilos, componentes, o nodos que trabajan juntos para resolver el problema identificado en el patrón.

Nota. Se debe aclarar que la implementación de los patrones puede volverse compleja, y lo mostrado aquí es solo para propósitos de introducción, así que mientras más se estudian los patrones en profundidad, se pueden observar aspectos más detallados y de mayor complejidad.

Patrón Singleton

Contexto. Controlar el acceso a una clase administrando su proceso de instanciación.

Problema. Una aplicación contiene un cierto tipo de data que necesita ser globalmente accedida y mantenida. Al mismo tiempo, este tipo de data es a menudo única en el sistema. Cómo proveer una interfaz accesible a una clase, pero controlar el número de instancias dentro del sistema.

Solución. La clase en si misma es responsable de crear una instancia simple y proveer acceso global a esa instancia. Crear una clase que contiene una instancia estática del Singleton que es retornada con un método estático.

public class MiSingleton
{
private static MiSingleton miInstancia = null
private MiSingleton() {}
public static MiSingleton ObtenerInstancia ()
{
if (miInstancia ==null)
{
miInstancia = new MiSingleton ()
}
return miInstancia
}
//... Funciones provistas por MiSingleton
}

El ejemplo anterior define un constructor privado, que hace que ninguna otra clase pueda instanciar a MiSingleton. La clase contiene una instancia estática miInstancia que es retornada con el método ObtenerInstancia().

Como se puede observar, el anterior es un ejemplo muy simple, pero que muestra la implementación esencial del patrón singleton, su objetivo y toda la utilidad que puede proveer dentro de nuestras aplicaciones. Es importante aclarar que los patrones no tienen una única solución o implementación, y están pensados para ser abiertos a cada tecnología.

Patrones en niveles diferentes

Los patrones existen en niveles diferentes de abstracción. Consideremos otro ejemplo, esta ves a un nivel más alto de abstracción que el nivel de codificación:

Estamos diseñando una aplicación basada en Web, que contiene una gran cantidad de lógica de negocio y de presentación. Cómo organizar este sistema a alto nivel para que sea flexible, débilmente acoplado, y aun así, altamente cohesivo?

Una solución a este problema involucra organizar el sistema dentro de una serie de capas, con cada capa conteniendo elementos aproximadamente en el mismo nivel de abstracción. Se identifican las dependencias en cada capa y decidir por una estrategia de capas estricta o relajada. Luego, se decide si se va a crear un esquema de capas personalizado o adoptar un esquema de capas previamente documentado por otros. Supongamos que vamos a usar una estrategia de capas bien conocida, una capa para presentación, para la lógica del negocio y para el acceso a datos.

Si siempre diseñamos sistemas de este modo, estamos empleando un patrón ya existente, independiente de cualquier patrón generalizado. Aún así, hay muchas razones por la que queramos entender los patrones que apoyan esta aproximación de diseño. Podemos ser curiosos y preguntarnos por qué los sistemas frecuentemente se diseñan de esta manera, podemos buscar aproximaciones más óptimas a los problemas que este patrón no resuelve.

Patrón Capas

Contexto. Estamos trabajando, con un sistema grande y complejo, y queremos administrar la complejidad por descomposición.

Problema. Cómo estructurar una aplicación para soportar tales requerimientos operacionales, como mantenibilidad, reusabilidad, extensibilidad, escalabilidad, robustez y seguridad?

Solución. Componer la solución dentro de un conjunto de capas. Cada capa debería ser cohesiva, y aproximadamente al mismo nivel de abstracción. Cada capa debería ser débilmente acoplada a las capas de abajo.

Esta simple estrategia, ayuda a organizar las aplicaciones para resolver dos desafíos en desarrollo de software: la administración de dependencias y la necesidad de componentes intercambiables. Construir aplicaciones sin una estrategia bien considerada para administración de dependencias, conlleva a componentes frágiles, los cuales son difíciles y costosos de mantener, extender y substituir.

Patrón de Aplicación de Tres capas

Contexto. Estamos construyendo una solución de negocio, usando capas para organizar nuestra aplicación.

Problema. Cómo organizar la aplicación para reutilizar lógica de negocio, proveer flexibilidad en el deployment, y conservar conexión a recursos valiosos.

Solución. Crear tres capas: presentación, lógica del negocio (dominio), y acceso a datos. Colocar todos los componentes responsables de la vista en la capa de presentación. Encapsular toda la lógica del negocio en componentes de la capa de dominio que implementan interfaces de componentes bien conocidas. Localice todo el código relacionado a la base de datos, incluyendo clientes de acceso a base de datos, y componentes de utilidad, en la capa de acceso a datos. La capa de datos es responsable por el pool de conexiones cuando acceda los recursos. Asegurarse de eliminar las dependencias entre componentes de acceso a datos, y componentes de la capa de negocio. Eliminar dependencias entre la capa de negocio y la capa de presentación o administrar las dependencias utilizando el patrón observador.

Refinamiento simple

Cabe notar que Aplicación de tres capas es realmente un refinamiento simple de Capas; el contexto, la importancia, y la solución identificada en Capas se mantiene aplicada en Aplicación de tres capas, pero no al contrario. Esto es, el patrón Capas restringe a Aplicación de tres capas, y el patrón Aplicación de tres capas refina el patrón Capas. Esta relación de patrones es útil para administrar la complejidad. Después de que entendamos un patrón, debemos solo entender las diferencias incrementales entre el patrón inicial y los patrones que lo refinan. Otro ejemplo, esta ves en el área de servicios web, debería ayudar a ilustrar el concepto de refinamiento.

Hemos escrito una aplicación para una empresa exitosa que se expande rápidamente. Ahora queremos extender la aplicación exponiendo su motor de lógica a socios de negocio e integrar los servicios adicionales de los socios (tales como compras) dentro de la aplicación. Cómo estructuramos nuestra aplicación de negocio para proveer y consumir servicios?

Una solución a este problema es extender el patrón Aplicación de tres capas adicionando responsabilidades relacionadas a servicios adicionales a cada capa. La capa de negocio adiciona la responsabilidad de proveer un conjunto simplificado de operaciones para aplicaciones clientes a través de Interfaces de Servicio. Las responsabilidades de la capa de acceso a datos van más allá de la base de datos e integran hosts para incluir comunicación con otros proveedores de servicios. Esta funcionalidad adicional en la capa de acceso a datos es encapsulada en componentes de Pasarelas de Servicios, los cuales son responsables por conectarse a servicios (tanto sincrónica como asincrónicamente), administrando el estado conversacional básico con el servicio, y notificando a los componentes de procesos de negocio de significativos eventos relacionados a servicios.

Patrón Servicios de tres capas

Contexto. Estamos construyendo una solución de negocio que usa capas de presentación, negocio y acceso a datos para organizar la aplicación. Queremos exponer algo de la funcionalidad central de la organización como servicios que otras aplicaciones puedan consumir y habilitar la aplicación para consumir otros servicios.

Problema. Cómo organizar nuestra aplicación para proveer y consumir datos granulares y elementos lógicos de fuentes altamente variables?

Solución. Descomponer la lógica de la aplicación dentro de un conjunto de servicios colaborativos que proveen partes de la funcionalidad completa del sistema. Luego, en la capa de dominio, identificar una Interfaz de Servicios por cada servicio que es independiente de la implementación subyacente. Finalmente, extender la capa de acceso a datos para utilizar Pasarelas de Servicio, para comunicarse con otros proveedores de servicio. Si la lógica de navegación de la aplicación es suficientemente compleja, consideremos usar componentes de proceso de interfaz de usuario como parte de la capa de presentación para encapsular y reutilizar esta lógica.

Es notoria la relación entre estos patrones. Capas introduce una estrategia fundamental para organizar una aplicación de software. Aplicación de tres capas refina esta idea y la restringe a los sistemas de negocio que requieren reutilizar lógica de negocio, flexibilizar el deployment, y uso eficiente de conexiones. Aplicación de servicios de tres capas refina a Aplicación de tres capas y extiende el diseño para proveer y consumir elementos granulares de datos y lógica de fuentes altamente variables.

Bien para terminar, ya iremos desarrollando algo práctico de todo esto, pero es muy importante iniciarse en la teoría y familiarizarse con la forma de documentar patrones, que realmente no es tan complicado, y tal ves tú, si tú, puedas encontrar nuevos patrones o refinar los existentes.

Feliz arquitectura

Wednesday, July 04, 2007

Excel AddIn con C# y VSTO

Hola de nuevo

Retomando uno de los temas que más me gusta, aqui les traigo un ejemplo bastante sencillo acerca de cómo crear addins de Excel 2007, utilizando VSTOs con C#.

Lo primero es adicionar un nuevo proyecto y seleccionar el template adecuado como le sindico en la siguiente imagen:

Luego de esto, VS crea para nosotros un proyecto de tipo AddIn de Excel, un proyecto de setup y toda una infraestructura de métodos, eventos y objetos, listos para comenzar a trabajar en el desarrollo.


Ahora, sobre el proyecto de AddIn, damos clic derecho y seleccionamos Add - New Item... y seleccionamos la opción Ribbon suport:Esto de ribbon es un nuevo concepto, introducido en Office 2007, digamos para ordenar las funcionalidades en diferentes pestañas, las cuales hacen parte del Ribbon que es la combinación de las barras de herramientas y el menú, que antes lo veiamos como una fila de botones.

Ahora bien, las clases sobre las que vamos a trabajar son las creadas por VS para nosotros: ThisAddIn.cs y Ribbon1.cs.

En la primera se encuentran los eventos ThisAddIn_Startup y ThisAddIn_Shutdown, los cuales son los puntos inicial y final del AddIn. Pero por ahora no los vamos a tocar, más bien creamos un nuevo método que sera el que preste la funcionalidad:


public void TestExcelRanges()
{
Excel.Range miRango = null;
Excel.Worksheet miSheet = null;
miSheet = this.Application.ActiveSheet as Excel.Worksheet;
miRango = miSheet.get_Range("A1", "A1");
miRango.set_Value(Missing.Value,10);
miRango = miSheet.get_Range("B1", "D5");
miRango.set_Value(Missing.Value, 100);
miRango = miSheet.get_Range("E:E",Missing.Value);
miRango.set_Value(Missing.Value, 200);
miRango = miSheet.get_Range("F1;G2;H3;I4", Missing.Value);
miRango.set_Value(Missing.Value, 400);
}
Es un método bastante sencillo que fija valores, basado en el establecimiento de rangos sobre la hoja de trabajo. Lo realmente importante es la definición de las instancias de tipo Range y Worksheet, que son el punto de inicio para todo el trabajo. Lo demás es ir descubriendo la funcionalidad de la gran cantidad de métodos, propiedades, etc etc. Entre las cosas que tenemos aca es la clase Missing. No se maten la cabeza, simplemente adicionen el namespace System.Reflection, para que tengan acceso a Missing.Value. Recuerden este método va en la clase ThisAddIn.


Ahora en la clase de tipo Ribbon, la idea es quitar los comentarios del método RequestService() y en la sección CallBacks deberia quedar así:

public void OnButton1(Office.IRibbonControl control)
{
Globals.ThisAddIn.TestExcelRanges();
}

En el archivo XML que se agregó al proyecto, debe quedar así:
Básicamente en ese archivo se define una imagén asociada al AddIn, el manejador del evento disparado por el botón adicionado al Ribbon, y otras propiedades más. Solo basta ejecutar la aplicación, y debe entonces abrirse Excel desplegando los valores asociados para cada rango establecido, como se muestra en la figura:

Felices lineas de código
!!

Monday, June 18, 2007

No lo digo yo

Hola de nuevo

Esta es una pequeña entrada para algo que vengo escuchando ya hace unos años. Perdidas y ganancias, solo un pequeño porcentaje de proyectos de software dan buenos resultados, el resto...

De acuerdo al Standish Group [Sta94], las empresas en los Estados Unidos de América, invierten US$ 250 mil millones en el desarrollo de software para aproximadamente 200 proyectos cada año. Sólo el 16% finaliza a tiempo y dentro del presupuesto. El 31% se anula, debido a problemas de calidad generando pérdidas de aproximadamente US$ 81 mil millones. Otro 53% excede el presupuesto por un promedio de 189%, generando pérdidas aproximadas de US$ 58 mil millones. Los proyectos que se completan promedian sólo el 42% de los que se planificaron en un principio.

No se asusten, más bien lean el Journal de Microsoft sobre aruqitectura, que me sorprende ahora encontarlo en español, o más bien me emociona, así se gasta menos tiempo teniendo que traducir, se digiere más rápido. A lo que hago referencia lo encuentran en el número 3, a partir de ahi la revista tiene todos sus números en español. Así que si quieren saber de arquitectura de la mano de los mejores, ya no se pueden quejar por falta de información!!

http://msdn2.microsoft.com/en-us/arcjournal/bb201656.aspx#spanish

Un abrazo y feliz arquitectura!!

Sunday, June 03, 2007

Qué alguien me muestre los procesos

Hola de nuevo

La clase Process es mi invitada para esta entrada, con la cual quiero mostrarles un ejemplo muy simple. La idea, listar los procesos que se están ejecutando localmente en nuestra máquina. Es bueno saber también que está clase me permite listar los procesos de una máquina remota. Además puedo, iniciar y detener procesos. En fin aqui les dejo el ejemplo.

Primero, crearse un proyecto de tipo Consola, en las plantillas de C#

Luego en su método Main() escriben lo siguiente:


Bastante simple la cosa, y en la salida de este ejemplo, podran ver listados todos los procesos ejecutandose actualmente, mostrandose su PID y su nombre.
De todos modos, si buscan más en la clase Process, encontrarán muchas más propiedades y métodos bastante interesantes que pueden servir para llaver a cabo otra serie de tareas.

Felices líneas de código.

Friday, June 01, 2007

Microsoft Technology Day: Ciclo de vida de Aplicaciones

Nuevo evento en Colombia, donde se va a mostrar todo lo que Microsoft tiene para ofrecernos en herramientas que ayudan a administrar todo el ciclo de desarrollo de aplicaciones.

Vean más información en el blog del señor Ivanov Cepeda de Microsoft Colombia.

http://blogs.msdn.com/devcolombia/archive/2007/05/24/microsoft-technology-day-ciclo-de-vida-de-aplicaciones.aspx

Tuesday, May 08, 2007

XMLHttpRequest AJAX Introducción

Hola de nuevo

Esta es una de mis primeras entradas, que quiero dedicar a lo que tiene que ver con AJAX.
Si quieren saber por donde va lo de AJAX y demás pueden visitar http://ajax.asp.net/default.aspx?tabid=47 donde vana
Encontrar toda clase de material para iniciarse en el tema.

Yo quiero que veamos AJAX desde un lado práctico, tocando ciertas partes fundamentales en la teoría.
Para esto comencemos con el objeto XmlHttpRequest, que dicen por ahí, es el corazón de la maquinaria de AJAX. Sin este Objeto volveríamos a los aburridos y viejos sitios estáticos. La idea es que veamos cómo va la movida de instanciar este objeto, sus sutiles diferencias, dependiendo de un browser y otro, y lo sencillo que es enviar una petición "server side", lo cual cómo apreciaremos es bastante sencillo para ser cierto.

Entonces aquí pueden ver el video, en uno de mis sitios favoritos, si señores YouTube, que se ha convertido en una Tool más de aprendizaje y por supuesto esparcimiento.



Ahora bien, que está pasando ahí debajo.

Si señores ese JavaScript, que si quieren probarlo deben colocar después de su etiqueta HTML y antes de su HEAD.
El método getHTTPRequestObject(), se encarga de instanciar adecuadamente el objeto XMLHttpRequest. La idea radica en que para IE, este se comporta como un objeto tipo ActiveX, pero ya todos conocemos los problemas de compatibilidad con los
otros browser. Por lo tanto la tarea de instanciamiento difiere un poco. Por ejemplo en el caso de IE actual, la línea que crea el objeto es xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); Si se fijan en mi video tengo un pequeño error y
es que me falta una P al instanciar dentro del primer catch(), así que simplemente disculpas. Pero bueno para la versión de mi IE, mi isntancia se crea en el segundo Try.
Ahora miren que si nuestra página es accedida por un browser tipo Mozilla o Safari, se utiliza:
xmlhttp = new XmlHttpRequest(); Esto es porque para esos browsers, el objeto es nativo, pre-construido.

En la página default.aspx, he puesto dentro del DIV un simple mensaje
XmlHttpRequest trabajando!!
Y finalmente he adicionado el archivo de texto "TextFile.txt" al proyecto web, el cual le inserto un texto cualquiera.

Por favor coloquen mucha atención a esta parte del script, donde está lo interesante:
xmlhttp.onreadystatechange = function()
{
if(xmlhttp.readyState == 4)
{
alert(xmlhttp.responseText);
}
}
Si señores, es una llamada asíncrona, donde el valor 4 indica que la llamada se ha realizado con éxito. La función onreadystatechange sirve para monitorear el estado actual de la llama asíncrona.

Los posibles valores de este estado son:

0:Uninitialized
1:Loading
2:Loaded
3:Interactive
4:Complete

Bien, lentamente iremos viendo más cosas sobre este interesante objeto y por supuesto todo lo que trae AJAX para nosotros en este mar de información y tecnologías que están ahí esperando a que las explotemos.

Monday, May 07, 2007

Mis recomendados de la semana

Hola de nuevo

Bueno esta ves quiero comentar un poco acerca de mi actualización y gastos varios en nuevos libros referentes a todo lo nuevo con .NET. Entre mis nuevas adquisiciones les quiero recomendar tres libros sensacionales. Pro C# with .NET 3.0, edición especial, del señor Andrew Troelsen. La verdad es lo más reciente que me llega, pero lo recomiendo, primero porque toca temas fundamentales de C# sobre Framewrok 3.0, así como los nuevos temas referentes a WCF, WPF y LINQ. Ahora está este otro libro bastante bueno, Pro Ajax and the .NET 2.0 Plattform, del señor Daniel Woolston, bastante bueno para iniciarse en AJAX, buenos ejemplos, y bien explicada cada cosa importante que se trata en cada una de sus páginas. Por último tengo en mis manos Expert Service-Oriented Architecture in C# 2005. La verdad creo que el título queda un poco grande a este libro, por cierto bastante delgado, le faltan vitaminas, pero como sea, no soy experto en el tema y está bueno para ganar conceptos básicos. Lo que si es rescatable, es que los ejemplos se basan en WSE 3.0, lo que si me ha parecido muy práctico. Este engendro es de los señores Jeffrey Hasan y Mauricio Duran.

Lo que si es importante en esto, es tener bastante lectura, aunque hay mucho en internet, yo prefiero tener mi biblioteca personal, y con estos nuevos visitantes, mi biblioteca crece dia con dia.

Saturday, April 28, 2007

DLL Hell? ustedes deciden

Hola de nuevo

No habia publicado esto mientras daba solución al problema:

"Load Report Failed" {"Not enough memory for operation."}

etc etc

Sip todo comenzó en nuestro servidor de pruebas, y luego por arte de magia me ocurrió en mi máquina de desarrollo. Los reportes lanzaban la excepción comentada y ya nada funcionaba.

Como dijo Willy Marroquin, todos los caminos conducen a GooGle y claro, después de 2 semanas de búsqueda y pruebas infructuosas, me encontré con una solución simple.

Correr el comenado regsvr32 para la DLL "crqe.dll" y todo volvió a la normalidad...

Un caso más del infierno de las DLLs? ustedes diran, yo pienso que sip. El problema grave es encontrar la solución pronta a problemas de este tipo.

Felices lineas de código!!

Jugamos a las escondidas?

Hola de nuevo

Esta es una entrada muy breve acerca de un "defecto" en VS.NET respecto de la ventana Field Explorer de Crystal Reports. Si señores, les ha pasado? estamos editando nuestro reporte desde VS.NET y el Field Explorer se oculta y "nunca jamas" como dice Poe en su gran poema, volvemos a ver el Field Explorer.

Les cuento que estando en VS.NET podemos ir a la opción Ver(View) del menú y seleccionar la opción Otras Ventanas y ahi buscar la opción "Esquema del documento" y bingo, ahi aparecerá el Field Explorer como por arte de magia.

Un abrazo y felices lineas de código!!

Wednesday, February 28, 2007

Artículo recomendado y algo más

Hola, en esta ocasión quiero recomendarles un artículo que me ha parecido excelente, totalmente en español, tema del número de MSDN Magazine de Marzo de 2007, donde el autor habla de manera muy interesante acerca de las nuevas caracteristicas de IIS 7.0. en resumen, tenemos un servidor Web que viene en su versión completa con Windows Vista, la misma que se utilizará en el Servidor Windows "LongHorn", un IIS totalmente modular, interrelacionado con nuestras aplicaciones ASP.NET, desde las cuales podemos automatizar casi por completo las funcionalidades existentes del IIS, y por supuesto crear nuestros propios modulos. Solo quiero decirles que le doy un 10 ha este artículo y sería bueno que le den un vistaso.

http://msdn.microsoft.com/msdnmag/issues/07/03/IIS7/default.aspx?loc=es

Quiero invitarlos nuevamente a escuchar MSDN radio
http://www.microsoft.com/spanish/msdn/latam/mediacenter/radio/default.aspx
Pueden encontrar mi entrada acerca de las ventanas de VS.NET, su utilidad y teclas rápidas y mucho más.

Para los amantes de ASP.NET no olviden visitar el Blog del señor Scott Guthrie, tiene unas entradas excelentes.
http://weblogs.asp.net/scottgu/rss.aspx

Wednesday, February 07, 2007

MSDN Radio

Amigos, les quiero compartir un link a un sitio de MSDN latinoámerica, que presenta contenido muy bueno y variado acerca de la tecnología .NET y totalmente en español, justo para la comunidad latinoaméricana.
http://www.microsoft.com/spanish/msdn/latam/mediacenter/default.aspx

Quiero invitarlos a escuchar una de mis entradas en MSDN Radio en:
http://www.microsoft.com/spanish/msdn/latam/mediacenter/radio/default.aspx
donde toco el tema de los Proyectos de SQL Server 2005 y su integración con el CLR.

Saturday, February 03, 2007

Programando OutlookAddin con VSTOs

Hola, esta ves quiero mostrarles cómo podemos programar fácilmente un addin para outlook.

Para los que no saben qué es un addin, básicamente es funcionalidad extra que podemos añadirle a las aplicaciones como Word, Excel, Oulook y todas las demás herramientas de la suite office, incluso el mismo Visual Studio .NET, para que se ejecute dentro del ambiente de estas aplicaciones y provea tareas que nosotros mismos programamos, y podemos ejecutar desde alguna de las opciones del menú de cada una de estas aplicaciones, como si fuera una funcionalidad cualquiera.

En esta ocasión quiero mostrales cómo crear un proyecto de addin de outlook y con esto adicionar una funcionalidad extra a esta herramienta de office system 2003, con la cual se ejecuta este ejemplo.

Para esto es necesario instalar las Visual Stuio Tools for Office, con lo cual podemos crear proyectos para office System 2003 e incluso office system 2007. En esta ocasión utilizo OutLook 2003 para correr el ejemplo.

Habiendo instalado las VSTOs, procedemos a crear un proyecto de Office y seleccionamos la plantilla Complemento de Outlook, como se puede apreciar en la figura.

Cómo con cualquier proyecto de Visual Studio .NET podemos asignarle un nombre, una ubicación y un nombre para la solución del proyecto.
Al dar clic en aceptar, visual studio crea para nosotros un archivo .cs llamado ThisApplication, en el cual adiciona dos métodos que son los puntos de entrada y salida de nuestro AddIn respectivamente:
ThisApplication_Startup y ThisApplication_Shutdown.
Lo primero que vamos a crear son 2 atributos privados de la clase:
private Office.CommandBarPopup miAddinMenu;
private Office.CommandBarButton miMostrarVentana;
El primero de tipo CommandBarPopup, sirve para asociar en cualquiera de las opciones del menú de OutLook, nuestro addin. El segundo de tipo CommandBarButton, nos sirve para asociar una de las opciones del menú del Addin.
A continuación creamos un método para que cree el menú del Addin, utilizando como contenedor, el menú Tools del Outlook.

private void CrearMenu()
{
// Obtiene una referencia a la ventana del explorador de outlook activa.
Outlook.Explorer miExplorador = this.ActiveExplorer();
// La adci¢n se hace al men£ tools
Office.CommandBar miMenu = miExplorador.CommandBars["Tools"];
// Crea el item en el men£ para el AddIn
miAddinMenu = miMenu.Controls.Add(Office.MsoControlType.msoControlPopup, 1, "", 1, true) as
Office.CommandBarPopup;
miAddinMenu.Visible = true;
miAddinMenu.Caption = "Mi primer Addin";
// Crea una opci¢n del men£.
miMostrarVentana = miAddinMenu.CommandBar.Controls.Add(Office.MsoControlType.msoControlButton, 1,
"", 1, true) as Office.CommandBarButton;
miMostrarVentana.Caption = "Mi opci¢n";
miMostrarVentana.Style = Office.MsoButtonStyle.msoButtonIconAndCaption;
//Despliega un icono de opciones
miMostrarVentana.FaceId = 1664;
miMostrarVentana.Click += new Office._CommandBarButtonEvents_ClickEventHandler(MiEventoButtonClick);
}
El método anterior se puede invocar desde el método ThisApplication_Startup, con esto tendremos nuestro Addin desplegado en el OutLook como una funcionalidad más del menú Tools.
Ya que se ha asociado un evento a la opción del AddIn, es necesario adicionar el siguiente evento a la clase:

private void MiEventoButtonClick(Office.CommandBarButton ctrl, ref bool cancelDefault)
{
//MessageBox.Show("Mi primer Addin de Outlook");
using (FormularioAddin miForma = new FormularioAddin())
{
if (miForma.ShowDialog() == DialogResult.OK)
{
Application.Exit();
}
}
}
Para el evento se debe haber creado una forma de windows con un botón, al cual se le asocia la propiedad DialogResult con el valor OK. La forma es instanciada dentro de la clausula using, la cual indica que todo recurso utilizado será liberado, como si fuera un bloque Try-Finally, y al dar click en el botón sobre la forma, simplemente se cierra el OutLook con la llamada al método Exit.
El poder adicionar formas de windows, hace de nuestro Addin una herramienta muy poderosa para extender la funcionalidad de Outlook, además el poder enlazar eventos y tener a mano todo el poder de programación del .NET Framework.
Espero este sencillo ejemplo pueda servirles para iniciar proyectos más complejos que aprovechen la funcionalidad de OutLook e igualmente la extiendan.


Saturday, January 20, 2007

.NET News y algo más

En esta entrada dejo un lado lo técnico parar referirles enlaces a temás importantes que nos mantienen al dia con todo o que está pasando con la tecnología .NET.

Para los seguidores de desarrollador 5 Estrellas 2005, ya está la 4ta estrella disponible, con muy buen material acerca
de los temás relevantes del .NET Framwork 3.0
http://www.mslatam.com/latam/msdn/comunidad/dce2005/

Algo que me ha llamado la tención y habia estado esperando es el show para televisión de MSDN latinoamérica. Con temas
de bastante interés es una opción más de aprendizaje a la que tenemos acceso.
http://www.microsoft.com/spanish/msdn/latam/mediacenter/msdntv/default.aspx

Imagina un mundo donde la tecnología facilite el acceso a la educación a todo el mundo...Este es el lema para el Imagine Cup 2007, ya ya está listo para que los estudiantes de todo el mundo se inscriban y participen en el evento tecnológico a nivel de Universidades que Microsoft realiza cada año.

El sitio recomendado para hoy es:
http://www.theserverside.net/, uno de mis sitios favoritos por las grandiosas entradas que hacen expertos en los diferentes temas de la tecnología .NET, además de poder conseguir apartes de libros, artículos, conversatorios, y mucho más.

Más TIPS sobre Crystal Reports

Continuando con la entrada anterior, acerca de tips de interés cuando utilizamos Crystal reports desde nuestras aplicaciones .NET (Windows Forms o ASP.NET), estas son algunas soluciones a ciertos problemas que se pueden presentar:

1. Supongamos que tenemos un reporte el cual contiene varios subreportes. Nuestro reporte principal tiene la orientación del papel de manera vertical, pero uno de los subreportes es demasiado ancho y necesita estar orientado de manera horizontal. Qué se puede hacer en este caso? Aqui está el código y el evento que debemos programar del CrystalReportViewer para alcanzar esta solución:

private void CrystalReportViewer1_DrillDownSubreport(object source, CrystalDecisions.Web.DrillSubreportEventArgs e)
{
if(e.NewSubreportName == "Subreport1")
{
ReportePrincipal.PrintOptions.PaperOrientation = PaperOrientation.Landscape;
}
}

Capturando el evento DrillDownSubreport, le estamos indicando en ese instante al subreporte que tiene asignado en su propiedad "name" el valor Subreport1, que debe utilizar el valor "Landscape" para la orientación del papel. Esta solución es muy efectiva para alcanzar el resultado esperado, además que podemos hacerlo con 1 o más subreportes adicionados al principal.

2. Cunado necesitamos agrupar información dentro de nuestro reporte, y mostrar cada grupo en una página diferente del reporte, Crystal ofrece un solución bastante simple, pero efectiva, que nos lleva a programar los eventos disparados por las diferentes secciones del reporte. En este caso vamos a programar el evento "New Page After" de las secciones GroupHeader y GroupFooter.

Lo primero entonces es indicarle al Group Header, que despligue la información del mismo grupo mientras no encuentre el último registro y el siguiente registro sea igual al que se está leyendo en el momento. Si no se cumple, entonces se ejecutaré el evento "New Page After", causando que se crea la nueva página para el nuevo grupo.

if(NOT OnLastRecord AND {sales.ord_num}=Next ({sales.ord_num}))then false

Pero esta solución causa un problema en el reporte y es que siempre se crea una página en blanco adicional, pero esto tiene una solución igualmente simple.
En la sección Group Footer, en el evento "New Page After" adicionamos la línea:

OnLastRecord

Con esto entonces tenemos dos simples soluciones a algo que en primera instancia parece ser un problema díficil de resolver. Como les decía en la entrada anterior sobre Crystal, esto es solo cuestión de conocer la herramienta y las capacidades que oferece a nível de programación.

Quiero recomendarles:
http://aspadvice.com/blogs/rjdudley/archive/tags/Crystal+Reports+.NET/default.aspx
http://www.crystalreportsbook.com/
Dos exelentes sites, de dos personajes que aportan bastante a dar soluciones efectivas a problemas con Crystal Reports utilizado desde nuestras aplicaciones .NET

SQLServer 2005 Administrado

En esta entrada hablaremos un poco acerca de la inclusión del CLR dentro de SQL Server 2005, y cómo esto nos permite exponer elementos administrados dentro del motor. Por ejemplo, procedimientos almacenados, funciones, triggers, UDTs(tipos definidos por el usuario), entre otros, escritos en un lenguaje administrado por el CLR (C#, VB.NET) y desplegados como objetos de la base de datos, pero administrados por el CLR para su ejecución, como cualquier ensamblado que se crea después de su compilación.

Para crear un proyecto desde Visual Studio .NET 2005 para SQL Server, se escoge la opción SQL Server Project:



Esta template, nos permite un proyecto de SQL Server, desde el cual podremos adicionar los siguientes items:


Seleccionando cualquiera de los items anteriores, visual studio crea por nosotros la clase en la cual podemos adicionar el método, que finalmente será desplegado dentro del motor como un objeto de la base de datos que puede ejecutarse como cualquiera de sus contrapartes escritos en Transact SQL.

Por ejemplo, veamos lo que sería un método administrado que SQL Server 2005 entiende como un procedimiento almacenado, con los elementos necesarios para que funcione como tal:


using (SqlConnection conexion = new SqlConnection("context connection = true"))
{
SqlCommand comando = new SqlCommand();
comando.CommandText = "SELECT LastName" + Convert.ToChar("+").ToString() + "' '" +
Convert.ToChar("+").ToString() + "FirstName, Title, BirthDate, Address, City " +
"FROM dbo.Employees";
comando.Connection = conexion;
conexion.Open();
SqlContext.Pipe.ExecuteAndSend(comando);
}

Es una consulta muy sencilla, donde se pueden evidenciar algunos elementos de importancia como son:

1. Al constructor de la clase SqlConnection ahora le pasamos el valor "context connection = true" que está indicando que nuestro código se va a ejecutar dentro del contexto de SQL Server, administrado por el CLR. Esto significa que no van a ejecutarse todos los mecánismos de conexión utilizados por SQLConnection a través del SQLDataProvider.

2. El método Send de la propiedad Pipe es equivalente a un PRINT en Transact SQL. La propiedad Pipe es de tipo SQLPipe, y permite insertar información en la corriente de salida utilizando para esto el protocolo TDS(Tabular Data String), con el cual SQL Server habla con un cliente. TDS permite poner ResultSets y Mensajes en el camino.

Bien este método entonces será desplegado como un procedimiento almacenado dentro del motor. Y el despliegue? sencillo, simplemente ejecutar el proyecto y con esto ya tenemos desplegado nuestro procedimiento almacenado administrado como un objeto del motor. Hay comandos propios de Transact SQL que se pueden también ejecutar desde SQL Server 2005, pero eso es tema para otra entrada. Es importante que antes de ejecutar cualquiera de estos comandos, el CLR debe estar activado dentro de SQL Server, ya que por seguridad viene deshabilitado por defecto.

Desde visual studio .NET podemos hacer uso del Server Explorer para ir viendo lo que está ocurriendo con nuestros elementos administrados dentro del motor, ahi en diferentes carpetas podemos desplegar la de "Stored Procedures" y entonces el procedimiento almacenado tendrá el nombre que le hayamos dado al método escrito en C#. Otra carpeta que se encuentra es Assemblies, en la cual queda desplegado el ensamblado el cual toma por defecto el nombre de nuestro proyecto.

En conclusión, con SQL Server - CLR, tenemos muchas ventajas como por ejemplo: poder extender la funcionalidad del motor, porque podemos escribir nuestra lógica utilizando lenguajes de alto nivel y no Transact SQL. Aunque SQL Server no sea un motor orientado a objetos, estas características le añaden orientación a objetos de cierto modo, pero debemos tener cuidado, ya que ciertas características de la POO, no pueden ser entendidas dentro del SQL Server 2005. Es muy importante saber que no puedo tomar todos mis objetos escritos en Transact-SQL y cambiarlos por objetos administrados, esto no es solución de ninguna manera. La idea de tener hospedado el CLR dentro de SQL Server, es para escribir cierta clase de objetos que con transact SQL pueden llegar a ser demasiado complejos y no tener el mismo desempeño que escritos con lengaujes administrados. Por ejemplo, funciones matemáticas, operaciones de encripción y desencripción, todo lo referente al trabajo con cadenas (lo cual tiene un desempeño pobre con Transact SQL), operaciones como envio de coreo electrónico. Pero entonces nunca podremos suplir el gran desempeño que Transact ofrece para lo que tiene que ver con operaciones de tipo conjunto, es decir consultas sobre la información almacenada dentro de nuestra base de datos, en este contexto, los objetos escritos con lenguajes administrados, van a arrojar un desempeño mucho menor que los de transact. y finalmente cabe resaltar la depuración sobre obejetos escritos en Transact SQL desde el entrono de Visual Studio .NET, con lo cual tengo un elemnto más a favor para poder verificar que está ocurriendo con la jecución de mis elementos no administrados.

Friday, January 19, 2007

Programando Crystal Reports I, una mirada práctica

Desde hace ya unos meses atrás vengo trabajando con la herramienta Crystal Reports para mi aplicación ASP.NET, y si algo es muy cierto, la versión actual de Crystal, la XI, es definitivamente una herramienta muy evolucionada para la creación de reportes que requieren un alto grado de complejidad, y que además de poder organizar los elementos para presentar la información con buena presentación gráfica, podamos automatizar y programar tareas que hacen de esos reportes elementos realmente útiles para el usuario final. Y es finalmente el usuario quien nos pide cosas que a veces parecen casi que imposibles de resolver, pero que al conocer un poco más las herramientas, estas resultan proveyendo toda una gama de características para hacer que esas tareas se vuelvan una realidad en código.

Quiero en esta oportunidad compartir con ustedes ciertos tips de código y diseño, que me han gastado varias horas de investigación y desarrollo, para poder plasmar el problema de negocio del cliente en una serie de reportes que resultan ser al final muy satisfactorios.

Subreportes:
Este es quizás uno de los temas, por los cuales la gente tiene muchos problemas cuando está construyendo reportes de nivel profesional, los cuales requieren diferentes elementos y jerarquías de cierta complejidad, las cuales pueden ser resueltas con esta característica provista por Cristal de una manera sencilla de utilizar. En esta parte entonces veamos cómo puedo desde mi aplicación ASP.NET y utilizando lenguaje C#, acceder a estos elementos, y adicionalmente poder enviar parámetros, tanto a su reporte contenedor, como a estos subreportes.

Las dos primeras instancias van a ser de tipo SubreportObject y ReportDocument. La primera nos permite definir el representante en código de nuestro subreporte que ya hemos adicionado en diseño al reporte contenedor. La segunda nos permite trabajar con nuestro subreporte, tal como si estuviéramos accediendo un reporte común y corriente, pudiendo acceder a propiedades para fijar por ejemplo la fuente de datos y parámetros si son necesarios.

SubreportObject subreportObject;
ReportDocument subReporte;
Reporte miReporte = new Reporte();
DataSet miDs = new DataSet ()
miDs = Consultar();
subReporte = new ReportDocument();
subreportObject = miReporte.ReportDefinition.ReportObjects["subReporte"] as SubreportObject;
subReporte = miReporte.OpenSubreport(subreportObject.SubreportName);
subReporte.SetDataSource(miDs.Tables[0]);

Adicionalmente a las dos instancias mencionadas, se tiene entonces un objeto de tipo DataSet, el cual servirá como contenedor para la data devuelta por el método que consulte la información desde algún repositorio, por ejemplo una base de datos. Es importante observar la colección ReportObjects, en la cual le indicamos al objeto subreportObject que será el contenedor de un subreporte llamado “subReporte”, nombre asignado en la propiedad Name del subreporte. Si no se tiene cuidado con el nombre asociado al subreporte, al ejecutar la aplicación, el Sistema lanza una excepción que indica que el índice está fuera del rango. Se utiliza un el operador “as”, el cual ofrece seguridad y eficiencia en este proceso, y adicionalmente no tenemos que hacer ni tratamiento de NULL ni manipular excepciones, pero esto será tema de otra entrada.
Entonces es claro que el objeto subreportObject, se ha vuelto el representante en código del subreporte, y por ejmplo lo pasamos como parámetro al método OpenSubreport() con el cual abrimos el subreporte y lo asignamos al objeto subReporte, con el cual finalmente asignamos la fuente de datos al subreporte. Es claro que cuando tenemos un reporte principal, con diferentes subreportes, podemos tener diferentes fuentes de datos para alimentar cada elemento del reporte principal, incluyendo la fuente de este último.

Finalmente podemos entonces consultar la información para el reporte principal.

miDs = new DataSet();
miDs = ConsultarPrincipal();
miReporte.SetDataSource(miDs.Tables[0]);
this.crvVisorReporte.ReportSource = miReporte;
this.crvVisorReporte.DataBind();

El objeto crvVisorReporte es una instanacia de la clase CrystalReportVoewer, que es el visor o control que encontramos en el ToolBox de Visual Studio .NET, el cual nos permite visualizar nuestros reportes en las páginas .aspx o Windows forms.
Quiero anotar algo, y es que en el método SetDataSource(), le pasamos el DataSet y se le indica el objeto Table de la colección que se va a utilizar. Si no se hace esto y si le pasamos solamente el objeto DataSet, inmediatamente el objeto crvVisorReporte, despliega uso campos para ejecutar logon contra la base de datos.

Pasar parámetros al Reporte y Subreportes

Primero que todo es importante conocer las posibles razones por las que ocurre el error más típico cuando se utilizan parámetros en Crystal reports que se envian desde el código de nuestra aplicación. Básicamente el error es Missing Parameter Value y Referencia a objeto no establecida. Esto es lo único que Crystal nos muestra en el visor. Ocurre cuando se han declarado parámetros en el reporte y subreportes, y no se les está enviando ningún valor. También puede ser que desde código estamos asignando un valor a un parámetro que no se ha definido aún en los reportes. Entonces se debe tener un poco de cuidado y así evitar este error que es difícil de depurar algunas veces.

miReporte.SetParameterValue("anio", 2004);
miReporte.SetParameterValue("mes", 1);

El código anterior está asignando los valores a 2 parámetros que deberán estar definidos en nuestro reporte principal y sus subreportes, bueno si es que los subreportes los necesitan, es decir si se requiere utilizar los parámetros en el subreporte deben definirse en el mismo. La manera de pasar los valores enviados desde código entre el reporte principal y sus subreportes es fijando en la opción Change subreports links, que se puede acceder en tiempo de diseño, parándose sobre el subreporte y haciendo clic derecho. Se abre entonces una ventana donde podemos seleccionar uno o más campos sobre los cuales se enlazan los parámetros que hayamos fijado en el reporte principal y sus subreportes. Esto es porque no podemos asignar valores a parámetros de subreportes directamente desde código.

En conclusión, una tarea que puede volverse dispendiosa cuando se hace por primera ves, realmente con el modelo de objetos de Crystal reports desde C#, realmente es sencilla y muy poderosa. Por ejemplo podemos asignar desde código valores a los parámetros, de acuerdo a determinada opción, y ya en el reporte, el valor de ese parámetro determinara el comportamiento del reporte, por ejemplo mostrar u ocultar una de sus secciones.