miércoles, 26 de febrero de 2014

Linq, recuperar número de filas y hallar la media en un join

Como tantas veces, estoy apasionado con una refactorización de código que me obliga a intentar ganar tiempo con Entity Framework, abandonado guarrerías de foreach y construyendo querys en Linq más complejas.

Así tengo un negocio que tiene a su vez unos productos asignados. Lo que quiero es crear un objeto negocio que me incluya el número de productos que tiene y la media de la puntuación que han recibido todos.

resultado = (from negocio negocio in db.negocios
                  
where negocio.Id == pNegocio.Id

                   join negociositem item in db.negociositems
                   on negocio.Id equals item.business_id into items
                                

                  select new negocioconrating
                                
{
                                     Id = negocio.Id,
                                     logo = negocio.logo,
                                     name = negocio.name,

                                     numrating = items.Count(),
                                     mediarating = items.Average(p => p.rating),
                                    
                                 }).ToList<
negocioconrating>();

¿Que está ocurriendo aquí?

Las primeras dos líneas son para seleccionar un negocio específico por medio de un parámetro llamado pNegocio que incluye un campo Id.

A continuación hago un join (internamente un inner join) con la tabla negociositems para recuperar aquellos item que tengan el campo business_id igual al id del item seleccionado. Es importante que este resultado (el del join) lo almacene en una variable temporal llamada items, porque esto es lo que me permitirá realizar operaciones sobre el listado completo.

Ahora hago un select sobre un nuevo objeto, en donde voy a almacenar los datos recuperados; así las primeras lineas son normales, cargando los resultados en las propiedades de la clase.

Lo interesante son las dos últimas líneas del select. En la primera hago un Count() diréctamente y recupero el número de item que he recuperado. La segunda línea utiliza el método Average que soporta los objetos IEnumerable, y le paso una lambda como función; en la cual escojo el campo del cual quiero obtener la media.

Una vez realizado parece sencillo, pero me ha tocado bucear un rato para encontrar estas dos soluciones.

Espero que sea de ayuda.

viernes, 14 de febrero de 2014

BootCamp Iniciación al ALM con Visual Studio Online, en Tajamar

Aunque me haya costado dormir más bien poco durante tres días, he de reconocer que mi primera bootcamp en solitario ha sido todo un éxito.

Durante más de 5 horas, que se me han echo muy cortas, he llevado de la mano a más de los 30 participantes en un viaje iniciático en la creación de un repositorio de código, sus primeros checkin, checkout, el primer etiquetado y la primera rama.

En la segunda parte rozamos la gestión de tareas en ScrumBut, construyendo una Pila de Producto sencilla, definiendo la iteración, entendiendo lo que es una historia de usuario, una tarea y una Pila de Sprint. Todo ello sazonado de “cuentos del abuelo cebolleta” y muchos consejos basados en mi experiencia personal.

La verdad que deseo expresar mi agradecimiento a Rafel Ansino por ofrecerme la oportunidad de disfrutar de las instalaciones de Tajamar, y del gran apoyo que me dio durante el largo evento. Al igual que a Cristian y a todos los asistentes.

Espero veros en el segundo capítulo, ya con ALM Avanzado, que voy a celebrar el próximo 1 de Marzo (en las mismas instalaciones) siendo coparticipante de Luís Fraile

WP_20140208_002

domingo, 9 de febrero de 2014

Community Day 2014


Un año más, y van tres, he podido disfrutar del evento de comunidades técnicas de Microsoft. Un evento centrado principalmente en el networking, en conversar con tantos buenos compañeros que habitualmente tratas solo de forma virtual, y con quienes cada año tengo más afinidad.

Un evento de donde siempre salgo con agujetas en los carrillos de tanto reírme y de pasarlo muy, muy bien.
Además este año ha sido muy especial para mí, al pasar de ser un mero asistente (que no es poco) a ser “forzado” por Bonnin a encargarme de organizar y realizar tres mesas redondas, de una forma muy sorprendente ya que no me lo notificó en ningún momento. De hecho, no llegue al inicio del evento, y se me nombro como coordinador sin saberlo aún yo ;)

Por suerte junto con el padre de la idea, Juan Manuel Servera, nos coordinamos y nos hemos llevado la sorpresa de una respuesta mayoritaria de muchos de los asistentes; de la calidad de los debates y conversaciones que salieron de estas reuniones casi auto organizadas (y eso que JuanMa y yo le cambiamos los nombres, le cambios salas y horarios, y aun así estaban llenas); y de las conclusiones y reflexiones que han emergido.
El escuchar a un cliente de empresas referentes en nuestra comunidad  “ponerle las pilas”, es algo de lo que se aprende mucho y te hace ver que no es todo oro lo que reluce, y que la realidad es un cubo multidimensional que se puede analizar desde muchos  puntos de vista.
También he disfrutado mucho del debate que  arrancó con una crítica feroz contra el modelo de consultoría como el origen de todos los males, y que poco a poco consiguió hacer dejarnos de mirar el ombligo y darnos cuenta que el problema es mucho más complejo. Que implica a clientes, economía y a nosotros mismos como profesionales. Que las empresas miran la informática (en general) como un coste y no como una inversión que produce beneficios por medio del aumento de la productividad y el ahorro de gastos. Y que si se nos percibiera tan buenos y necesarios como nos vemos nosotros, aun así no hay garantía que los sueldos fueran mejores.

También DPE se apuntó a organizar  mesas redondas y así Cristina invocó a todos los MVP (gracias por invitarme a asistir) para debatir sobre un programa muy interesante de mentoring de estudiantes MSP. Un programa que me parece de gran potencial y que está muy relacionado con una conversación surgida en otra mesa redonda sobre la resistencia feroz e injustificada que se percibe en la universidad a todo lo que huela Microsoft por parte del cuerpo docente.
Por su parte, José Bonnin, convocó a los más activos en la comunidad para hablar de temas de gammificación, de los cuales sigo siendo muy incrédulo en su aplicación. También buscamos fórmulas para mejorar la declinación de los foros en España y Latam, para lo cual ha surgido un compromiso de una mayor coordinación entre los moderadores, y en la que presenté mi ayuda a Luís Franco en lo que pueda aportar.

Y llegó el final de los eventos técnicos, y llegamos a las sesiones finales en donde los organizadores nos dieron las gracias a los asistentes, los asistentes aplaudimos a rabiar e hicimos chistes de todo y de todos; y aconteció el único “pero” de toda la reunión.
Por suerte, la cordura y el sentido común se impuso, y tanto a Juan Manuel Servera como a mí, los asistentes pidieran que nos obsequiará la organización con un regalito (un Nokia 710), que le he dado a Luis Fraile por si le es útil en la asociación que preside.

Después, viajecito en moto a Aranjuez detrás de la BMW de Fraile, y una cena muy animada, con muy buenos compañeros de mesa, y con una interesantísima conversación con Rafael Ansino, Xavi y un MVP de CRM (que no me acuerdo de su nombre).
A la hora de las copas, salté de un corro a otro hasta cuando me dispuse a partir hacia Madrid de vuelta, que al día siguiente tenía mi primer bootCamp sobre introducción al ALM con Visual Studio Online en Tajamar, y justo en ese momento Juan Manuel Servera, Luís Fraile, Asier (que tampoco me acuerdo del apellido) damos por inaugurada una nueva comunidad virtual: “Orgullo Backend”… ya os contaré.

Muchas gracias a todos, coordinadores, y asistentes. Entre todos hacéis que el orgullo de participar en esta comunidad, se convierta además en un verdadero placer.


 



sábado, 1 de febrero de 2014

Test unitarios de un Controller que devuelve IHttpActionResult

Sigo con el intenso aprendizaje de construir una API REST con ASP.NET Web API, y me encontraba con el problema de que necesitaba poder realizar los test a los fallos que me estaban enviando los desarrolladores de las app que consumen este API.

La parte buena de trabajar con Web API, es que utiliza´el patrón MVC, el cual me permite testear el controlador (incluso la vista si me pusiera), la dificultad es que nunca había testeado el interfaz de  IHttpActionResult.

Pero es bastante sencillo, y me ha mostrado una debilidad de mi formato de mensajes (que ya me habían avisado Ambrin y Julio).

Voy a probar que el resultado de una operación es efectivamente un código de error específico.

Para lo cual tengo una clase Error tal que así:

    public class MensajeDeError
   
{
       
public string Code { get; set; }
       
public string Message { get; set; }
       
public string MessageDetail { get; set; }
       
public string MoreInfo { get; set; }
    }

El Controlador que voy a testear es algo tal que así:

        [HttpPost] public IHttpActionResult PostItem(negociositem item)
        {
           
if (item != null)
            {
               
var accion = new Items();
               
var error = new MensajeDeError();

               
var resultado = accion.AddItem(item, out error);

               
if (error.Code == ObtenError.Sin_error().Code)
                {
return Json(resultado); }
               
else
               
{ return Json(error); }
            }
           
else
           
{
               
return Json(ObtenError.Item_no_valido());
            }
        }

Como creo que se lee fácilmente, lo que hago es intentar persistir un item. Y si tengo algún error, lo que me devuelve (en vez del objeto resultado) un objeto mensaje de error. (Y aquí está la debilidad de devolver dos mensajes diferentes).

¿Cómo pruebo esto? Haciendo un test que fuerce un error, y comprobando que el código de error sea el esperado.

using api.Controllers;
using api.Entidades;
using System.Web.Http.Results;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace api.Controllers.Tests
{
    [
TestClass()]
   
public class ItemsControllerTests
   
{
        [
TestMethod()]
       
public void PostItemTest()
        {
           
var accion = new ItemsController();
           
var item = new negociositem { business_id = 0,
                                                          name =
"borrame",
                                                          description =
"",
                                                          origin = 2, picture =
"" };

           
var resultado = accion.PostItem(item);

           
Assert.AreEqual("503", ((JsonResult<api.MensajeDeError>)resultado).Content.Code);
        }
    }
}

¿Qué es lo importante aquí?

Primero asegurarme que me estoy importando al proyecto de Testing los namespaces adecuados. Es decir, los que contienen los tipos de objeto que voy a usar (Controllers, y Entidades), y el interfaz de respuesta (System.Web.Http.Results).

Segundo (y que vuelve a mostrar la debilidad del formato de respuesta), debo asegurarme de que el tipo de la respuesta sea la esperada. Por ejemplo, si todo hubiese ido bien, no hubiera recibido un tipo MensajeDeError, si no un tipo negociositem… lo cual es incómodo para testear y trabajar con esta api (pero es bueno para reducir el consumo de tráfico ya que devuelve solo lo que necesitas.

A partir de aquí, se me habré el horizonte de poder probar como si estuviera enviando peticiones a la API como cualquier otra APP, y pudiendo hacer test casi de integración.

Espero que sea de utilidad para alguien.