This graph shows how many times the word ______ has been mentioned throughout the history of the program.
Amigos, vamos a darle cañita.
Ya os digo que tenemos aquí el código
y voy a abrir por aquí el curso.
Abrimos aquí el curso, ¿vale?
Abrimos las clases, tú, tú, tú.
Y fíjate que tenemos clase 1, clase 2, clase 3.
Nos quedamos en la clase 3 y en la clase 3,
en la clase 3 hicimos una REST API, ¿vale?
No solo hicimos una REST API para crear,
actualizar con recursos,
os expliqué que es una REST API y todo esto,
sino que además arreglamos el tema de Cores
y te expliqué desde cero qué es Cores,
por qué te da problemas
y por qué no es un problema que ocurra en el servidor,
sino que es un tema de seguridad del navegador, ¿vale?
Y cómo solucionarlo correctamente
y cómo no poner un asterisco y tal.
Muchas veces, 10.000 millones de veces
os habéis quejado de las Cores
y os puedo asegurar que no os ha explicado nadie
el tema de las Cores como lo expliqué yo en la anterior clase
porque mucha gente os dice
no, pon aquí Cores, pones un asterisco
y se arregla, ¿ah?
Y eso, eso no es que entiendas qué es Cores,
eso es que te han dicho cómo arreglarlo,
no como, no para que lo entiendas, ¿ah?
Así que importante, si eso,
échale un vistazo a la siguiente clase
y te va a quedar clarinete, clarinete.
De hecho, os expliqué incluso
qué es esto de Cores Preflight,
cuándo ocurre, madre mía,
si es que luego me dicen
que no hacemos contenido avanzado
y esto hay senios que tienen 10 años de experiencia
que yo en la última empresa no tenía ni idea
que era esto, no lo sabían.
Dicho esto, esto, todo esto que hicimos,
todo esto está muy bien, ¿vale?
Entonces hicimos esquemas,
hicimos validaciones,
las hicimos con Zot,
estuvo buenísimo,
pero no lo desplegamos a producción
y he pensado, hostias,
pues lo podíamos desplegar.
Así que lo primero que vamos a hacer
es desplegar a producción nuestra API, ¿ok?
Vamos a utilizar FL0,
FL0,
que fijaos que se llama
Backend Engineering,
Deploy Backend Applications and Databases in Minutes.
¿Por qué os recomiendo ahora este servicio?
Que claro, estas cosas ya sabéis cómo pasan,
a veces cambia la cosa, pero tal, ¿no?
Pero ¿por qué ahora es interesante FL0?
FL0, en el pricing,
tienen una capa gratuita
que al final tienes aquí,
0 dólares al mes,
0 dólares al mes.
Y lo importante que tenemos
es que ni siquiera hay que poner
la tarjeta de crédito.
Veremos esto, cambia y tal.
Pero la capa gratuita es generosa,
es muy buena
y vais a poder tener un proyecto
100% gratis con estas limitaciones, ¿vale?
256 megas de RAM,
compartida la CPU,
obviamente que le vamos a hacer,
10 gigas de transferencia,
storage de 1 giga,
no tiene auto-scaling,
eso faltaba, claro, ya es increíble,
pero está bastante, bastante bien.
Vale, pues le vamos a dar a singing,
¿ok?
Y vamos a ver qué nos ofrece aquí esto.
Creo que le vamos a dar a Github,
iniciamos sesión con Github,
más rápido, ¿eh?
Más rápido.
No me tiréis a FL0 ahora, ¿eh?
Que os conozco.
Muy bien.
Entonces, yo no tengo ningún proyecto todavía,
así que vamos a ello.
Vamos a crear un nuevo proyecto
y vamos a llamarle aquí REST API,
que es la que hicimos la semana pasada, ¿eh?
Creamos un nuevo proyecto
y aquí tenéis dos opciones.
Una es para desplegar directamente
una base de datos Postgre,
que ya veremos más adelante,
añaden otras,
y tenéis la de deploy code with GitHub,
o sea, que podéis crear un repositorio de GitHub
en el que podáis poner ahí
vuestra aplicación y desplegarla.
Pues vamos a ir a GitHub, ¿vale?
Y vamos a crear aquí un proyectito.
Le damos aquí.
Voy a decir que el owner soy yo.
REST API deploy.
Voy a llamarle, ¿vale?
Venga, así que lo tengo
para desplegar la API de Node a FL0, ¿vale?
Público, bla, bla, bla.
Ahora mismo estará vacío.
Y lo que voy a hacer es, pues,
este repositorio lo voy a clonar, ¿vale?
Lo voy a clonar aquí mismo, ¿vale?
Git clone, me pego esto por aquí,
CD REST API deploy.
Muy bien, ahora abro aquí el editor.
Este proyecto está vacío, obviamente.
Entonces, vamos a desplegar nuestra API.
Vamos a volver al código.
Vamos a volver al código que tenemos aquí
en el curso de Node, ¿vale?
Y aquí la clase 3 la voy a abrir en el Finder, ¿vale?
Me voy a bajar por aquí.
Y me voy a traer todo este contenido por aquí.
Copy folders.
Quiero copiar las folders, ¿vale?
¿Qué es lo que he hecho?
Básicamente lo que he hecho es copiar el contenido
que teníamos en la clase 3.
Me lo he traído aquí.
Y aquí, bueno, ahora revisaré el package log.
Tendríamos las dependencias que necesitamos.
Cores, express, thought, ¿vale?
En lugar de clase 3 vamos a poner REST API.
Y aquí, que puede ser interesante,
es que le pongamos un start, ¿vale?
Y el start será node.app.js.
La verdad no sé qué script necesita para ejecutarse.
Ahora lo miraremos, ¿vale?
Pero lo importante es que tengamos como un script
que sea para inicializar nuestra API.
Ejecutamos con Node nuestro archivo app.js,
que es el que tenemos aquí,
que es justamente el que tiene todo nuestro código de la API.
Ahora bien, importante, una cosa básica
que hagáis despliegues a cualquier servicio
es, exacto, revisar esta parte de aquí, ¿vale?
¿Por qué?
Porque a veces hacéis esto.
Si hacéis esto, esto puede ser problemático, ¿vale?
¿Por qué?
Porque normalmente el puerto lo está metiendo
por variable de entorno el servicio
donde lo vamos a hospedar, ¿vale?
Así que es súper importante que siempre, siempre hagáis esto, ¿vale?
Entonces, ¿qué es lo que estamos diciendo?
Oye, si me viene por variable de entorno el puerto,
porque el puerto lo va a asignar de forma automática
el hosting que nosotros vamos a utilizar,
utiliza ese.
Y si no, utiliza por defecto este.
Lo digo porque muchas veces me he encontrado
con el problema que mucha gente dice,
es que no sé por qué no me funciona.
Y es porque hacéis esto, que siempre utilice un puerto
o que utilice un puerto random.
Y claro, lo que necesitáis siempre, siempre
es utilizar la variable de entorno del proceso.
¿Qué más?
Ah, vamos a poner aquí un gitignore
para que no pegue el no modules, ¿vale?
No modules fuera.
Y en principio, yo creo que con esto ya lo tendríamos, ¿no?
Vamos aquí al REST API, vamos a hacer un MPM install
simplemente para que nos aseguremos y ya está, ¿eh?
Porte en mayúscula.
Me ha pasado a veces que lo dejo en minúscula y no funciona.
Efectivamente, el port este, las variables de entorno
siempre son en mayúscula.
Importante.
¿Por qué no funciona?
Pues es muy fácil, es muy fácil.
¿Por qué no funciona?
Porque si tú no pones, si tú no utilizas el puerto
que te está asignando el hosting, el hosting...
Tú le dices, no, es que yo utilizo el 1.2.3.4.
Claro, esto está muy bien en tu máquina, el local.
Porque tú sabes, tú sabes que en tu máquina
el puerto 1.2.3.4 está libre o lo puedes utilizar
o tienes permisos para utilizarlo.
Pero en el hosting, cuando tú vas a hospedar tu API,
tú no sabes cuál es el parking en el que te vas a poner, ¿no?
No tendrías ni idea.
Así que tienes que decirle que te lo dejen,
el hosting, que te lo diga.
Y así es como te lo dice.
Te lo dice por variable de entorno.
Muy bien, vamos a pushear los cambios de nuestra API.
Vamos a deploy API to FL de cero, ¿vale?
Confirmamos.
Y ahora nos aseguramos que hacemos aquí el push
para que lo llevemos.
Muy bien, revisamos, que aquí tengamos todo el tema.
Tenemos el package log, package json, perfecto.
No le he puesto un readme, tampoco hace falta, ¿ok?
Y ahora lo que vamos a necesitar es ir a FL de cero.
Nos vamos aquí al deploy code with GitHub, ¿ok?
Y aquí nos va a permitir, supongo que si es la primera vez que entras,
seguramente podría ser que te pida permisos.
¿Por qué?
Porque a lo mejor no tienes permisos por defecto
para listar todos los proyectos.
Entonces, ahora sí, fíjate que además te los ordena
por cuál es el más reciente y ya nos sale el primero.
Así que le vamos a dar connect para que conecte.
Esto nos pregunta, ¿cuál es la rama?
Efectivamente, es main, que es la que tenemos aquí, ¿ves?
Y aquí es donde queremos tener el código que vamos a desplegar.
De forma que cada vez que nosotros hagamos un commit y push
a esta rama, se va a volver a desplegar a producción.
Luego, la región.
Bueno, Australia nos pilla un poco lejos,
pero ahora mismo parece ser que es la única,
así que vamos a tener que dar a Australia, ¿vale?
Y fíjate que pone add environment variables.
Hice hafan.ev.
Aquí pone por defecto, esto me lo ha puesto por defecto,
esto yo no lo he puesto.
Así que me voy a fiar, me voy a fiar,
porque si miramos aquí, yo no tenía un .ev, ¿no?
No, no tenía un .ev.
O sea que por defecto, me está poniendo el 8080.
¿Veis lo que os decía?
O sea, vosotros no sabéis en principio cuál va a ser el puerto
que vamos a poder utilizar.
Así que nada, vamos a darle deploy your app,
aunque tengo dudas, porque una cosa que tengo dudas es del script.
O sea, no me ha preguntado por qué es lo que tiene que ejecutar
y todo esto.
A ver, blog express, mira, aquí veo que tienen un ejemplo.
Vamos a ver el package.json un momento.
Vale, hay un start, vale.
Normalmente esto es una cosa que muchas veces no lo comentan,
pero en los scripts deberíais tener un comando start
y por defecto suelen mirar eso.
Pero hay veces que es o configurable o que te lo preguntan.
Aquí ni me lo preguntan.
Así que por defecto ya veis que está siendo este, ¿vale?
Muy bien, le vamos a dar a desplegar y vamos a ver qué hace.
Vale, ya está detectando cositas.
Está haciendo aquí un start build.
La forma en la que funciona es bastante, bastante similar
a como era Heroku.
De hecho, utiliza build pack,
que es algo parecido a lo que utilizaba Heroku.
Vale, pues fijaos que tenéis aquí el deploying.
Este sería la rama que ha desplegado.
Y si no me equivoco, este es el último commit que hemos hecho.
Sí, es este, ¿ves?
F799.
Este justamente es el commit que está desplegando ahora,
que es lo que tenemos por aquí.
Mira, ahora ya está funcionando.
¿Veis?
Ya ha hecho el deploy.
Me ha puesto un check.
Me ha dicho la URL, que la tenemos justamente aquí.
¿Vale?
La URL.
Vamos a mirar la URL y a ver qué pasa.
¿Vale?
La URL me ha redirigido directamente donde le ha dado la gana.
O sea que no ha ido muy bien.
Vamos a ver.
View logs.
A ver, los logs parece que funcionan, funcionan.
Pero me parece que ahora, ¿vale?
Yo creo que la URL que me ha dado ahí, esta no es correcta.
O que había tardado y todavía no la tenía, ¿no?
Mira, ya tenemos la API desplegada.
¿Cuánto hemos tardado?
No hemos tardado ni dos minutos, ¿no?
Entonces, ya lo tendríamos aquí justamente en producción nuestra API.
¿Vale?
Para revisar, pues aquí podríamos ver que ha ido todo bien.
Perfecto.
Podríamos ver los usage metrics.
Esto, pues puede tardar un poquito.
¿Vale?
Environment variables.
¿Se puede hacer algo con serverless functions en Vercel barra API?
Sí, pero es que de nuevo es que no es lo mismo.
Podéis hacer serverless functions que al final son funciones en la nube que es algo más parecido a Edge Functions que no tienen nada que ver con tener un servicio como este.
O sea, son cosas diferentes.
Pero obviamente sí.
Si os referís a que podéis desplegar una API, sí.
Pero desplegar un servicio como este así no se puede hacer exactamente igual en Vercel.
Para bien y para mal, ¿eh?
Bueno, y tendréis los logs también.
Una cosa interesante es que podéis, aquí no tenemos muchos logs, pero en el caso de que vuestra aplicación tuviese un log, aquí podríais ver logs.
¿Vale?
Ya sea de errores, de lo que sea.
Así que muy chulo.
Mira, el usage metric, ¿sabéis si es alguna cosa?
Bueno, casi no lo hemos usado, pero alguna cosa sí que sale.
No se ve casi, pero aquí ya tendríais, por ejemplo, ¿veis?
20 megas de memoria RAM del límite de 256, lo cual está bastante bien.
Y ya está.
O sea, ahora cada vez que hagamos un cambio, por ejemplo, cada vez que, mira, aquí vamos a intentar utilizar esto, ¿vale?
¿Veis?
Funciona perfectamente.
Lo podríamos meter, hacerle un post, el put, el delete.
Podríamos hacerlo todo y funcionaría correctamente.
Y os dejo este repositorio por aquí, ¿vale?
Os dejo este repositorio para aquí, por si tenéis ideas o queréis, no sé, tenéis dudas de ostras.
¿Cómo se despliega en producción?
Bueno, pues ya lo sabéis, ¿vale?
Os dejo también el enlace de FL0, creo que era .com, ¿vale?
Para que no os lo perdáis y así lo tengáis ahí.
Pues ya tenemos la clase 4, vamos a partir de la clase 3, ¿vale?
Así que hemos hecho la copia y ya tenemos exactamente lo mismo que teníamos en la clase 3.
Vamos a revisar un poquito, lo teníamos aquí, pero ¿qué problemas nos estamos encontrando con nuestro REST API, que es la que hemos desplegado?
Pues tenemos diferentes problemas.
Primero, que fíjate que tenemos aquí todo como juntado.
Tenemos juntado las validaciones, el control del input, el dónde se recuperan los datos y todo este tipo de cosas, ¿vale?
Total, que lo tenemos aquí todo mezclado.
Lo que vamos a hacer y en lo que vamos a trabajar ahora es en el hecho de decir, ostras, vamos a ver si esto lo separamos mejor.
Pero antes de hacer la separación, una cosa que te comenté el otro día era el tema de CommonJS.
En Node.js tenemos dos formas de trabajar con las dependencias, ¿vale?
Tenemos CommonJS, que sería esta que tienes aquí, y tendríamos la de Enmascript Modules.
Mira, tenemos CommonJS, ¿vale? Sistema de módulos de Node.js.
¿Y qué significa un sistema de módulos? Pues es lo que nos permite justamente compartir código para no repetirlo.
Tenemos por un lado CommonJS, ¿vale? Lo vamos a poner rojo, y tenemos por otro lado Enmascript Modules.
Este diríamos que es el clásico, el clásico es el de toda la vida, y este lo que tiene sería el require y el module.export, ¿vale?
Esto es como funciona este de aquí.
Este es el clásico, es el que hemos utilizado hasta ahora, pero hoy vamos a migrar nuestra aplicación a Enmascript Modules.
Y te preguntaréis, ¿por qué lo vamos a hacer? ¿Por qué vamos a hacer esto? Bueno, por dos cosas, ¿vale?
Primero, porque Enmascript Modules es el moderno y recomendado.
Recomendado en diferentes cosas. Uno, de que siempre que puedas es el que deberías utilizar, porque es el que es parte de la especificación de JavaScript.
Y también recomendado, porque al final es el que se está utilizando en todos los sitios.
Y esto sería import-export, ¿vale? Y estas serían las dos formas de tener sistemas de módulos en Node.js.
Hasta ahora hemos visto este de aquí.
Hemos visto este de aquí.
Pues hoy lo que vamos a hacer es pasar de uno a otro.
Pero tiene algún reto que es bastante interesante, que está muy bien que lo aprendas para que te suene, ¿vale?
Así que vamos a verlo. Fíjate, tengo todo requires.
Lo primero que tenemos que hacer para pasar un proyecto de Common.js a Enmascript Modules de Node.js es ir a nuestro Packet JSON.
Y aquí le podemos indicar el tipo del proyecto.
Por defecto, el tipo del proyecto es este, ¿vale? Este sería el default, Common.js.
Por eso no hace falta ponerlo para que funcione como Common.js.
Pero si quieres cambiarlo a Enmascript Modules y quieres que todos tus ficheros se comporten como Enmascript Modules
y por lo tanto puedas utilizar los impos y los expos sin necesidad de cambiar extensiones ni nada raro,
aquí podrías decirlo tipo módulo, ¿vale?
¿Qué pasa con esto?
Que una vez que hacemos este cambio, si yo ahora intento, vamos a la clase 4,
vamos a la clase 4 y yo intento ejecutar mi proyecto, fíjate que ya me empieza a petar y me dice,
oye, require no está definido en el scope de los Enmascript Modules, puedes utilizar import en su lugar.
Bueno, no pasa nada.
Para eso nos vamos a lab.js y te voy a enseñar el truco del almendruco
para que no te pongas como un loco ahí a escribir los impos y tal.
Fíjate, ¿ves que hay aquí tres puntitos?
¿Ves? Hay tres puntitos, ¿no?
Le das aquí y haces comando, punto, ¿vale?
Y ves que te pone aquí convertir en módulo Enmascript.
Así que le damos aquí y te voy a explicar una cosa.
Ha ido bien hasta cierto punto.
Ha ido regulinchis.
¿Por qué ha ido regulinchis?
Porque esto sí que lo ha hecho bien, esto también lo ha hecho bien,
esto también lo ha hecho bien, este también lo ha hecho bien,
pero este no lo ha hecho bien.
La línea 5 la ha hecho mal.
¿Por qué?
Porque el import movies, él ha creído que como el movies era un array,
también estaba importando del movies.json,
también estaba importando los métodos filter y tal.
O sea, lo ha hecho bastante bien, pero tampoco tanto.
O sea que lo que vamos a hacer, para arreglarlo del todo,
es que vamos a buscar donde ha utilizado filter, ¿vale?
Este filter, por ejemplo, lo vamos a tener que buscar
y vamos a tener que utilizar ponerle justo antes el correcto, ¿vale?
Este find, por lo mismo, donde se ha utilizado el find,
pues el find resulta que en realidad sí que es de movies porque es un json.
Pero bueno, esto luego verás por qué estoy haciendo esto
y por qué igualmente esta línea nos va a dar problemas.
Pero es muy interesante porque muchas veces,
mucha gente que pasa a Inmascript Modules,
se encuentra estos problemas y así los vas a solucionar, ¿vale?
Venga, vamos a hacer el find index, un momento.
Aquí le tenemos que poner movies, porque es que movies es un json, ¿vale?
No se estaba importando esto como una dependencia.
Y aquí tendríamos el movies y ya nos queda solo el splice, ¿vale?
Muy bien, vamos con el splice, splice, entonces movies.splice.
Y ya está, con esto ya lo tenemos.
Vamos a ver si hasta aquí funciona.
Nos vamos a encontrar algún problema más,
así que vamos a ver cuál es el problemita.
Vamos a hacer node.js, tenemos algún problema más.
Y es que nos dice que no puede encontrar el módulo de esquemas movies.js.
Otro cambio muy importante, fíjate aquí.
No tenemos la extensión, ¿vale?
No teníamos la extensión.
El cambio que tenemos es que cuando utilizamos el sistema de CommonJS,
las extensiones no son obligatorias.
¿Por qué?
Porque node tiene internamente una cosa que se llama resolver,
que lo que hace es resolver la extensión.
e intenta diferentes extensiones y diferentes salidas.
¿Qué es lo que intenta aquí?
Por ejemplo, aquí intentaría .esquemas, barra movies, barra index.js, ¿vale?
.esquemas, movies, .js.
Va intentando diferentes, ¿vale?
Hasta que lo encuentra.
En este caso, con EnmascreenModules no tenéis que hacer esto, ¿vale?
Tenéis que hacer .js.
Le tenéis que poner la extensión.
Entonces, ¿sabéis qué pasa?
Que el no poner la extensión es una mala práctica
que estamos acostumbrados, por desgracia,
tanto por empaquetadores, como malas decisiones de TypeScript,
como un montón de cosas.
Y no es parte de la especificación.
La especificación indica que hay que poner siempre la extensión.
Por desgracia, hay cosas que hacen magia
y no nos hemos tenido que preocupar de esto, ¿vale?
Dicho esto, hasta aquí bien, ¿vale?
En el archivo de esquemas también, como era JavaScript,
tenemos que cambiar esto, así que lo cambiamos,
lo convertimos en un módulo.
En este caso, lo voy a hacer a mano
para que no me haga cosas raras.
Import C, set, from, aquí, ¿vale?
Y tenemos que exportar las funciones.
En lugar de utilizar módulo exports,
nos vamos aquí, export function, export function.
Y ya con esto, ya tenemos todo el JavaScript preparado.
Pero queda una cosa muy importante.
Vamos a probar, ¿vale?
A ver si ahora funciona.
Me sigue petando.
Pero ahora me peta por otra cosa, ¿vale?
Me peta por el movies.json.
Dice que necesita una sección de tipos de JSON, ¿vale?
¿Qué significa esto?
Y esto te lo explico porque esto te va a servir
para toda la vida para JavaScript, ¿vale?
El tema es que esto no es válido.
No puedes importar Jasons en enmascriptmodules así tal cual
porque no están parte de la especificación, por desgracia.
Entonces, ¿qué es lo que pasa?
Pues que necesitamos decirle qué tipo de archivo es el que estamos importando en este caso.
En este caso le tenemos que decir, oye, ¿ves que la sintaxis no la soporta?
Ahora te explico por qué, ¿vale?
Pero te lo explico porque esto es algo que es bastante experimental,
que está a punto de llegar, no ha llegado del todo,
pero que es importante que sepas.
Lo que está pasando aquí es que le tenemos que decir a Node.js
es que este archivo lo tiene que importar como si fuese del tipo JSON
porque si no se equivoca y va a intentar importarlo como si fuese un JavaScript.
Entonces, si yo esto ahora lo intento ejecutar, ¿vale?
Node.js, fíjate que ahora funcionar funciona,
pero me da un aviso, me dice experimental warning,
import assertions no es todavía una feature que sea estable
en el lenguaje de JavaScript.
Así que intenta evitar apoyarte de este comportamiento y esta sintaxis
porque puede cambiar en el futuro.
¿Y quieres saber una cosa?
¿Quieres saber una cosa?
Sorpresa, ya ha cambiado.
O sea, este warning tiene todo el sentido del mundo
porque la realidad es que esta sintaxis, esta sintaxis no existe.
Por eso te lo quería avisar porque puedes encontrarte
que está gente utilizando esta sintaxis y tal,
como ves, era experimental y no existe.
No deberías utilizarla.
¿Por qué pasa esto?
Bueno, TC39, proposal, assert, vamos a verlo.
Aquí tendríamos los import attributes, ¿sí?
Esto eran los import assertions.
Vale, fíjate, ¿qué pone aquí?
Ahora pone with, no pone assert.
Y es que la sintaxis ha cambiado.
Te voy a dar una buena noticia.
La buena noticia es que no va a cambiar más
porque ahora ya está en la fase 3,
ya ha inicializado, o sea, ha avanzado bastante la especificación.
Parece que ahora sí que está bastante estable
y, por lo tanto, esta parece ser la sintaxis que va a ser definitiva.
Así que esta sintaxis era experimental,
no funciona, o sea, funciona,
pero se va a romper eventualmente porque va a dejar de funcionar.
Luego, si ponemos with, esta no la soporta.
A día de hoy, por desgracia, ¿ves?
No la soporta.
Y, por lo tanto, podemos hacer diferentes formas
de hacer esto mejor, ¿no?
Que sea algo que sepamos que no se va a romper solo.
Así que no lo vamos a hacer así.
Hay dos formas de hacerlo, ¿vale?
Una sería utilizando fs,
como lo hemos hecho en algunas clases, ¿no?
Importar fs from note fs...
Bueno, fs e importar este archivo de forma...
Podemos read file, read file sync, ¿vale?
Barra movies, y aquí tendríamos el movies.
Lo que pasa es que esto también, además,
tenemos que parsearlo, ¿vale?
Y ya está.
Esto podríamos hacerlo.
Lo he hecho muy rápido.
Vale, funcionar funciona.
Fíjate, si nos vamos aquí, barra movies,
debería funcionar.
Vale, no está mal.
¿Qué es lo que hemos hecho?
Lo que hemos hecho es importar el file system de Node.js
y lo que hacemos es leer de forma síncrona
el fichero movies.json.
Le decimos que la codificación es UTF8
y esto lo tenemos que transformar,
parsear a un JSON, ¿vale?
Esta sería una forma.
No está mal, pero como puedes ver,
uno te obliga a hacer un JSON parse.
Luego tienes que utilizar el file system read file.
Tienes que hacer ahí como unas cosas, ¿no?
Esta podría ser una forma.
Yo te la voy a dejar comentada
por si la quieres utilizar,
porque no está mal, ¿vale?
Como leer un JSON en enmascrimodules, ¿vale?
Esta sería una, ¿vale?
Hay otra que también es engorrosa.
O sea, no voy a decir, no, es súper bien,
pero seguramente a día de hoy sería como yo creo
la más correcta en enmascrimodules, ¿vale?
¿Cómo leer un JSON en smodules?
Recomendado por ahora, ¿vale?
Por ahora.
Pues lo que tenéis que hacer es crear un require.
Y esto es bastante interesante.
Muy poca gente lo conoce,
pero el require que hemos visto hasta ahora
en todas las clases, ¿vale?
Cuando estamos estos requires,
ves este require, require, require.
Fíjate que este require,
¿ves que tiene paréntesis?
¿Eso qué quiere decir?
Si estamos llamándolo entre paréntesis.
¿Eso qué quiere decir?
Que es una función, ¿verdad?
Entonces, si es una función, ¿qué significa?
Pues que podemos justamente crear esa función.
Y no.js tiene una forma
en la que podemos crear una función.
¿Por qué?
Porque no podemos utilizar el require aquí.
Esto está prohibido, ¿vale?
Pero sí que podemos importar el create require
de node module
y podemos crear un require
diciéndole, vale, créame un require
utilizando el import.meta.url.
Esto, el import, como ves,
es una palabra reservada
que tenemos aquí en Emagrin Modules
que no solo te permite para importar módulos,
sino que también tiene información
sobre nuestro propio proyecto.
En este caso, el import.meta.url
lo que tiene es la dirección del archivo actual.
Por lo tanto, podemos crear un require
que le digamos, vale, pues quiero traer movies
de este require que he creado
que es del archivo actual
y tienes que ir a .barra movies.json.
Y aquí, con esto, ya le estamos diciendo
de dónde se supone que tiene que sacar
este archivo del movies.json.
Hemos creado un método require
y lo hemos creado nosotros.
¿Por qué te enseño esto?
¿Es súper necesario?
No sé qué.
A ver, te enseño esto porque
si en alguna vez te estás encontrando
la transición de Common.js a Emagrin Modules,
te vas a encontrar un montón de estos problemas.
Hay veces que puede ser que necesites
crear tu propio require para cositas así
y a veces puede ser buena idea.
Y en este caso en concreto
de utilizar un JSON,
puede ser buena idea
intentar evitar utilizar el file system
y seguir utilizando el require
que de forma nativa
ya eres capaz de comerse los JSON.
Al menos hasta que tengamos
y funcionen perfectamente los JSON
a la hora de importarlos.
¿Vale?
Así que esta podría ser otra forma.
Yo la recomiendo
porque aquí al final
lo que estáis haciendo
es utilizar el JSON parse.
Esto sería seguramente una cosa
mucho más lenta
que no utilizando esto
que es la forma nativa
que tiene Node.js
y que ya está compilado
estos módulos internos
a la hora de parsear la información.
Cualquiera de las dos funciona,
pero sobre todo para JSON
que sean lo suficientemente grandes,
yo os recomiendo
que si no lo soporta todavía,
utilicéis esta.
Y con esto,
a ver, vamos a ver
si lo hemos hecho bien.
¿Veis?
A ver, papapá.
1, 2, 3, 4,
barra movies.
¿Vale?
Y aquí tenemos exactamente lo mismo.
¿Ok?
Así que ahí tenéis
las dos formas de hacer
y de importar los JSON.
y con esto
ya hemos migrado
nuestro pedazo de proyecto
a Inmascreen Modules.
¿Vale?
¿Crees que harán el import
de forma más práctica?
De la actual es mucho rollo.
Sí,
de hecho,
ya lo he comentado, ¿no?
El import será así, ¿vale?
El import del futuro
va a ser así.
Import movies from
movies JSON
with type JSON.
¿Vale?
Esto será así
y será en una sola línea.
Esto es como va a ser pronto.
Todavía no ha llegado,
pero llegará.
O sea,
que no os preocupéis.
Lo que pasa es que por ahora
pues hay que hacer
o leyéndolo así
o creando vuestro propio require.
Que esto lo podéis crear una vez,
que no hace falta
que esto lo estéis creando constantemente.
Quiero decir,
esto lo podéis tener aquí
una función
que sea export const read JSON,
¿vale?
Y que sea así.
Ya está.
Y entonces,
cada vez que queráis leer
un JSON,
read JSON
y lo repetís
y punto.
¿Entendéis?
O sea,
esto lo extraéis
a un útiles,
por ejemplo.
Útiles o como le quieráis llamar.
Útiles,
no sé qué.
Y ya no lo veis más.
Lo dejáis aquí,
exportáis esto,
papapá.
Y ahora,
claro,
lo malo aquí
es que seguramente,
ah,
no,
estaría bien.
Read JSON,
¿vale?
Y ya está.
No tenéis por qué saber
cómo se ha hecho por dentro.
Es que esta es la idea,
¿vale?
Esta es la idea,
básicamente,
no que estéis constantemente
creando el require.
Como que lo hagáis una vez,
ya está,
¿vale?
Pues hasta aquí
ya tenemos todo el sistema
de Mascreen Modules y tal.
Venga,
vamos con el tema
del MVC.
MVC.
Vamos a mejorar
un poco nuestras rutas,
¿vale?
Porque fíjate,
todo lo que tenemos aquí,
buf,
esto es un rollo.
Vamos a empezar
a ir separando
capa por capa
y lo primero
que vamos a separar
antes de entrar
en la arquitectura de MVC,
vamos a separar las rutas.
Para eso,
creamos una carpeta roots
y a mí personalmente,
aquí cada una,
cada persona que haga
lo que quiera,
pero a mí me gusta
ponerle el nombre
de la ruta.
Hay gente que pone
movie roots,
hay gente,
yo recomendaría
mejor así,
pero a mí me gusta
que sea el nombre
de la ruta
y no me gusta repetir
constantemente
el nombre de la carpeta.
Esto es algo subjetivo,
pero a mí me gusta
que si de roots
voy a hacer la ruta
de movies,
pues le llamo movies,
¿vale?
Y no lo hago en singular,
sino que lo hago
realmente como es la ruta.
Fíjate que tenemos
todas las rutas aquí
puestas y tal.
¿Qué vamos a hacer?
Vamos a importar
router
y esto lo vamos a hacer
de Express.
Ahora que tenemos,
hemos importado router
de la dependencia de Express.
Router
es una clase
un poquito especial
que lo que nos va a permitir
es crearnos
un enrutador
a partir del cual
vamos a poder responder
todos los paths.
¿Cómo funciona esto?
Pues imagínate,
vamos a crear aquí
router
y hacemos router,
¿vale?
Y en este router
podríamos tener,
¿vale?
Cuando en este router
vaya a la raíz,
entonces respondemos
con esta función de aquí.
Y aquí le llega
exactamente lo mismo
que hemos visto
en nuestra aplicación,
¿vale?
Fíjate que en nuestra aplicación
teníamos la request
y la response.
Pues esto mismo
lo tenemos aquí,
request y response.
Ahora,
¿qué es lo que queremos
que responda
cuando esté en la raíz
de las rutas de Movies?
Pues solo tenemos que mirar aquí.
Fíjate,
a.get barra Movies.
Pues esto que hemos hecho aquí
nos lo vamos a traer
aquí dentro,
¿vale?
Vamos a mover esto,
pa, pa, pa,
y nos lo ponemos aquí.
Ahora,
¿qué nos falta?
Fíjate que nos faltan
algunas cosas.
El Movies este
que habíamos hecho,
el query require,
no sé qué,
no sé cuánto,
este readjson,
pues esto lo vamos a tener
que mover de sitio.
Así que nada,
lo movemos de sitio,
¿vale?
¿Qué pasa?
Que seguramente aquí,
ahora,
bueno,
ahora veremos si nos falla
porque a lo mejor no lee
el fichero y tenemos que cambiar
la ruta,
pero bueno,
por ahora lo dejamos.
Y esto lo seguimos haciendo
con todas las rutas,
¿vale?
Vamos a hacer pequeño esto
para que no nos moleste por ahora.
¿Ves?
Ya teníamos aquí
el get del Movies,
aquí nos faltaría,
nos faltaría algo,
así que vamos a poner aquí
un to do,
solo para que se me quede en rojo,
¿vale?
Y seguimos con la siguiente ruta.
Pero,
¿qué pasa con esta ruta?
Esta ruta,
fíjate que es
barra Movies
barra dos puntos ID.
Bueno,
por lo mismo,
solo que aquí
vamos a hacer
barra ID
barra dos puntos ID
y aquí
es donde ponemos esto.
lo importante es
que no ponemos aquí
el Movies
porque luego verás
por qué.
Porque lo que vamos a hacer
es que todas las rutas
que sean
barra Movies
van a responder
a este router
que nosotros estamos creando.
Es como que estamos
separando
una rama
de todo nuestro enrutador
en un archivo
totalmente separado
y lo que nos va a permitir
es tener
en nuestro archivo app
las rutas
mucho más fáciles
de entender
y todo lo que tenga que ver
con barra Movies
tenerlo totalmente separado.
Y esto,
pues nada,
lo repetimos.
Nos vamos por aquí,
¿vale?
Vamos a poner aquí
el to do también
y volvemos a hacer
router.post
barra
y aquí
no hace falta poner
tampoco el barra Movies,
¿vale?
No hace falta poner
el barra Movies
porque es el que es por defecto.
Hola, Midu.
Hola.
¿Conoces Quick?
¿Qué opinas de él
y harías un curso?
Conozco Quick
y de hecho
trajimos aquí
al creador de Quick.
O sea,
que imagínate
si lo conozco.
Imagínate si lo conozco.
Haremos un curso
más adelante.
Pero ahora mismo,
el otro día
lo estuve probando
y tampoco,
o sea,
me gusta,
pero hay cosillas todavía
que creo que hay que
afinar un poco,
no sé.
Y me parece
el principio
la curva de aprendizaje
me parece un poco exagerada.
No sé,
no me gusta
que deje tantos archivos
ahí en medio.
me gusta más
el estilo de Next.js
y me sorprendió
un poco
el cómo por ahora
lo tienen hecho.
No sé.
Pero más adelante
seguro que hacemos
alguna cosa en Quick.
Bueno,
me he traído los simples
estos de los esquemas,
¿vale?
Porque los vamos a necesitar.
También me he importado
el random UID
que lo necesitamos aquí,
¿vale?
Y ya solo nos quedaría,
vamos a poner
el que todo,
todo,
todo,
el delete.
Así que nos traemos
el delete.
De hecho,
una cosa podría hacer
es para que veáis
la diferencia, ¿no?
Aquí en lugar de app
pondríamos el router
y aquí lo que nos tenemos
que asegurar
es que quitamos el movis
y ya está.
Queda exactamente lo mismo.
Y aquí ponemos el to do
y aquí el patch,
pues lo mismo.
Voy a copiarme
todo este patch,
¿vale?
Y lo extraemos
también en el router.
Aunque ahora
esto es el primer paso
y a partir de aquí
luego haremos
la arquitectura con MVC,
¿vale?
Quitamos esto por aquí,
¿vale?
El patch
y ahora,
importante,
ahora que hemos llegado
a este punto
que ya lo tenemos todo,
lo que tenemos que hacer
es un export
y tenemos que exportar,
podríamos exportar
por defecto el router
o podríamos ponerle
un nombre
o podríamos hacer
lo que queramos,
¿vale?
De hecho,
que le hemos creado aquí
como router,
podríamos directamente,
en realidad,
podríamos exportar
el router este
y llamarle
movisrouter,
¿vale?
Y entonces,
todos los routers
estos que hemos hecho
para que quede mucho mejor,
¿vale?
El nombre,
vamos a hacer esto,
movisrouter
y ya no hacemos
un export default
al final
y lo hacemos
con un export nombrado
que seguramente
quedará mucho mejor,
¿vale?
Y entonces,
vamos a dejar este
como todo,
¿vale?
Todo,
vale.
Vamos a quitar
los imports
que ya no necesitamos
y vamos a importar
este
movisrouter
from
router
routes
movis.js
Ahora tenemos que utilizar
este router,
este enrutado
que hemos hecho,
¿no?
Vale,
para utilizar este enrutado
lo único que tenemos que hacer
es decir,
bueno,
¿dónde queremos utilizar esto?
Pues fíjate que aquí teníamos
app.get,
app.get,
app.post,
app.delete,
pero esto ya lo tenemos aquí
realmente.
¿Veis que tenemos aquí
a movis.router?
Esto ya lo tenemos aquí.
Así que lo único
que le vamos a decir
es,
oye,
lo que quiero es que
mi aplicación,
vamos a hacer
app.use
cuando accedo
a barra movis
voy a cargar
todas las rutas
que tengo
en movisrouter,
¿vale?
Así que ahora
lo que estamos haciendo
es separando totalmente
todas las rutas
que tienen que ver
con barra movis
que este va a ser
como el prefijo
y entonces lo que va a hacer
la aplicación de express
es,
vale,
cuando yo detecte
que en la URL
al entrar y hacer las requests
hay un barra movis
me voy al movisrouter
y si dentro del barra movis
hacen un get
a la barra
entonces
respondo con todo esto
si hacen un barra
dos puntos id
entonces hago esto,
¿vale?
Con esto ya hemos hecho
estamos como
básicamente
aplanando
cómo es nuestra aplicación
y fíjate
que ya
porque tengo aquí
las explicaciones
estas de
de los imports
de los json,
¿no?
Pero fíjate
que excepto por el course
que esto también
lo podríamos separar
porque ya podríamos
empezar a tener aquí
my del words,
¿vale?
Podríamos poner aquí
course.js
y fíjate
que incluso
al poner my del words
mi sistema de directorios
detecta
y te pone
una carpeta especial,
¿vale?
Bueno,
pues aquí
con este course
podríamos hacer esto,
lo podríamos extraer
y este app use
podríamos hacer
export
con course
my del word,
¿vale?
Que esto
básicamente
fuese
que nos devuelva
esto.
Importamos
course
from course,
¿vale?
para tenerlo solo aquí,
este course my del word
tendríamos que importarlo
y ejecutarlo
y ya lo tendríamos.
Fíjate ahora,
esto ahora lo quitamos
y ya tenemos
las rutas
y los my del words
totalmente separados.
Lo que he hecho
con el course
lo que he hecho
es crear una función
que al ejecutarla
me devuelva justamente
la funcionalidad
de course.
¿Por qué?
Porque a veces
puede ser interesante
que aquí le podamos
inyectar options,
¿no?
Y a partir de las options
estas que le pasaríamos
aquí,
como por ejemplo
los hosts
y todo esto,
le podamos cambiar
la información
que tenemos aquí.
Por ejemplo,
los accepted origins.
Pues esto puede ser
el valor por defecto,
¿vale?
Lo podemos mover fuera
ahora que lo tenemos
totalmente externalizado,
¿no?
Que no está en mitad
del fichero.
Así que por valor
por defecto
tendríamos esto,
tendríamos que poner aquí
que valor por defecto
también sea aquí.
De esto,
el valor por defecto
es una llave vacía,
un objeto vacío,
porque si no le pasamos
si no,
esto petaría
y aquí le podríamos pasar
el accepted origins,
le podrías pasar
lo que tú quieras.
No lo necesitamos
porque ya tenemos
el que por defecto
funciona bien,
pero podría ser
una posibilidad,
¿vale?
Este accepted origins
lo utilizamos aquí
y ya está.
O sea,
ya estaríamos
teniendo una forma
de configurar
cores
desde fuera
y esto
ya lo tenemos
totalmente separado,
¿no?
Así que
esta sería un poco
la idea
a la hora de empezar
a extraer
lo que sería
tanto middlewares
como rutas.
¿Por qué MVC?
A ver,
por diferentes razones.
La primera
es que Express
es un framework
que está muy pensado
para utilizarlo
con MVC.
Lo segundo
es que MVC
es un patrón
de arquitectura.
Hay mucha discusión
si es un patrón
de diseño
o si es una arquitectura.
Yo la verdad
es que me quedo
con que está más cerca
de la arquitectura
que patrón de diseño,
¿vale?
Pero es verdad
que no es una arquitectura
que lo engloba todo
porque no te explica
como, por ejemplo,
dentro de la vista
tienes que hacer las cosas.
Ahora os explicaré
qué es MVC,
¿vale?
Pero MVC
es un patrón
de arquitectura
muy conocido,
muy utilizado
en muchos lenguajes
de programación
y en muchos frameworks.
Entonces,
yo creo que es muy interesante
que lo aprendáis.
Por eso os lo digo,
¿vale?
Y MVC
significa modelo,
vista, controlada.
Diferencia entre patrón
de diseño y arquitectura.
Un patrón de diseño
sería un patrón repetible,
fácil de hacer
para solucionar
una cosa en concreto
y una arquitectura
vendría a ser ya algo más
de toda tu aplicación,
de cómo arquitecturas
toda tu aplicación,
¿vale?
Y un patrón de diseño
en realidad sería algo,
un patrón repetible
en una parte de tu código,
¿vale?
Entonces, por ejemplo,
puedes tener patrón observer,
patrón factory,
patrón módulos.
De hecho,
aquí podéis ver
un patrón de diseño
que estamos utilizando aquí
es el patrón módulo.
Esto es un patrón,
pero no es la arquitectura
de nuestra aplicación,
¿verdad?
porque aquí tenéis un patrón
que estamos utilizando,
el patrón módulo,
que es el de import y export.
Es una forma,
es un patrón de diseño
que se puede repetir
constantemente
para solucionar
el compartir código,
pero no dirías
que es una arquitectura,
¿vale?
La arquitectura
es replicable,
pero es replicable
a nivel de toda la aplicación,
¿entendéis?
O sea,
la arquitectura
no se replica
dentro de la aplicación.
¿La arquitectura
contempla la infraestructura?
Por supuesto que sí,
puede contemplar
la infraestructura
o al menos
cómo te comportas
con la infraestructura,
no tanto
qué infraestructura utilizas,
sino cómo
te comunicas con ella.
MVC,
MVC
es un acrónimo
de modelo
vista controlador
y es un patrón
de arquitectura
que se utiliza
muchísimo,
ampliamente utilizado
en el desarrollo
de software,
especialmente en aplicaciones
web y móviles,
¿vale?
También en móviles,
¿por qué?
Porque durante mucho tiempo
se ha utilizado en Android,
muchos frameworks
ya estaban preparados
para eso,
pero bueno,
también te puedes encontrar
un montón de frameworks
en web,
que no significa frontend,
sino en frontend
también teníamos,
por ejemplo,
backbone,
pero ha habido también
pues Ruby on Rails,
hay un montón de frameworks
que se basan
en modelo vista controlador,
porque esta arquitectura
de alguna forma
te proporciona
una estructura
que te obliga
a separar tu aplicación
en tres componentes
interconectados
esenciales
y que separan
las preocupaciones
de tu aplicación
y son estos tres componentes
que le dan nombre
a la arquitectura,
modelo,
vista
y controlador.
Hay un montón,
a partir de MVC,
han existido
un montón
de mutaciones,
modificaciones,
mejoras,
evoluciones,
como le quieras llamar,
¿no?
Pero hoy vamos a intentar
basarnos
a hablar
en el que digamos
el más puro
o el más parecido
al clásico.
Tendríamos aquí,
vamos a hacer el modelo
y vamos a hacer aquí
el modelo verde.
El modelo representa
la lógica del negocio,
la estructura de datos,
las reglas que tiene
el negocio
de forma interna,
¿no?
Y es que el que se encarga,
por ejemplo,
de acceder a la base de datos
o de actualizar
la información
correctamente
o de ver
si la integridad
de los datos
es correcta,
por ejemplo,
si vas a crear una idea
que esa idea no exista,
este tipo de cosas,
¿vale?
Representa
la lógica
del negocio.
Así que,
importante.
Ahora,
otra parte importante,
el controlador,
que es el que controla.
Es el que actúa
como un intermediario
entre el modelo
y la vista,
que es el que está respondiendo
a las entradas
del usuario
cada vez que el usuario
pues está
utilizando nuestra página web,
nuestra aplicación
o lo que sea,
está dando,
enviando entradas
y antes de llegar
al modelo,
el controlador
es el que se está encargando
de responder,
ver esas entradas,
tratar esas entradas
y ver si tiene que solicitarle
al modelo
que haga operaciones,
a qué modelo
le tiene que pedir
y qué le tiene que pedir,
¿vale?
El orquestador,
me gusta,
el orquestador,
orquestador
y orquestador
y trata,
vamos a poner que trata,
actúa como intermediario.
Tenemos,
finalmente,
la visual,
la más importante
para el usuario,
claro,
porque el usuario
directamente no puede ir
ni al modelo
ni al controlador,
va a la vista
y qué es lo que hace
en la vista
es poder interactuar,
representar la interfaz
que el usuario
va a poder utilizar,
presentarle los datos,
mostrar estos datos,
enviar las acciones,
desde la vista
vamos a poder enviar
las acciones
que queremos hacer,
así que esto sería
la interfaz
del usuario.
Ya ves,
una estructura
en la que se están separando
aquí diferentes capas
y en las que podemos ver
además
cómo interactúan cada una.
Ahora bien,
estas son como las tres partes.
Obviamente,
las tres partes
para que funcionen correctamente
tienen que interactuar
entre ellas
de alguna forma.
El controlador primero
debería iniciar la vista,
es lo primero que se hace,
lo primero que hace
es iniciarla,
porque le tenemos que iniciar
con los datos,
así que primero
inicia.
Cuando la vista,
claro,
para iniciar antes
lo que tenemos que hacer
es que el modelo
te dé los datos
y todo esto,
pero pongamos que el controlador
ya le ha pedido
la información
de los datos,
¿vale?
El modelo le envía aquí
los datos,
vamos a poner por aquí,
¿vale?
Entonces,
lo primero que hacemos
es iniciar.
Luego,
a partir de esto,
la vista,
el usuario,
pues enviará acciones,
¿no?
Lo que dirá es,
oye,
pues quiero hacer alguna,
actualizar,
interaccionar,
lo que sea.
Y al usarlo,
el controlador
lo que dirá es,
bueno,
esto ha pasado tal,
ha hecho lo otro
y lo que va a hacer aquí
es pedirle,
ya sea modificar,
leer,
modificar,
lo que sea,
¿no?
O recuperar,
actualizar y directamente
aquí tendríamos,
¿no?
Que le está enviando
los datos,
¿vale?
Enviando los datos
y ya lo tendríamos.
Esto sería un poco
lo que está haciendo.
Desde la vista,
no puedes,
no puedes que,
no sé por qué,
hay en algunos sitios
que he visto
que hace algo así,
¿no?
Ah,
pues directamente a la vista.
Esto no está bien.
Sí que es algo
que pasa
de forma,
digamos,
indirecta,
¿vale?
De forma indirecta
podríamos entender
que la vista
interacciona con el modelo,
pero no se hace
nunca directamente
de verdad.
Nunca la vista
va a tener acceso
directo al modelo,
a la lógica de negocio.
Siempre va a tener
este tipo de conexión
porque siempre pasa
por el controlador
que va a ser
el que va a orquestar
cuando la vista
hace algún tipo de acción
o cuando el modelo
se actualiza
y le tiene que enviar
esa información a la vista,
¿vale?
Siempre pasa
por el controlador.
Nunca desde la vista,
desde la interfaz
del usuario,
vamos directamente
a tirar contra el modelo.
Eso no va a ocurrir
y lo vais a ver
en el código
que vamos a hacer
con un ejemplo
bastante claro.
Ahora,
para que os hagáis una idea,
en la vista
tendríamos,
por ejemplo,
podría ser React,
podría ser Next.js
directamente la vista,
aunque con Next.js
es un poco complicado
porque Next.js,
claro,
como es un framework,
normalmente ya tiene,
lo podrías llegar a hacer
pero tendrías que forzarte
mucho para hacer
un modelo vista controlador
porque al ser un framework
ya tiene algunas decisiones
que te complica
el hecho de poder hacerlo
exactamente igual,
pero lo podrías hacer.
Tendríamos,
yo que sé,
podrías utilizar JSON,
al final también podrías,
el JSON podrías considerarlo
como una list,
una vista,
porque es una forma
de representar los datos
que el controlador
ha recuperado del modelo.
más ejemplos,
pues aquí,
por ejemplo,
tendríamos,
pues,
MySQL,
que el modelo
lo que hace
es acceder directamente
al modelo,
está,
pues,
preguntándole a un,
hay una conexión aquí
con MySQL
o también,
pues,
con MongoDB
o puede haber,
el modelo se puede conectar
en un montón de sitios
y lo importante
es que el modelo,
como tiene la lógica de negocio,
siempre sea igual,
siempre se comporta igual
y eso lo vamos a ver en código
y lo vas a entender,
ya verás cómo,
¿vale?
Puede ser local,
puede ser lo que tú quieras,
¿vale?
Podríamos poner también aquí
que sea MongoDB,
lo que sea.
De hecho,
hoy vamos a ver con MongoDB
y el local.
Ahora,
antes de seguir,
¿cuál es la ventaja de esto?
¿No?
Porque,
¿para qué sirve esto?
Obviamente,
la ventaja principal
es separar
la lógica de negocio,
el modelo,
porque la lógica de negocio
es lo más importante
que vas a tener
en tu aplicación
a la hora de cómo se conecta
a una base de datos,
todo esto.
Claro,
si tú lo tienes eso
mezclado en tu código
a la hora de,
ya sea usarlo en otro sitio,
iterarlo,
arreglarlo,
lo que sea,
va a ser bastante complicado.
Así que es importante
separar tanto la interfaz
y el controlador
de la lógica de negocio.
Luego también,
esto te ayuda a la administración,
la escalabilidad
y las pruebas.
También lo veremos,
no sé si hoy nos dará tiempo,
pero seguramente
la semana que viene
haremos testing
y vamos a ver
cómo nos ayuda esto,
¿vale?
Y obviamente,
al no tener esto en medio,
fíjate que la vista,
tú el día de mañana
puedes cambiar React,
puedes cambiar
y en lugar de utilizar React,
ahora utilizas Vue
y no has tenido que tocar
ninguna de estas dos partes,
¿vale?
Has cambiado Vue
por React
y todo esto
lo sigues reutilizando
exactamente igual.
Esta justamente
es una de las grandes glorias.
el hecho de que puedes hacer cambios
en el modelo
que no afectan a la vista,
en el controlador
que no afecta
al modelo a la vista,
que cambian la vista
y no afecta al modelo,
¿vale?
O sea,
que es súper importante.
Y en el contexto
del desarrollo web,
como te digo,
frameworks y tal,
Django,
Rubin Race,
ASP.NET,
que también ASP.NET,
MVC,
y muchos otros
adoptan esta solución
justamente por la facilidad
que te da
de tener una separación
de conceptos
que hay gente que te dirá
que no es la mejor,
pero al menos
es una separación de conceptos.
Y para el código
vamos a crear primero ya
nuestras carpetas.
Vamos a crear por un lado
nuestra carpeta
y más adelante,
porque esto es lo típico,
¿no?
Lo de las carpetas,
que vamos a tener controllers,
vamos a tener models
y vamos a tener views.
Pero más adelante,
en una clase más adelante,
te voy a enseñar
lo que es
Screaming Architecture
y lo haremos justamente
con este proyecto
para que veas
cómo se le puede dar
un poco la vuelta
a la estructura de carpetas
que estamos haciendo
y la que seguramente
es la mejor estructura
de carpetas
recomendada
por grandes arquitectos
del mundo del software.
Pero por ahora
vamos a hacer esta, ¿vale?
Vamos a empezar
con los modelos, ¿vale?
Vamos a hacer los modelos
un poco especiales
para que veas también
la gracia de los modelos.
Así que vamos a poner
los modelos,
vamos a poner
movie,
movie.js,
lo decimos ahora
en singular, ¿vale?
Porque el modelo
es de movie
y lo que vamos a hacer aquí
es separar
la información
que tenemos aquí en Roots,
¿vale?
Fíjate que cuando
vamos aquí en Roots,
aquí tenemos que si hay
un género,
la recupera todas,
que no sé qué.
Claro,
esto es un poco,
es un poco rollo, ¿no?
Porque aquí está
la información
de cómo,
cómo se filtra,
se filtran
los datos
y de dónde,
de dónde se recuperan,
¿no?
Está aquí en medio.
Esto lo podemos mejorar.
Vamos a crear aquí
una clase
que vamos a exportar,
le vamos a llamar
movie model
y vamos a tener
diferentes
métodos estáticos.
Vamos a tener
método estático
que sea get all
para recuperar
todas las películas
y que se le puedan
pasar filtros,
pues se puede pasar
aquí el género.
Voy a hacer una cosa,
bueno,
joder,
muy bien,
que hack o pilot,
así no lo tengo que copiar,
gracias.
Por ahora hay que hacer esto,
¿no?
Que sería lo mismo
que tenemos aquí,
fíjate,
lo mismo que tenemos aquí,
me lo ha copiado
básicamente aquí,
me lo ha adaptado un poquito.
¿De dónde sacamos
las movies?
Bueno,
este modelo
por ahora
vamos a seguir haciendo
que sea como esto,
que lo esté sacando
del JSON
que teníamos por aquí.
Así que
hacemos el read JSON,
lo traemos de asútiles,
esto ahora lo vamos a tener
que sacar de punto punto
barra de útiles
y esto punto punto
barra movies punto JSON.
Ah,
no sé si esto funcionará,
pero bueno,
lo probaremos,
a ver si esto,
igual este import no le gusta
o si le gusta,
ahora lo veremos.
El tema,
este movies
tiene el JSON
y aquí le decimos
cómo tiene que recuperarlos todos.
Ahora,
en lugar de tener que hacer esto
que hemos hecho aquí,
¿vale?
Por ahora voy a dejar
este movies aquí,
pero voy a ir
quitando los que no necesitamos.
Por ejemplo,
esto, ¿no?
Esto ahora no vamos a hacer
aquí el rest JSON
y todo esto,
sino que simplemente
lo que vamos a hacer
es decir,
vale,
vamos a traernos
el movie model
y vamos a recuperarlos todos,
¿vale?
Y esto,
lo que me debería devolver
son las películas,
pero yo no sé,
yo no sé cómo lo hace,
yo simplemente sé
que me las devuelve.
Fíjate que,
aunque parece una tontería,
el hecho de tú
en esta parte
ya no sabes
cómo se filtra,
cuál es la lógica
que se utiliza
para filtrar
y además
esa lógica de filtrar
obviamente
no va a ser la misma
en este modelo
que es de la película
en local
con el JSON
como la de MongoDB.
Va a ser totalmente distinta,
pero esa lógica
la tenemos aquí
y ya no nos tenemos
que preocupar
de realmente
cómo se tiene que hacer.
Imagínate
que tenemos aquí
pages,
offset,
que tenemos un montón
más de filtros.
Esta lógica
en lugar de tenerla
dentro de esta función
y este callback,
lo que estamos haciendo
es extraerla
a nuestro modelo
para que sea el que se encargue
de saber
cómo se tienen que tratar
estos datos.
A esto se le llama
lógica de negocio
porque es esta lógica
que es lo que está haciendo
especial tu función,
tu aplicación,
tu negocio
de que sabes
cómo se tienen que filtrar
las cosas,
cómo se tienen que ordenar,
cómo se pagina.
No es lo mismo
cómo se filtran
los tweets de Twitter
a cómo se pueden filtrar
los posts de Instagram.
Puede ser
que muchas veces
parece que puede ser similar,
pero no es lo mismo.
Hay muchas reglas
de negocio ahí
que a lo mejor
un usuario
solo puede filtrar
20 posts,
que puede filtrar
de diferentes géneros,
que puede filtrar
de diferentes formas
y ese tipo de cosas
tienen que estar
totalmente separadas
de dónde se está
haciendo esto.
Así que cuando hablamos
muchas veces
de arquitectura
y tal,
estamos hablando de esto.
¿Tiene que ser
forzosamente la clase?
No,
no tiene que ser
forzosamente la clase.
De hecho,
también podríamos hacer
export cons,
get all,
no sé qué.
¿Pero por qué va a ser
una clase?
Os lo voy a comentar
porque es interesante.
Vamos a hacer
que sea una clase
porque es interesante
el hecho
de que tenga
un contrato.
Podríamos tener
un contrato también,
obviamente,
con módulos,
exportar aquí
un get all
y no sé qué,
pero la clase
más adelante
cuando esto
lo pasemos
a TypeScript
nos va a ayudar
al hecho
de poder tipar
perfectamente
cómo tienen que ser
nuestros modelos
para que sean
intercambiables
y eso lo entenderás
un poquito más adelante
ahora cuando
continuemos.
¿Vale?
Por ahora
ya tenemos aquí
el get all
pero antes de esto
antes de esto
vamos a hacer
un cambio
sutil
pero importante
para el día de mañana
para lo que haremos
más adelante
porque fíjate
que este método
estático
es síncrono
y el hecho
de que sea síncrono
está mal.
¿Por qué lo vamos
a hacer asíncrono?
¿Vale?
El hecho de hacerlo
síncrono
es que
entonces sabemos
es como que sabemos
que el modelo
por dentro
va a tratar siempre
con datos síncronos
¿no?
Y esto está mal
porque realmente
no deberíamos saber
cómo trabaja el modelo
desde fuera
o sea
desde este punto
no deberíamos saber
que el get all
va a darme los datos
de forma síncrona.
Así que
vamos a ponerle aquí
un await
y vamos a pasar esto
como un async await
y lo que podemos hacer aquí
es que esto también
sea un async
¿vale?
Así que lo pasamos
a asíncrono
y así directamente
¿qué es lo que nos vamos a asegurar?
Que siempre que creamos
modelos
de nuestras películas
y tal
lo que podemos hacer
es que siempre tengan
exactamente
el mismo
contrato
que todos tengan
que devolver
una promesa
aunque
independientemente
de que nosotros
sepamos
que la implementación
es síncrona
pero eso no importa
porque al final
lo importante
es que el día de mañana
sea asíncrono
o asíncrono
va a ser compatible
con todas las soluciones
por eso
es súper importante
el hecho de
pensar en algo
que sirva para todo
y no para lo específico
que tenemos ahora
¿ok?
entonces
ahora ya podríamos ir
static
async
getID
por cierto
que he hecho aquí
con el igual
pero no es obligatorio
o sea
podrías poner
el async
aquí de delante
getById
¿vale?
esto lo podrías hacer así también
bueno
lo voy a dejar
sin el arrow function
porque no es obligatorio
y porque tampoco necesitamos
que sea arrow function
y así quedará
un poco más claro
y un poquito menos de código
entonces aquí
pues nada
movie find
y si tenemos película
la devolvemos
que bueno
aquí
si no devolvería
no sé
podríamos mirar aquí
el getID
¿vale?
si tiene película
entonces json movie
¿vale?
pues devolvemos directamente
la película
static async
el create
aquí le pasaríamos
el input
no sé si
en realidad el input
debería ser así
¿vale?
lo que pasa es que no sabemos
que tener el input
y aquí viene un tema
de debate
e importante
pero yo te lo voy a explicar después
el tema de las validaciones
¿vale?
el create
lo tenemos aquí
¿vale?
y fíjate
que lo que hace
aquí
en este post
¿vale?
fíjate que tenemos aquí
la validación
del request.body
y aquí
si el resultado
no ha estado bien
hace esto
y finalmente
es aquí
donde se está haciendo
lo de la base de datos
digamos ¿no?
pues esto mismo
sería la parte
que vamos a hacer
directamente
en nuestro modelo
o sea
lo vamos a hacer aquí
solo que este random uid
sí que es una parte del modelo
que la id
pues hay veces
que la maneja
la base de datos
o hay veces
que la manejamos
nosotros
que la creamos
en este caso
necesitamos crearla
nosotros
pues tiene sentido
que la creemos
no pasa nada
en lógica de negocio
y justamente
en esta lógica
nos está diciendo
que es él
el que se encarga
de crearla
pero lo importante
es que esté aquí
porque es quien sabe
cómo se crea la idea
y todo esto
no lo tenemos que tener fuera
¿vale?
y este
y este
y result
simplemente
va a ser el input
este input
ya lo tendríamos aquí
y así es como actualizaríamos
nuestra base de datos
ahora mismo
luego tendremos otra base de datos
un poquito más en condiciones
y la haremos de otra forma
y finalmente
devolvemos
el new movie
que esto
entonces
para ir migrando
¿vale?
para que vayamos migrando
por ejemplo
aquí tendríamos
movie
await
movie
model
punto
get by id
get by id
entonces
todo esto
esto ya lo podemos quitar de aquí
y
esto lo tenemos que pasar
a sync await
¿vale?
ya tenemos
este lo tenemos hecho
este
lo acabo de hacer
ahora vamos con el post
el post
que tendríamos todo esto
en base de datos
ahora esto
ya lo podríamos hacer
await
movie model
punto
create
con el result data
y esto sería
el new movie
¿vale?
entonces ya nos
no sabemos cómo lo hace
pero lo hace
¿vale?
esto ya lo tenemos
ahora nos faltaría el delete
¿no?
que tenemos aquí
el movie index
no sé qué
no sé cuánto
bueno pues lo mismo
vamos con el static
async
delete
le pasamos la id
vale
una cosa importante
que a lo mejor
estás diciendo
hostia esto
no sé qué
no sé cuánto
mira
una cosa importante
es que fíjate
que los parámetros
estoy utilizando siempre
objetos ¿vale?
estoy utilizando siempre objetos
porque
el día de mañana
si tú le pasases
delete id
sería como más difícil
de extender
y entonces tendrías
que ponerle aquí
no sé qué
no sé cuánto
si le pasas directamente
objetos
será mucho más fácil
de extender
el día de mañana
si por lo que sea
tienes que pasarle
otra cosa aquí
return count
o yo que sé
lo que sea
bueno aquí
no tiene mucho sentido
pero si tuvieses
que ponerle una option
o lo que sea
es mucho más fácil
además te obliga
directamente
el hecho de que
cuando utilices el delete
sepas
y sea más fácil
de descubrir
que eso es una idea
con typescript
no es tanto problema
pero con javascript
es bastante más recomendado
¿vale?
que sí que lo utilices
vale
el movie index
esto sí que lo necesitamos
luego aquí
vale
si esto
si esto
es tal
pues pasamos
hacemos un false
y si no
pues aquí
vamos a hacer el splice
para modificar
la base de datos
de películas
quitando esta película
y ya podemos hacer
devolver el true
y ahora nos faltaría ya
el update
update
que le pasamos la id
y el input
ah mira
por eso
ves
por eso es interesante
por eso es interesante
pasar el input así
así que en el post
le vamos a pasar el input
que creo
creo que tiene sentido
ves
es que yo
me he traicionado
porque digo
hay que utilizar objetos
y en el de antes
no lo he utilizado
claro porque tiene sentido
porque así en el update
le puedes pasar el id
y el input
a la vez
y ya está
y así todos te quedan
exactamente igual
¿vale?
me voy a fiar
más o menos
de lo que ha hecho
yhackopilot
porque entiendo
que me lo está copiando
del download
movie index
¿vale?
lo está actualizando
y todo esto
asyncupdate
¿vale?
perfecto
movies
entonces
vamos a actualizar aquí
el create
ya lo tenemos arreglado
el delete
este delete
que ha hecho todo esto
vamos a hacer aquí
no
movie index
no
movie model
punto delete
por id
await
y aquí podemos tener
el result
¿vale?
tenemos que hacer esto
que sea async await
y aquí
si el resultado
si el resultado
es false
¿vale?
esto lo podríamos mejorar
que el resultado
te volviese un objeto
y tal
pero tampoco lo quiero
empezar a liar
muy a saco
¿vale?
así que vamos a
dejarlo un poquito así
si es false
es que no se encontró
la película
porque no la pudo borrar
y finalmente
aquí en el patch
pues un poco lo mismo
aquí
toda esta parte
que tenemos por aquí
toda esta parte
¿vale?
teníamos la
updated movie
de
await
movie model
punto
update
se le pasa
la id
input
del result
data
y esto
lo tenemos que pasar
a async await
¿vale?
y
update movie
es lo que devolvemos
¿vale?
ya hemos separado
toda la parte
que sería
del modelo
la hemos separado
directamente
de todas las rutas
¿vale?
fíjate que ahora ya
no necesitamos esto
tampoco necesitamos esto
tampoco necesitamos esto
ya hemos simplificado
todo lo que sería
la parte
de
el modelo
todo lo que es
en el movie
fíjate que aquí
no tenemos
nada
o sea
hacemos una
wait
movie model
que como se tiene que crear
le pasamos el input
y este movie model
¿por qué es importante?
¿por qué es interesante esto?
porque lo que estamos
haciendo aquí
es que
esto ahora
son como
tres cajas negras
cada una
hace una cosa
pero que cada una
de ellas
no sabe
cómo la hace
esa
esa
es la clave
del mundo
de la arquitectura
y el código limpio
cuando hablamos
de separación
por capas
separación
de conceptos
olvídate
de las implementaciones
olvídate
de todo esto
lo importante
realmente
porque hay muchas veces
que nos volvemos locos
como
es que clean code
es que clean architecture
es que no sé qué
lo importante realmente
es que
las capas
no tienen que saber
la implementación
por dentro
por eso es súper importante
¿vale?
no tener en ningún sitio
el hecho de decir
ostras
es que
aquí sabe
cómo tienes
si está haciendo
síncrono
si está utilizando
una base de datos
si está utilizando
es que no tienes
por qué saberlo
y eso es lo importante
porque ahora
este modelo
podría cambiar
totalmente
y ya no tendrías
ningún tipo de problema
lo podrías cambiar
no deberías
tener ningún problema
si esto lo pasas
a una base de datos
o lo que sea
ahora que ya tenemos
todo esto
y ya lo tenemos
más o menos migrado
una cosa que deberíamos hacer
para asegurarnos
que esto es realmente
robusto
como ahora estamos
empezando a utilizar
async await
deberíamos
esto
todo lo deberíamos
podríamos llevarlo
a diferentes puntos
pero una cosa
que deberíamos hacer
es envolverlo todo
en un try catch
y si tenemos algún error
además un error
inesperado
porque lo mejor
que podríamos hacer aquí
es manejar los errores
de forma mucho más
interesante
por ejemplo
el modelo
si quisiéramos
en lugar de que
siempre responda
con errores
de los que hay que hacer
un catch
lo mejor que se podría hacer
es utilizar algún tipo
de sistema
en el que devolviese
por un lado
el error
y por otro lado
el resultado
y así asegurarte
que puedes tener
un try catch
más a nivel
de que tu aplicación
está petando
por algo muy gordo
que es un error
del servidor
y por otro lado
tener aquí
por ejemplo
un result
en el que al final
en el result
si el result
es access
¿vale?
pues puedas tener
el JSON movies
y por otro lado
puedas manejar
el error
de una forma
mucho más granular
¿vale?
lo vamos a hacer
por ahora sí
porque no da tiempo
pero básicamente
para que te hagas
a la idea
esto del try catch
estaría interesante
porque al final
lo que estamos haciendo
es decir
ostras
es que tenemos
un problema
de que
todas las
todos son async await
obviamente
hacer un try catch
constantemente
en todos los endpoints
es un poco rollo
así que lo que haremos
también
en lugar de hacer esto
para que sea
mucho más ágil
lo que haremos
es manejar
este try catch
directamente
en un middleware
eso lo haremos
más adelante
porque ahora vamos
a seguir con el MVC
pero esa es la razón
por la que podemos
no hacer el try catch
lo hacemos en el middleware
y al menos ahí
sí que tenemos
la capacidad
de decir
bueno
vamos a evitar
que pete el proceso
y ya está
pero es súper importante
nos acordemos
que los async await
si hay un async await
necesitamos también
manejar los errores
¿vale?
que no se nos olvide
porque si no
lo que hacemos
es que nos pete la aplicación
sin control
y eso es lo peor
que nos puede pasar
¿vale?
centralizaremos
el manejo de excepciones
en un sitio
y ya lo tendremos
ahora que ya tenemos
los modelos
podemos continuar
con los controladores
un tema de las validaciones
como ven las validaciones
las estoy dejando aquí
hay dos tipos
de validaciones
¿vale?
o sea
os voy a comentar un poco
bueno
voy a hacer primero el código
y luego os comento
lo de las validaciones
lo que tenemos que hacer aquí
en los controllers
pues nada
vamos a crear un poco
lo mismo
vamos a crear aquí
controllers
vamos a poner
movies.js
a mí
la verdad
que la clase
a mí me gusta bastante
me gusta bastante
porque te obliga
de alguna forma
a tener como
la seguridad
de que el contrato
y tal
yo voy a continuar
haciendo con la clase
ahora
¿qué es lo que le llega aquí?
aquí no vamos a tener
por ejemplo
el genre y tal
aquí el controlador
lo que estamos entendiendo
por controlador
en cada uno
hostia
¿qué ha pasado aquí?
ahora
lo que estamos entendiendo
por controlador
en cada uno
es en realidad
esta parte de aquí
esta parte de aquí
es la que vamos a sacar
¿vale?
esta parte
request
esto de aquí
es lo que realmente
vamos a sacar aquí
así que ahora
podemos tener
por un lado
que el movie controller
cuando quiere recuperarlos todos
recupera la request
y la response
es lo que tenemos
ahí en medio
y es el que decide
además
qué es lo que renderiza
que en este caso
en la vista
podríamos tener un JSON
pero también
podríamos estar devolviendo
un HTML
al que le estuviésemos
inyectando los datos
y cualquier cosa
que también
lo seguiremos haciendo
más adelante
y el movie model
pues ya sabemos
de dónde lo podemos sacar
lo más interesante
que tenemos
en este punto
es que este movie model
y lo vas a ver después
solo cambiando
una línea de código
puedes hacer
que toda tu aplicación
cambie
entre
tirar de local
o una base de datos
¿vale?
y eso
lo vas a ver después
y te va a llamar
un montón la atención
vamos a ir sacando
esto rápidamente
¿vale?
tenemos aquí a sync
y fíjate que ahora
en lugar de utilizar esto
lo que vamos a hacer
es que el movie router
no va a tener
la información
de cómo lo hace
el control
sino que simplemente
aquí le decimos
movie controller
punto get all
¿vale?
sino que ya directamente
tenemos el controlador
de las películas
y es lo que va a llamar aquí
que el día de mañana
solo queremos tocar
el controlador
pues tenemos que ir aquí
y ya sabemos
cómo tiene que funcionar
y esto lo tenemos que hacer
con todos exactamente igual
¿no?
tendríamos aquí
con async await
¿vale?
esto lo sacamos de aquí
esto lo movemos aquí
y aquí pues igual
movie controller
punto get by id
fíjate ahora ya
cómo está quedando esto
está quedando
como para lamerlo
¿no?
un poquito
o sea ya no tiene nada que ver
con lo que
con lo que era antes
¿vale?
esto por aquí
el vali de movie
las validaciones
esto te lo explico ahora
lo de las validaciones
¿por qué las dejamos
estas validaciones aquí?
¿y qué tipo de validaciones
más o menos irían cada una?
¿vale?
esto ya lo ponemos por aquí
movie controller
punto create
¿vale?
ya quitamos aquí
esta validación de aquí
tendríamos el delete
así que igual
en este caso
yo les estoy llamando igual
no es obligatorio
que el controlador
y el modelo
tengan métodos
que se llamen exactamente igual
de hecho
no tiene por qué
en este caso
yo lo estoy haciendo
porque visualmente
para nosotros
nos va a ayudar un montón
a la hora de asociarlos
pero no tiene nada que ver
o sea
el modelo puede tener
nombres totalmente diferentes
de hecho
será lo más normal
porque en el modelo
muchas veces
desde el controlador
puedes llamar a más
de un modelo
por ejemplo
a lo mejor
cada vez que
insertas una película
pues resulta que
a la vez que insertas la película
también insertas
un director
y cada vez que insertas
una película
pues hay que incrementar
un contador
en otro sitio
que no sé qué
no sé cuánto
puede ser
que utilices
o que tengas
un modelo
que es el que lo agrupa todo
y el que sabe esa lógica
que normalmente sería
lo más correcto
o que desde el controlador
sea el que orquesta
y el que se hace
estas conexiones
también lo podría hacer
normalmente debería ser
en los modelos
que supiese
dónde tiene que llamar
vale
si es falso
no sé qué
delete
bueno pues aquí tenemos esto
movie controller
y ya solo nos quedaría
el de patch
vale
el de actualizar
así que esto
lo movemos por aquí
static
así
bueno que ahora me estoy
estoy
mira
aquí estoy poniendo
update
vale
validate movie
no sé qué
vale aquí el validate movie
este está mal
esto debería ser
partial movie
no sé por qué
no me la copia bien
vale
y hasta aquí
esto ya lo tendríamos
así que movie controller
punto
update
vale
muy bien
pues mira
fíjate que además
ahora lo podemos dejar así
para que quede mucho
mapónico
y esto además
lo podemos quitar
y ya tendríamos esto
tendríamos por un lado
el controlador
tendríamos por otro lado
las rutas
y fíjate que ahora
todos los conceptos
se están quedando
totalmente separados
o sea
ahora ya tenemos
cuando vamos
a nuestra app
pues aquí tenemos
justo lo necesario
de la app
ahora
en la enrutado
de las películas
tenemos
el enrutado
de las películas
el hecho de
cómo se controlan
estas rutas
no lo sabemos
aquí
sino que simplemente
es el controlador
el que sabe
cómo tiene que controlar
las películas
y aquí
es que sabe
a qué modelo
tiene que llamar
y entonces
en el modelo
es que sabe
cómo recupera
las películas
vale
entonces fíjate
cómo hemos separado
en diferentes capas
la información
cómo se tiene que ir moviendo
y lo puedes ver
un poco
con lo que hemos hecho aquí
obviamente en la vista
no hemos hecho
la página web
que eso lo podemos hacer después
como el controlador
pues le pasa la vista
que puede ser el JSON
la vista directamente
que muchas veces creemos
que solo puede ser
una aplicación de RIA
no puede ser JSON
puede haber XML
puede ser un montón de cosas
luego
cuando usamos
el controlador
el controlador
es el que se encarga
de ir al modelo
y el modelo
es el que envía
los datos
vale
esto es el punto 0
y el 4
vale
pero la vista
y el modelo
nunca directamente
van a llevarlo
así que lo que hemos hecho
ahora
es separar esto
validaciones
dónde van las validaciones
dónde van las validaciones
porque
hay gente
que a lo mejor ve esto
y dice
hostia
las validaciones
son algo del modelo
deberían
las validaciones
estar en el modelo
y es que
tiene razón
y no tiene razón
o sea
validaciones
hay en todas las capas
vale
o sea
hay que validar los datos
aquí
aquí
y aquí
solo que las validaciones
que se van a hacer
en cada una
son diferentes
son de diferentes niveles
vale
por ejemplo
las validaciones
del input
del usuario
se pueden realizar
en diferentes lugares
en los tres
de hecho
pero obviamente
el nivel de validación
de cada una
va a ser diferente
en el controlador
normalmente se centran
de formato
y de coherencia
que tengan los datos
que hemos recibido
que se puedan procesar
para antes de enviarlo
al modelo
justamente
el input del usuario
que es el que llega
de la vista
es buena idea
que lo validemos
en el controlador
antes de enviarlo
al modelo
o sea
mapearlos
y tal
comprobarse un campo
requerido
que esté presente
que la cadena
tenga un formato
un correo electrónico
que el número
esté dentro de un rango
o sea
esto
lo que hace
es que haya
unas validaciones
que ya te previenen
que haya procesamientos
de entrada
en el modelo
que son incorrectos
o maliciosos
y así
antes de llegar
a la lógica de negocio
ya tienen sentido
luego
obviamente
la vista
tiene que tener
pues las típicas
de interfaz
del usuario
son las más inútiles
en cuanto a lógica
de negocio
pero son las más necesarias
para la experiencia
del usuario
lo que quiere decir esto
es que
las que son
obligatorias
obligatorias seguro
son
estas validaciones
y las validaciones
que hacemos
aquí
son interesantes
para mejorar
la UX
¿vale?
la experiencia
del usuario
si un campo
es requerido
es mejor
que se lo
indiquemos
al usuario
en la vista
antes de hacer
todo tipo
de que vaya
al controlador
que pete
que no sé
qué no sé cuánto
¿vale?
para evitar
justamente
que el usuario
tenga que esperar
tanto
pero las requeridas
obligatorias
están aquí
porque tenemos
que asegurarnos
que los datos
que están intentando
meter el usuario
no son maliciosos
no son incorrectos
que no están rompiendo
lógica de negocio
y todo esto
así que
súper importante
que tengas en cuenta
de esto
ahora en el modelo
si hacen validaciones
en el modelo
también se hacen
validaciones
en el modelo
normalmente
las validaciones
que se hacen
en el modelo
son validaciones
más de regla
de negocio
coherencia
de datos
relacionados
sobre todo
con la persistencia
de estos datos
en la base
de datos
o sea
si en la base
de datos
el campo
es
integer
es imposible
que intentes
meter una cadena
de texto
y por lo tanto
ya tienes una validación
en ese punto
pero hay otras
por ejemplo
intentas guardar
un usuario
¿sabes?
el controlador
te pasa
un usuario
que tiene una ID
y resulta que esa ID
en la base de datos
ya existe
esa validación
de verificar
que ese usuario
no exista
solo la puedes hacer
o solo la podrías hacer
en el modelo
o si alguien
intenta registrar
un email
que ya existe
garantizar la integridad
y la coherencia
de los datos
es del modelo
y son validaciones
que obviamente
hay que hacer
en el modelo
no podrías hacer
en el controlador
por ejemplo
una validación
de integridad
de datos
porque no sabes
en el modelo
sí que podríamos
llegar a discutir
y comentar
si tendría sentido
que el modelo
te exportase
un método
que pudieses llamar
desde el controlador
para validar datos
por ejemplo
para decirle
oye
existe esta idea
y entonces que el controlador
sea el que lo verifica
pero esa implementación
no la vas a poder tener
dentro del controlador
va a estar dentro del modelo
la puedes llamar
del controlador
pero va a estar en el modelo
dicho esto
he preparado
un pequeño ejemplo
lo primero que voy a hacer
es ver que esto funciona
porque igual todo esto
que hemos hecho
está muy bien
súper interesante
y tal
pero no funciona
así que vamos a ver
vamos a recuperar
todas las películas
parece que
recuperar las películas
funciona después
de todo lo que hemos hecho
recuperar una idea
una película por idea
también funciona
recuperar todas las películas
por un género
esto sigue funcionando
también
luego crear una película
vamos a ver
si crear una película
funciona
también ha creado
la película
vamos a ver
si
le falta el delete
vamos a poner aquí
borrar una película
delete
http
localhost
234
barra movies
barra
vamos a utilizar
la película
esta
que parece que existe
vamos a ver si la podemos borrar
movie deleted
o sea que sigue funcionando
y luego
actualizar una película
y entonces hacemos esto
y vale
no existe la película
porque la acabo de borrar
bien por mi
que es la que he borrado
vamos a actualizar
esta película
con esta idea
ok
y nos vamos por aquí
vamos por aquí
hacemos
cambiamos esta idea
y vamos a ver si
le podemos actualizar
vale
pues efectivamente
se ha actualizado con el año 2022
o sea
todo lo que hemos hecho
pues lo tenemos funcionando
perfectamente
voy a subirte esto
pero ahora voy a hacer
otra cosa
para que entiendas
hasta que punto llega esto
de modelo vista controlador
así que vale
quitamos todo esto
hacemos
add class for
para que tengáis los cambios
que muchas veces
me echáis bronca
con razón
de que no he subido los cambios
vale
lo interesante de los modelos
es que fíjate
que tenemos este modelo aquí
con este
con todo esto
si yo
pusiéramos aquí
que tengo modelos
y pongo local
o local
file system
vamos a poner
movie.js
vale
podríamos tener aquí
este
podríamos tener aquí
el local file system
que este es el que hemos utilizado
y podríamos tener
el modelo este
también
podríamos ponerle
por ejemplo
database
vale
y podemos poner aquí
movie.js
esto ahora lo voy a hacer así
pero te voy a explicar
cómo podríamos inyectarle
realmente esto
pero bueno
por ahora vamos a hacer así
y luego lo vamos comentando
a ver
imagínate
que
este
en este caso
fíjate que esto está tirando
de un json
está tirando de un archivo
que tenemos
bueno
no sé si conoces un servicio
se llama
atlas
mongo db atlas
hoy no te voy a poder explicar
la base de datos
de mongo db
desde cero
pero mongo db
es una base de datos
no sql
no relacional
que está basado en documentos
en colecciones
y que es muy interesante
está muy chula
y mongo db atlas
además te permite
tener tu base de datos
totalmente gratuita
os podéis
podéis registraros
crearos la vuestra
si queréis saber más de mongo db
que lo vamos a ver más adelante
pero si queréis saber más de mongo db
podéis buscar youtube
mongo db
midudev
vale
y ves
yo tengo ahí un montón de cursos
de mongo db
que te explico y tal
más adelante veremos
mongo db
y mysql
o sea vamos a verlo todo
y justamente la clave
de tener los módulos
los modelos separados
es que
vamos a poder hacer cosas como esta
de cambiar entre uno y otro
súper fácil
vale
lo importante
ahora
no es tan importante
la base de datos
sino que solo que sepas
lo que vamos a utilizar
y todo esto
le podrías dar aquí al connect
y en el connect
aquí en drivers
tendrías la información
que tienes que utilizar
de que tienes que instalar
para utilizarlo
y todo esto
vale
yo voy a instalar
voy a asegurarme
que tenemos en la clase 4
voy a instalar la dependencia
de mongo db
vale
vamos a instalar la dependencia
de mongo db
lo haremos otro día
y lo haremos nativo
y luego utilizaremos
mongoose
o sea
mongoose es un ORM
que te facilita mucho
pero es interesante
primero verlo de forma nativa
y todo esto
ok
entonces
que es lo que vamos a hacer
hacemos un npm install
de mongo db
que es el driver nativo
para conectarnos
a la base de datos
de mongo db
vale
aquí nos dan
toda la información
de hecho aquí tienes
todo el código
de cómo te tienes que conectar
vale
pero ahora mismo
ya te digo
que no te quiero enseñar
tanto cómo conectarte
y tal
lo que te quiero enseñar
lo que realmente
te quiero enseñar
es
cómo
con todo lo que hemos hecho
con todo lo que hemos hecho
podríamos tener
otro modelo
de la película
que se llama
movie model
vale
que se va a conectar
a la versión
de
en este caso
de mongo db
vale
teníamos aquí la conexión
de mongo db
todo esto
pero fíjate
que lo importante
es que tenemos aquí
el get all
que devuelve
una promesa
y no es importante
ahora que
cómo lo hace
qué es lo que hace
y todo esto
no es importante
vale
lo importante
es que
esto
es una caja negra
y que fíjate
que aquí
se conecta la base de datos
recupera esta información
de la base de datos
que hace un montón de cosas
base de datos
base de datos
borra en la base de datos
todo en la base de datos
vale
lo hace en una base de datos
y que solo
solo
teniendo
un modelo
que uno se conecta
a un archivo físico
y otro se conecta
a una base de datos
dos archivos
que tienen
el mismo contrato
el mismo contrato
y esto es clave
solo con esto
solo cambiando
un fichero
un fichero
en este movie model
en lugar de tirar
de models movie
models
database
movie
punto js
solo con un cambio
solo con un fichero
una línea
que esto la idea
y ya lo veremos
más adelante
no es cambiar
el import
la idea
de esto es
inyectarle el modelo
lo veremos más adelante
porque te voy a hablar
de más arquitectura
y más de patrones
de diseño
pero por ahora
solo quiero que veas
la potencia de esto
¿no?
entonces
cambiamos el import
¿vale?
podemos actualizar
aquí
esto
¿vale?
note
no puedo encontrar
el esquemas movies
ah
porque esto
hostia
no sé por qué esto
es verdad
que aquí no tenía un JS
que ha pasado ahí
y eso funcionaba antes
bueno
localhost
1,2,3,4
barra movies
vale
fíjate
lo que ha ocurrido
es que
está pasando
todo
hemos cambiado
una línea de código
no he cambiado
nada más
o sea
has visto
que yo
me he copiado esto
¿vale?
lo haré
esto lo vamos a hacer
desde cero
pero de nuevo
no es importante eso
lo que te quiero decir es
teníamos este
que este es el que hemos creado
aquí juntos
¿vale?
he copiado
un modelo
que se llama Movie Model
que tiene el mismo contrato
pero que obviamente
el modelo hace cosas diferentes
de cómo crea las películas
cómo la borra
y todo
y el tema
es que
con esto
con todo lo que hemos hecho
y esta es la clave
de la arquitectura
que por qué es importante
la arquitectura
por qué vale la pena
aprender patrones de diseño
y todo esto
pues es el hecho
de que de forma
totalmente transparente
ahora estamos conectados
a una base de datos
bueno igual
hay alguna cosa
que no he hecho bien
¡ah!
vale vale
ya sé que ha pasado
es que las ideas
claro las ideas
no las he hecho exactamente igual
vale vale
claro cuando tengo las movies
tengo que
la idea no existe
no son las mismas
y es que el formato
tampoco es el mismo
que esto es una cosa
que no me ha dado tiempo
de hacer objetos
a ideas y tal
y esto sería importante
que todos tengan
el mismo tipo de idea
pero bueno
recuperar una nueva película
vale
aquí ves
recuperar la película
el género de acción
vale
recuperar películas
que tienen acción
crear una nueva película
pues
crea la película
vale
aquí lo tendríamos con la idea
también tendríamos
borrar la película
pues nada
le cambiamos aquí la idea
borramos la película
película borrada
o sea exactamente lo mismo
vale
y actualizar una película
vamos a actualizar
una película
por ejemplo
The Good Father
vale
actualizamos una película
send request
y actualizamos la película
vale
ah
lo que pasa es que esto
me está devolviendo
el documento antiguo
esto es porque
es normal
en MongoDB
te devuelve
el documento antiguo
tendría que pasarle
un flag
diciéndole que me devuelva
el nuevo
pero bueno
no pasa nada
el tema que le ha actualizado
el tema
de esto
es que esta es la importancia
de cuando hablamos
de por qué es importante
la arquitectura
por qué son importantes
los patrones de diseño
es el tema
de que
lo que estamos consiguiendo
es que nuestra aplicación
ahora
sea más escalable
y mantenible
que antes
si yo
hoy
por lo que sea
en lugar de
MongoDB
por lo que sea
queremos cambiar
a Redis
solo tengo que tocar
un archivo
de todo nuestro proyecto
solo tengo que tocar
bueno
solo tengo que crear
el archivo
del modelo
de la película
para Redis
y por otro lado
solo tengo que cambiar
un import
vale
un import
ya está
no tienes que tocar
nada del controlador
porque para el controlador
ya sabe
cómo tiene que recuperar
y llamar a los modelos
lo importante
es que nuestros modelos
tengan exactamente
el mismo contrato
vale
y eso
es justamente
la clave
de por qué
en empresas de producto
en servicios
y tal
es importante
aplicar arquitecturas
porque no es lo mismo
cuando tú tienes un proyecto
muy interesante
seguro
tuyo propio
como a mí me pasa
que yo no utilizo arquitecturas
ni en broma
para mis proyectos
que sé que van a ser fungibles
que van a durar
dos meses
tres meses
seis meses
un año
y hay gente que me lo dice
pero por qué no utilizas
arquitectura sagonal y tal
porque no tiene sentido
no tiene sentido
siempre utilizar arquitectura
si GitHub
va a hacer una landing page
para un producto
que va a durar
seis meses
para anunciarlo
no vale la pena
hacer arquitectura
pero
la arquitectura
es importante
aprenderla
y entenderla
porque para ser
ingeniero de software
y no de carrera
no hablo de carreras
hablo de mentalidad
que para ser ingeniero
de software
tenemos que crear
productos que sean
escalables
mantenibles
y por supuesto
que funcionen
así que también
haremos testing
la semana que viene
¿vale?
así que esto ha sido
todo por hoy
amigos
espero y deseo
que hayáis aprendido
model view controller
que hayáis visto
que hayáis visto
qué importancia
puede tener
en un proyecto
real
la semana que viene
vamos a hacer test
vamos a hacer test
porque vais a ver
cómo vamos a inyectar
dependencias
vamos a hacer
más patrones de diseño
un poquito más de arquitectura
y testing
porque el testing
amigos
es súper importante
y no se os puede caer
la cara de vergüenza
que vayáis a una prueba técnica
y digáis que no sabéis hacer test
¿vale?
así que bueno
pues espero
amigos
que os haya gustado la clase
que hayáis aprendido algo nuevo
que os ha valido a pena
sé que era
contenido avanzado
que sé que muchas veces
es que de decir
o que no sé qué
no sé cuánto
pues oye
esto es un contenido
más avanzado
pero creo que es el que
marca la diferencia
creo que lo puede entender
cualquier persona
creo que es contenido
que una persona que sea junior
puede llegar a entender
puede empezar a dominar
y que necesita
y que
que a ver
no es curso desde cero
no es
cómo esto desde cero
cómo tus primeros pasos en tal
pero es que estas son las cosas
que dan de comer
así que amigos
¡chop chop!