miércoles, 31 de octubre de 2007

Libro: Flexibilidad con Scrum - Juan Palacio

Juan Palacio, autor de Navegapolis, acaba de publicar un libro muy recomendable sobre Scrum: Flexibilidad con Scrum.

Y digo que es muy recomendable porque si es la mitad de bueno que los artículos de su página será imprescindible para todos los que nos iniciamos en esta metodología.
Sólo le he echado un primer vistazo, pero por la pinta que tiene y de quien es no hay duda que es muy recomendable.

El libro está disponible en descarga gratuita (gracias por compartirlo Juan) o compra en lulu.com.

miércoles, 10 de octubre de 2007

No hagas el tunicado, no te absorbas el cerebro

Hace días que quiero comentar un post muy interesante de El blog salmón , recomendable para los que no tenemos ni idea de economía (aunque tratan otros temas como los recursos humanos).


Como decía, es este post del 4 de octubre (cuyo autor es IC) que por falta de tiempo no he podido comentar antes, pero este tiempo extra me ha permitido madurar un poco más lo que iba a decir. Allí se comenta un artículo de Eduard Punset sobre la zona de seguridad, que es cuando nos encontramos seguros y a gusto en un sitio, y su relación con el cerebro y la evolución, según sus palabras:


Cambiar de lugar y de profesión no sólo será muy importante en el mundo multidisciplinar que estamos anticipando, sino que también lo fue en el pasado. Es fascinante descubrir que el cerebro nació, precisamente, para permitir a las larvas de los tunicados encontrar el lugar adecuado donde iban a fijar su residencia en su etapa de adultos. Aquel antecesor de nuestro cerebro les permitió orientarse en el espacio para vivir una vida adulta sin moverse. Una vez instalados en la seguridad del lugar elegido, absorbían su propio cerebro porque ya no lo necesitaban.


Dios mío! Eso lo he vivido yo muchas veces con algún pedazo de imb… persona humana, y nunca he podido encontrar una explicación mejor, hay gente que literalmente se absorbe el cerebro porque ya no lo necesita, algunos lo deben sustituir por otra cosa (una tostadora, un poco de cera de los oídos,...) pero la mayoría dejan un espacio vacío en su cráneo.


Pero vamos a esperar un momento y dejemos hablar al señor Punset, que sigue diciendo cosas muy interesantes:

Mucha gente y, sobre todo, muchos funcionarios se comportan de forma similar a los tunicados. Una vez instalados en la seguridad, se diría que absorben su cerebro y dejan de pensar en otras posibilidades de innovar. Esta actitud es peligrosa para ellos mismos y para el colectivo en el que están insertados.


Punset habla de funcionarios, pero yo pregunto ¿cuantos de vosotros no conocéis a algún tunicado que no sea funcionario? Para mi desgracia, me he encontrado con unos cuantos tunicados a lo largo de mi vida, sobre todo la profesional.


Y ahora es cuando me toca hablar algo de informática, que es el motivo de este blog, así llevo todo esto a mi terreno, que todo este rollo tiene algún fin (creo).


¿Qué clase de persona es un tunicado informático?

Como se explica antes los tunicados absorbían su cerebro cuando alcanzaban la zona de "seguridad o comodidad", a mi personalmente me gusta más de "comodidad" para el caso de la informática.

Un tunicado informático es el que se ha acomodado en su puesto (programador/a, analisto/a, jefecillo/a,...) y absorbe su cerebro porque ya no lo necesita. Ya no necesita conocer los cambios del SP2 de Visual Studio 2012, ni que hay de nuevo en el framework 5.0, no necesita leer blogs (así que no creo que ningún tunicado lea esto), y no se entera de lo que le explican, porque realmente sólo quiere que le digas que lo que él (recordemos que se ha absorbido el cerebro, así que debe tener un manual de DNA en su sitio) propone, no haciendo caso de lo que le digas.

(Jose, Santi y yo mismo conocemos a alguno que cumple con todas a la vez).


¿Y que efectos tienen sobre un grupo que trabaja en un proyecto?

Pues los más devastadores que os podáis imaginar:

  • no escuchan
  • no ayudan en nada
  • siempre le ponen pegas a todas las propuestas (y eso que no escuchan)
  • siempre necesitan tu ayuda cuando estás hasta arriba de trabajo para que le expliques algo que está en cientos de sitios (en internet y en los libros que tiene encima de la mesa)
  • no hace caso de lo que le explicas (porque no escucha)
  • siempre quieren imponer su opinión (ya dije que no escucha, no)
  • consigue que te enfades con él, con el proyecto y con la informática en general
  • consigue que te pongas de mal humor y no te salga nada en todo el día

Y lo peor de todo, consigue que tú también pierdas el interés por el proyecto y por las novedades, porque, si a él no le hace falta a ti tampoco. Y esto es lo peor de todo porque puedes llegar a su nivel y absorber tu propio cerebro.

Vaya no me había dado cuenta de la similitud de los tunicados y los zombis, pero con su propio cerebro como comida.


¿Y como se puede luchar contra ellos?

No se puede, así que lo mejor que se puede hacer es resignarse e intentar evitar que se metan en los proyectos en los que estás trabajando, porque los llevarán a un tremendo y rotundo fracaso (y encima será culpa nuestra, como si lo viera). Lo mejor es hacer ver que estás muy ocupado cuando te venga a preguntar algo (sí, quedas como un borde, pero conservarás el cerebro) y no hacerle mucho caso en las reuniones, siempre parecerá que sabe de que habla, pero nosotros podemos demostrar que tenemos razón.


