¿Por qué son importantes los patrones? – Libros de Referencia

A estas alturas… todavía me encuentro con aplicaciones donde es imposible
comprender el diseño e interpretar las intenciones del desarrollador.

Básicamente, pienso que hablan por sí solos, es decir, revelan la intención del
diseño, son un lenguaje común; cuando en un equipo de desarrollo se habla en
términos de patrones de código, se está hablando de las características,
cualidades y restricciones que el patrón representa. Hablamos simplificando los
problemas y partes del diseño de nuestras aplicaciones.

Prácticamente no hay API ó Framework (la de SharePoint es una excepción) donde
no se haga uso de patrones, esto hace que el uso y comprensión así como las
extensiones que realicemos sea mucho más sencillo.

“Cada patrón describe un problema que ocurre una y otra vez en nuestro ambiente
y describe el corazón de la solución del problema, de esta manera podemos usar
esta solución una y otra vez sin hacerlo de la misma manera dos veces”
Christopher Alexander [AIS+77, page x]

Los patrones nos dicen como estructurar clases y objetos para resolver
problemas, y es nuestro trabajo adaptarlos a nuestros diseños.

Y esto es lo más grande, porque esa adaptación a un problema particular no
oculta las intenciones del programador, viendo que patrón se ha adaptado nos
permite vislumbrar en que ha pensado a la hora de tomar decisiones.

En fin, para todos aquellos que comienzan, y para algunos que todavía… os dejo
una lista de libros que son (no todos) de obligada lectura.

De arriba abajo:

* Patrones de diseño, edición en castellano de

Design Patterns
Lectura obligatoria
*

Design Patters
(GOF Book) – Lectura obligatoria
*

Analysis Patterns
– Es un libro más profundo, sobre todo orientado al
análisis y diseño de aplicaciones, con ejemplos (sin código) del diseño de
aplicaciones de negocio y de aplicación de patrones en el diseño –
Lectura Recomendada
*
AAgile Principles, Patterns and Practices in C#
– Para mi uno de los mejores
libros que he leído, no solo hace hincapié en los principios de diseño más
básicos, sino que también añade una completa referencia de los patrones más
usados. – Lectura Muy Recomendada.
*
Patterns of Enterprise Application Architecture
– Fantástico, aquí se
incluyen muchos de los patrones más usados que no se encuentran en el GOF Book,
desde Active Record, Lazy Load, Unit Of Work … aproximadamente 50 patrones
menos conocidos, pero ampliamente usados. – Lectura
Obligatoria.

*
Refactoring to Patterns
,, un pedazo de libro, que es como el eslabón que une
refactorizaciones y patrones, perfectamente explicado, realmente impresionante
como une el libro de Design Patterns, con el de
Refactoring
  (Fowler) – Lectura Muy
Recomendada.

*
Implementation Patterns
– Un libro que realmente habla más del estilo de
código que de patrones, un poco flojo, recomiendo leer

Clean Code
de Robert C. Martin. – Lectura Medio
Recomendada.

* C# 3.0 Design Patterns – Un libro con ejemplos de patrones (GOF) en C# 3.0
sin más. – Lectura Medio Recomendada.
* C# Design Patterns, los GOF con ejemplos en C#,
Libro recomendado para los que comienzan con C#.

* xUnit Test Patterns – Si haces pruebas ó TDD es imprescindible.
Lectura Muy Recomendada.
*
Design Patterns in Ruby
– Si eres un salsas, como yo, no esta de más ver
como se implementan los GOF en Ruby, muy entretenido.
Lectura Pasatiempo.

Por último tengo un librito que aunque parece que esta en chino, no es así, esta
en ingles, pero es una edición Design Patterns para China, a mi me gusta para
llevarlo en la maleta cuando doy charlas o cursos.

YACAMLQT (Yet another CAML query tool) Redux (2)

Continuando con la explicación del código de YACAMLQT.

Habíamos visto la parte relacionada con el Lexer el analizador morfológico. Como es obvio detrás debe haber un analizador sintáctico y semántico el Parser.

El analizador sintáctico y semántico (NParser) se ha implementado siguiendo el patrón interpeter, (seguramente sea uno de los que menos se ven), el objetivo es obtener los distintos Tokens desde el Scanner y montar un árbol sintáctico (AST) este árbol contiene Nodos (ASTNodeBase) y estos nodos representan de manera abstracta y simplificada la estructura sintáctica de la consulta en SQL.

(diagrama NParser)

A la clase NParser se le puede inyectar una factoria (ASTNodeFactoryBase) en función del código que queramos generar, por el momento solo esta implementado el CAML, pero se puede extender sencillamente para generar CAML.Net.

Partiendo de un nodo abstracto (ASTNodeBase) podemos definir las distintas unidades sintácticas, por medio de la herencia. Estos nodos abstractos (heredados de ASTNodeBase ) conforman las distintas expresiones que se usan en el analizador sintáctico y semántico (NParser), para ello se ha definido una clase para cada uno de los Tokens a modo de plantilla (template),  y estas clases son a su vez son las distintas expresiones abstractas, que se usan en  el patrón interpreter implementado en el parser. (NParser).

