Front_End
El diseño web de la aplicación es el que se ilustra en la figura 1:
Figura 1.
Como se puede apreciar, hay una barra de menús que permite al usuario navegar entre los conceptos de la aplicación. Por cada concepto, existe una forma de ver el conjunto de elementos creados (en el caso de la lista de libros, se ven en forma de galería), de crear uno nuevo, de editar uno existe o de borrar uno existe.
Decisiones de diseño
El Front_End de Ejemplo Book se diseñó en 4 módulos uno por cada clase del modelo conceptual. Hicimos coincidir la noción de módulo funcional con un módulo Angular. La figura 2 muestra la vista de desarrollo del proyecto web en Angular, los casos de uso que se van a desarrollar en el módulo Book y la clase Book del modelo conceptual.
Figura 2.
La navegación entre los módulos se diseñó siguiendo una noción básica de estados y se implementó utilizando la librería ui-router de angular. La figura 3 representa los estados principales de la aplicación: book, author, editorial. El usuario llega a estos a través de sus acciones sobre la barra de navegación principal.

Figura 3.
Estructura del proyecto web
La estructura del proyecto Front_End está inspirada de las mejores prácticas de organización de aplicaciones angular. En esta estructura se define:
- una carpeta por cada módulo que contiene: sus templates html, sus controladores, sus servicios, la definición de módulo, su mock y demás archivos del módulo.
- un index.html (Single Page) que utiliza la noción de vistas para remplazar el contenido correspondiente a un cambio de estado en la aplicación.
- un app.js que contiene el módulo principal de la aplicación y donde se organizan los estados.

Figura 4.
Anexos
Promises en JavaScript
Una de las características más útiles de Javascript es la posibilidad de hacer llamados asíncronos al servidor (más conocido como AJAX). Gracias a esta técnica, las aplicaciones web pueden hacer peticiones al backend, las cuales se ejecutan en segundo plano sin detener la ejecución de la aplicación mientras se espera una respuesta.
Tengamos en cuenta el siguiente fragmento de código:
$http.get('/books'); //solicitar el recurso books al backend
console.log('código después de petición AJAX');
En este fragmento, es posible que la segunda línea se ejecute antes de recibir respuesta a la petición de la primer línea. Esto puede generar confusión y problemas de sincronización. Para esto se crearon los promises. Este tipo de objetos representan promesas de que se recibirá una respuesta, sea exitosa o no, y permiten definir acciones a realizar cuando esta llegue.
Para lograr esto, se debe invocar la función then(), la cual recibe dos funciones como parámetros, la primera para ejecutar en caso de éxito, y la segunda en caso de error. Ambas funciones reciben como parámetro la respuesta del servidor
En el ejemplo anterior, la primer línea retorna un promise, con el cual podríamos hacer lo siguiente:
$http.get('/books').then(function(response){
console.log('código ejecutado cuando se recibe respuesta exitosa');
},function(response){
console.log('código ejecutado cuando se recibe respuesta no exitosa');
});
console.log('código ejecutado después de realizar la petición, independiente de si ya se recibió respuesta');
De esta manera, tenemos la posibilidad de esperar por una respuesta en cada petición, o seguir ejecutando código sin bloquear la aplicación.
Para mayor información haga click aquí
Procesamiento de respuesta con error
Cuando se hace una petición al backend, es posible que se presente algún error y haya que procesar la respuesta de manera diferente. Sin embargo, para esta aplicación, se estandarizó la manera en que se recibe los mensajes de excepción. Estos, además de tener un código de error (4xx o 5xx), deben incluir el mensaje de error en el cuerpo de la respuesta.
Debido a esta estandarización, se implementó en cada controlador una función llamada responseError. Esta función permite obtener el mensaje de error enviado por el servidor, y desplegarlo en una alerta en la interfaz gráfica.
var self = this;
function responseError(response) {
self.showError(response.data);
}
Con esta implementación, podemos incluir responseError como la función por defecto a invocar cuando una petición recibe mensaje de error. Esto lo logramos incluyéndola en el segundo parámetro de los promise:
this.fetchRecords = function () {
return svc.fetchRecords().then(function (response) {
//Codigo en caso de éxito
}, responseError); //uso de responseError para mostrar mensajes de error
};