You are on page 1of 10

SQL Server - Programacin Back End

Business rules
Desarrollo Cliente/Servidor Ubicacin de las Reglas de Negocio

Introduccin
Toda aplicacin trata de reflejar parte del funcionamiento del mundo real, para automatizar tareas que de otro modo seran llevadas a cabo de modo ms ineficiente, o bien no podran realizarse. Para ello, es necesario que cada aplicacin refleje las restricciones que existen en el negocio dado, de modo que nunca sea posible llevar a cabo acciones no vlidas. A las reglas que debe seguir la aplicacin para garantizar esto se las llama reglas de negocio, o business rules. Ejemplos de tales reglas son: no permitir crear facturas pertenecientes a clientes inexistentes, controlar que el saldo negativo de un cliente nunca sobrepase cierta cantidad, etc. En realidad, la informacin puede ser manipulada por muchos programas distintos:

As, una empresa puede tener un departamento de contabilidad que controle todo lo

relacionado con compras, cobros, etc., y otro departamento tcnico, que est interesado en relacionar diversos parmetros de produccin con los costes. La visin que ambos departamentos tendrn de la informacin y sus necesidades sern distintas, pero en cualquier caso siempre se debern respetar las reglas de negocio. El hecho de que la informacin sea manipulada por diversos programas hace ms difcil garantizar que todos respetan las reglas, especialmente si las aplicaciones corren en diversas mquinas, bajo distintos sistemas operativos, y estn desarrolladas con distintos lenguajes y herramientas.

Tipos de reglas de negocio


Antes de seguir adelante con el estudio de la problemtica que presenta la implementacin de las reglas de negocio, vamos a establecer una clasificacin de las mismas en varios grupos.

1. Reglas del Modelo de Datos.


El primer grupo de reglas de negocio engloba todas aquellas reglas que se encargan de controlar que la informacin bsica almacenada para cada atributo o propiedad de una entidad u objeto es vlida: no hay precios de artculos negativos, el sexo de una persona solo puede ser masculino o femenino, una fecha siempre debe ser una fecha vlida (no existe el 30 de Febrero, cierto?), etc. A estas reglas las llamaremos reglas del modelo de datos.

Lic. Jorge Medi@nero A.

Pag. 1

SQL Server - Programacin Back End

2. Reglas de Relacin.
Otro grupo importante de reglas incluye todas aquellas reglas que controlan las relaciones entre los datos. Estas reglas especifican, por ejemplo, que todo pedido debe ser realizado por un cliente, y que el mismo debe estar dado de alta en nuestro sistema: adems, una vez que un cliente haya hecho algn pedido, se deber garantizar que no es posible eliminarlo, a menos que previamente se eliminen todos sus pedidos. Estas reglas constituyen las reglas de relacin.

3. Reglas de Derivacin.
Es frecuente que a partir de cierta informacin se pueda derivar otra: por ejemplo, el total de un pedido se puede calcular a partir de las distintas lneas que lo componen, mientras que el total de cada lnea se puede calcular a partir del nmero de unidades vendidas y el precio por unidad. Al conjunto de reglas que especifican y controlan la obtencin de informacin que se puede calcular a partir de la ya existente se las llama reglas de derivacin.

4. Reglas de Restriccin.
Otro grupo de reglas de negocio es el compuesto por las reglas de restriccin, que restringen los datos que el sistema puede contener. Ntese que este grupo de reglas se solapa en cierto modo con las reglas del modelo de datos, dado que aquellas tambin impiden la introduccin de datos errneos, como se vio anteriormente. La diferencia estriba en que las reglas de restriccin restringen el valor de los atributos o propiedades de una entidad ms all de las restricciones bsicas que sobre las mismas existen: por ejemplo, para un saldo existe una regla bsica (regla del modelo de datos) que indica que ste debe ser un nmero (no por obvia es menos regla!), pero adems puede haber una regla que indique que el saldo nunca puede ser menor que cierta cantidad tope establecida para cierto tipo de clientes. Esta sera lo que aqu denominamos una regla de restriccin, y la diferencia fundamental estriba en el hecho de que este tipo de reglas requiere para su verificacin del acceso a otros fragmentos de informacin, algo que no sucede con las reglas del modelo de datos. Esto tiene ciertas consecuencias que se vern ms adelante.

5. Reglas de Flujo.
El ltimo grupo de reglas de negocio incluye aquellas reglas que determinan y limitan cmo fluye la informacin a travs de un sistema. Por ejemplo, un cliente puede hacer una peticin de anlisis a un laboratorio, que anota un encargado: hecho esto, se genera un parte para uno o ms analistas, estos realizan las mediciones correspondientes y devuelven los partes con la informacin pertinente, a partir de la cul se genera un informe de anlisis, que ser un anlisis vlido solo cuando sea firmado por los responsables de garantizar su correccin. A las reglas que indican qu camino recorre la informacin y obligan a que se sigan solo los caminos vlidos se las llama reglas de flujo.

Lic. Jorge Medi@nero A.

Pag. 2

SQL Server - Programacin Back End

Arquitectura Cliente Servidor. (n-tier)


Capas en un sistema Cliente/Servidor En un esquema Cliente/Servidor clsico (Figura A) existen dos capas, el cliente y el servidor: ste est ubicado normalmente en otra mquina, y suele ser un gestor de base de datos, como DB2, SQL Server, Oracle, aunque tambin puede ser una base de datos ms pequea, como Paradox, dBase, etc., que accedemos directamente desde nuestra aplicacin cliente.

Figura A: Esquema C/S clasica

Los mejores gestores de base de datos relacionales proporcionan soporte para implementar en ellos bastantes reglas de negocio, mediante el uso de claves primarias, integridad referencial, triggers, etc., mientras que sistemas como dBase y otros apenas proporcionan soporte para reglas de negocio. Suponiendo que tengamos la informacin en un gestor de bases de datos potente, podremos despreocuparnos de llevar a cabo la codificacin de numerosas validaciones en nuestras aplicaciones: as, si en la base de datos creamos una regla de integridad referencial que indica que todo pedido pertenece a un cliente, el gestor de base de datos rechazar cualquier intento de almacenar un pedido en el que se nos haya olvidado indicar el mismo. Cualquier aplicacin que acceda a esta base de datos se beneficiar de esta y otras validaciones automticamente, sin tener que aadir ni una lnea de cdigo. Si estamos utilizando una base de datos menos potente, como dBase, no estamos de suerte. Casi todas las reglas de negocio debern implementarse dentro de los programas que accedan a la base de datos. Si los programas que acceden a la base de datos son varios, garantizar que en todos ellos se respetan todas las reglas puede llegar a ser muy difcil y engorroso, especialmente si se desarrollan con distintas herramientas. La necesidad de implementar reglas de negocio dentro de las aplicaciones cliente puede surgir tambin utilizando gestores de bases de datos ms potentes. En primer lugar, las bases de datos relacionales son cada vez ms potentes, pero no todas las reglas de negocio pueden reflejarse en ellas: por ejemplo, las reglas de flujo son bastante difciles de implementar dentro de la base de datos, y suelen ser las aplicaciones cliente las que controlan que la informacin sigue una ruta vlida a travs del sistema. Sin embargo, muchas de las reglas de negocio pueden reflejarse adecuadamente a nivel de la base de datos con estos gestores. El problema se agrava cuando la informacin del negocio se encuentra en distintas bases de datos, gestionadas por distintos gestores, digamos DB2 y Oracle: si, por ejemplo, en DB2 almacenamos la informacin sobre facturas, etc., y en la base de datos Oracle almacenamos informacin tcnica, como reparaciones llevadas a cabo en la maquinaria, cmo reflejamos que ciertas facturas corresponden a una reparacin, y garantizamos que no podamos relacionar una reparacin con una factura inexistente? Evidentemente, aqu no hay manera de establecer una regla de integridad referencial entre tablas almacenadas en dos bases de datos distintas y correspondientes a distintos gestores de

Lic. Jorge Medi@nero A.

Pag. 3

SQL Server - Programacin Back End


