Arquitectura, buenas prácticas y desarrollo sobre la nueva herramienta de Microsoft SharePoint 2016

Test Unitarios, Inyecciones de dependencias y ALM es posible en SharePoint

Generalmente, procesos «normales» en el desarrollo software (como son ALM, Test Unitarios, TDD e inyecciones de dependencias) son conceptos un tanto alejados de la realidad de muchos desarrolladores de SharePoint.

¿Motivos? Si yo tengo que trabajar sí o sí con SharePoint y no puedo aislarme de SharePoint, necesito ejecutar esta sentencia sí o sí dentro de nuestro servidor favorito. Ahora bien, ese mismo problema no lo tienen los desarrolladores que quieren acceder a los datos de la base de datos seleccionadas, ya sea SQL Server, Mongo DB, MySql u Oracle. Por lo tanto debemos de plantearnos que tenemos que trabajar igual que se hacen en otras plataformas/entornos.

¿Ahora bien como lo podemos conseguir?

Tal y como publicó el Maestro (Gustavo Velez) desde Microsoft han desarrollado un emulador de SharePoint de tal forma que en tus pruebas unitarias «emulas» que tienes un SharePoint (aunque físicamente no lo tengas). Optar por esta solución, sin contar que solamente está disponible para los usuarios de Visual Studio Ultimate no me parece la más elegante ni verídica. Primero, porque de alguna forma has de llevar tus dll en tu «entorno» sin SharePoint porque si no, tu proyecto no compila ya que no tiene librerias.  Y segundo, tu capa de acceso a datos no la tienes aislada de SharePoint.

¿Como lo solucionamos nosotros?

Siguiendo los patrones SOLID de programación, nosotros dentro de nuestro FrameWork propio Enmarcha tenemos una interfaz Data que es semejante a la siguiente:

namespace Encamina.Enmarcha.Data.Interfaces
{
    public interface IRepository<I, T> : IPageable
    {
        T Get(I id);
        ICollection<T> GetAll(int page);
        ICollection<T> Query(IQuery   query, int page);
        int Insert(T data);
        bool Save(I id, T data);
        bool Delete(I id);
        int Length();
    }
}

Esta interfaz parece simple, pero tiene diversos aspectos muy interesantes. Por un lado, podéis observar que está preparada para una Clase Generica de tal forma que es válida tanto para una clase «Maestro» como para una clase «Coche» y la podemos útilizar en los diversos desarrollos.

El segundo aspecto interesante es que utilizamos una Interfaz IQuery donde implementamos una interfaz de Consultas, de forma que si utilizamos SharePoint tendremos una clase CamlQuery que implemente esta interfaz. Pero si utilizamos consultas SQL tendremos otra interfaz SQLQuery que la implemente.
¿Que ganamos con esto?

  1. Agilizamos el cambio de la plataforma en la que almacenamos los datos (en algunos desarrollos quizas no nos interese almacenar los datos en listas de SharePoint y optamos por un modelo relacional). Este cambio, ahora es algo intranscendente en nuestra aplicación y con cambiar la inyección de dependencia lo tenemos solucionado.
  2. Ahorramos mucho trabajo a los front-end developers que no se tienen que preocupar por lo que tienen debajo. Ellos trabajan directamente con el modelo que proponemos y cualquier cambio de la plataforma en la que lo almacenamos no le afecta.
  3. Estandarizamos la forma de acceder a los datos de SharePoint, no nos tendremos que preocupar de si el desarrollador llama correctamente al método SPQuery, si indica el número de elementos a devolver… esta responsabilidad solamente la tendremos una vez vamos a implementar la interfaz.

Inyecciones de dependencias

Ahora bien, para poder conseguir tener esta clase aislada por un lado los datos y, por otro, la lógica de negocio entran en juego el término «inyección de dependencia» e «inversión de control».

Inyección de Dependencias (en inglés Dependency Injection, DI) es un patrón de diseño orientado a objetos, en el que se suministran objetos a una clase en lugar de ser la propia clase quien cree el objeto.

Inversión de control (Inversion of Control en inglés, IoC) es un método de programación en el que el flujo de ejecución de un programa se invierte respecto a los métodos de programación tradicionales, en los que la interacción se expresa de forma imperativa haciendo llamadas a procedimientos (procedure calls) o funciones. Tradicionalmente el programador especifica la secuencia de decisiones y procedimientos que pueden darse durante el ciclo de vida de un programa mediante llamadas a funciones. En su lugar, en la inversión de control se especifican respuestas deseadas a sucesos o solicitudes de datos concretas, dejando que algún tipo de entidad o arquitectura externa lleve a cabo las acciones de control que se requieran en el orden necesario y para el conjunto de sucesos que tengan que ocurrir.