¿Y si aún no se ha absorbido totalmente el cerebro?

Este caso aún tiene una solución, aunque hay que tener mucha paciencia con ellos. Lo que se tiene que hacer es ayudarle a que se interese por las novedades de las herramientas en las que trabaje. Obligarle a leer artículos y blogs, a ir a conferencias (que es más fácil que leer y hasta un tunicado lo puede hacer), que se una a grupos, en definitiva, darle caña para que espabile.

Es una tarea muy difícil, ellos pueden ser más, pero nosotros somos mucho más valientes.


Así que si te cruzas con un tunicado en tu trabajo, PON TU CEREBRO A SALVO!!!


PD: Otro artículo interesante del Blog Salmón es este, en el que nos hablan de como salir airoso en una entrevista de trabajo en la que nos ponen pegas.

A más de uno nos ha pasado y seguro que a los demás también les pasará, a no ser que seáis unos tunicados.


PD2: vaya ladrillo me ha quedado para comentar un post de otro blog, me parece que tendré que hacer un curso de síntesis y copia/pega de otros blogs.

viernes, 7 de septiembre de 2007

Bloqueo exclusivo de objetos en C# y VB.NET

Leyendo el libro Microsoft Windows Workflow Foundation Step by Step escrito por Kenn Scribner me encontré con una instrucción para realizar un bloqueo de exclusión mutua en objetos. Posiblemente esto sea a lo que se refiere Ciro Franz el comentario que me hizo en mi blog en BcnGeeks, y como me quedaría un comentario muy largo, prefiero hacer un post.


C# (lock)

Vamos a ver de qué se trata, en C# se realiza con la instrucción lock() que según MSDN: marca un bloque de instrucciones como una sección crucial, para lo cual utiliza el bloqueo de exclusión mutua de un objeto, la ejecución de una instrucción y, posteriormente, la liberación del bloqueo.

Vaya, otra definición extraña de MSDN, pero si seguimos leyendo lo aclaran un poco más: La instrucción lock permite garantizar que un subproceso no va a entrar en una sección crucial de código mientras otro subproceso ya se encuentre en ella. Si otro subproceso intenta entrar en un código bloqueado, esperará, o se bloqueará, hasta que el objeto se libere.

Y esto no es ni más ni menos que una forma de control de concurrencia sobre un objeto, pero lo más interesante es la forma de usarlo, esta instrucción contiene un bloque de código que se ejecuta mientras el exista el bloqueo. Mejor me explico con código:



Object objeto;

lock(objeto)
{
//codigo....
//codigo....
}

Si otro proceso intenta ejecutar la instrucción lock(), y el objeto está bloqueado, tendrá que esperar a que se acabe de ejecutar todo el bloque de código.

Vale, vamos a poner un ejemplo práctico en el que no hay bloqueos, para luego demostrar como funciona la instrucción lock. Como casi siempre, será una aplicación de consola en C#, a la que añadimos el siguiente código:




using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace PruebaLock
{
class Program
{
static void Main(string[] args)
{
//Declaramos 10 hilos que ejecuten en método EjecutarMetodoEstatico
Thread[] threads = new Thread[10];
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(ClaseEstatica.EjecutarMetodoEstatico));
threads[i] = t;
}

//Ejecutamos los hilos
for (int i = 0; i < 10; i++)
{
threads[i].Start();
}

//Esperamos a que se pulse una tecla para finalizar
Console.WriteLine("Pulse una tecla para salir...");
Console.ReadKey();
}
}

public static class ClaseEstatica
{
public static void EjecutarMetodoEstatico()
{

Console.WriteLine("Ejecutando bloque de código...");
// La instrucción Sleep suspende la ejecución del hilo,
// la utilizo en vez de un bloque de código que tarde
// 1 segundo en ejecutarse
Thread.Sleep(1000);
Console.WriteLine("Fin bloque de código.");
}
}
}

Ejecutamos (F5), y se obtiene este resultado:



Como podemos ver, los objetos se ejecutan en paralelo y finalizan a la vez.

Bien, vamos a probar el bloqueo, cambiamos el código que teníamos antes por este, fijaos en que el bloque en el que está la instrucción Sleep(), empieza con lock(objetoBloqueo):



using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace PruebaLock
{
class Program
{
static void Main(string[] args)
{
//Declaramos 10 hilos que ejecuten en método EjecutarMetodoEstatico
Thread[] threads = new Thread[10];
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(ClaseEstatica.EjecutarMetodoEstatico));
threads[i] = t;
}

//Ejecutamos los hilos
for (int i = 0; i < 10; i++)
{
threads[i].Start();
}

//Esperamos a que se pulse una tecla para finalizar
Console.WriteLine("Pulse una tecla para salir...");
Console.ReadKey();
}
}

public static class ClaseEstatica
{
// Declaramos el objeto que se va a bloquear, debe ser private
private static object objetoBloqueo = new object();

public static void EjecutarMetodoEstatico()
{
lock (objetoBloqueo)
{
Console.WriteLine("Ejecutando bloque de código...");
//La instrucción Sleep suspende la ejecución del hilo,
//la utilizo en vez de un bloque de código que tarde 1 segundo en ejecutarse
Thread.Sleep(1000);
}
Console.WriteLine("Fin bloque de código.");
}
}
}