base de datos. De nuevo, la solucin al problema es implementar el chequeo en cada aplicacin cliente, comprobando que exista la factura en la tabla DB2 antes de referenciarla en la tabla de reparaciones Oracle. Ya que parece que de cualquier modo seremos nosotros mismos los encargados de obligar a que se cumplan algunas reglas de negocio, puede ser conveniente encontrar la manera de centralizar la gestin de estas reglas en un nico lugar, de modo que todo el cdigo necesario no se haya de duplicar en cada una de las aplicaciones. La solucin puede ser crear una aplicacin que se encargue de llevar a cabo estas tareas, de modo que todos los clientes pidan o enven informacin a la misma, no al gestor de base de datos en el servidor: a ste solo acceder la nueva aplicacin, que conforma una nueva capa dentro de un sistema Cliente/Servidor, la capa intermedia o middle-tier (Figura B), con lo que nuestro sistema ha pasado de ser un sistema Cliente/Servidor convencional a ser un sistema con tres capas (three-tiered). Conviente apuntar que pueden haber varias de estas aplicaciones, que llamaremos servidores de aplicacin, lo que permite distribuir la carga de trabajo.

Figura B: Arquitectura C/S en tres capas ( Three-Tier) Cuadro A: Algunas consideraciones sobre la capa intermedia.

Hemos hablado hasta ahora de la capa intermedia como si se tratara de una aplicacin cualquiera, pero esto no es as. En los esquemas Cliente/Servidor tradicionales, de dos capas, suele ser el gestor de bases de datos el que proporciona la conectividad, as como capacidades tan fundamentales como el soporte de transacciones. La introduccin de una capa intermedia puede romper con esto, al ser necesario un modo de comunicar las aplicaciones cliente con la aplicacin que lleva a cabo las labores de la capa intermedia, siendo ahora sta la que se aprovecha de las capacidades de conectividad, el soporte de transacciones y las distintas capacidades que proporciona el gestor de base de datos. Solucionar todos los problemas de conectividad, etc., no es tarea fcil, y lgicamente debera utilizarse uno o ms productos que solucionen algunos de estos problemas, basados en DCOM, CORBA y tecnologas similares: es el caso de MIDAS/OleEnterprise, de Borland, que proporciona proteccin contra la cada de servidores, conectividad e importacin de algunas reglas del negocio a los clientes (aunque no soporta transacciones distribuidas), y de Microsoft Transaction Server (que proporciona conectividad y transacciones distribuidas, pero no proteccin contra cadas de los servidores).

Para ms informacin sobre DCOM y CORBA es muy recomendable el artculo "CORBA & COM.", de Alberto Lpez Talln publicado en el nmero 31 de RPP. Tambin puede hallar informacin sobre MIDAS, la solucin

Lic. Jorge Medi@nero A.

Pag. 4

SQL Server - Programacin Back End

Ubicacin de las reglas de negocio