Todos estos nodos que forman las expresiones abstractas al fin al cabo son plantillas (templates), y podrían a su vez ser clases abstractas, yo opte por una implementarlas como clases normales. Ya que algunos de los nodos son terminales y otros intermedios y no tienen por qué ser heredados, de este modo la factoria base (ASTNodeFactoryBase) usa miembros virtuales parar crear dichos nodos.

(diagrama parcial de ASTNodeBase)

Para crear todos estas expresiones abstractas existe una factoría abstracta (ASTNodeFactoryBase ) a través de la cual creamos los distintos nodos. Como puede verse, para añadir una variante como CAML.Net, solamente hay que añadir las expresiones abstractas heredando de las ya existentes e implementando PreCode() y PostCode().

Todos estos nodos que forman las expresiones abstractas al fin al cabo son plantillas (templates), y podrían a su vez ser clases abstractas, yo opte por una implementarlas como clases normales, debido a que algunos de los nodos son terminales y otros intermedios y no tienen por qué ser heredados, de este modo la factoria base (ASTNodeFactoryBase) usa miembros virtuales parar crear dichos nodos terminales e intermedios.

Después para poder inyectar en el parser dichas expresiones debemos crear una nueva factoría heredada de la factoría base (ASTNodeFactoryBase).

(diagrama ASTNodeFactoryBase)

Para generar CAML lo que he hecho es heredar de cada plantilla ó expresión abstracta definida, una nueva clase que redefine los métodos virtuales PreCode() y PostCode() que son los encargados de sustituir cada nodo del árbol sintáctico en CAML.

Y crear una factoría (ASTNodeCAMLFactory) que se encarga de crear las expresiones.

YACAMLQT (Yet another CAML query tool) Redux (1)

Hace un mes, John Holliday, me pidió a ver si podíamos integrar su CAML.net con mi YACAMLQT, a la vez que ampliar mi herramienta para soportar otro tipo de consultas como adds y updates.

YACAMLQT, es una utilidad que convierte una sentencia SQL en CAML, el lenguaje de consulta de Sharepoint. (Véase YACAMLQT, YACAMLQT2 y YACAMLQT-CAML.Net)

Estos días entre rato bueno y rato malo, he reescrito totalmente el código de YACAMLQT, para hacerlo más sencillo (por supuesto usando TDD), en principio el objetivo ha sido emular el antiguo YACAMLQT, pero dotándolo de un diseño más sencillo y ampliable.

YACAMLQT, es un programa que convierte una sintaxis tipo SQL en CAML (el lenguaje de consulta de SharePoint).

Es decir esto:

WHERE ((Column1 = “Value1”) AND (Column2 = “Value2”)) OR ((Column3 = 10)
AND (Column3 <> NULL)) GROUPBY Column1 ORDERBY Column1, Column2 ASC, Column3 DESC

En esto:

<Query>
  <Where>
    <Or>
      <And>
        <Eq>
          <FieldRef Name="Column1" />
          <Value Type="Text">Value1</Value>
        </Eq>
        <Eq>
          <FieldRef Name="Column2" />
          <Value Type="Text">Value2</Value>
        </Eq>
      </And>
      <And>
        <Eq>
          <FieldRef Name="Column3" />
          <Value Type="Integer">10</Value>
        </Eq>
        <IsNotNull>
          <FieldRef Name="Column3" />
        </IsNotNull>
      </And>
    </Or>
  </Where>
  <GroupBy>
    <FieldRef Name="Column1" />
  </GroupBy>
  <OrderBy>
    <FieldRef Name="Column1" />
    <FieldRef Name="Column2" Ascending="True" />
    <FieldRef Name="Column3" Ascending="False" />
  </OrderBy>
</Query>

El proyecto completo lo subiré a CodePlex en unos días, con su código fuente que poco a poco y con ayuda espero ir ampliando.

Por si alguien quiere echar una mano en el proyecto, voy a contar alguno de los entresijos del diseño de la aplicación.

Lo primero que he diseñado es el analizador morfológico (lexer) que se encarga de identificar dentro de un string, las distintas unidades sintácticas (tokens) con las que construiremos un analizador sintáctico y semántico (parser) con el cual construiremos un árbol sintáctico (AST) que por último recorreremos para transformar el SQL en CAML u otra variante como CAML.Net.

El lexer, está compuesto por una clase base, ScannerBase que contiene las partes más básicas del lexer, he extraído esta clase base una vez que tenía el analizador morfológico completo ya que de esta manera podemos realizar otro tipo de analizadores.

Las funciones básicas como comerse los espacios (EatSpaces()), detectar si es el final de línea (EndOfLine()) , saltar caracteres (SkipChar()) son parte de ScannerBase. Lo más importante de esta clase es la propiedad CurrentChar que devuelve el último carácter leído y el método GetCharMoveNext(), que obtiene un carácter y se mueve a la siguiente posición.

Para los que habéis usado el unix flex, GetCharMoveNext() es similar a input().

Esta clase ScannerBase utiliza internamente una clase ScannerState que mantiene el estado para poder releer un token ó unidad sintáctica.

Los tokens en el caso de YACAMLQT, consisten en las palabras reservadas propias de SQL, así como los distintos operadores, los campos y los valores (cadena, fecha, lógico y numérico).

