Reserva de hotel corporativo

Introducción

Debes construir un motor de reservas para hoteles corporativos. Este motor tiene que satisfacer las necesidades de 3 tipos de actores diferentes:

  • La manager del hotel: define los diferentes tipos de habitaciones de su hotel y su respectiva cantidad.
  • El administrador de la empresa: añade/elimina empleados y crea políticas de reserva para la empresa y sus empleados.
  • El empleado: reserva las habitaciones del hotel.

Para lograr esto, el motor debe ofrecer 4 servicios principales que trabajan en estrecha colaboración entre sí.

A continuación se describen estos cuatro servicios. El  <?> indica que puedes utilizar cualquier primitive o type que desees.

Servicio de hotel

Este servicio es utilizado por la manager del hotel para definir los tipos de habitaciones y el número de cada tipo de habitación en el hotel. Con un ID del hotel, este servicio también puede dar información sobre el mismo.

public class HotelService {

// Collaborators(?)

void addHotel(<?> hotelId, <?> hotelName);

void setRoom(<?> hotelId, <?> number, <?> roomType);

<?> findHotelBy(<?> hotelId);

}

 

Reglas

El método addHotel(...) debe lanzar una excepción si el ID del hotel ya existe o, de lo contrario, debe crear el hotel.

El método setRoom(...) debe lanzar una excepción si el hotel no existe. Debe inserir o actualizar una habitación según el número de la habitación.

El findHotelBy(<?> hotelId) debe dar toda la información sobre el número de habitaciones del ID especificado.

Servicio de la empresa

Este servicio le permite a los administradores de la empresa añadir y eliminar empleados.

public class CompanyService {

// Collaborators(?)

void addEmployee(<?> companyId, <?> employeeId);

void deleteEmployee(<?> employeeId);

}

 

Reglas

  • Los empleados no deben estar duplicados.
  • Al eliminar un empleado, todas las reservas y políticas asociadas al empleado también se deben eliminar del sistema. 

Servicio de política de reservas

Este servicio le permite a los administradores de la empresa crear políticas de reserva para la empresa y sus empleados. Las políticas de reserva determinan si la solicitud de reserva de un empleado está permitida por su empresa. Hay dos tipos de políticas de reserva:

  • Política de reserva de la empresa: Indica qué tipo de habitaciones se pueden reservar. Por ejemplo, puede que una empresa sólo permita reservar habitaciones estándar (individuales/dobles), o puede que permita habitaciones estándar y junior suite.
  • Política de reserva de empleados: Indica qué tipo de habitaciones puede reservar un empleado en concreto. Por ejemplo, puede que un empleado sólo pueda reservar una habitación estándar, mientras que otro puede reservar una habitación estándar, una suite junior y una master suite.
public class BookingPolicyService {

// Collaborators(?)

void setCompanyPolicy(<?> companyId, <?> roomTypes);

void setEmployeePolicy(<?> employeeId, <?> roomTypes);

boolean isBookingAllowed(<?> employeeId, <?> roomType);

}

 

Reglas del negocio

  • Las políticas de los empleados tienen prioridad frente a las políticas de la empresa. Si existe una política para un empleado, esta deberá respetarse independientemente de lo que diga la política de la empresa.
  • Si no existe una política para los empleados, entonces se debe hacer recurso a la política de la empresa.
  • Si no existen políticas para el empleado ni para la empresa, el empleado debe poder reservar cualquier habitación.

Reglas técnicas

  • Los métodos setCompanyPolicy(...) y setEmployeePolicy(...) deben crear una nueva política o actualizar una existente. No se permite duplicar políticas de empresa ni de empleados.
  • El método isBookingAllowed(...) debe tener en cuenta al empleado y a la empresa para la que trabaja.

Servicio de reserva

Este servicio le permite a los empleados reservar habitaciones en los hoteles.

public class BookingService {

// Collaborators (?)

Booking book(<?> employeeId, <?> hotelId, <?> roomType, Date checkIn, Date checkOut);

}

 