Y el resultado:



La instrucción Console.WriteLine("Pulse una tecla para salir..."); se ejecuta la primera, porque los hilos están ocupados con los bloqueos, y no se ejecuta un hilo hasta que haya acabado el anterior, con lo que ya tenemos montado una especie de control de concurrencia pesimista.


VB.NET (Synclock)

En VB.NET la instrucción que realiza el bloqueo es Synclock() y su uso es idéntico al de lock() de C#, lo curioso es que en MSDN, esté descrita de la siguiente forma: Adquiere un bloqueo exclusivo para un bloque de instrucciones antes de ejecutar el bloque.

Si alguien lo entiende, que me lo explique, porque la definición de lock() es complicada, pero por lo menos se entiende.

Bueno, vamos a olvidarnos de las definiciones de MSDN, y vamos al mismo código de ejemplo pero en VB.NET:




Imports System.Threading

Module Module1

Sub Main()
'Declaramos 10 hilos que ejecuten en método EjecutarMetodoEstatico
Dim threads(10) As Thread
For i As Integer = 0 To 10
Dim t As Thread = New Thread(New ThreadStart(AddressOf ClaseEstatica.EjecutarMetodoEstatico))
threads(i) = t
Next

' Ejecutamos los hilos

For i As Integer = 0 To 10
threads(i).Start()
Next

' Esperamos a que se pulse una tecla para finalizar
Console.WriteLine("Pulse una tecla para salir...")
Console.ReadKey()
End Sub

End Module

Public Class ClaseEstatica

' Declaramos el objeto que se va a bloquear, debe ser private
Private Shared objetoBloqueo As Object = New Object()

Public Shared Sub EjecutarMetodoEstatico()
SyncLock objetoBloqueo

Console.WriteLine("Ejecutando bloque de código...")
' La instrucción Sleep suspende la ejecución del hilo,
' la utilizo en vez de un bloque de código que tarde 1 segundo en ejecutarse
Thread.Sleep(1000)

End SyncLock
Console.WriteLine("Fin bloque de código.")
End Sub
End Class


Si lo ejecutáis, funciona exactamente igual que el ejemplo de C#.


Conclusión

Como siempre alguno se puede preguntar ¿y para qué quiero bloquear el acceso a un bloque de código?

Pues en el libro de Kevin Scribner sirve para hacer una clase singleton que devuelve una única instancia de WorkflowRuntime a todas los procesos que llamen a una clase estática, que es una solución que a mi me parece muy interesante.

Pero está claro que si no estás realizando un proceso multi-hilo, la concurrencia no te debería importar demasiado, pero, a poco que crezca tu aplicación, los hilos serán imprescindibles y el control de concurrencia puede ser muy útil.

Aunque el uso que le deis queda en vuestras manos, o más bien abierto a vuestra imaginación.

miércoles, 29 de agosto de 2007

Implementar una interface con un solo clic

Hace tiempo prometí explicar cómo se puede implementar una interface con sólo 2 clics, pero me he dado cuenta de que únicamente hace falta 1.

Qué es una interface y qué los dos tipos de implementación que podemos usar lo tenéis muy bien explicado en esta página.
Una vez vista la teória, voy a ir a un ejemplo mucho más práctico para demostrar como funciona otra de las ayudas de Visual Studio 2005. Supongamos que tenemos la siguiente interface:
Una interface muy sencilla con 2 métodos, bien, creamos una clase que la va a implementar:


Si os fijáis, el IDE de Visual Studio hace que aparezca un pequeño rectángulo azul debajo del nombre de la interface (cuando el cursor está sobre antes, después o en medio del nombre de la interface), este rectángulo será el que nos ayude a implementarla.
Vamos a pasar el ratón sobre el rectángulo, y veamos que pasa:


(clic en la imagen para ampliar)

Vaya, se despliega este menú para implementar la interface, hagamos clic en la primera opción:


(clic sobre la imagen para ampliar)

Ya tenemos la interface implementada con tan solo 1 clic. Bueno, falta escribir el código de los métodos, pero en principio ya funcionan (aunque sólo lancen una excepción).

Pero alguno puede pensar, “vaya tontería, esos 2 métodos no me cuesta tanto escribirlos”, y tiene razón, pero
- ¿qué pasa si la interface tiene 200 métodos?
o
- ¿qué pasa si no tenemos documentación sobre los métodos porque es una interface del sistema o de un tercero?
En estos casos el IDE de Visual Studio viene en nuestra ayuda, como hemos visto.

Casi se me olvida, ¿qué pasaría si a la interface le añadiésemos un método?, tal que así:



Pues lo único que tenemos que hacer es volver a realizar los mismos pasos, cursos sobre el nombre de la interface, ratón sobre el rectángulo azul y clic sobre la opción:



(clic en la imagen para ampliar)

viernes, 24 de agosto de 2007

Estoy Leyendo...

De vuelta de unos días de descanso he decidido hacer unos cambios en el blog. Si os fijáis en el panel de la derecha, debajo de las etiquetas, he añadido una sección con los libros que estoy leyendo actualmente.

Me parece que la primera vez que vi algo así fue en el blog de Rodrigo Corral y me pareció muy buena idea, sobre todo porque Rodrigo también comenta los libros, yo intentaré imitarle (siempre hay que copiar de los mejores) y cuando acabe de leerlos o los tenga muy avanzados escribiré un post, aunque supongo que las más 500 páginas de WCF step by step y las más de 700 de CLR via C# me tendrán entretenido una buena temporada.