A diferencia del unix flex, esto no se trata de un unput(), ya que mediante este volveríamos al carácter anterior. En este caso, como lo importante del analizador es obtener una unidad sintáctica, o token, lo que he hecho es implementar un método llamado BackToken() que lo que hace es posicionar el lexer justo al comienzo del último token obtenido, de modo que GetToken() volverá a devolvernos el mismo token.

La clase Scanner, hereda como es de suponer de ScannerBase, e implementa GetToken(), el responsable de de devolver un token, y CheckCorrectBracketsAndQuotes() que es el responsable de comprobar que los paréntesis y las comillas están correctamente.

Dentro de la clase Scanner, el método GetToken() es el responsable de identificar cada uno de los tokens, para lo cual he realizado un método para identificar cada uno de los distintos tokens. GetToken() usa los métodos ScanDate(), ScanString(), ScanOperator(), ScanNumber() y ScanReservedWordOrSymbol().

ScanOperator() y ScanReservedWordOrSymbol() usan un diccionario para identificar los distintos operadores y palabras reservadas. En el caso de ScanReservedWordOrSymbol(), si el token leído no se encuentra en el diccionario de palabras reservadas estaremos identificando un símbolo ó identificador.

Para terminar con esta primera parte, y siguiendo el principio de responsabilidad única, se ha implementado la clase Token como un contenedor y TokenFactory como una factória encargada de crear los distintos tipos de tokens ó unidades sintácticas. La clase Scanner es la que usa la factória para crear los distintos Tokens.

La clase Token, puede contener los distintos tipos de tokens, en principio todos aunque pueden ser de diferentes tipos, mantendrán su valor como un string. El resto de propiedades para identificar el tipo de token (TType) ó el tipo de valor (ValueType) son una enumeración.

Mi particular visión del Test Driven Development (TDD)

Cuando nos enfrentamos al diseño de un programa sea el que sea, partimos de un estado que podemos llamar “A” problema, y como es obvio un estado “B” en el que tenemos resuelto el problema, por medio de un programa.

Si la programación fuera como las matemáticas, cosa que “no es” aunque  se fundamente en ello; la solución ideal sería la línea recta. Una línea recta que nos lleva del punto “A” al punto “B”, directamente, sin rodeos.

Es la solución más ELEGANTE, por qué es la solución más CLARA y BREVE que se puede dar.

Hay partes de la programación en donde existen uno o varios algoritmos que podemos usar y que son como la línea recta es decir ya están optimizados y no hay manera de mejorar (algoritmos de ordenación, búsqueda, etc..) pero cuando hablamos de un sistema de mayor tamaño, donde se ven involucrados más componentes la cosa cambia.

Existen miles de maneras de llegar de “A” a “B”, podemos hacer tirabuzones, hipérbolas, curvas mágicas y un sinfín de figuras geométricas que nos llevarán también de “A” a “B”. Los programadores somos capaces de crear miles y miles de esas formas mágicas. (Es nuestra naturaleza, como le dijo el escorpión a la rana)

De modo que nos enfrentamos a un problema doble, llegar del punto “A”, problema, al punto “B”, programa  sin morir en el intento. Y hacerlo de la manera más ELEGANTE.

No hace mucho, hablaba Rodrigo, del “Principio KISS” y del “Divide y Vencerás”, este último es sin duda la práctica que seguimos todos los programadores desde que tenemos conocimiento de nosotros mismos, es decir de que somos eso “Programadores”.
 
Debemos resolver un problema, es decir crear un programa “B”, que resuelva “A”, y hay miles de soluciones ó caminos posibles que nos llevarán de “A” a “B”.

Nosotros no disponemos de un algoritmo determinado, de una solución magistral como la ecuación de la recta que pasa por dos puntos, cada programador es un mundo y su percepción tanto del problema como del modo de llegar a la solución (diseño) podemos decir que es casi única, cuya aproximación es inversamente proporcional a la complejidad del problema.

A un problema más sencillo, hay más posibilidades de que dos programadores sigan el mismo camino, a un problema más complejo la desviación entre las soluciones tiende a distar más.

No existe la certeza de que nuestra solución sea la más optima, clara y concisa y lo que es peor tampoco podemos medir desviación alguna, puesto que cuanto más complejo es el programa más variantes tiene y por ende para poder medir dicha desviación, deberíamos conocer la línea recta, cosa que a priori es imposible.

Partiendo como base de que la línea recta sería la solución “perfecta” del problema, tenemos una complicada tarea.

Pero por otro lado una línea no es más que una sucesión de puntos, de modo, que podemos interpretar cada punto como una parte de la solución, y aquí volvemos al “Divide y Vencerás”.

Gracias a que tenemos técnicas como el TDD o ATDD, podemos ir punto por punto trazando nuestra línea.

“Solo escribimos el código necesario para pasar la prueba”, esta frase que resume en esencia que es “Test Driven Development”, también es la mejor manera que conozco de ir punto por punto trazando la solución de “A” a “B”, siguiendo esa imaginaría línea recta que sería la solución más ELEGANTE, CLARA y BREVE que se puede dar.

Veneno en los dedos

En la vida de todo programador hay un “día especial”, algunos tendréis que hacer memoria, otros mucha memoria y algunos no lo recordareis pero es el día en que uno toma conciencia de sí mismo y se da cuenta de que es un “PROGRAMADOR”. (¡Qué fea palabra!… léase “CODER” please)

No estoy hablando de ser “programador”, si no de ser “PROGRAMADOR”. Me refiero al momento en que te das cuenta de que el código es importante, que eres una máquina de tirar líneas que buscas mejorar día a día y de que el veneno de los 1s y los 0s está dentro de ti, del momento en que te das cuenta que todo es programable, de que a la silla de ruedas de tu abuelo se le puede poner un motor y programarlo, de que la gameboy de tu primo lleva un Z80 y seguro que hay alguna forma de meterle mano y…..en fin, te das cuenta de que el teclado es una extensión de tus dedos.

Os contaré como fue mi momento.

Yo cacharreaba con ordenadores como muchos de vosotros, que si un ZX81, un Commodore 64, etc…,etc… Allá por el año 1989 (yo tenía 19 años), un amigo de mi cuadrilla (Iñaki) me propuso hacer un programa para la empresa en que trabajaba su padre, era una empresa de excavaciones pequeña, CAMES, que hacía cosas generalmente para empresas más grandes.

El programa demandado consistía en llevar un control de los partes de los empleados y las máquinas; había que controlar el número de horas que se empleaba en cada obra. Tuvimos algunas reuniones en la oficina de la empresa y me explicaron con todo detalle cómo se llevaban los partes manualmente y los controles que se debían hacer semanalmente y mensualmente, así como los trabajos que había que re-facturar a terceros.
Durante las reuniones tome un montón de notas tratando de no perder detalle de lo que querían que el programa hiciera exactamente.
Por aquel entonces, había aprendido algunos leguajes de programación, como Basic, Pascal, C, algo de Lisp y Prolog, y dBase3, para el asunto me decante por dBase3, no por nada especial, pero las librerías btreeve que usaba entonces en Basic y en C, daban bastante guerra. También pensé en la comodidad de que dBase contaba con campos de entrada que admitían validaciones sin mucho esfuerzo, así como poder examinar las tablas y ver cualquier detalle de los datos. Otro de los factores importantes en la decisión fueron los listados, ya que hacer listados con dBase era coser y cantar. En fin dBase era perfecto para hacerlo todo sin demasiado esfuerzo.

De modo que me encerré en casa e hice el programa; unos días más tarde recibí en mi casa (la de mis padres en realidad y en mi habitación más concretamente) a las personas a las que debía enseñar el programa. Estuvimos toda la tarde revisando las especificaciones y surgieron varias cosas. Al terminar, yo no estaba del todo satisfecho con el programa a pesar de que cumplía con las especificaciones salvo en algún pequeño detalle que surgió durante la demo.

Un amigo me hablo de Clipper el compilador de dBase, me dejo un manual y me dijo que sería mucho más profesional hacerlo con Clipper (87). Así que rehíce el programa completamente desde cero.

Finalmente entregué el programa y cobre 60.000 pesetas (un dineral en el año 89) y muy agradecido asesoré a la empresa también acerca del ordenador y la impresora que debían comprar.

Los primeros viernes de cada semana, momento en que se pagaban las horas extras a los empleados, yo tenía que bajar a la empresa exclusivamente por si surgía algún problema o alguno de los cálculos no salían correctamente. El argumento de “Benito”, el encargado,  era que los empleados (tíos muy curtidos de la obra y con carácter más bien duro) sabían mejor que nadie cuanto debían cobrar de modo que, por si acaso, sería mejor que yo estuviese allí en caso de que no coincidieran las cifras.

Lo estuvimos haciendo aproximadamente durante un mes hasta que lo dieron por válido, ya que, los cálculos siempre salían correctamente si se habían introducido bien los datos.

Ese fue mi primer programa de ordenador, y mis primeros ingresos como “programador”.

Aún así, todavía no era un programador.

Tiempo después, mientras estudiaba FP por las mañanas, entre a trabajar por las tardes en una empresa de programación. Ellos programaban en Clipper pero no muy bien, de modo que, les di algunas lecciones, suena chulesco lo sé, pero lo mejor de todo es que mi profesor de COBOL de FP, trabajaba allí por las tardes, de modo que, él por la mañana me daba COBOL y yo por la tarde le daba Clipper a él. Cosas de la vida.

Bueno, estando allí hice multitud de programas, facturaciones, contabilidad,  etc…etc …

Aún así, no era un programador de los que hablaba al principio, pero el momento llegó y lo recuerdo perfectamente.

No estaba satisfecho con algunas de las cosas repetitivas que hacíamos programando, así que, cree un meta lenguaje que nos ahorraba horas y horas de programación de esa repetitiva, lo hice en casa por las noches e incluso hice un manual para que todo el mundo en la empresa pudiese usarlo. Ese fue el momento que arruinó mi vida :-).

Ese momento en que no te basta con lo que los lenguajes te dan, cuando empiezas a crear bibliotecas de código, a optimizar en ensamblador rutinas lentas, cuando creas un sistema que es capaz de ahorrar multitud de horas de programación, cuando los días y las noches se funden en la pantalla tirando líneas de código, leyendo programas de otros para aprender más y más, cuando no puedes pasar sin programar algo, lo que sea aunque sea solo por auténtico ocio, por ver si eres capaz de hacerlo o por la razón que sea, que seguro que es lo suficientemente buena como excusa para teclear.

¿Cómo te entro a ti el veneno?

Testeo unitario para SharePoint: La importancia de llamarse "Test"

Testing es algo que todos los desarrolladores deberíamos hacer, y muy pocos hacen. Por no decir “Testing intensivo y consecuente”, pues los números se reducen a prácticamente cero… si le da curiosidad, revise las estadísticas mostradas en:



Especialmente el segundo vinculo es interesante, aunque por experiencia propia me arriesgaría a decir que los porcentajes de aplicación de testeo son mucho, mucho mas bajos.


Siendo sincero, escribir software es una de las cosas más divertidas para hacer en el mundo (lo digo por deformación profesional, probablemente), pero hacer pruebas para ese mismo software es una de las más aburridas. Y en algunos casos, es simplemente imposible, como lo es hacer pruebas para SharePoint.


Pero para comenzar por el principio, hay que hablar algo sobre testing en general.


El mundo del testing es amplio y ajeno: hay tantos tipos de testeo como tipos de desarrolladores… pero mirándolo desde una perspectiva global, podemos decir que hay:


– “Unit Test” (Prueba unitaria) – verifica que las unidades individuales de código fuente funcionan como se espera. Normalmente la unidad de código más pequeña es una función, método o propiedad.
“Regression Test” (Pruebas de regresión) – Cuando se modifica algo que ya ha sido probado que funciona (con el Unit Test), es necesario garantizar que sigue funcionando apropiadamente después de algún tiempo: este es el trabajo de Regression Test
“Integration Test” (Pruebas de Integración) – Cuando todas las unidades (que ya han sido probadas con Unit y Regression Test) se unen para trabajar conjuntamente, es necesario garantizar que todas funcionen como una unidad apropiadamente. Este es el trabajo del Integration Test
“System Integration Test” (Pruebas de Integración de sistemas) – puede ser visto como una ampliación del anterior: este test garantiza que nuestro sistema (que ya ha sido probado con Unit, Regression e Integration Tests) puede funcionar con otros sistemas externos apropiadamente


En cuanto a metodologías, mis dos hermanas sicólogas me enseñaron que hay tres tipos de pruebas: Black Box, White Box y Grey Box testing (el modelo ha sido tomado “prestado” de la psicología).


“Black Box Testing” – la prueba no sabe nada sobre cómo funciona internamente el sistema a probar… solamente que si se le entregan algunos parámetros de entrada, deben salir algunos resultados. Black Box Testing le entrega parámetros a una función (correctos e incorrectos) y observa los resultados que la función devuelve
“White Box Testing” – por el contrario, la prueba conoce perfectamente el funcionamiento interno del sistema a probar, y crea las pruebas basado en el.
“Grey Box Testing” – ya se imaginaran lo que es, una mezcla de los dos.


Finalmente, es necesario hablar de algo que está de moda, “Test-driven development” (TDD). Esta es una técnica de programación basada en escenarios de prueba o de funcionamiento (Test o User Cases), bastante ligada a metodologías de desarrollo como Agiles, que indica que primero hay que hacer el diseño del software (sus clases, métodos, propiedades y eventos), luego generar las definiciones (el “esqueleto” del código), luego crear los métodos de prueba ANTES que el código mismo, y finalmente, crear el código para rellenar el esqueleto.