Reglas

  • La reserva debe tener un ID único e incluir el employeeId, el hotelId, el roomType, el checkIn y el checkOut.
  • La fecha del check out debe ser al menos un día después de la fecha del check in.
  • Valida que el hotel exista y que proporcione el tipo de habitación reservada.
  • Verifica que la reserva este permitida según las políticas de reserva definidas (si las hubiera). Consulta el servicio de política de reservas para más información.
  • Sólo se permitirá hacer una reserva si hay al menos un tipo de habitación disponible durante todo el periodo de reserva.
  • Lleva un registro de todas las reservas. Por ejemplo, si el hotel tiene 5 habitaciones estándar, no deberíamos tener más de 5 reservas en el mismo día.
  • Las habitaciones del hotel pueden reservarse varias veces siempre que no haya conflictos con las fechas.
  • Envía la confirmación de la reserva al empleado o, de lo contrario, envía un mensaje de error (también se pueden utilizar excepciones). 

Normas de la Kata

  • Se debe utilizar Outside-In TDD.
  • Empieza por las pruebas de aceptación, una en una.
  • Define tus pruebas de aceptación como pequeños cortes verticales, que incluyan al menos dos servicios.
  • Una vez que una prueba de aceptación fallida inicie a compilarse y a fallar por las razones correctas (los servicios no están implementados), empieza a testear los servicios, un método público a la vez.

Normas de diseño

  • La interfaz pública de los servicios no puede ser modificada, salvo por sus mismos constructores para añadir colaboradores. 
  • <?> puede ser sustituido por el type o primitive que prefieras.
  • Los servicios no deben tener dependencias circulares. Es decir, si el servicio A utiliza el servicio B, el servicio B no puede utilizar el servicio A.
  • Los servicios no deben tener ningún estado.
  • Los datos persistentes deben almacenarse en un repositorio (in-memory).
  • Crea una buena estructura de paquetes, respetando los diferentes usuarios y áreas de la aplicación.

Variaciones de la kata

A continuación presento algunas variaciones de esta kata que puedes mezclar.

1. Servicios definidos, interfaces públicas no definidas

En esta variante sigue siendo necesario utilizar los 4 servicios definidos anteriormente, pero tienes la libertad de crear los métodos que quieras en cada uno de los servicios.

2. Diseño inicial sin definir (Avanzado)

En esta variante, los requisitos empresariales para los tres actores siguen siendo los mismos; sin embargo, tienes la libertad de diseñar a tu gusto. No es necesario aferrarse a los 4 servicios.

3. Política de reservas hoteleras

En los requisitos originales, sólo se tiene en cuenta los tipos de habitaciones. En esta variante, también podemos definir qué hoteles están permitidos por cada empresa o para cada empleado. Por ejemplo, una empresa puede permitir reservas de habitaciones estándar y junior suites para el hotel "1" y sólo permitir habitaciones estándar para el hotel "2". Lo mismo aplica para las políticas de los empleados.

4. Política de overbooking

Regla adicional: algunos hoteles pueden permitir un pequeño porcentaje de overbooking. Por ejemplo, el 5%.

5. Límites estrictos de los componentes

En esta variante, cada servicio representa la interfaz pública de un componente empresarial (área funcional o contexto delimitado). Ningún otro servicio debe poder acceder a todos los componentes internos. Los componentes internos sólo pueden interactuar a través de su interfaz pública. Por ejemplo, el servicio A puede comunicarse con el servicio B, pero no con el repositorio B.

6. Hacer un diagrama de secuencia

En esta variante, no necesitas escribir ninguna prueba o código. Sólo debes crear un diagrama de secuencia a nivel de código (colaboradores, métodos, parámetros, tipo devuelto, estructuras de datos, etc.) que represente la solución detallada. El diagrama de secuencia debe representar la interacción de los 3 actores con los servicios y los componentes internos de cada servicio, incluyendo su colaboración con otros servicios y colaboradores internos.