Ya tenemos Beta 2 del libro "" . Se puede bajar desde codeplex
Creo que una imagen vale más que mil palabras.
El siguiente diagrama no cambia mucho del que teniamos en la guia 1, pero voy a decir las "cajitas" que me parecieron mas significativas:
- Business Entities: Me parece curioso que pongan esta capa. ¿Nos estan invitando a tener entidades customizadas? Si este libro no lo hace, yo los invito

- MessageTypes: Los message Types son clases dedicadas a ser objetos de transferencia, es decir Request y Response. Usar esta capa, aunque puede resultar en más tiempo de desarrollo para mapear las business entities con un Message Type, valen la pena, porque si lo sacas y retornas directamente las Business Entities y en algún momento agregas una propiedad a una business entity, esa propiedad cambiaría la firma del servicio. Si el servicio es un servicio de WCF usado por muchas aplicaciones externas, todas las aplicaciones externas dejarian de funcionar porque no sabrían como deserializar el mensaje.

Lo mejor de todo, es que aunque sea beta 1 no tiene ninguna incidencia de instalación
La saga continúa, hoy nos llega una factoría que se vale de la herencia entre los elementos a crear para simplificar y generalizar el código del cliente.
Factoría de métodos (Factory Method)
Sinopsis
Se necesita crear un objeto para tratar un proceso o evento. El tipo de objeto a crear depende del tipo de evento o de datos externos. Necesitamos en el cliente (o creador) usar el mismo código. El creador necesita crear instancias de diferentes tipos, por tanto no se puede usar un tipo concreto.
Contexto
Consideremos la creación de un formulario base para el mantenimiento de personas. Queremos en el formulario base colocar la llamada al servidor, esto nos indica que el formulario base nunca trabajara con objetos de un tipo concretos, sino que usara la clase base y esta clase base depende del formulario desde donde se llama. Por ejemplo, desde el formulario de proveedores se mostrará un objeto proveedor con su información sobre el IVA, mientras que en el formulario de empleados se obtendrá un objeto empleado, no tendrá información sobre el IVA, pero si sobre el número de expediente. Esto implica que:
- Hay un modelo de herencia.
- Que una clase abstracta o interfaz provee una lógica que podíamos denominar de mínimo común múltiplo.
- Que las clases concretas implementarán tareas específicas para ellas.
Solución
Hay un principio de los diseños orientados a objetos conocido como Principio de sustitución de Liskov. Este principio nos dice que cualquier función que utilice una referencia a una clase base debe ser capaz de usar cualquier clase derivada sin saberlo. Por ejemplo, si tengo que elegir entre crear una instancia de IEnumerable o de ArrayList, elegiré IEnumerable porque esta implementada por más. No hace falta llegar a object, pero la idea es encontrar esa clase base.
Siguiendo con el ejemplo de persona y empleado del post anterior, el código debe verse así:
Persona persona = new Empleado ();
Y no así
Empleado cliente = new Empleado ();

Esto es un patrón de factoría, y como dije en el primer post, debemos evitar el uso del new. Por lo tanto el new de empleado debe irse, ¿pero por que lo remplazamos? No podemos hacer un new de la clase Persona porque es abstracta, ni hacer una factoría simple porque, según el problema planteado al principio del post, este codigo cliente se debe usar para crear tanto empleados como clientes. Entonces terminamos cayendo en factory method. Justamente el problema que se plantea para resolverlo por medio del Factory Method es que una clase cliente necesita instanciar una clase hija, pero no sabe cuál. La solución que propone el Factory Method es crear una clase base con un metodo cuya función sea crear la clase que se necesita, permitiendo a la clase que deriban de ellos concretar el tipo a crear.