Bien, esto es más o menos la parte teórica. Como los desarrolladores de código que somos, ¿Qué es lo importante de todo esto?



  1. Primero que todo, y antes que nada, Unit Test. Unit Test me permite dormir tranquilo, pues me asegura que mi código funciona correctamente y seguirá funcionando después de que lo he modificado (¿se puede usar Unit Test como Regression Test? Esta es una discusión bizantina a la que nunca nadie llega a una conclusión, algo por el estilo a que es mejor CSharp o Visual Basic, o Windows o Linux. Vea por la ejemplo la discusión que surgió en el ultimo PDC al respecto en http://channel9.msdn.com/pdc2008/TL61/).

  2. Como segunda medida, si se está usando (o se quiere usar) TDD, la decisión de usar Black o White Test es importante… o, mejor dicho, si se quiere usar TDD, hay que usar Black Box Testing. Punto. O hay que iniciar una nueva discusión bizantina sobre si es posible iniciar el desarrollo en Black Box y luego continuarlo en White Box, lo que lleva al modelo de Grey Box…

Noten que hasta ahora he intentado no tomar partido por ninguno de los puntos mencionados. Todo porque mi punto es SharePoint, no discusiones teológicas sobre cómo, cuando y donde hacer testeo de software. Pero llegamos a la parte interesante: SharePoint.


Cuando se trata de crear Testeo Unitario para software creado por uno mismo, es decir, en donde se tiene el código fuente, construir las clases de prueba es largo y tedioso, pero es posible de hacer con las herramientas estándar para el efecto (como las que tiene Visual Studio mismo, por ejemplo). Cuando lo que se desea es testear código que utiliza el Modelo de Objetos de otro programa, como ocurre cuando se escribe software para SharePoint o cualquier otro servidor (SQL, Exchange, BizTalk, etc), es necesario “hacerle creer” a nuestro código que esta interactuando con el servidor, pero sin que lo haga en realidad, porque no se desean tener dependencias con él.


Imagínese una situación no tan hipotética: se crea un método que comprueba los derechos de una Librería de SharePoint; si se utiliza una instalación real de SharePoint para hacer las pruebas, es necesario mantener esa configuración por todo el tiempo del desarrollo y mas allá para garantizar que los resultados de las pruebas sean consistentes en el tiempo. Peor aún, todos los desarrolladores del grupo tienen que disponer de la misma instalación para que sus pruebas también sean consistentes entre desarrolladores. Esto es prácticamente imposible de conseguir y, además, muy engorroso. Para solucionar el problema existen diferentes tipos de herramientas que “falsifican” el Modelo de Objetos del servidor (Mockers, Stubbers, etc)


Como ya hemos dicho varias veces Carlos y yo, el problema con SharePoint y Unit Test es que el Modelo de Objetos de SharePoint tiene muchas clases selladas o sin constructor público. Este ha sido el gran problema hasta ahora para poder usar Mockers y Stubbers, pues ellos no saben qué hacer con un objeto sellado o sin constructor público. El posting “Testeo Unitario para SharePoint: acercándose a la respuesta definitiva – parte 1” que escribimos anteriormente comenzó a mostrar cómo se puede iniciar el testeo unitario para SharePoint usando la última versión de TypeMock. Las próximas partes continuaran con la parte práctica de la creación y codificación de las clases de prueba. Pero en esta segunda parte se trata de discutir la importancia de Unit Test, Regression Test, Black y White Box Testing y TDD.


Uno de las características más importantes de TypeMock es la relación intrínseca entre el código de trabajo y el código de testeo, es decir, el fabricante ha escogido por un modelo de “White Box Testing”. Veamos un ejemplo el ejemplo de una función que simplemente imprime los elementos de una Lista de SharePoint:


Código de trabajo:

        public void GetCollection01()
{
SPSite mySite = new SPSite(“http://wsses”);

using (SPWeb myWeb = mySite.OpenWeb())
{
foreach (SPList myList in myWeb.Lists)
{
foreach (SPItem myItem in myList.Items)
{
Console.WriteLine(mySite.Url + ” – “ + myWeb.Title + ” – “ + myList.Title + ” – “ + myItem.ID.ToString());
}
}
}
}


Código de Prueba:
        [TestMethod()]
public void GetCollection01Test()
{
SPWeb fakeWeb = Isolate.Fake.Instance<SPWeb>(Members.ReturnRecursiveFakes);
SPList fakeList = Isolate.Fake.Instance<SPList>(Members.ReturnRecursiveFakes);
SPItem fakeItem01 = Isolate.Fake.Instance<SPItem>(Members.ReturnRecursiveFakes);

using (var recorder = RecorderManager.StartRecording())
{
SPSite myFakeSite = new SPSite(“”);
recorder.ExpectAndReturn(myFakeSite.Url, “fakeSiteUrl”).RepeatAlways();
recorder.ExpectAndReturn(myFakeSite.OpenWeb(), fakeWeb);
}

Isolate.WhenCalled(() => fakeWeb.Title).WillReturn(“fakeWeb”);
Isolate.WhenCalled(() => fakeWeb.Lists[2].Title).WillReturn(“fakeList”);
Isolate.WhenCalled(() => fakeItem01.ID).WillReturn(1);

Isolate.WhenCalled(() => fakeWeb.Lists[2].Items).WillReturnCollectionValuesOf(new List<SPItem>
{
fakeItem01
});

Class1 target = new Class1();
target.GetCollection01();

var fakeItemList = fakeWeb.Lists[2].Items;

foreach (SPItem item in fakeItemList)
{
Isolate.Verify.WasCalledWithAnyArguments(() => item.ID);
}
}



Para la prueba unitaria se está usando una combinación de “Natural Mocks” y el nuevo “AAA API” de TypeMocks. Observe un par de puntos específicos:



  • Cada objeto “real” necesita un objeto “mockeado”: myWeb -> fakeWeb, myList -> fakeList, etc

  • Para cinco líneas de código de trabajo se necesitan 17 líneas de código de prueba

Esto conlleva las siguientes consecuencias generales:


Para poder crear un objeto “fantasma” (un mock) que sustituya efectivamente al objeto “real” en la clase de trabajo, es necesario conocer explícitamente su construcción. Esto excluye directamente la utilización de TDD: código de prueba debe ser escrito antes del código de trabajo



  • Una consecuencia de esta consecuencia es que el código unitario deberá ser escrito por el desarrollador mismo que está escribiendo el código de trabajo: al final, es él/ella el que sabe que está haciendo. El peligro con esta construcción es que se van a escribir clases de prueba que casi siempre van a pasar el examen… voluntaria o involuntariamente, el desarrollador va a omitir las pruebas que tienen más posibilidades de fallar

  • Una segunda consecuencia de esta consecuencia es que el desarrollador probablemente utilizara más tiempo creando las clases de prueba que las clases de trabajo

  • Por la relación tan estrecha entre código de trabajo y de prueba, cuando se modifica algo en el código de trabajo, hay que modificar también el código de prueba. Es decir, Regression Test es imposible de realizar

El fabricante de TypeMocks está trabajando intensivamente para darle solución a estos problemas, y los primeros resultados van saliendo: ciertas partes del Framework de TypeMocks es capaz de crear mocks para trabajar con Black Box Testing, es decir, entregando un objeto “mockeado” al método de trabajo y revisando los resultados producidos, sin tener conocimientos de su funcionamiento interno.


En cualquier caso, la discusión de si testeo blanco o negro es el mejor, o si Test-Driven Development es realmente valido continuaran hasta el fin de los siglos. Lo importante para nosotros, los que estamos metidos en el lio de hacer que código funcione apropiadamente no son las discusiones teóricas, sino los Frameworks que nos permitan trabajar confortablemente. TypeMocks es hasta el momento lo que más se acerca a una solución viable para hacer testeo de código de SharePoint, así que vale más que la pena de darle por lo menos una mirada e intentar hacerlo funcionar.

Drupal and SharePoint. Dos formas de hacer una tortilla (charla en Navarra)

El próximo día 18 de diciembre tendremos en el Grupo de Usuarios de Navarra la charla (de los huevos y de los CKarlos), Karlos G. Liberal y un servidor hablaremos de algunas de las bondades de nuestras herramientas de trabajo (Drupal y SharePoint).


El magnifico cartel ha sido realizado por nuestros amigos de Sistema Formación.



La Agenda del evento es la siguiente:


La jornada será el jueves, 18 de diciembre
Hora de recepción: 18:00


Centros de Excelencia Software
Salón de actos
Plaza Cein, 1, Polígono Mocholi
Noáin Navarra 31110
España


AGENDA
18:30 – 19:30: Drupal and SharePoint. Dos formas de hacer una tortilla. Los CKarlos.
19:30 – 20:00: Celebración 2º aniversario de NavarraDotNet: zorionak zuri y tarta de cumpleaños
20:00 – 21:00: Drupal and SharePoint. Dos formas de hacer una tortilla. Los CKarlos
21:00 – … : Cena!


Para apuntarse podéis hacerlos desde este enlace*
http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032393640&Culture=es-ES

Cenando, Buenas Practicas, Historia de terror

Cenando


El otro día paso Unai por Pamplona y estuvimos cenando y departiendo sobre todas esas cosas frikis que nos gustan. Una suerte para los que habéis podido asistir a los cursos que ha impartido de Entity Framework  y WCF.

Durante la cena, [[degustábamos unos “Penne Arrabiata” (no seáis mal pensados, que son macarrones con tomate un poco picante) y un “Ochoa Tempranillo” (recomendado)]], hablamos de; libros, de código, de más código, de bugs, de depuración, de tecnología, del bien y del mal (lo típico), no sé si ayer hablamos de sexo (no me acuerdo, pero con el frio que hacía es posible que no :-).

Bueno, la cosa es que le comenté algunas de las cositas del Api de SharePoint.

¿Buenas Prácticas?

Como ya he contado en alguna ocasión, las colecciones de SharePoint, son a la antigua usanza (Net 1.0), es decir que implementan IEnumerable, en una clase contenida, esto lo hacen en una clase abstracta SPBaseCollection del cual heredan el resto de colecciones de SP.

Bien, hasta el momento no hay mucho problema, es un tema de diseño, necesario para implementar las serializaciones de los objetos además de la persistencia que realiza sharepoint via COM.

Si realicemos una consulta usando SPQuery, (SPQuery nos permite recuperar elementos de una lista usando CAML, que es un meta-lenguaje basado en XML que tiene SharePoint para muchas cosas, entre ellas recuperar elementos de las listas)

<Where>
<Geq>
<FieldRef Name=”ID/>
<Value Type=”Integer>10</Value>
</Geq>
</Where>
Nos devolverá todos los elementos de una lista donde el ID sea mayor que 10.

Para poder ejecutar una consulta CAML sobre una lista tenemos una clase llamada SPQuery a través de la cual montamos la consulta.

SPQuery query = new SPQuery
{
Query = “CONSULTITA EN CAML”
};

Para recuperar una colección de Items que cumplen esta consulta basta con indicar a la lista los items que queremos pasandole un SPQuery:
SPListItemCollection ítems = lista.GetItems(query);
Bien, como muchos ya sabéis que no es muy buena práctica devolver null, para no tener que comprobar si ítems es null antes de acceder, de modo que lo correcto es devolver una colección vacía (en este caso, como veremos luego tiene otro fundamento).

GetItems internamente nos devuelve una nueva colección
public SPListItemCollection GetItems(SPQuery query)
{
return new SPListItemCollection(this, query);
}


Pero qué pasa si la consulta está mal formada ó es incompleta.  Lo que cabe de esperar es:

1.- Que nos devuelva una excepción en el momento de crear SPQuery (cosa que no hace)
2.- Que nos ofrezca una propiedad o algo para comprobar si la consulta es correcta (cosa que no hace)
3.- Que nos devuelva una colección vacía (cosa que hace peligrosamente a medias)

¿Por qué lo hace a medias? Porque aparentemente nos devuelve una colección vacía, es decir si la consulta está mal, ítems no es null. Pero OJO no es una colección valida.

SPQuery query = new SPQuery
{
Query = “MI mala CAML Query”
};

SPListItemCollection items = list.GetItems(query);

if (items!= null)
{
Debug.WriteLine(“Soy una colección no nula. Parece que valgo…”);

// Ahora reviento
foreach (SPListItem item in items)
{
}
}


Las colecciones de este tipo en SharePoint, son de carga retardada de modo que la colección se carga cuando realmente vamos a usarla (Lazy-Load / Proxy), en ese momento se hace una petición SPRequest que es al que se encarga de recuperar el contenido y obtener la colección de elementos. (fundamento)

En ese momento se usa la consulta SPQuery que le hemos pasado para recuperar los datos, y al tratar de cargarla, como la consulta está mal formada, da una excepción (no advertida ni documentada), y la colección sigue siendo una colección hasta que usemos alguna de sus propiedades o tratemos de recorrerla. Es decir no es una colección vacia, si no una colección donde todo se ha quedado mal inicializado si intentas un items.Count antes de recorrer la colección tambien dará una excepción ya esta va a producirse de igual manera al cargar los datos.

De modo que la buena práctica se convierte en mala práctica ya que se pasa de hacer una comprobación de null antes, a tener que hacer un Try/Catch en el momento de recorrer la colección (como decimos por aquí, cojonudo).

Como alternativa, se puede implementar un método por ejemplo, vía extensión;  para comprobar que la consulta es valida y en caso de no serla que nos devuelva una colección bien formada cuando menos. Otra alternativa podría ser otro método como EnsureCollection, a través del cual podamos recuperar la excepción si nos interesa comunicar que la consulta esta mál formada.

La cosa sería algo así:


public static SPListItemCollection TryGetItems(this SPList list, SPQuery query)
{
SPListItemCollection items;

try
{
items = list.GetItems(query);
int count = items.Count;
}
catch(SPException ex)
{
query.Query = string.Empty;
items = list.GetItems(query);
}

return items;
}



JA, pero ahí no termina la cosa …  los señores de SharePoint son unos fenómenos optimizando y lo que hacen SPQuery internamente es generar una Vista (propiedad ViewXml de SPQuery), para optimizar el rendimiento, esta vista en Xml, se genera reuniendo todas las propiedades de SPQuery, y se genera siempre y cuando no se ha generado antes (optimización)

De modo, que si cambiamos la propiedad Query de SPQuery, la consulta interna ViewXml no cambia (ya se genero antes), manteniendo la última consulta generada, para lo cual debemos limpiar ViewXml.


query.Query = string.Empty;
query.ViewXml = string.Empty;
items = list.GetItems(query);


¿Por qué que les habría costado implementar un flag de suciedad y reconstruir la ViewXml cada vez que el objeto este sucio? ¿por qué no documentarlo?

En fin, la cena estuvo genial.

He leido "Code Clean", de Robert C. Martin

He terminado de leer el último libro de Robert C. Martin, Clean Code. 

De Robert, había leído otros dos libros, “UML para programadores Java”, una guía práctica y sin rodeos de cómo usar UML en proyectos reales; y cuando digo práctica es que no se anda por las ramas y en ocasiones en un tono incluso “irónico” explica perfectamente cómo debemos usar UML.




El otro libro es Agile Principles, Patterns, and Practices in C# (Robert C. Martin Series), que puedo decir de este libro ampliamente comentado, uno de los que se deben tener.  (Ya sabéis que se lo recomiendo a todo el mundo)

Bueno, de modo que “Clean Code: A Handbook of Agile Software Craftsmanship (Robert C. Martin Series) ” tenía todos los boletos de ser un gran libro. No ha defraudado en absoluto.

Apenas empezarlo, en la introducción ya me había pillado. (Ilstración de la introducción)


http://www.osnews.com/images/comics/wtfm.jpg


El libro explica cómo escribir buen código, código legible y eficiente.  Los ejemplos son en Java, pero tener en cuenta que estamos hablando de cómo escribir buen código, habla del significado de los nombres, de las funciones,  de los argumentos, del tipo de retorno, de cómo comentamos el código, de las reglas de formato, de objetos y estructuras de datos, de la gestión de errores, de las pruebas unitarias, del diseño simple, de sistemas, de concurrencia, de refinamiento, de olores y heurística.  Habla de estilo, de buen estilo.

De veras, me ha parecido un libro impresionante, con unos ejemplos claros, con un estilo cuidado y detallado, sin dejar cosas fuera, insistiendo en las cosas importantes (esto a mí me gusta, así entran mejor las cosas)

Vamos un libro que entra de lleno en mi TOPTEN.

Resumen del DevCamp en NavarraDotNet

Un “poquito” tarde (y con mucha ayudita) os dejo el resumen con todos los detalles del DevCamp en el blog de NavarraDotNet


http://www.navarradotnet.com/post/navarradotnet-en-el-7bdev_camp7d.aspx


Y la información sobre el próximo evento el University Tour


http://www.navarradotnet.com/post/el-University-Tour-viene-a-la-UPNA.aspx 


(Para los que no lo sepan, en la Upna se esta organizando un DotNetClub)


http://www.navarradotnet.com/post/se-esta-cociendo-un-DotNetClub-en-la-UPNA!!.aspx

y como no, siempre vuelve a casa por navidad … (como el turron)

http://www.navarradotnet.com/post/Chema-Alonso-en-CuatroVientos-Una-sesion-dirigida-a-estudiantes.aspx


Toda la información sobre el paso del Guille por Pamplona (Gracias Guille)


http://www.navarradotnet.com/post/gracias-Guille.aspx