La decisin de dnde ubicar una determinada regla de negocio dentro de una arquitectura C/S de tres capas puede simplificarse mucho si se atiende al tipo de regla de que se trata, utilizando la clasificacin introducida ms arriba. Las reglas del modelo de datos especifican los valores vlidos de cada atributo de las diversas entidades que se almacenan, lo que simplificando es lo mismo que decir los valores vlidos para cada campo de cada tabla. Estas reglas deben, a ser posible, reforzarse en el servidor: esto se hace en primer lugar escogiendo correctamente el tipo de los campos de cada tabla (no almacenar una fecha en un campo de tipo cadena si nuestra base de datos dispone de campos del tipo fecha), y donde el servidor lo soporte, mediante restricciones (por ejemplo, en Interbase es posible especificar mediante CHECK diversas condiciones que debe verificar un dato para poder almacenarse en un campo), etc. El hacer esto as proporcionar mayor robustez a la base de datos. Como complemento de esto, sin embargo, se debe implementar estas validaciones tambin a nivel de cliente, por una simple razn: evitar trabajo y esperas innecesarias a los usuarios. Todos hemos rellenado algn formulario HTML varias veces hasta que por fin los datos introducidos son vlidos: esto es as porque en un formulario HTML raramente se lleva a cabo la validacin de los datos en el cliente, por lo que la informacin no se chequea hasta que llega al servidor, debiendo el usuario en el cliente esperar a cualquier mensaje de xito o error. Lo mejor sera no tener que llevar a cabo ningn tipo de programacin, y que las reglas del modelo de datos se pudieran importar del servidor al cliente, hacindose en el mismo gran parte de los controles necesarios para garantizar la validez de la informacin introducida por el usuario: esto no es muy difcil, dado que son chequeos relativamente sencillos, al afectar solo a un campo, y de hecho algunos productos, como OleEnterprise de Borland, incorporan la posibilidad de importar estas reglas del servidor. Por lo que respecta a las reglas de relacin, el lugar ms adecuado para implementarlas es, sin lugar a dudas, el servidor. La mayor parte de los gestores de base de datos proporcionan integridad referencial y los mecanismos necesarios para implementar fcilmente estas reglas, y esto proporciona una robustez enorme a la base de datos. Adems, el hecho de que los datos necesarios para verificar si se respetan las relaciones residan en la misma base de datos/mquina hace que estas verificaciones sean muy rpidas, mientras que si el chequeo se hace en el cliente se incrementar el trfico de red. El problema lo encontraremos si el negocio est distribuido en varias bases de datos: si ese es el caso, ser necesario implementar alguna de estas reglas en la capa intermedia, y que sta resida lo ms cerca posible de las bases de datos, a ser posible en la misma mquina o red local. Las reglas de derivacin pueden variar mucho en complejidad: la informacin derivada ms simple, como calcular el total de una lnea de pedido, puede calcularse a partir de otros campos del mismo registro. Dado que no se requiere informacin adicional, y en general toda la informacin de un registro viaja a la vez al cliente, calcular esta informacin en el mismo es trivial, y no resulta gravoso. Ahora bien, si lo que se desea es calcular la suma de todos los pedidos de un cliente desde 1960, el volumen de informacin necesaria para calcular el total es enorme, y hacerla viajar a travs de la red no es recomendable. Lo ideal ser implementar el clculo de esta informacin de modo que se ejecute en el servidor, posiblemente mediante un procedimiento almacenado, o al menos mediante una sentencia SQL de agregacin, con lo que la nica informacin que viajar hasta el cliente ser el total, no todos los registros necesarios para calcularlo. Sin embargo, SQL, o las extensiones de SQL que proporcionan los distintos gestores de base de datos, no es un lenguaje de propsito general, por lo que puede ser difcil o imposible implementar ciertas reglas de derivacin. La solucin ideal puede pasar por implementar las reglas de derivacin en la capa intermedia: si sta reside en la misma mquina que el servidor, la informacin no deber viajar por la red, y aunque el clculo no ser tan rpido como si lo hace el gestor, puede ser suficiente. Si tenemos los datos distribuidos en diversas bases de datos, sta ser la nica solucin para implementar muchas de las reglas de derivacin.

Lic. Jorge Medi@nero A.

Pag. 5

SQL Server - Programacin Back End


Por otro lado, las reglas ms sencillas pueden tambin implementarse en la capa intermedia, de modo que tengamos las reglas centralizadas en una nica aplicacin, no desperdigadas por diversas aplicaciones, no importa lo sencillas que sean. Las reglas de restriccin deben implementarse en el servidor, o en la capa intermedia. Dado que estas reglas contemplan restricciones en los datos que dependen casi siempre de informacin presente en varias tablas, llevar a cabo el control en el cliente puede implicar cierto trfico de red, por lo que es ms conveniente situar la implementacin de la regla ms cerca de los datos. El lugar ideal podra ser el servidor, pero aqu nos encontramos con las limitaciones del SQL de los gestores de base de datos, y con el posible problema del acceso a diversas bases de datos, por lo que ubicar estas reglas en la capa intermedia puede ser de nuevo una buena solucin. Por ltimo, quedan las reglas de flujo: estas reglas son excelentes candidatas a ser implementadas en la capa intermedia, dado que su complejidad suele ser bastante grande, lo que las hace inmanejables por un gestor de bases de datos.

Conclusiones
No hay una nica posibilidad a la hora de distribuir las reglas de negocio dentro de un esquema Cliente/Servidor. Sin embargo, s hay ciertas pautas que se pueden tener en cuenta a la hora de tomar una decisin, basadas en una clasificacin de las reglas de negocio aqu expuestas: en general, lo ms recomendable suele ser implementar todas las reglas de negocio relativas al modelo de datos y las relaciones en el servidor, dado que los modernos servidores suelen llevar a cabo estas tareas muy eficazmente. Por lo que respecta al resto de las reglas, la mejor solucin suele ser implementarlas en la capa intermedia: si tuvisemos que acceder a varias bases de datos, habramos de migrar aqu algunas de las reglas que de otro modo iran al servidor, especialmente las de relacin. Si bien el trfico en la red se incrementar al utilizar una capa intermedia, este puede quedar aliviado haciendo que sta resida en la misma mquina que el servidor de datos, o al menos dentro de la misma red local. La Figura C muestra grficamente la ubicacin recomendable de las reglas de negocio dependiendo de su tipo (para acceso a una nica base de datos).

de de en

Figura C: Ubicacin las Reglas Negocio una

Arquitectura Three-Tier

Lic. Jorge Medi@nero A.

Pag. 6

SQL Server - Programacin Back End


Por ltimo, vale la pena resaltar la conveniencia de implementar las reglas del modelo de datos tambin en el cliente, para hacer fluida la interaccin con el usuario, siendo lo ideal importarlas dinmicamente del servidor de base de datos. Por lo dems, la implementacin de reglas en las aplicaciones cliente puede dar lugar a muchos problemas, tanto de velocidad como de portabilidad y fiabilidad, al tener que reflejar una y otra vez las mismas reglas en distintas aplicaciones, quiz desarrolladas con distintos lenguajes y ejecutndose bajo distintos sistemas operativos.

Copyright J.Medi@nero.A.2010.

Software R-DBMS:
Sistemas de base de datos de servidor
Los sistemas basados en un servidor se construyen de manera que una base de datos en un equipo central, conocido como un servidor, se comparte entre varios usuarios. Los usuarios tienen acceso al servidor a travs de una aplicacin. En un sistema abierto de conectividad de varios niveles, la lgica de la aplicacin cliente se ejecuta en dos o ms ubicaciones: El cliente reducido se ejecuta en el equipo local del usuario y se encarga de presentar resultados al usuario. La lgica empresarial se encuentra en aplicaciones de servidor que se ejecutan en un servidor. Los clientes reducidos solicitan funciones a la aplicacin de servidor, que, a su vez, es una aplicacin multiproceso capaz de operar con varios usuarios simultneos. La aplicacin servidor es la que abre conexiones con el servidor de base de datos. La aplicacin servidor se puede ejecutar en el mismo servidor que la base de datos; o bien, se puede conectar a travs de la red con un servidor diferente que est actuando como un servidor de base de datos. En sistemas complejos, la lgica empresarial se puede implementar en varias aplicaciones de servidor interconectadas o en varias capas de aplicaciones de servidor.

ste es el escenario tpico de las aplicaciones de Internet. Por ejemplo, una aplicacin de servidor multiproceso se puede ejecutar en un servidor con Microsoft Internet Information Services (IIS) y servir a miles de clientes reducidos que se ejecutan en Internet o en una intranet. La aplicacin de servidor utiliza un grupo de conexiones para comunicarse con una o ms instancias de SQL Server. Las instancias de SQL Server pueden estar en el mismo equipo que IIS o en servidores diferentes de la red. En un sistema cliente-servidor de dos niveles, los usuarios ejecutan una aplicacin en su equipo local, conocido como aplicacin cliente, que conecta a travs de una red con una instancia de SQL Server que se ejecuta en un equipo servidor. La aplicacin cliente ejecuta la lgica empresarial y el cdigo para mostrar el resultado al usuario. Por ello, se le denomina a veces cliente amplio.

Lic. Jorge Medi@nero A.

Pag. 7

SQL Server - Programacin Back End

Ventajas de un sistema de base de datos de servidor

El tener los datos almacenados y administrados en una ubicacin central ofrece varias ventajas: Todos los elementos de datos estn almacenados en una ubicacin central donde todos los usuarios pueden trabajar con ellos. No se almacenan copias separadas del elemento en cada cliente, lo que elimina los problemas de hacer que todos los usuarios trabajen con la misma informacin. El sistema no necesita garantizar que todas las copias de los datos se actualizan con los valores actuales, porque hay una nica copia en la ubicacin central. Las reglas de empresa y de seguridad se pueden definir una sola vez en el servidor para todos los usuarios. La exigencia de las reglas se puede llevar a cabo en una base de datos utilizando restricciones, procedimientos almacenados y desencadenadores. Las reglas se pueden exigir tambin en una aplicacin de servidor, puesto que estas aplicaciones son, asimismo, recursos centrales a los que tienen acceso muchos clientes reducidos. Los servidores de base de datos relacionales optimizan el trfico de la red al devolver slo los datos que la aplicacin necesita.