Un artículo muy interesante sobre inyección de dependencias y entornos de SharePoint lo escribió el maestro Edin Kapic para CompartiMOSS
En nuestro FrameWork, por un lado, hemos implementado dos tipos de clase «Datos»: por un lado una clase «Mock» y, por otro, una clase «SharePointData».
La clase «Mock» es una clase que realiza operaciones ficticias sobre objetos de .NET. Para rellenar los datos hacemos uso de NBuilder . La implementación de un método de la clase «Mock» es algo semejante a la siguiente:

     public Status<T> Get(I id)
        {
            try
            {
                var dataReturn = new List<T>();
                var item = _data[Convert.ToInt32(id.ToString())];
                var result = new Status<T>();
                dataReturn.Add(item);
                result.Data = dataReturn;
                result.Success = true;
                return result;
            }
            catch (Exception ex)
            {
                return new Status<T>
                {
                    Success = false,
                    Error = new Error
                    {
                        Id = ex.HResult,
                        Message = ex.Message,
                        Code = 0
                    }
                };
            }
        }

Ahora bien, para la clase «DataSharePoint» implementaremos un método ya semejante pero con los artefactos propios de SharePoint. Un ejemplo seria el método insert:

        public int Insert(T data)
        {
            try
            {
                Web.AllowUnsafeUpdates = true;
                var list = Web.Lists.TryGetList(Lista);
                SPListItem item = list.AddItem();
                var props = typeof(T).GetProperties();
                foreach (var prop  in props )
                {
                    var valor = prop.GetValue(data);
                    if (valor == null) continue;
                    if (valor.GetType() == typeof(List<string>))
                    {
                        var listValor = (List<string>) valor;
                        if (listValor.Count>0) item[prop.Name] = listValor[0];
                    }
                    else
                    {
                        if (valor.ToString() != "0") item[prop.Name] = valor;
                    }
                }
                item.Update();
                return item.ID;
            }
            catch (Exception)
            {
                return -1;
            }
        }

Lo más interesante de este código es que aprovechamos la potencia que tiene un lenguaje como C# para establecer unas reglas para facilitarnos la vida. Por un lado, hacemos un mapeo entre cada propiedad de la clase con un nombre interno de la lista, de esta forma podemos acceder al valor de este campo y cualquier modificación en el modelo automáticamente se refleja en nuestras clases, con lo cual, tenemos todo centralizado en nuestro modelo de datos lo que nos ahorra mucho trabajo y hace nuestra aplicación más robusta.

Conclusión

SharePoint no es una plataforma difícil, el principal problema es que queremos aislar tanto SharePoint del resto de los ecosistemas de la organización, que nos hace trabajar de forma erronea. Para muestra de este fallo solamente hay que observar el Nuevo Modelo de Apps de SharePoint (en el que queremos incluir todas las Apps de nuestra organización en un entorno SharePoint). Trabajar en SharePoint no significa trabajar mal, sin ningún patrón ni ninguna estrategia y con herramientas obsoletas. Trabajar con SharePoint es un gran reto y hay que conocer mucho la plataforma para poder potenciar los puntos fuertes de SharePoint (Gestión Documental, búsqueda, workflows) y minimizar los puntos débiles (acceso a datos). Para plantear una buena solución sobre SharePoint tenemos que tener una buena Arquitectura en la que se sustente nuestro desarrollo.

mm

Sobre Adrián Díaz

Adrián Díaz es Ingeniero Informático por la Universidad Politécnica de Valencia. Es MVP de Microsoft en la categoría Office Development desde 2014, MCPD de SharePoint 2010, Microsoft Active Profesional y Microsoft Comunity Contribuitor 2012. Cofundador del grupo de usuarios de SharePoint de Levante LevaPoint. Lleva desarrollando con tecnologías Microsoft más de 10 años y desde hace 3 años está centrado en el desarrollo sobre SharePoint. Actualmente es Software & Cloud Architect Lead en ENCAMINA.
Esta entrada ha sido publicada en buenas practicas y etiquetada como , , . Enlace permanente .
Suscríbete a Desarrollando sobre SharePoint

Suscríbete a Desarrollando sobre SharePoint

Recibe todas las actualizaciones semanalmente de nuestro blog

You have Successfully Subscribed!

ENCAMINA, piensa en colores