La verdad es que también me gustaría tener un apartado de "Jugando a..." como César Reneses pero no dispongo de tiempo, tal vez cuando esté de vacaciones.

jueves, 9 de agosto de 2007

Principios del desarrollo de software

Hace un par de días leí en Navegapolis la traducción de los principios del Waterfall Manifesto y la verdad es que me identifico mucho con estos 2 (en negrita mis comentarios):

- Los cambios de requisitos son un grano en el culo, sobre todo cuanto más tarde te los dicen. Házselo saber al cliente y haz que pague caro si está pensando siempre en cambios.

Quien no se ha encontrado con un cliente/jefe que cambia los requerimientos cada 2 días, dependiendo de como se levante esa mañana. A un cliente le puedes cobrar por los cambios, pero ¿qué haces si es tu jefe?

- Los buenos procesos forjan héroes. Los gestores, programadores y usuarios tienen que saberlo y reconocer que se enfrentan a un difícil reto.

Totalmente cierto, el poder finalizar con éxito algunos proyectos sólo puede ser tarea de un héroe.


Y este otro es una verdad como un templo:

- La complejidad -el arte de maximizar el tiempo necesario para comprender tu diseño y tu código- es esencial para que se vea tu valor como programador (y garantizar tu puesto de trabajo).

Sin palabras.

miércoles, 8 de agosto de 2007

Montar un servicio WCF en 10 pasos

Para los que no conozcáis Windows Comunication Foundation (WCF para los amigos) os dejo unos cuantos enlaces muy recomendables:

Visión Global de Arquitectura de Windows Communication Foundation

Artículos de Aaron Skonard en MSDN Magazine (aunque los veáis en inglés, redirecciona a los artículos en castellano)

Artículos de Juval Lowy en MSDN Magazine (lo mismo que los de Skonnard)

Fundamentals of WCF Security – Michele Leroux Bustamante (en inglés, pero merece el esfuerzo)

Blog de Oskar Álvarez en Geeks.ms

En este post me voy a centrar en la implementación de un servicio WCF muy básico y con pasos muy concretos (algunos mucho más fáciles que otros).