Ahora viene la sección en que el abuelo cuenta sus batallitas.
Me he encontrado con este patrón al programar los asientos sobre los libros contables, donde dependiendo de la cuenta se registra en el libro mayor o en el libro menor. Hace poco tiempo, use este patrón para una gestión de siniestros en una empresa de seguros. Podía existir distintos tipos de siniestros (autos, casa, etc) pero todos se informaban, se visualizaban, etc.
Roles
Producto (Persona)
Define la interfaz de los objetos que crea el método de fabricación.
ProductoConcreto (Empleado)
Implementa la interfaz Producto.
Creador (CreadorPersona)
Declara el método de fabricación, el cual devuelve un objeto del tipo Producto. También puede definir una implementación predeterminada del método de fabricación que devuelve un objeto ProductoConcreto.
CreadorConcreto (CreadorEmpleado)
Redefine el método de fabricación para devolver una instancia de ProductoConcreto.
Consecuencias
Proporciona "enganches" para las subclases: Crear objetos dentro de una clase con un método de fabricación es siempre más flexible que hacerlo directamente.
Conecta jerarquías de clases paralelas: La clase AdministradorCliente crea un objeto Cliente, la clase AdministradorEmpleado crea un objeto Empleado, etc.
Mantenimiento del algoritmo que decide que clase se creará.
Implementaciones
Existen dos variantes posibles, que la clase con Rol Creador sea una clase concreta o abstracta (también una interfaz). Si es abstracta nos permitirá escribir un nuevo método de creación para cada clase, mientras que si es concreta debemos primero marcarlo como virtual, y después sobrescribirlo en la clase hija con el peligro que puede ser olvidarse de sobrescribir uno.
Aquí se muestra el código por medio de una clase abstracta.
public abstract class CreadorPersona{
public abstract Persona CrearPersona();
}
public class CreadorCliente : CreadorPersona{
public override Persona CrearPersona(){
return new Cliente();
}
}
public class CreadorEmpleado : CreadorPersona {
public override Persona CrearPersona(){
return new Empleado();
}
}
El código anterior es la implementación que mas se usa, pero también puede suceder que la creación del objeto suponga la utilización de muchos recursos. En esto casos podemos realizar una creación tardía.
public abstract class CreadorPersona{
protected abstract Persona CrearPersona();
public abstract Persona CrearPersona();
}
public class CreadorCliente : CreadorPersona{
public override Persona CrearPersona(){
if (persona==null)
persona = new Cliente();
return persona;
}
}
También deberemos proveer un mecanismo para saber cual de las clases concretas es la que debemos usar. Para esto usamos un método estático que nos pueda devolver una instancia en base a un valor. En el ejemplo de abajo se usa el tipo como parámetro, pero bien puede ser un enumerado o un string que se saque de un archivo de configuración.
public class CreadorPersonaFactory {
public static CreadorPersona Create(Type tipo) {
CreadorPersona rtv = null;
switch(tipo.Name){
case "Cliente":
rtv = new CreadorCliente();
break;
case "Empleado":
rtv = new CreadorEmpleado();
break;
default:
throw new NotImplementedException("Tipo no valido");
}
return rtv;
}
NOTA: Esto es un ejemplo, en la vida real comparar por el tipo y no por el nombre. 
Desde el cliente el código se vería así:
CreadorPersona creador = CreadorPersonaFactory.Create(Cliente.GetType());
Persona persona = creador.CrearPersona();
persona.Operacion1();
Uso dentro de .Net
Existen diferentes ejemplos dentro de la plataforma, quizás el mas evidente por el nombre que usa es el gestor de manejadores en asp.net. Se definen dos interfaces, IHTTPHandler y IHTTPHandlerFactory, esta segunda interfaz tiene un método GetHandler() que devuelve un IHTTPHandler, De esta manera, las distintas factorías pueden especificar el tipo de IHTTPHandler. Se puede ver en la figura siguiente.

Conclusiones
En este post vimos como tratar un problema recurrente como es el crear un objeto sin saber exactamente cual es el tipo final. Vimos como por medio de factory method podemos solucionarlo y de esta manera tener clases bases que simplifiquen tareas comunes y repetitivas. Un ejemplo, puedo hacer un formulario base para la edición de un linea o fila ¿de que tipo será la fila? De una de las 20 tablas maestras que tengo en la aplicación.
Siguiendo con el hilo del
anterior artículo, ahora llega el turno de analizar en detalle cada tipo de factoría que se propuso. En esta entrada cubriré la factoría simple.
Factoría simple
Sinopsis
Este tipo de factoría se usa solo para la
misión básica de las factorías, es decir ocultar el conocimiento de cómo crear
una instancia de una clase.
Contexto
Consideremos
el problema de hacer una solución grande, estoy hablando de 150 tablas con todas
las capas de desarrollo que necesitemos. Tenemos dentro de este sistema una
clase cliente. El usuario nos informa después de 4 meses de desarrollo que el
código de cliente no puede ser consecutivo, que hay rangos de números
especiales, por ejemplo el 990-999 se usa para los clientes internos. Ahora nos
encontramos con el problema de tener que buscar en todo el código el momento
que creábamos una instancia de la clase cliente y le asignábamos un valor
consecutivo. Si esto estaría encapsulado en una función, pues seria tan fácil
como cambiar esta función.
Consecuencias
- Código más ordenado y fácil
de interpretar.
- “No hables con extraños” La
factoría habla con los constructores, los otros proyectos solo se
comunican con la factoría evitando que los cambios en el constructor repercutan en todo
el proyecto.
- Sistema con alta cohesión.
Se dice que hay alta cohesión cuando un módulo solo cumple con una
función, en el caso de la factoría esta bien claro cual es su propósito. Parafraseando a El Guille "la factoría que factorize buena factoria será".
Implementación
El primer paso para ello es dejar la clase publica si lo es y agregar un
constructor internal (Friend en VB). De esta manera la clase se podrá ver desde otro proyecto
pero no se podrá crear directamente, sino a través de la factoría. Esto nos
permite luego agregar si lo deseáramos seguridad por roles en la factoría.
Algo muy importante Hay que tener en cuenta el uso
de servicios Web, cualquier clase que se use como parte de la firma de un
servicio Web (es decir, que forme parte de los parametros o el valor de retorno) deberá igualmente tener un constructor público porque es necesario
para la serialización y deserialización a XML.
Un
método por constructor
Tenemos distintas implementaciones posibles, la
primera dice que una clase tiene la responsabilidad de crear a las instancias
de las otras por medio de un método por cada constructor de las clases que se tienen
que crear. Como solo necesitaremos de una sola instancia de la factoría, puede venir
acompañada por el uso del patrón singleton.
Aquí va un ejemplo sencillo, sin el singleton
para no complicarlo aun más
public class FactoriaSimple {
public
static Cliente
CrearCliente(){
return new Cliente();
}
public
static Empleado
CrearEmpleado(){
return new Empleado();
}
}
El mantenimiento de esta primera
implementación puede ser difícil porque tenemos que estar pendientes de agregar
un método cada vez que se agregue una clase y/o constructor.
Quien llame a este código lo tendrá que hacer
de la siguiente manera
Cliente
oCliente= FactoriaSimple.CrearCliente();
Empleado
oEmpleado= FactoriaSimple.CrearEmpleado();
Factoría estática en
clase
Esta opcion es fruto de la refactorización. Se crea un método estático que retorne una instancia de la misma clase. Aquí
el mantenimiento es más sencillo que en el primer ejemplo porque queda en la
clase, es decir que al modificar el constructor como regla debo modificar el
método estático. Una de las ventajas principales es que si cambio a la clase de proyecto, esta se lleva la factoria, por lo tanto es buena usarla cuando aun no tenemos muy claro en que proyecto estará la clase.
Si tenemos un poco de tiempo hasta podríamos hacer un snippet
que haga más sencilla la tarea o si usamos un generador de código como Code
Smith o similar agregarlo a una plantilla. El siguiente código muestra como
implementarlo.
public class
Cliente : Persona {
internal
Cliente() { }
public
static Cliente
Crear() {
return new Cliente();
}
}
Desde
el cliente el código se vería así:
Cliente oCliente = Cliente.Crear();
Empleado
oEmpleado = Empleado.Crear();
En base a las necesidades, los parametros del metodo CrearX pueden cambiar. Recuerdo un proyecto donde trabaje que le pasaba un XML, y a su vez desde el constructor estático, por ejemplo de la clase cliente se llamaba al constructor estático de la clase dirección.
Factoría genérica
Esta opcion es parecida a la primera opción (un método por constructor) pero nos valemos de generics
para que el mantenimiento sea nulo. Esto va muy bien si solamente hacemos un
new, es decir si no hay tareas complejas. Básicamente todas las entidades a
crear heredan de una entidad base, luego creamos una clase que será la factoría
para que use generics y desde el cliente le especificamos el tipo a crear.
public class Factoria<T>
where T:Persona, new() {
public
static T NewInstance(){
return new T();
}
}
La
herencia en este ejemplo se usa solo para que la cláusula where permita crear
objetos que son de un determinado tipo (en este caso Persona) y además que
tengan un constructor público. OJO constructor público es igual a que te pueden crear una instancia por fuera de la factoria. Como se ve, el método NewInstance solo se limita
a crear la instancia, no hay ningún algoritmo, ni se asocian constructores, por lo
tanto tener presente de usarlo solo para creaciones muy sencilla.
El
código cliente se vería así:
Cliente cli = Factoria<Cliente>.NewInstance();
cli.Operacion1();
También podemos aprovecharnos de la herencia
y escribir el siguiente código
Persona per = Factoria<Cliente>.NewInstance();
per.Operacion1();
Factoría genérica e
inversión de control
En este punto es bueno comentar las
herramientas de inversión de control que nos pueden ayudar para crear objetos,
y especialmente como podemos centralizar la creación de estos objetos a un solo
punto de la aplicación.
La única y gran diferencia que tiene esta factoría con la anterior es que la anterior necesita especificar el tipo concreto, mientras que esta con la interfaz le alcanza. La razon que la anterior necesita el tipo concreto es que no se puede hacer un new de una interfaz o de una clase abstracta. Esto le quita independencia al codigo cliente.
Las herramientas de inversión de control se
basan en un archivo XML para mapear el nombre de una interface y el objeto a
crear. Por ejemplo, usando StructureMap, una factoría se vería así.
public static class Factory{
public static T GetInstance<T>() {
return
StructureMap.ObjectFactory.GetInstance<T>();
}
}
Como se ve, se quita la restricción where que estaba en el ejemplo anterior, pudiendo asi crear cualquier tipo de objeto.
El XML que necesite el StructureMap sería algo así
<DefaultInstance
PluginType="EjemploFactoria.IEmpleado, EjemploFactoria"
PluggedType=" EjemploFactoria.Empleado,
EjemploFactoria"
Scope="PerRequest" />
El código cliente se vería así
IEmpleado empleado = Factory.GetInstance<IEmpleado>();
El resultado de esto es que obtendriamos una instancia del tipo EjemploFactoria.Empleado que implementa IEmpleado.
Conclusión
Los patrones de factoria simple cumplen con algo básico de la informática, que es el ocultamiento de la información que mas tarde con la llegada de la programación orientada a objetos se llamo encapsulación. (Cuando hago estos comentarios me doy cuenta que no nací con un mouse bajo el brazo
) Si hablamos de factoría, lo que ocultan o encapsulan es la forma en que se crean las intancias. Aqui he mostrado diferentes formas porque no existe una sola solucion generica. Pero por regla general las factorias simples son buenas usarla cuando no existe un modelo de herencia, sino ya tenemos que pasar a la próxima entrada del blog, las factorias de métodos.
Dentro de los patrones de diseño, existen un
grupo que se dedica a la creación de objetos. Dentro de este grupo, hay unos
específicos que se dedican a creación por medio de factorías. Son los patrones
mas usados. Veremos como crear objetos de una forma adecuada, encapsulándolos
de distintas maneras.
Quizás antes de avanzar sobre los patrones de
factorías, deberíamos preguntarnos cual es el anti-patrón, o en otras palabras
"¿Cual es la peor manera de crear una instancia de un objeto?". Y aunque
parezca mentira es la manera más utilizada, especificando desde un proyecto el
tipo de una instancia que esta en otro proyecto. Es decir el clásico new
fijando el tipo, especialmente si el tipo esta en otro proyecto porque de esta manera
fijamos dependencia no solo entre clases, sino dependencia entre proyectos. El
día de mañana te quieres llevar ese trozo de código y resulta que te tienes que
llevar media aplicación.
La siguiente historia esta basada en hechos reales
Una vez me dijeron que supervise el código de
todo un equipo de desarrollo, este equipo llevaba un historial de unos 30
proyectos y eran cerca de 120 desarrolladores. Decían tener un entorno de
trabajo maduro, que aparentemente soportaba todo lo que le echen. Pedí una
conexión a la red y un usuario en el Visual Source Safe (que tiempos aquellos) para
poder ver el código. Después de bajarme el código, le pedí al explorador de
Windows que me busque todos los archivos que tenían la palabra "factoría"... el
resultado fue nulo, como me gusta pensar bien busque "factory" pero el
resultado fue el mismo. Me acerque al jefe de desarrollo y le pregunte si
estaban usando factorías, la respuesta fue: "Eso ¿Qué es?". Es imposible lograr
un entorno de trabajo sin factorías. Las factorías son unos de los patrones de
diseño más usados, especialmente cuando se montan entornos de trabajo, porque
dan independencia a quien usa el servicio.
Los objetos de factorías tienen la
responsabilidad de crear instancias de objetos de otras clases que generalmente
están en el mismo proyecto. Tienen además la responsabilidad y el conocimiento
necesario para encapsular la forma en que se crean determinados tipos de
objetos en una aplicación.
Este artículo es una reseña, pero iré agregando una entrada con el detalle de cada uno de los que hablo acá. Existen diferentes tipos de patrones de factorías,
la factoría simple, los métodos de factoría (Factory Method) y las factorías abstractas (Abstract Factory).
Cada una de estas factorías se usa en situaciones distintas y se puede
refactorizar un sistema pasando de una a otra siguiendo el orden planteado mas
abajo.
Antes de entrar en detalle, un pequeño resúmen
de los propósitos de cada uno de los patrones:
- En
la factoría simple cada método se mapea a un constructor diferente de cada
uno de las entidades a crear. Con la introducción de .Net Framework 2.0 y posteriores esto además se puede generalizar.
- En
el Factory Method primero debe existir herencia entre las entidades a crear (o implementar una interfaz común) y luego trasladamos esta herencia a la construcción
de objetos. Por ejemplo, puede existir la entidad persona como clase
padre, y tener clases hijas como cliente, empleado, etc... Deberíamos
crear una interfaz de construcción de persona y luego entidades concretas
para los subtipos.
- En
el Abstract Factory tenemos un caso parecido al caso anterior porque tenemos
una herencia, pero además existe una familia de objetos que no pueden
relacionarse con otra familia de objetos, por ejemplo si creamos una
conexión a SQL Server no podemos asociarle un comando de Oracle. Esto
dentro de Microsoft, especialmente después de la versión 2.0 del Framework,
se conoce con el nombre de proveedor (provider).
En la figura 1, por medio de UML, se ve cada modelo de factoría antes explicadas:

Ya esta disponible y actualizado el sitio web con el material para empezar a programar en Sharepoint. Contiene 10 labs con sus correspondientes ppts. También existe una maquina virtual con todo lo necesario para programar en WSS para que no te encuentres con problemas de administración y/o instalación.
A modo de adelanto, pongo los temas que cubre, a saber:
- Web Parts (Normales y con Ajax)
- Data List (copiar ítem entre listas, algo muy útil para migrar)
- Event Handler (o como lanzar Workflow mas personalizados)
- Workflow (Sin y con Visual Studio 2008 + WF)
- SilverLight 2.0
- Page Navigation (o como agregar ítems en los menús de WSS)
- Page Branding (o como tratar de hacer hedkandi
)
- Web Services
- Content Types
- User Managment.
A disfrutar con la programación en WSS.
Aquellos que están en .Net desde las betas de la versión 1.0, recordaran entonces una guía que influyo como pocas en el desarrollo de aplicaciones, Application Architecture for .NET: Designing Applications and Services.
Ahora, luego de mas de 6 años, están sacando la versión 2.0. El link en el CodePlex contiene ahora un overview, aunque se espera que para principios del 2009 este completa. Algún adelanto se puede ver en los wiki.Los puntos que me parecieron interesantes son:
- Programación funcional (mucho mas usada desde que se incluyeron las expresiones lambda)
- SaaS
- RIA
- Model-Driven
- Por la parte de desarrollo de software, ALM, Lean, Scrum y XP (Si, yo lo tuve que leer 3 veces)
- Han incluido algo de requerimientos con los Quality Attribute.(ver el libro "Software Requirements, 2nd Edition" de Karl E. Wiegers)
- Deployment Patterns.
Esta claro que no es una actualización del viejo documento con distintos nombres sino que será una guía nueva e integral de todo el proceso de desarrollo.
Para mas info, pueden visitar el blog de J.D. Meier.
Model View Presenter es un patrón de diseño que se utiliza
para poder separar las operaciones de la interfaz de usuario con su
implementación. Este patrón está pensado especialmente para poder realizar
pruebas automatizadas de la interfaz de usuario, aunque siguen existiendo operaciones
de la interfaz de usuario que no se pueden probar, como puede ser arrastrar y
tirar. Existen en el mercado productos que facilitan la creación de objetos
falsos para la creación de pruebas basándose en la interfaz que debe
implementar el objeto. Esto hace el patrón aun más potente porque podríamos
usarlo en diferentes tipos de clientes (Windows Forms, WPF o Web)
Voy a dar un caso práctico muy sencillo. Tenemos como
requerimiento – es tan obvio que muchas veces ni está escrito como
requerimiento - que cuando una aplicación se cierra y hemos realizado algún cambio
en ella, que nos pregunte si deseamos salir sin guardar los cambios. Si no se
hizo ninguna modificación, pues no sale el mensaje.
Aquí identificamos los tres partes
Model: Los objeto de dominio que pudieron sufrir cambio.
View: La Interfaz grafica que presenta los datos.
Presenter: Toma control de los eventos/acciones de la vista.
Con los requerimientos en mano, primero definimos como
debería ser la vista
public interface IViewEmpleado
{
void SetCambios(bool
valor);
bool TieneCambios();
void Close();
bool UsuarioConfirmaCambios();
}
Definimos dos métodos para controlar el estado del
formulario, uno para decirle si ha cambiado o no y otro para saber si ha
cambiado. Tambien se define el método que le preguntara al usuario si desea
grabar o no. El método Close tiene un poco de trampa. Como verán todos los
demás lo he escrito en español, lo que sucede es que el formulario que
implementara la interfaz ya tiene un evento close que cierra el formulario, por
lo que no será necesario que yo lo implemente.
El modelo en este caso es la clase Empleado, pero como
explique en otro post, mejor hacerle una interface.
public interface IEmpleado : INotifyPropertyChanged
{
string
Apellido { get; set;
}
int
Edad { get; set;
}
string
Nombre { get; set;
}
}
Como se ve, la interfaz hereda de INotifyPropertyChanged,
necesario para saber cuándo se ha cambiado una de sus propiedades.
Por último, el presenter.
public class EmpleadoPresenter
{
private
readonly IViewEmpleado
_view;
public
EmpleadoPresenter(IViewEmpleado view)
{
_view =
view;
}
public IEmpleado
CargarEmpleado()
{
IEmpleado emp = new
Empleado();
emp.Nombre
= "Daniel";
emp.Apellido = "Mazzini";
emp.PropertyChanged += new PropertyChangedEventHandler(onCambioEmpleado);
_view.SetCambios(false);
return
emp;
}
void
onCambioEmpleado(object sender, PropertyChangedEventArgs
e)
{
_view.SetCambios(true);
}
public void Close()
{
bool puedeCerrar = true;
if (_view.TieneCambios())
{
puedeCerrar = _view.UsuarioConfirmaCambios();
}
if (puedeCerrar)
_view.Close();
}
Como decía, el presenter controla la vista y se encarga de sus
eventos, en este caso son dos. Cuando el usuario carga los datos de un empleado
nos suscribimos al evento de cambio para poder mantener la vista con el estado
actualizado. El segundo es cuando se cierra el formulario. En este caso miramos
si hay cambios y le pedimos al usuario que confirme si desea salir.
Algo importante del presenter es su constructor. Como se ve
usa la interfaz de la vista. Esto nos permite hacer Inversión de control, algo
muy útil a la hora de hacer las pruebas unitarias. En este caso no fue
necesario, pero en el mismo constructor podríamos suscribir los eventos, por
ejemplo, si cada vez que se hable el formulario tienen que estar cargados unos
datos (combos, etc.) podríamos suscribirnos al evento Load.
Una consideración sobre la vista y el presenter. Si hace dos
años hubiera hecho este mismo ejemplo, es posible que a la vista le hubieses
agregado una propiedad de tipo bindingSource y hubiese quedado el método
CargarEmpleado diferente.
public void CargarEmpleado()
{
IEmpleado emp = new
Empleado();
emp.Nombre
= "Daniel";
emp.Apellido = "Mazzini";
emp.PropertyChanged += new PropertyChangedEventHandler(onCambioEmpleado);
_view.SetCambios(false);
_view.binding.DataSource = emp;
}
La diferencia principal es que ahora está preparada para las
dos tecnologías de formularios (Windows Forms y WPF). Pero si tuviera que
hacerlo en una aplicación de cero, preguntaría sobre cual tecnología se hace
porque es conveniente este segundo método, donde todo queda más encapsulado en
el presenter.
Por último, decía que una de las ventajas son las pruebas
unitarias que podemos hacer. En este caso uso RhinoMocks como herramienta de
creación de objetos falsos o sustitutos.
[TestMethod]
public void CerrarSinCambios()
{
MockRepository
repositorio = new MockRepository();
IViewEmpleado
view = repositorio.CreateMock<IViewEmpleado>();
Expect.Call(view.TieneCambios()).Return(false);
view.Close();
repositorio.ReplayAll();
EmpleadoPresenter
presenter = new EmpleadoPresenter(view);
presenter.Close();
repositorio.VerifyAll();
}
Usando una vista falseada, lo que hago es decirle que espero
que el método TieneCambios retorne un falso y después espero que se llame al
método Close, ambos de la vista. Al hacer el ReplayAll, es como decirle que los
pasos anteriores eran una simulación. Trabajamos con el presenter y luego de
hacer los pasos de prueba, con el método VerifyAll le decimos que compare la
simulación anterior con los datos que tiene ahora. Aquí no lo explico, pero con RhinoMocks
también podríamos lanzar eventos para luego realizar validaciones, que nos
pueden servir con requerimientos como “si el checkBox Tiene Carnet de Conducir
esta marcado, se debe habilitar el textBox para que el usuario ingrese su
número de carnet”.
Este principio fue escrito por Bárbara Liskov, en su trabajo sobre abstracción de tipos de datos. Este principio está relacionado con un principio que se podria decir que nació junto con la programación orientada a objetos, que es el diseño por contratos.
¿Cansado de datos históricos? OK, como decía el dermatólogo, vamos al grano. El principio dice que cualquier función que utilice una referencia a una clase base debe ser capaz de usar cualquier clase derivada sin saberlo. Es decir que el cliente usa una referencia a la clase base, sin saber si se usa la clase derivada A o la B.
Para lograr esto, hay que usar abstracción de datos y polimorfismo, que son las bases del principio de abierto cerrado. De hecho muchas veces descubrimos que estamos fallando al principio de abierto cerrado después de descubrir un error de diseño que va en contra del principio de Liskov. En el ejemplo de código que deje en el post del principio abierto cerrado es justamente un método que debe cambiar ante un nuevo tipo de dato, incluso existiendo herencia. El problema es que la mayoría de veces descubrimos el problema demasiado tarde porque usamos casi siempre la clase concreta en lugar de la clase base. Nos damos cuenta de ello cuando empezamos a poner If en el código preguntando por el tipo del objeto.
Este principio, tal como hacía alusión antes, se usa para medir el correcto uso de una herencia. Haciendo un poco de memoria –apenas 5 años – una de las razones por las que me negaba a usar DataSet era esta. Podías tener un DataSet empleado y otro DataSet cliente, pero ninguno heredaba de persona. Cuando tenias que escribir el User Control que mostraba los datos personales, tenias que saltarte este principio y preguntar si el Dataset era de tipo Empleado o de tipo Cliente. Es decir que la herencia que me proponía el Dataset no me servía para mis reglas de negocio, pero si para su funcionamiento. (léase HasChange, AcceptChange, etc.)
Me gusta ver como ahora se enseña y aplica este principio cuando se utiliza WCF. Los ejemplos y las buenas prácticas escritas por Microsoft nos muestran una interfaz que tiene un conjunto de operaciones y luego un servicio que las implementa. Primero se busca abstraer y luego implementar.
Tal como decía al principio del post, existe una fuerte relación entre LSP y el concepto de diseño por contrato que enseña Bertrand Meyer en Construyendo Software orientado a objetos. Usando diseño por contrato los métodos de una clase declaran pre-condiciones y post-condiciones. Las pre-condiciones deben ser verdaderas para que el método se ejecute. Una vez terminado, el método garantiza que las post-condiciones sean ciertas. Usando LSP, la pre-condición se traduce a que cualquier clase derivada debe aceptar cualquier cosa que la clase base puede aceptar. La post-condición se traduce a que las clases derivadas deben ajustarse a todas la post-condiciones de la clase base. Es decir, sus comportamientos y los resultados no deben infringir ninguna de las limitaciones establecidas para la clase base. Los usuarios de la clase base no debe confundirse ante una nueva clase derivada.
Esto va de la mano con algo que menciono desde que me lo enseñaron, se debe tener dos criterios para usar clases bases, uno es dar a una aplicación un comportamiento común, y el otro usar métodos de ayuda para las clases derivadas. Pero sobre todo lo primero. Yo puedo crear un formulario base porque quiero que todos los formularios tengan el mismo comportamiento frente al evento Closing, pero también lo puedo hacer para tener funciones de ayuda del tipo CargarListaEnCombo. Siempre prefiero el primer criterio porque el segundo criterio lo puedo aislar luego en una clase de ayuda de simple instancia (lease singleton) y llevármelo a otro proyecto.
Volviendo nuevamente al porque de estos artículos, encontramos que un sistema que use este principio será más fácil de mantener que otro que no lo use. Este principio está relacionado con otros que veremos más tarde, como cohesión o acoplamiento entre clases (No hables con extraños) y con los patrones de diseño de tipo factorías (¿cómo se si debo desde el cliente usar la clase A o la B?)
Por ultimo, un comentario a nivel de usuario. El editor de Visual Studio, incluso en la versión 2008, no ayuda a usar clases bases. Si defines una variable que es del tipo de una clase base o interfaz, cuando quieres hacerle un new, el editor de Visual Studio retorna todas las clases, como si no pudiera filtrar solo aquellas clases que heredan de la clase base o implementan la interfaz.
Primero que nada, este artículo va de formación, pero también de tiene contenido no técnico. Estuve echándole un ojo a los próximos eventos más importantes que organiza Microsoft.En orden cronológico, tenemos primero el
PDC que se hace en los Ángeles la última semana de octubre, y si te apuntas sin descuentos te sale por 2395 dólares, unos 1550 €. Luego, dos semanas más tarde viene el
Tech-ed Dev Europa que se hará en Barcelona, y si te apuntas sin descuentos te sale por 2245 € + IVA. Yo, porque vivo cerca de Barcelona y no tengo gastos de viaje y hotel me sale casi igual ir a uno que a otro, pero alguien que venga desde cualquier otro punto de España o el resto de Europa, creo que le sale más a cuenta irse a Los Ángeles. Eso sin contar que se pueden comprar otras cosas.
Creo que deberíamos hacer algo para que nos bajen los precios, ya que la escusa común cuando los precios aumentan es "el dólar subió". Este no es un fenómeno solo Microsoft, pasa con las cámaras de foto, los libros, y una larga lista de etc. Siempre nos quedará skybox. 
Para los mas osados
ya se encuentra el SP1 de Visual Studio 2008, Visual Studio Team System y .Net Framework 3.5 que esta en beta aca. Este incluye varias actualizaciones, pero especialmente el soporte para SQL Server 2008. Scott
Guthrie ha puesto un post con todos los detalles (que no son pocos) del SP1.
Solo me gustaria agregar una opinión personal. Es que me cuesta creer que el SP1 del TFS 2008 pese 114 MB. Entiendo que ahora esta integrado con SQL Server 2008, pero aveces dan la imagen que se han olvidado medio producto. Ademas te ponen en la pagina de Download que tienen un problema de compatibilidad con Expression Blend, pero que es compatible con la versión de Expression Blend 2.5 Preview de Marzo. Total: Si lo instalas te quedara el entorno de desarrollo y el de diseño grafico en beta. Pero lo mas curioso es que si repasas las novedades del SP1 de TFS que quedas preguntando ¿cual de todas ellas tiene que ver algo con Expression Blend? A mi entender ninguna. Abajo las pego, por si alguien ve alguna que me ponga un comentario y se lo agradeceré. Yo ya he descartado la última "Soporte para crear proyectos de equipos desde la linea de comandos" 
- Support for Windows Server 2008.
- Support for SQL Server Codename Katmai CTP6.
- The Add to Source Control dialogs have been improved to be easier to use and more scalable.
- Drag & Drop from Windows Explorer to add to Source Control.
- Support for Version control operations on files not in bound solutions.
- Right-click access to set Working Folder/Cloak of folders from within Source Control Explorer.
- Check in date/time column in Source Control Explorer.
- Editable path field for the Source Control Explorer.
- Email work items and queries to someone.
- A new API to download files to a stream.
- Links to Team System Web Access pages from notifications.
- Improvements to the number of projects per server.
- Performance and scale improvements.
- Improvements to the VSS converter to make it much more robust.
- Support for creating Team Projects from the command line.
Cuando dimos la charla en marzo, tuvimos problemas de conexión y no pudimos hacer la charla online. Esto ya lo había comentado en otra entrada.
Hablando con José Luis, creímos mas que justo que las personas que se habían visto afectadas tuvieran de nuevo la oportunidad de verlo, por eso repetimos mañana a las 19.
Abajo esta la dirección donde pueden suscribirse.
Event URL : http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032376406&Culture=es-ES
Subo el código y la presentación del evento del jueves 27 de marzo que dí junto a Sergio Polo de EWS.
Con Sergio llegamos una hora antes al recinto, pero aún así no se pudo transmitir la conferencia por internet por problemas de conectividad. Lo siento mucho por aquellos que no pudieron vernos. (si es por ver nuestras caras no se perdieron nada
).
PPT
Código
Si tienes problemas con el navegador, puedes ir a está página y descargarlos.
Saludos.
Unas aclaraciones ante de meterme de lleno en la solución
¿Cuál era el problema con el diseño del otro día?
public List<Persona> PersonasOrdenasPorNombre(){
listaPersonas.Sort(new OrdenarPersonasPorNombre());
return listaPersonas;
}
En cierta forma, lo que decía Sergio Polo y después confirmaba Daniel Puntos, si quiero cambiar el criterio de ordenación, la clase no esta preparada. Tiene un método que sólo es capáz de ordenar de una forma, si quiero tener otro criterio de ordenación, debe crear otro método.
El secreto es aislar lo que cambia, ¿qué puede cambiar? el criterio de ordenación, el método para ordenar debe ser el mismo y debemos pasarle distintos criterios de ordenación. ¿Cómo? Haciendo que la clase agenda acepte un criterio de ordenación en lugar de tenerlos todos predefinidos.
public class Agenda{
…
public List<Persona> OrdenarUsando(IComparer<Persona> comparador) {
listaPersonas.Sort(comparador);
return listaPersonas;
}
}
public class OrdenarPersonasPorNombre : IComparer<Persona> {
public int Compare(Persona x, Persona y) {
return x.Nombre.CompareTo(y.Nombre);
}
}
public class OrdenarPersonasPorApellido : IComparer<Persona> {
public int Compare(Persona x, Persona y) {
return x.Apellido.CompareTo(y.Apellido);
}
}
En este caso, se ve que podemos ordenar por nombre o por apellido, es decir que tenemos distintas ESTRATEGIAS de ordenación. De ahí viene el patrón Strategy, como su nombre indica.
Y que pasa si quiero ordenar por orden descendente ¿creo un IComparer para el orden ascente y otro para el descente?.Este es justamente uno de los problemas que puede presentar el patrón estrategia, una explosión de clases hijas.
Siguiendo con la solución, el cliente necesitará algo más, que sería una factoría de las distintas estrategias posibles. Hago una rápida y fácil.
public class EstrategiaOrdenPersonas{
public static IComparer<Persona> ObtenerCriterio<T>() where T: IComparer<Persona>, new(){
return new T();
}
}
¿quién dijo que generics era solo para usarlo en colecciones?
El código del cliente se vería así:
Agenda agenda = new Agenda();
//agregar personas
IComparer<Persona> criterio = EstrategiaOrdenPersonas.OrdenadaTipo<OrdenarPersonasPorNombre>();
List<Persona> listaPersonas = agenda.OrdenarPersonasPor(criterio);
Hasta la próxima.
Después de haber dicho que una de las características principales del software es su capacidad para mantenerlo, me gustaría explicar un principio que ayuda a mantener esta característica.
La cruda realidad nos dice que todos los sistemas cambian durante su ciclo de vida. Por otro lado, esta realidad también me enseño que si le digo a un cliente una burrada de días para un cambio – porque es difícil o porque no me interesa hacerlo, elige la opción que más te guste J – el cliente empezará a desconfiar del código que estas escribiendo. Es decir que debemos pensar cuando desarrollamos más allá de la primera versión (o incluso de la primera fase) y ver de poner algo fácil de mantener. Esto no se contradice con hacer un diseño simple, sino que se trata de hacer un diseño adecuado que nos permitirá ser agiles luego. Ahora bien, ¿Cómo podemos crear nuestros diseños, módulos y clases para que sean estables y que duren mas allá de la primera versión?
Las entidades de software deben ser abiertas para ser extendidas y cerradas para no ser modificadas.
En otras palabras, debemos ser capaces de cambiar aquello que hace una clase (y por tanto el resultado que se obtiene) sin cambiar el código de la clase.
Con esto en mente, y poniendo un ejemplo ¿Qué está mal en el siguiente código?
Código 1
public enum TipoFigura {
Circulo,
Cuadrado
}
public class Figura {
public TipoFigura FiguraTipo;
}
public class Circulo : Figura {
public double Radio;
public System.Drawing.Point Centro;
}
public class Cuadrado : Figura
{
public double Lado;
public System.Drawing.Point SuperiorIzquierda;
}
public class MiAutoCAD
{
public void DibujarCirculo(Circulo cir)
{
}
public void DibujarCuadrado(Cuadrado cua)
{
}
public void DibujarTodos(List<Figura> listaFiguras)
{
foreach (Figura item in listaFiguras)
{
switch (item.FiguraTipo)
{
case TipoFigura.Circulo:
DibujarCirculo((Circulo)item);
case TipoFigura.Cuadrado:
DibujarCuadrado((Cuadrado)item);
default:
break;
}
}
}
}
Pues lo que está mal es que ahora puede que la aplicación solo acepte Cuadrados y Círculos, pero el día de mañana ¿Qué tengo que hacer si se aceptan elipses? Cada vez que agrego una nueva clase que herede de Figura tengo que hacer 3 cambios:
- Agregar un tipo al enumerado TipoFigura
- Crear un nuevo método en MiAutoCAD que sepa dibujar la nueva figura
- Cambiar el método DibujarTodos para que el switch tenga presente al nuevo tipo.
Demasiadas tareas para tan poco código ¿verdad? Es decir que no es un modulo fácilmente extensible, y muchos menos cerrado porque como comente debería hacer 3 cambios.
¿Cuál es el problema de raíz de este diseño? En que cada clase Figura debe asumir su responsabilidad de saber dibujarse en lugar de asignarle esa responsabilidad a la clase MiAutoCAD.Sin duda, repartir la responsabilidad de una forma adecuada es una de las tareas más cruciales en un diseño.
¿Cómo podemos solucionarlo? Dejando que la clase Figura tenga esa responsabilidad y haciendo que el DibujarTodos llame al dibujar de cada clase.
Codigo 1 refactorizado
public abstract class Figura
{
public abstract void Dibujar();
}
public class Circulo : Figura
{
public double Radio;
public System.Drawing.Point Centro;
public override void Dibujar()
{
//Dibujando Circulo
}
}
public class Cuadrado : Figura
{
public double Lado;
public System.Drawing.Point SuperiorIzquierda;
public override void Dibujar()
{
//Dibujando Cuadrado
}
}
public class MiAutoCAD
{
public void DibujarTodos(List<Figura> listaFiguras)
{
foreach (Figura item in listaFiguras)
{
item.Dibujar();
}
}
}
Ahora si es un modulo que cumple con el principio de Abierto Cerrado porque si agrego una nueva figura ya no debo:
- Acordarme del enumerado (de hecho ya no existe)
- la clase MiAutoCAD no tiene la responsabilidad de saber dibujar cada figura, por lo tanto, no tiene que agregarse un nuevo método.
- El método DibujarTodos está preparado para cualquier figura que se le agregue.
Ahora bien, a fin de que participes, te dejo el código que está debajo y quiero que sin miedo a equivocarte me digas como no se respeta el principio de Abierto Cerrado y que harías para solucionarlo. En dos días publico la solución.
Código 2
public class Persona
{
private string _nombre;
public string Nombre
{
get { return _nombre; }
set { _nombre = value; }