Por ejemplo, Si una aplicacin que trabaja con un servidor de archivos tiene que presentar la lista de los representantes comerciales de Oregn, debe obtener el archivo de empleados completo. Si la aplicacin trabajara con un servidor de bases de datos relacionales, enviara este comando:

SELECT first_name, last_name FROM [srv22].Northwind.dbo.employees WHERE emp_title = 'Sales Representative' AND emp_state = 'OR'

La base de datos relacional del servidor [srv22], slo devuelve los nombres de los representantes comerciales de Oregn y no toda la informacin de todos los empleados.

Lic. Jorge Medi@nero A.

Pag. 8

SQL Server - Programacin Back End

Los gastos en hardware se pueden minimizar.


Como los datos no estn almacenados en los clientes, stos no tienen que dedicar espacio de disco para almacenarlos. Los clientes tampoco necesitan la capacidad de procesamiento para administrar los datos localmente y el servidor no tiene que dedicar capacidad de procesamiento para presentar los datos. El servidor se puede configurar para optimizar la capacidad de E/S de disco necesaria para obtener los datos y los clientes se pueden configurar para optimizar el formato y presentacin de los datos obtenidos desde el servidor. El servidor puede estar almacenado en una ubicacin relativamente segura y estar equipado con dispositivos como sistemas de alimentacin ininterrumpida, lo que resulta ms econmico que si se protegieran todos los clientes. Las tareas de mantenimiento como las copias de seguridad y restauracin de los datos son ms sencillas porque estn concentradas en el servidor central.

Ventajas de SQL Server como servidor de base de datos


SQL Server puede proporcionar los servicios de base de datos necesarios para sistemas extremadamente grandes. Los servidores de gran tamao pueden tener miles de usuarios conectados a una instancia de SQL Server al mismo tiempo. SQL Server dispone de proteccin total para estos entornos, con medidas de seguridad que evitan problemas como tener varios usuarios intentando actualizar los mismos datos al mismo tiempo. SQL Server asigna tambin de manera muy eficaz los recursos disponibles, como memoria, ancho de banda de la red y E/S del disco, entre los distintos usuarios. Los sitios de Internet extremadamente grandes pueden dividir sus datos entre varios servidores, extendiendo la carga de procesamiento entre varios equipos y permitiendo que el sitio sirva a miles de usuarios simultneos. En un nico equipo se pueden ejecutar varias instancias de SQL Server. Por ejemplo, una organizacin que proporcione servicios de base de datos a muchas otras organizaciones puede ejecutar una instancia de SQL Server para cada organizacin cliente, todas ellas en un solo equipo. Esto asla los datos para cada organizacin cliente, a la vez que permite a la organizacin que ofrece el servicio reducir costos teniendo que administrar nicamente un equipo servidor. Las aplicaciones de SQL Server se pueden ejecutar en el mismo equipo que SQL Server. La aplicacin se conecta a SQL Server utilizando los componentes de comunicaciones entre procesos (IPC) de Windows, tales como memoria compartida, en lugar de una red. Esto permite utilizar SQL Server en sistemas pequeos en los que una aplicacin debe almacenar los datos localmente.

Lic. Jorge Medi@nero A.

Pag. 9

SQL Server - Programacin Back End

Capas n-Tier:

Conectividad Abierta

La ilustracin muestra una instancia de SQL Server actuando como servidor de base de datos para un sitio Web de gran tamao y un sistema cliente-servidor heredado.

Los sitios Web de mayor tamao y los sistemas de procesamiento de datos a nivel corporativo generan a menudo un mayor procesamiento de base de datos del que puede admitir un nico equipo. En estos grandes sistemas, los servicios de base de datos vienen proporcionados por un grupo de servidores de base de datos que forman un nivel de servicios de base de datos. SQL Server no es compatible con una forma de equilibrio de carga de agrupacin para crear un nivel de servicios de base de datos, pero s admite un mecanismo que se puede utilizar para dividir los datos entre un grupo de servidores autnomos. Si bien cada servidor se administra individualmente, los servidores cooperan para expandir la carga de procesamiento de la base de datos entre el grupo. Un grupo de servidores autnomos que comparten una carga de trabajo se denomina federacin de servidores.

Lic. Jorge Medi@nero A.

Pag. 10

You might also like