Empecemos, en Visual Studio creamos una solución en blanco (a mi me gusta trabajar así, cada cual con sus manías), a la que añadimos dos proyectos de consola (con C#): Host y Cliente.

Y ahora vamos por partes:

Proyecto Host

1. Agregar referencia al ensamblado System.ServiceModel.

2. Definir una interface con el atributo [ServiceContract] para indicar que es la que define el contrato de WCF. Los métodos de esta interface que se vayan a exponer en deben incluir el atributo [OperationContract].




[ServiceContract]
public interface IClase
{
[OperationContract]
string Funcion1();

[OperationContract]
int Funcion2();

// Este método no se expone porque no tiene el atributo
//[OperationContract]
void MetodonoImplementado();
}


3. Definir una clase que implemente la interface IClase (en un futuro post explicaré cómo se implementa una interface con sólo dos clics).



class Clase : IClase
{
string IClase.Funcion1() { return "Respuesta"; }

int IClase.Funcion2(){ return 10; }

void IClase.MetodonoImplementado(){ return; }
}




4. Añadimos un fichero de configuración (app.config) al proyecto, para establecer las propiedades del servicio.


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<!--Comportamiento se define un poco más abajo, en la sección BEHAVIORS-->
<service name="Host.Clase" behaviorConfiguration="Comportamiento">
<host>
<!--Se establece la URL del servicio-->
<baseAddresses>
<add baseAddress="http://localhost:8000/WCF/"/>
</baseAddresses>
</host>
<!--En el enpoint se define el ABC de los servicios WCF, Address, Binding y Contract-->
<endpoint address="Clase"
binding="wsDualHttpBinding"
contract="Host.IClase"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Comportamiento">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>




5. En el método Main() iniciamos el servicio.



class Program
{
static void Main(string[] args)
{
Type tipo = typeof(Clase);
using (ServiceHost miHost = new ServiceHost(tipo))
{
miHost.Open();
Console.WriteLine("Servicio en ejecución");
Console.WriteLine("Pulse una tecla para salir...");
Console.ReadKey();

miHost.Close();
}
}




6. Ejecutamos únicamente el proyecto Host.

7. Desde la consola de Visual Studio * ejecutamos la herramienta svcutil.exe, que creará los ficheros que servirán de proxy entre el cliente y el servicio.




Se crean 2 ficheros:
- Clase.cs - definición del proxy.
- Output.config - fichero de configuración, que debe ser renombrado como
app.config para los proyectos Windows (web.config para proyectos Web)

* Consola de Visual Studio, la podemos encontrar en: Inicio - Todos los programas - Microsoft Visual Studio 2005 - Herramientas de Visual Studio


Paramos la ejecución y pasamos al otro proyecto.

Proyecto Cliente

8. Agregamos la referencia al ensamblado System.ServiceModel, igual que el paso 1 del proyecto Host.

9. Añadimos los ficheros que genera la herramienta svcutil.exe (paso 7 del proyecto Host), Clase.cs y app.config.

10. En el método Main() iniciamos el proxy y ejecutamos los métodos.

class Program
{
static void Main(string[] args)
{
Console.WriteLine("Pulse cualquier tecla cuando el servicio esté iniciado...");
Console.ReadKey();

using (ClaseClient proxy = new ClaseClient(“WSDualHttpBinding_IClase”))
{
Console.WriteLine(proxy.Funcion1());
Console.WriteLine(proxy.Funcion2().ToString());
Console.WriteLine("Pulse cualquier tecla para salir...");
Console.ReadKey();
proxy.Close();
}
}
}




Ya lo tenemos todo listo, vamos a probarlo, para ello tenemos que ejecutar los dos proyectos al mismo tiempo, por lo que en las propiedades de la solución hay que establecer Proyectos de inicio múltiples y establecer la acción de ambos proyectos a Iniciar, y ejecutar (F5).



Por supuesto que WCF es mucho más complejo, pero como toma de contacto creo que está bien, en próximos post entraremos en profundidad en más características.

martes, 31 de julio de 2007

Campaña MasFoxPro

Yo aprendí a programar con Visual Basic 6, pero cuando empecé a trabajar programando, que son cosas muy distintas, fue con Visual FoxPro 6. Vamos, que me ha dado de comer muchos años, y también es el "culpable" de que esté en Barcelona.

Y aunque he tardado un poco en hacerlo, me he unido a la campaña MasFoxPro para pedirle a Microsoft que siga con el desarrollo de Visual FoxPro o, si no le resulta rentable o no entra en sus planes de negocio, lo libere para que la comunidad de desarrolladores de FoxPro lo haga.

Y seguro que lo harán encantados, porque comunidades como PortalFox, Foxite, CodeFox, y muchas otras, llevan muchos años ayudando a que programar con VFP sea más fácil, y haciendo el trabajo que Microsoft no está interesada en hacer, como traducir el IDE de VFP al castellano y sacar herramientas de informes o reparación de bases de datos.

Así que ya sabes, si alguna vez has trabajado con Visual FoxPro, por favor, únete a la causa.


PD: este post va por la gente que he conocido gracias a VFP, Suso, Leo, Eva, Juanji, Elena, Samu, Juan Carlos, Mercè, Merce, Josep, Humi, Manel, Pere, Xavi Rubio, los Javeros de Costaisa, Ade, Icu, Jose, Xavi, Joaquín, y todos los demás con los que he trabajado y que me deben perdonar por mi mala memoria al recordar los nombres pero de los que no me olvido.

sábado, 28 de julio de 2007

Code Snippets (II)

Trasteando con los code snippets

Como vimos en el anterior post, los code snippets ayudan a escribir código, y el Visual Studio incluye una gran cantidad de ellos, vamos a ver cómo encontrarlos.
Seleccionamos Herramientas -> Code Snippets Manager, y nos muestra la siguiente ventana:



Seleccionamos el lenguaje que estemos utilizando, y nos actualiza las categorías que trae por defecto, si os fijáis existe la categoría My Code Snippets para incluir los que creemos.

Bien, vamos a buscar el code snippet que utilizamos en el post anterior:



Si echáis un vistazo a todas las categorías y los code snippets que se incluyen podéis ver que están contempladas muchas acciones comunes, pero ¿qué pasa si no encontramos el code snippet que nos hace falta? Pues aquí tenemos 2 opciones:

- Modificar uno existente para que incluya un cambio o crear uno nuevo a partir de uno existente
- Buscar code snippets que alguien haya creado

Modificar un code snippet existente

Si nos fijamos en la imagen anterior, al seleccionar un code snippet nos muestra dónde está, en este caso el que define una propiedad se encuentra en C:\Archivos de programa\Microsoft Visual Studio 8\Vb\Snippets\1033\common code patterns\properties and procedures\DefineAProperty.snippet.

Con esta ruta podemos ver un par de cosas: que cada code snippet se guarda en un fichero .snippet y las colecciones están agrupadas en directorios, por lo que la agrupación física y la lógica coinciden.

Vamos a modificar este snippet para que el tipo de la propiedad siempre sea string. Abrimos el fichero DefineAProperty.snippet con el Visual Studio (o con el bloc de notas), y podemos observar la estructura de un code snippet sencillo:


<?xml version="1.0" encoding="UTF-8"?>
<CodeSnippets mlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>Define a Property</Title>
<Author>Microsoft Corporation</Author>
<Description>Defines a Property with a backing field.</Description>
<Shortcut>Property</Shortcut>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>PropertyName</ID>
<Type>String</Type>
<ToolTip>Replace with property name.</ToolTip>
<Default>NewProperty</Default>
</Literal>
<Literal>
<ID>PropertyType</ID>
<Type>
</Type>
<ToolTip>Replace with the property type.</ToolTip>
<Default>Integer</Default>
</Literal>
<Object>
<ID>PrivateVariable</ID>
<Type>Object</Type>
<ToolTip>Replace this with the private variable name.</ToolTip>
<Default>newPropertyValue</Default>
</Object>
</Declarations>
<Code Language="VB" Kind="method decl">
<![CDATA[
Private $PrivateVariable$ As $PropertyType$
Public Property $PropertyName$() As $PropertyType$
Get
Return $PrivateVariable$
End Get
Set(ByVal value As $PropertyType$)
$PrivateVariable$ = value
End Set
End Property
]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>


Vaya si es XML. ¿Qué más podemos ver?
Que hay una cabecera Header donde poner los datos del creador del code snippet, su descripción y el ShortCut o alias del code snippet.
Que hay un elemento Declarations donde se definen los literales del code snippet (los que se muestran en un cuadrado verde) y se especifica el texto que se debe mostrar cuando se pase el ratón sobre él.
Y que hay un elemento Code, que es donde se está el código que va a aparecer cuando introduzcamos un snippet. Aquí podemos ver los literales que se defienen arriba y se deben reemplazar por el nombre de la variable o el tipo de dato.

Parece fácil, así que vamos a hacer una pequeña modificación para que la propiedad siempre sea de tipo String, para ello tenemos que comentar el literal PropertyType y en el elemento Code poner en su lugar String, algo así:


<?xml version="1.0" encoding="UTF-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>Define a string Property</Title>
<Author>bousan</Author>
<Description>Defines a string Property with a backing field.</Description>
<Shortcut>SProperty</Shortcut>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>PropertyName</ID>
<Type>String</Type>
<ToolTip>Replace with property name.</ToolTip>
<Default>NewProperty</Default>
</Literal>
<!--<Literal>
<ID>PropertyType</ID>
<Type>
</Type>
<ToolTip>Replace with the property type.</ToolTip>
<Default>Integer</Default>
</Literal>-->
<Object>
<ID>PrivateVariable</ID>
<Type>Object</Type>
<ToolTip>Replace this with the private variable name.</ToolTip>
<Default>newPropertyValue</Default>
</Object>
</Declarations>
<Code Language="VB" Kind="method decl">
<![CDATA[
Private $PrivateVariable$ As string
Public Property $PropertyName$() As string
Get
Return $PrivateVariable$
End Get
Set(ByVal value As string)
$PrivateVariable$ = value
End Set
End Property
]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>


Como se puede ver, he cambiado el shorcut, la descripción, he comentado el literal PropertyType y lo he sustituido en el elemento Code por string.

Ahora tenemos 2 opciones: guardarlo con en el mismo fichero que estaba, lo cual no es muy recomendable porque no siempre vamos a querer crear propiedades de tipo string, o guardarlo en un fichero diferente, por ejemlplo DefineAStringProperty.snippet, que es lo que vamos a hacer.
Si volvemos al Code Snippet Manager podemos encontrar el snippet que acabamos de crear.

También podemos crear un snippet desde cero y añadirlo a una de las carpetas que ya están registradas por el Code Snippet Manager.


Buscar code snippets

Como yo sé que no soy el único programador del universo siempre que se me plantea un problema, y antes de empezar a devanarme los sesos, busco en Internet si alguien tuvo el mismo problema y ha encontrado una solución. Con los code snippets ocurre lo mismo, hay muchos en diferentes webs que han sido creados por otros programadores que posiblemente se han encontrado en la misma situación que nosotros. Sólo hay que poner "code snippet" en vuestro buscador favorito (el mío es Google, por si alguien lo quiere saber) y tener un poco de suerte.

Una vez que encontremos el snippet que nos hace falta, creamos un fichero .snippet y lo copiamos en él. Si el fichero está en uno de los directorios que están referenciados en el Code Snippet Manager, el nuevo snippet aparecerá en la lista de los existentes. Pero si lo creamos en otro directorio, por ejemplo uno de red para que puedan acceder todos los programadores de un grupo de trabajo, hay que añadir ese directorio al Code Snippet Manager, aunque lo más fácil es mantener la estructura lógica que ya nos presenta Visual Studio.

Casi se me olvida, en MSDN podéis encontrar un editor de Code Snippets en Visual Basic, para no tener que pelearos con el XML.

Y con esto finalizan los posts sobre Code Snippets, por ahora, porque prometo más.

domingo, 22 de julio de 2007

Code snippets (I)

¿Qué son y para qué sirven?

Visual Studio 2005 tiene un par de novedades que hacen que la tarea de escribir código sea un poco menos pesada. Una de estas novedades son los code snippets.

Según MSDN son: "bloques de código reusables orientados a tareas". Vaya definición, así que vamos a poner un ejemplo para que se pueda ver más claro. Si programando en C# tenemos que crear una propiedad dentro de una clase tendremos que escribir algo parecido a esto:


private string _miPropiedad;

public string miPropiedad
{
get
{
return _miPropiedad;
}

set
{
_miPropiedad = value;
}
}


Bien, esto son 19 palabras (sí, las he contado), y unos 150 caracteres, y sólo para una propiedad. Imaginaos si hay que escribir una clase con 50 o 100 propiedades, la cantidad de tiempo que te puede llevar. ¿Y no habrá en algo en Visual Studio para ayudarnos? Pues esto es lo que hacen los code snippets.

Vamos a usar este mismo ejemplo y usar un code snippet para ver lo fácil que es. Escribimos “prop” y el Intellisense (si lo tenemos activado) nos muestra lo siguiente:


Si presionamos TAB, ocurrirá lo siguiente:


Podemos observar que aparece en un rectángulo verde el tipo de variable asociada a la propiedad, el nombre de esa variable y el nombre de la propiedad. Como se puede suponer, al cambiar el tipo de dato de la variable automáticamente se cambia el tipo de dato de la propiedad.
Para movernos entre los diferentes elementos que se pueden cambiar hay que presionar la tecla TAB y para volver al elemento anterior con Shift + TAB, y cuando finalicemos de modificar este código y tengamos la propiedad que deseamos sólo hay que pulsar ENTER para seguir con el resto del código.

Para obtener el primer fragmento de código de este post, tendremos que escribir: string (una sola vez), _miPropiedad, y miPropiedad. En total son 4 palabras y unos 33 caracteres. Vaya cambio, ¿no?

Pues esto es un code snippet, un fragmento de código que se activa con Intellisense mediante un “alias” que tiene cada snippet.

¿Y en VB.NET? Pues es algo parecido, puesto que después de escribir el alias o identificador del code snippet hay que poner un “?”, con lo que tenemos prop? y presionar TAB.

Hay otra forma de insertar un snippet es presionando el botón derecho en la ventana de código y eligiendo la opción de Insertar Snippet, con lo que tenemos:


Además Visual Studio nos permite modificar los snippets existentes o crear unos nuevos, pero eso será tema par otro post.

lunes, 16 de julio de 2007

Control de concurrencia pesimista en ADO.NET (VB.NET)

Como lo prometido es deuda, aquí esta el código en VB.NET del anterior artículo


Imports System
Imports System.Text
Imports System.Data
Imports System.Data.SqlClient

Namespace BloqueoPesimista

Module Module1

Sub Main()
Dim ds As DataSet = New DataSet()
Dim conexion As SqlConnection = New SqlConnection()
Dim transaccion As SqlTransaction
Dim comando As SqlCommand = New SqlCommand()
Dim da As SqlDataAdapter = New SqlDataAdapter()

Console.WriteLine("Pulse una tecla para iniciar...")
Console.ReadKey()

Try
' La cadena de conexión indica que atacamos a la base de datos Northwind del servidor local
conexion = New SqlConnection("Data Source=.;Initial Catalog=Northwind;Integrated Security=True")

comando.Connection = conexion
comando.CommandType = CommandType.Text

' El SELECT tiene un parámetro para evitar SQL Injection
comando.CommandText = "SELECT ProductID, ProductName FROM Products WITH (Rowlock,Xlock) " & _
"WHERE ProductID = @ID"
comando.Parameters.AddWithValue("@ID", 1)
da.SelectCommand = comando

'Abrimos la conexión y ejecutamos en comando
'Nota: también se puede hacer con la sentencia Using() que nos evita abrir y cerrar la conexión
conexion.Open()

' La transacción no tiene constructor, se crea a partir de la conexión a través de un Class Factory
transaccion = conexion.BeginTransaction(IsolationLevel.ReadCommitted)

' Una vez creada la transacción la asignamos al comando
comando.Transaction = transaccion

' Ejecutamos el comando mediante el SQLDataAdapter
da.Fill(ds, "Products")

' Mostramos el registro bloqueado
Console.WriteLine("Registro con ProductID = {0} está bloqueado.", ds.Tables("Products").Rows(0)("ProductID"))

Console.WriteLine("Pulse una tecla para finalizar el bloqueo...")
Console.ReadKey()

' Finalizamos la transacción, aquí ya se deshace el bloqueo
transaccion.Rollback()

' Cerramos la conexión
conexion.Close()

Catch ex As Exception
If conexion.State <> ConnectionState.Closed Then
conexion.Close()
End If

Console.WriteLine(ex.Message)
Console.ReadKey()

End Try

End Sub

End Module

End Namespace

viernes, 13 de julio de 2007

Control de concurrencia pesimista con ADO.NET (C#)

Esta es la primera entrada seria del blog, después de la presentación, así que espero que me salga bien.

El tema a tratar es el control pesimista en ADO.NET como solución para la concurrencia entre varios usuarios al acceder a un mismo registro de una tabla. El caso concreto que voy a tratar corresponde a una base de datos SQL Server. Para otro tipo de bases de datos existen otras soluciones.

Para los que no conozcáis como maneja la concurrencia ADO.NET tenéis una introducción en este blog, o en esta entrada de MSDN.

En este post vamos a tratar el caso de la concurrencia pesimista, esto es, cuando un usuario accede a un registro éste quedará bloqueado para los demás usuarios que tengan acceso a la base de datos.

Para que os hagáis una idea de por donde van los tiros, se trata de especificarle a SQL Server que queremos bloquear un registro mientras estamos en una transacción.

¿Cómo se hace?

Vayamos por partes, lo primero que tengo que explicar es que en SQL Server existe una instrucción en la sentencia SELECT para que bloquee un registro cuando lo leemos. Esta instrucción se conoce como Table Hint y lo que hace es indicarle al optimizador de consultas (query optimizer) el método de bloqueo de la tabla o vista.

Por emplo: SELECT * FROM MiTabla WITH(Rowlock, Xlock) WHERE id = 10;

Rowlock -> fuerza el bloqueo de los registros que devuelva la instrucción.
Xlock -> indica que el bloqueo es exclusivo.

Y esta sentencia SELECT la tenemos que iniciar con una transacción abierta. El bloqueo existe mientras la transacción esté en curso, por tanto, hasta que no se finalice la transacción (Commit o Rollback), se salga de su alcance o se cierre la conexión, el bloqueo permanecerá activo. Para que el bloqueo sea efectivo el nivel de asilamiento de la transacción (isolationLevel) puede ser ReadCommitted, ReadUnCommitted, RepetableRead o Serializable, no aceptandose Chaos, ni SnapShot, ni Unspecified.



El código

Seguro que viendo el código lo entenderéis mejor de que va todo esto, así que aquí lo tenéis:




using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace BloqueoPesimista
{
class Program
{
static void Main(string[] args)
{

DataSet ds = new DataSet();
SqlConnection conexion = new SqlConnection();
SqlTransaction transaccion;
SqlCommand comando = new SqlCommand();
SqlDataAdapter da = new SqlDataAdapter();

Console.WriteLine("Pulse una tecla para iniciar...");
Console.ReadKey();

try
{

// La cadena de conexión indica que atacamos a la base de datos Northwind del servidor local
conexion = new SqlConnection("Data Source=.;Initial Catalog=Northwind;Integrated Security=True");

comando.Connection = conexion;
comando.CommandType = CommandType.Text;

// El SELECT tiene un parámetro para evitar SQL Injection
comando.CommandText = "SELECT ProductID, ProductName FROM Products WITH (Rowlock,Xlock) " +
"WHERE ProductID = @ID";
comando.Parameters.AddWithValue("@ID", 1);
da.SelectCommand = comando;

//Abrimos la conexión y ejecutamos en comando
//Nota: también se puede hacer con la sentencia Using() que nos evita abrir y cerrar la conexión
conexion.Open();

// La transacción no tiene constructor, se crea a partir de la conexión a través de un Class Factory
transaccion = conexion.BeginTransaction(IsolationLevel.ReadCommitted);

// Una vez creada la transacción la asignamos al comando
comando.Transaction = transaccion;

// Ejecutamos el comando mediante el SQLDataAdapter
da.Fill(ds, "Products");

// Mostramos el registro bloqueado
Console.WriteLine("Registro con ProductID = {0} está bloqueado.", ds.Tables["Products"].Rows[0]["ProductID"]);

Console.WriteLine("Pulse una tecla para finalizar el bloqueo...");
Console.ReadKey();

// Finalizamos la transacción, aquí ya se deshace el bloqueo
transaccion.Rollback();

// Cerramos la conexión
conexion.Close();
}
catch (Exception e)
{
if (conexion.State != ConnectionState.Closed)
conexion.Close();

Console.WriteLine(e.Message);
Console.ReadKey();
}
}
}
}



Se trata de una aplicación de consola en C#, en un futuro post pondré el código en VB.NET. Así que sólo hay que copiarlo en un proyecto de consola.


Vamos a probarlo

Para poder pobrarlo, hay que Generar el proyecto, con lo que nos creara un fichero .EXE en la carpeta Bin/Debug del proyecto.
Ejecutamos el exe una vez y pulsamos una tecla para que se inicie el bloqueo.







Si volvemos a ejecutar el exe e iniciamos el bloqueo, la aplicación se quedará esperando que se libere el registro.






En cuanto finalicemos la primera ejecución, la segunda podrá acceder al registro y bloquearlo.


Y con esto finalizamos por hoy. Para ser la primera entrada me ha quedado un poco larga, pero espero que pueda ayudar a cualquiera de los que la lean.

Cualquier duda o sugerencia, por favor, en los comentarios.


PD: ¿Es el control de concurrencia pesimista la mejor opción? En absoluto, pero para algún caso en concreto puede ser LA SOLUCIÓN. Queda a vuestro criterio el usarlo o no.

jueves, 12 de julio de 2007

Presentación

Sed todos bienvenidos a esta aventura en forma de blog.

Antes de nada me presento, me llamo Pablo y trabajo como programador en la central de MRW de Barcelona. Aunque soy gallego llevo varios años vivendo en tierras catalanas y disfrutando de su clima (los gallegos que viváis en Barcelona ya me entendéis) y de su gente.

El principal motivo para crear este blog es poder compartir con la comunidad de programadores mis experiencias en el desarrollo de aplicaciones en .NET, y así ayudar a los que se encuentren con algún problema con el que ya me he peleado, o con los que me esté peleando. Sí, peleando porque cualquiera que haya programado sabe que con las aplicaciones te peleas, bueno, más bien te peleas con la tecnología por que no consigues que haga lo que pretendes o no hace lo que debería hacer.

No me considero ningún experto, sólo soy alguien que tiene la suerte de trabajar en lo que le gusta y disfruta de su trabajo, y que quiere aportar su pequeño granito de arena a la comunidad.

¿Por qué sobre .NET?
Esta pregunta tiene una respuesta muy fácil: porque es con lo que trabajo a diario (es lo que me da de comer) y es lo que más conozco. No voy a entrar en si .NET es mejor o peor que Java o que Ruby o que X o que Y. Yo sólo puedo hablar sobre lo que conozco, y como casi toda mi experiencia profesional se ha basado en .NET sería un poco absurdo si hablase sobre otro lenguaje.

También podría hablas sobre Visual Fox Pro o sobre Visual Basic 6.0, que es con lo que empecé a programar, pero como los tengo un poco abandonados no creo que aportase demasiado.

Pero que yo hable sobre .NET no quita que en este blog se acepten aportaciones sobre cualquier tema (relacionado con la programacióno la informática, claro) de cualquiera. Estaré encantado de que me enviéis cosas para publicar o añadir un link a vuestro blog.


Lo dicho, sed todos bienvenidos.


Actualización 18/07/2007: la postdata me quedó un poco borde, así que mejor la quito. Podéis poner lo que queráis en los comentarios que ya lo moderaré cuando tenga tiempo.