Una de las novedades que trae el nuevo FrameWork es que podemos saber cuál es el entorno en el que se está ejecutando nuestro desarrollo. De esta forma, podemos ejecutar el WorkBench en local, o bien en un Tenant de Office 365. A la hora de programar, es mucho más rápido en un entorno en el que nos centremos en el desarrollo y no en pelearnos con autenticación, seguridad, etc.. Por este motivo, en WorkBench o entorno de NodeJS, es muy importante esta nueva forma de desarrollar. Crearemos Mocks de tal forma que podamos probar nuestros desarrollos de una forma desacoplada a SharePoint y agilizando el desarrollo.
Todo esto esta suena muy bien, pero tal y como lo plantean en el ejemplo del Repositorio de GitHub, en mi modesta opinión, no está bien enfocado, ya que lo que hace es hablar de una duplicidad de métodos. Esta duplicidad, en un «Hello World» se puede permitir, sin embargo, no es una buena opción materializarlo en proyecto real.
Por poner un símil con un desarrollo en C#, no es lo mismo poner directivas de compilación, que hacer inyección de dependencias. En JavaScript, aunque mucha gente lo desconozca, se puede hacer inyección de dependencias. Por ejemplo, Angular utiliza mucho la inyección de dependencias para su correcto funcionamiento.
Para desarrollar en SharePoint FrameWork, utilizamos un lenguaje TypeScript para aprovechar todo lo que nos da este lenguaje y simplificar el desarrollo. Por este motivo vamos a utilizar Interfaces e inyección de dependencias en los constructores de las clases, de una forma muy similar a lo que hacemos en C#. La idea no es hacer de TypeScript un lenguaje como C#, sino intentar seguir los principios SOLID a la hora de programar y tratar de hacer bien las cosas.
Vamos a ver un ejemplo de cómo plantear la solución que comentan en el Repositorio de SharePoint, pero utilizando Inyección de Dependencias. Por si alguien no se quiere leer el artículo del repositorio, lo que se hace en el ejemplo de GitHub es una parte en el entorno de Test, y otra dentro del Tenant de Office 365/SharePoint Online. Ésta, según mi opinión, no es la forma correcta, ya que al ser dos «contratos» totalmente distintos, puede darse el caso que el código de Test funcione, pero en Producción no.
Vamos a implementar ese «Contrato» para que nuestra aplicación se comporte igual, tanto si estás en Test, como si estás en Office 365. Para ello, en primer lugar se implementa una Interfaz que se encargará de hacer las consultas a SharePoint.
import { ISPLists} from "./IList"; export interface ISharePoint { getList(): Promise<ISPLists>; }
Nota: El atributo export, es similar al public de C#. El import, es similiar a los using de C#. Una vez tenemos la interfaz, vamos a crear dos clases que implementen esta interfaz. Por un lado, implementaremos una clase de Mock y por otro lado, implementaremos una clase con los accesos a SharePoint (para ello utilizaremos la librería de PnP como veremos más adelante).
Clase MockSharePoint
import {ISharePoint} from "./ISharePoint"; import {ISPLists,ISPList} from "./IList"; import MockHttpClient from "./MockHttpClient"; export class MockSharePoint implements ISharePoint { Url:string; constructor(url:string){ this.Url=url; } getList(): Promise<ISPLists> { return MockHttpClient.get(this.Url) .then((data: ISPList[]) => { var listData: ISPLists = { value: data }; return listData; }) as Promise<ISPLists>; } }
Clase PnPSharePoint
import {ISharePoint} from "./ISharePoint"; import {ISPLists,ISPList} from "./IList"; import pnp from "sp-pnp-js"; export class PnPSharePoint implements ISharePoint { Url:string; constructor(url:string){ this.Url=url; } getList(): Promise<ISPLists> { return pnp.sp.web.lists.getByTitle("Documents").items.get().then((data: ISPList[]) => { var listData: ISPLists = { value: data }; return listData; }) as Promise<ISPLists>; } }
Una vez implementadas las clases que vamos a utilizar, el siguiente paso es crear una clase (la que vamos a llamar en el arranque del WebPart, en la que nosotros le inyectemos el entorno en el que estamos). En C#, nosotros utilizaríamos una herramientas como AutoFact, Unity, Castle, etc. En JavaScript hay FrameWorks que lo implementan de serie, como he comentado anteriormente. En nuestro caso, al NO utilizar ningún FrameWork, lo haremos de forma más artesana.
Para ello, implementaremos la clase Render, a la que llamaremos en el momento de la carga de nuestro WebPart:
export class Render{ SharePoint:ISharePoint; RenderPrint: Element; public constructor(sharePoint:ISharePoint, renderPrint:Element) { this.SharePoint=sharePoint; this.RenderPrint=renderPrint; } public RenderList() { this.SharePoint.getList().then( (response) => { this._renderList(response.value); }); } private _renderList(items: ISPList[]): void { let html: string = ""; items.forEach((item: ISPList) => { html += ` <ul > <li class="${styles.listItem}"> <span class="ms-font-l">${item.Title}</span> </li> </ul>`; }); this.RenderPrint.innerHTML = html; } }
Si os fijáis, en el constructor de la clase tiene dos parámetros: la Interfaz que hemos implementado y el elemento en el cual vamos a pintar el HTML.
Por último, lo que haremos en el método Render del WebPart que estamos implementando, es crear una clase de tipo Render. Dependiendo del entorno en el que nos encontremos, crearemos una clase de tipo Mock o de tipo PnP. Quedaría de la siguiente forma:
if (this.context.environment.type === EnvironmentType.Local) { this.fly= new Render(new MockSharePoint(this.context.pageContext.web.absoluteUrl),this.domElement.querySelector('#spListContainer')); } else{ this.fly= new Render( new PnPSharePoint(this.context.pageContext.web.absoluteUrl),this.domElement.querySelector('#spListContainer')); } this.fly.RenderList();
Resumen
En SharePoint, tradicionalmente a nivel de desarrollo siempre se ha criticado que los desarrolladores no seguían las buenas practicas ni recomendaciones del Lenguaje. En ocasiones se echaba la culpa a la propia peculiaridad de SharePoint. Sin embargo, esto no es excusa para al menos no intentar hacer las cosas bien.
Ahora, con el cambio de habilidades de los desarrolladores de SharePoint, no debemos seguir con los errores del pasado y tenemos que seguir las buenas prácticas y recomendaciones del lenguaje que utilicemos. Éste es un caso de mala utilización del lenguaje y que apoya las palabras de los críticos de SharePoint.
El código fuente de este ejemplo lo podéis encontrar en el siguiente repositorio de GitHub: