NodeJS Repository Pattern | Clean Architecture
Vložit
- čas přidán 5. 08. 2024
- En este video hablamos sobre el patrón Repository y cómo podemos implementarlo en TypeScript. Aprenderás cómo separar la lógica de datos del acceso. Además, veremos cómo usar este patrón utilizando una arquitectura hexagonal.
Capítulos:
0:00 Introducción
02:20 Creación del proyecto
05:56 Patrón Repository
22:06 Arquitectura Hexagonal con el Patrón Repository
26:08 Conclusiones
🔔 No te olvides de suscribirte y activar la campanita
► czcams.com/users/AlbertHerna...
🌍 Puedes encontrarme en: alberthernandez.github.io/hello
🐦 Twitter: / alberthernandev
Os dejo aquí el link al proyecto en GitHub: github.com/AlbertHernandez/repository-pattern-typescript-example
Y también el link al skeleton: github.com/AlbertHernandez/express-typescript-service-skeleton
Por cierto, ¿habéis implementado este patrón anteriormente? ¿Qué desafíos habéis encontrado al implementarlo? Os leo en los comentarios 😁
Menuda joya de vídeo, encima me encanta tu formato de edición de vídeos!! Grande Albert!
Muchas gracias 💪😁
Muchas gracias Albert por el vídeo, esta genial, es realmente interesante para aplicarlo en los proyectos, tal vez si recomiendo realizar uno con BD real, podría ser Mongo y MySql, una basada en documentos y la otra relacional, también para diferencial el manejo del mongoId y el id para MySQL, inclusive levantar las BD con Docker, aunque igual este es un contenido de mucho valor, Gracias de nuevo
Excelente material ! me gusta este tipo de contenido, gracias
Gracias por el video!!! Excelente explicación!
Excelente aporte
Muchas gracias por la claridad y la serenidad al explicar. Es un vídeo de gran valor.
Me alegra leer que le ves el valor al video, gracias por las palabras 💪
Gracias Albert! Ahora mismo estoy implementando este patrón en mis proyectos laborales, un crack como lo explicas. Gracias :D
Nada gracias a ti :) Me encanta ver como vamos compartiendo cosillas y todos vamos aprendiendo 😁
Eres muy bueno explicando man, acabe de descubrir tu canal, nuevo seguidor en todas tus redes, gracias crack
Muchas gracias! Creo que debería empezar a ser más activo en otras redes, pero donde más caña le estoy dando es aquí por CZcams. Un saludo!
excelente contenido, muchas gracias crack
Gracias Albert !
Me has ayudado mucho a entender este patrón tan importante en las aplicaciones modernas que van innovando a nivel de arquitecturas y patrones de diseño !
Dios te bendiga mi amigo, y sigas subiendo más videos de esta índole rica en sabiduría !
Eres tremendo Albert !!
Muchas gracias por esas palabras tan bonitas, me alegra mucho que os esté ayudando todo este contenido 😊😊
Muchas gracias por el video, aprendí bastante
Es un placer 🤟 Me alegra ver como todos aprendemos juntos
Genial el video. Gracias por compartir tus conocimientos 👍
Es un placer 😁. Yo también aprendo mucho haciendo los videos y leyendo los comentarios con las conversaciones que tengo con vosotros. Me encanta ver cómo al final todos acabamos aprendiendo unos de otros
Demasiodo útil, explicación clara, excelente Albert!
Me alegra, pensé que al igual era un video un poco largo pero si así se entiende y esta claro me alegro que os haya servido 😁
@@AlbertHernandez claro, mi secreto en YT es que todo lo veo a 2x jajajaj ya me acostumbré, solo aquello que es complejo de digerir, lo reduzco y listo
Qué buena, yo si me ponen el código fuente voy directo a él y ya si hay cosas que no entiendo me veo el video o la parte que más me interese hehe
Hola Albert, he visto un par de videos tuyos (clean architecture y hexagonal architecture) y es un contenido de calidad como muy pocos aquí, tienes un nuevo suscriptor. Como sugerencia, creo que un video creando una app con TS, microservicios, y subirlo a Docker sería algo único aquí en español. Gracias por compartir y un saludo.
Muchas gracias 😁. Sí, es uno que tengo pendiente, pero creo que lo haré en formato de curso con una lista de videos, ya que uno solo en el que se muestre todo puede ser demasiado largo y pesado. Un saludo!
Great video! I learned a lot from it. It would be better if you had added at least one more functionality, like 'findByName,' for example. Anyway, thank you for sharing your knowledge with us.
Thank you! Yes, but the video would have been much longer and I preferred to shorten it a bit. However, if you think it would be good to extend it a little, we can do that in future videos. Greetings!
Uf! Me gusta mucho tu contenido y siento que voy aprendiendo más. ¿Tal vez en algún futuro podrías hacer algún video sobre microservicios con Node JS? Ejemplo creación de usuarios, envío de emails, registro de compras, etc..?
Sería genial.
Saludos :)
Me alegro de que te guste :) Claro, en el futuro estoy pensando en sacar algún curso más completo donde montemos una aplicación desde cero que haga varias cosas. Así, podremos ver todos los conceptos que vemos en estos videos aplicados juntos y cómo se conectan unos con otros 😁
Muchas gracias!! Pues me encantaría ver un video similar a este, pero con la conexion a la base de datos de mongo (por seguir el ejemplo del video) Me ha gustado como esta explicado.
Es un placer :) Pues justo tengo un video donde vemos eso de mongo pero con NestJS, si crees que os seria util uno con NodeJS sin framework me dices y me lo apunto
Tip: Desde express v4 trae los middleware the json y urlencoded y no hay q instalar bodyparser.
Muy bueno el vídeo, gracias Albert! Es posible hacer un base repository para no tener que repetir el código para cada entity, como se hace por ejemplo en . NET? Podrías enseñar un ejemplo ? A mi personalmente me gustarían mucho más videos sobre los design patterns y la arquitectura hexagonal, porque lo explicas muy bien
Muchas gracias! Sí, sería posible, algunos ORM como TypeORM (typeorm.io/) hacen eso, tu le pasas una entidad y te devuelven un repositorio para esa entidad, encima tienen el código abierto y puedes ver cómo funciona :D
Sobre .NET apenas he trabajado con ese lenguaje así que no creo que pueda haceros contenido de alta calidad ahí... pero te recomiendo que le des un vistazo al canal de hdeleon.net (www.youtube.com/@hdeleonnet) tiene videos con muy buena pinta
Hehe si claro, la idea es ir haciendo más videos sobre design patterns y diferentes arquitecturas, espero poco a poco ir haciendo más y poder tener una buena lista :D
Un saludo!
Qué gran contenido Albert, me encanta el concepto de videos "cortos", que entiendo que detrás tienen mucho mas trabajo que los 30 minutos. 🎉🎉
Una pregunta, a parte de tu contenido, que me estoy terminando ya casi todo, ¿ qué recursos recomiendas para dominar NodeTS y Express?. Y no hablo de conceptos básicos como los miles que hay de crea una API Rest en 30 minutos, etc. Sino a contenido similar al tuyo en los que se dan por entendida esa base y se profundiza más en conceptos como arquitectura y clean code. Puede ser en ENG/ESP.
Un saludo
Muchas gracias! Me alegra ver que todos estos videos os estan gustando :)
Pues si quieres conceptos asi mas avanzados a mi me gusta mucho el equipo de CodelyTV, tienen contenido de una altisima calidad y unos cursazos que son obras maestras, te paso uno que tienen con typescript que me gusto mucho: pro.codely.com/library/ddd-en-typescript-modelado-y-arquitectura-172533/375662/about/
Hola Albert, veo muy útil el skeleton que nos facilitas, pero, para que los menos experimentados podamos sacarle el máximo provecho, por favor ¿Podrías tener en cuenta el tratar en un video-tutorial todas las dependencias que utilizas en él, cuáles son sus respectivas funcionalidades y como están definidos los archivos de configuración asociados? Muchísimas gracias por tus aportes!
Buenas! Sí, justo hice un video explicando muchas de estas cosas, lo tienes disponible aquí: czcams.com/video/l--D8yslyUk/video.html&lc=Ugw4ilrTKUvFGRkunUd4AaABAg
También, iré creando mas contenido sobre muchas cosas que estan en ese skeleton, como github actions y otras cosillas muy interesantes, espero que os guste ^^
Un saludo!
Buen video me gustaria una continuacion de diferencias del patron repository vs el dao
Apuntado! :)
Buenas Albert, buenísimo el vídeo. Hace falta contenido así! ^^ fantástico y maravilloso :), me encanta!!
Te comento, cuando dices en el min 22:18 que dejas el vídeo de arquitectura hexagonal, el vídeo (al menos a mí) no me aparece como se ve otras veces arriba a la derecha. No sé cómo funciona el tema... pero te lo comento para que tengas constancia de ello y lo puedas solucionar si es posible ya que es muy buen video tmb y 100% recomendable :)
Un saludo, muchas gracias por tu tiempo y x compartir tus conocimientos, un saludo!!
Espero más contenido 😃👍
Me ha aparecido como contenido relacionado, pero no sé si es por el dispositivo móvil. Ya me quedo en duda xd, pero arriba a la derecha no me sale jajajja. Simplemente es por comentartelo y que tuvieras constancia de ello. ^^
Saludos!!
@@juanisidorogarcia1699 Gracias! Me alegra que te haya gustado.
Pues he visto lo del min 22.18 y si me aparece la tarjeta al menos con el ordenador, aunque no descarto que haya hecho algo mal haha aun estoy aprendiendo estas cosas :P
@@AlbertHernandez pues listo ^^ no problem!! Será en mi tlf que se ve en otro lado y me lío yo jajaja y te lo quise comentar con mi buena intención xd.
Muchas gracias por tu respuesta y ánimo con la generación de contenido, me encanta!!! Un saludo!!
Sisi se agradece que me lo dijeras, así lo he podido verificar por si las moscas que nunca se sabe, muchas gracias! 😁
Os dejo aquí el link al proyecto en GitHub: github.com/AlbertHernandez/repository-pattern-typescript-example
Y el también el link al skeleton: github.com/AlbertHernandez/express-typescript-service-skeleton
Por cierto, ¿habéis implementado este patrón anteriormente? ¿Qué desafíos habéis encontrado al implementarlo? Os leo 😁
El caso donde esto aplica muy bien es usando Realm y Mongo. Cuando no tienes internet usas Realm que sincroniza con Atlas cuando vuelva la conexión. Caso contrario usas mongodb.
Mala idea nulear una respuesta mucho mejor excepciones y poder documentar el problema vs devolver un valor no esperado y que te tocará además comparar fuera para probar si funcionó o no pa llamada... de hecho hay un capítulo sobre eso del tío Bob no se que pensais
Buen video compa un saludote y gracias por el video
Buenas! Supongo que como siempre, todo depende del contexto (e incluso muchas veces del gusto personal). A mí, por ejemplo, suele gustarme que los repositorios me devuelvan nulls en lugar de lanzar excepciones de este tipo, delegando este comportamiento a clases de dominio, como por ejemplo, a los finders. En este caso, lo que haría sería crearme un UserByIdFinder que me devuelva el usuario o lance una excepción de UserNotFoundException en el caso de no encontrarlo. Suelo hacer esto así porque, dependiendo del caso de uso, esto puede ser esperado, y no quiero estar ensuciando la lógica de la aplicación con todos los try-catch. También hay otros desarrolladores que no les gusta trabajar con excepciones ya que, al final, una excepción como su nombre indica tiene que ser algo excepcional. Lanzar un error porque no se encuentra un usuario no es algo excepcional, por lo que prefieren trabajar con otro concepto llamado Eithers (si no lo conoces, dale un vistazo, creo que te gustará hehe)
Te paso también un par de artículos donde hablan más de todo esto:
- softwareengineering.stackexchange.com/questions/422254/error-handling-for-repository-exceptions-or-wrapping-return-value
- minasami.com/2020/09/14/should-repositories-throw-exceptions.html
- twitter.com/fn_schubert/status/1542034442377744385?lang=es
También hay otros que hablan sobre por qué prefieren lanzar excepciones en lugar de devolver null. Al final, como te comentaba al principio, depende más del contexto y del gusto personal en muchas ocasiones
muy bueno el video, se podra quitar eso de bind() ??? porque como que complica la asimilacion o interpretacion un poco.
Buenas! Si, se podría quitar si usáramos arrow functions, por ejemplo, en el router:
```ts
userRouter.get("/:id", (req, res) => userGetController.run(req, res));
```
Otra solución sería convertir el método run del controller en arrow function
Excelente video Albert!!, soy desarrollado node en México, y estoy implementando este patrón en mi sistema de control de asistencias, una duda, como soporta este patrón el siguiente escenario? tengo mi modelo "User" y mi Modelo "Post" que tiene como llave foránea "userId". Si quiero recuperar un Usuario a partir del Post, en que abstracción pongo ese método?, en UserRepository o en PostRepository???
Buenas! Te comento lo que pienso al respecto (quizá otro compañero o si te animas tú, pueda dar también su opinión y así tenemos un bonito debate):
El modelo del User es totalmente independiente, imaginémonos que tenemos un id, un nombre y un correo electrónico. En este modelo y en su tabla no sabemos nada sobre Posts.
El modelo del Post tiene las propiedades de un id, un título y la llave foránea del user id. Este modelo sí conoce cosas del modelo del usuario, pero no a la inversa.
Dado que el User no sabe nada del Post, pero el Post está vinculado al Usuario, le veo más sentido tenerlo en el PostRepository. Lo que podríamos hacer es, por ejemplo, añadir un método en el PostRepository llamado getAuthorByPostId, el cual primero obtendría el userId a partir del PostId y luego, por ejemplo, usaría el userRepository para obtener el usuario a partir de ese id. Esto último es algo opcional ya que aunque un post lo realice un usuario, puede ser que no queramos que el Author tenga todas las propiedades del User, ya que puede haber distintos casos de uso y estaría correcto.
Te paso cómo podría ser una pequeña implementación:
```ts
export class InMemoryUsersRepository implements UsersRepository {
async findById(userId: string): Promise {
// implementación de cómo encontrar un usuario por su id
}
}
export class InMemoryPostRepository implements PostRepository {
constructor(private readonly usersRepository: UsersRepository) {}
async findAuthorByPostId(postId: string): Promise {
const post = await this.findById(postId);
if (!post) {
return null
}
return await this.usersRepository.findById(post.userId);
}
async findById(postId: string): Promise {
// implementación de cómo encontrar un post por su id
}
}
```
Espero que te haya ayudado, ya me dices que piensas al respecto, un saludo!
Hola, me dirias que interface de IDE utilizas? Es muy clara la vision. Gracias.
Hola! Si claro, uso IntelliJ Idea, lo que pasa que quite muchos de los menus, tabs y demas para hacerlo lo mas limpio posible solo con las cosas que de verdad necesito, un saludo!
Hola Albert, muy buen video. Tengo una pregunta.... ¿Cómo se usaría el patrón si tengo que hacer unos inserts a la BD y debe ser ejecutado por transacciones?
Buenas! Pues hay varias estrategias que puedes seguir, si la transaccion la manejas desde el mismo repositorio, no tendrias problema ya que estarias en la capa que toca y ahi puedes hacer uso de las transacciones de esa pieza de la infra.
En el caso de que necesitaras crear una transaccion en la capa de aplicacion entre varios repositorios, una comun es la de crear una clase transaccion que luego se pase a los repositorios, sin embargo aunque esta es simple creo que no es la mejor. Me he estado documentando mas al respecto a esto y el problema que introduce es que dejas saber a tu logica de aplicacion temas de mas bajo nivel como son las transaciones lo cual no es muy deseable.
En estos casos igual lo mejor es manejar todo el tema de las transacciones a nivel de middleware http o del que llame al caso de uso, lo que podria hacer es por ejemplo guardar que va a comenzar una transaccion en un async local storage, y luego todos los repositorios podrian acceder aqui para usar esta transaccion, una vez hemos acabado todo pues ya le indicariamos de hacer el commit.
Lo bueno que tiene esta ultima solucion es que no estariamos acoplando cosas de infrastructura como puede ser las transacciones de la base de datos a la logica de dominio
Hola Albert, una pregunta... Las conexiones a las diferentes BBDD (p.ej. MySQL, Microsoft SQL), utilizadas por las diferentes infraestructuras de las entidades del proyecto, ¿Dónde las deberíamos de definir para no romper la arquitectura hexagonal? ¿En un directorio "shared" o similar dentro de la carpeta "src"? En el tuto utilizas un "mock", en formato JSON, específico para cada entidad, pero supongo que en la implementación real, dicho "mock" se obtendrá a partir de la correspondiente conexión a BBDD, con lo que solo se necesitará importar dicha conexión, en sustitución del entity-database.json (ej. user-database.json). ¿Podrías aclararme esto que planteo?, pues no lo tengo del todo claro. ¡Saludos y mil gracias!
Buenas! Pues va a depender mucho del caso, si tienes distintas piezas de infraestructura que necesitan algo común entre ellas, podrías crearlo en una carpeta shared dentro de infra como comentas, de esa manera puedes reutilizar esas utilidades que necesites en todas ellas si. De esa manera no estarías rompiendo la arquitectura hexagonal ya que la infra si puede usar piezas que estén en la infra, aunque sean cosas compartidas.
Al final quedaria algo asi:
- src
- users
- application
- domain
- user-repository.ts
- infrastructure
- user-repository
- mock-user-repository.ts
- postgresql-user-repository.ts
- mongo-user-repository.ts
- shared
- // aqui puedes tener tus archivos shared
Incluso si quieres, puedes directamente quitar la carpeta shared y tener todos los ficheros ahi, ya como quieras, va a depender sobretodo de cuantos ficheros y cuan complejo sea lo que quieres hacer.
Espero que te sirva, un saludo!
Seria genial que crees un proyecto rest api con los principios SOLID, patrón de diseño, orm con detalle-maesteo y clean code junto a jwt passport o librerías que se usan hoy en día tipo app de mini ecommerce o algo por el estilo q se pueda implementar todo eso igualmente gracias maestro!!!
Pinta que estas buscando un cursillo mas completo, por ahora me estaba centrando mas en ir haciendo videos sueltos donde ver distintos patrones, frameworks... pero si que estaria bien tener un curso mas completo donde se aplique todo esto ya de manera conjunta, tomo nota :)
@@AlbertHernandez Genial, gracias por la consideración, seria interesante que vayas construyendo un proyecto tipo así mas adelante, ayudarías a muchos!!!
Que buen video, me queda una duda!
Si mi fuente de datos es otra API, puedo definirla como repository tambien o que patron usaria en ese caso? services?
Buenas! Pues no hay una respuesta para todos los casos, va a depender mucho de esa fuente de datos, pero si, podrías abstraer esa API en un Repository
Hola! Muy buen video, te agradezco :))
Aprovecho para preguntar, que IDE usas?
Gracias :)
Pues estoy utilizando el IDE de IntelliJ Idea hehe, creo que crearé un video donde hable de este IDE y porque lo prefiero a vs-code, ya sois varios los que me habéis preguntado sobre esto 😁
@@AlbertHernandez Es que se ve mas minimalista y sencillo. Muchas gracias, un saludo!
Si hehe, lo tengo muy minimalista lo que es el IDE, si ves en verdad como es IntelliJ Idea flipas con todo lo que viene integrado que es muy caótico pero estuve investigando como quitar todo lo que no necesitaba para así simplificar y dejar lo mas importante
Hola Albert, muy bueno tu vídeo, muchas gracias. También estaba revisando tu template, está muy interesante, quería consultarte si tienes algún vídeo de análisis de tu template y como lo fuiste construyendo y las razones, ahora con eslint 9 es funcional? Si no tienes el vídeo sobre el template, te dejo como inquietud ya que sería muy aportante e interesante.
Muy buenas!
Pues no tengo un video donde muestre como construí el template ya que al final sería muy extenso por todo lo que incorpora, así que lo que hice fue hacer videos pequeños de distintos temas que luego fui incorporando en el template, por ejemplo:
- El template esta dockerizado -> Hay un video donde muestro como dockerizar un servicio
- Hay pipelines con github actions -> Hay un video que se habla de como construir estas pipelines
- Tiene configuracion de husky, conventional commits, eslint --> Hay un video que hablo donde todo esto
Como te comento esta hecho así porque sino facilmente nos podriamos ir a un video de más de 5 horas sin exagerar 😅
También hay cosas en los templates que tengo que traer ya que aún no me ha dado tiempo, por lo que si ves algo que te puede interesar y aun no haya hecho video, comentamelo y así lo intento priorizar
Un saludo!
@@AlbertHernandez Muchas gracias Albert, y sigue adelante, tu vídeos son muy buenos.
@@AlbertHernandez hola, el vídeo que se me ocurre y que sería interesante para la comunidad es: package-lock file, qué es, lo debemos subir a github, razones, pros y contras. Siempre tengo la duda.
Buenas! Venga me lo apunto para traerlo próximamente, gracias por la sugerencia ^^
Hola, Que editor de código usas?
Actualmente estoy usando IntelliJ Idea
Una duda Albert : Si tuviera una segunda ruta para la entidad usuario, ¿sería conveniente crear otro fichero como controller para esa nueva ruta, verdad? Es decir, tener un único controller + useCase por ruta.
Buenísimo el video!
¡Buenas! Pues... como siempre, depende. A mí, sí me suele gustar más hacerlo así como indicas. De la misma manera que suelo tener un archivo por caso de uso, me gusta tener un archivo por controlador para ese caso de uso, pero otras personas igual no y prefieren tener algo más grande como un UserController donde pongan ahí todo. Supongo que esto va más a gusto personal y decisión de equipo.
Lo que mas te recomendaría es que pruebes ambas versiones y luego decidas cual te gusta mas, puede ser incluso que dependiendo del proyecto elijas una u otra y estaría bien
@@AlbertHernandez Buenísimo! gracias por tu respuesta y por compartir tan valiosos conocimientos!
Hola, ¿tendrás un ejemplo de código mas grande en donde se use el patrón Repository y la arquitectura hexagonal?
Hola! Si claro, te paso un enlace a otro proyecto mas grande, aunque video de este no tengo, dale un vistazo y si tienes dudas o algo me dices:
github.com/AlbertHernandez/system-status
Y si tuviera más metodos como: createUser(), findUserByEmail(), deleteUser() como sería?? se agregaria nuevos ficheros .ts para cada metodo por separado?
Si hablamos de repositorios, no veo problema en tener los métodos en el mismo archivo, por ejemplo:
```ts
interface UserRepository {
create(user: User): Promise,
findByEmail(userEmail: string): Promise,
deleteById(id: string): Promise,
...
}
```
Pero si hablamos de casos de uso, prefiero tenerlos en archivos separados ya que se enfocan en diferentes acciones y requisitos. Si quieres profundizar más en esto, te recomiendo que veas el video sobre arquitectura hexagonal (czcams.com/video/nfaq_UKunsE/video.html), un saludo!
Si tuvieramos algo como DTOs, en que directorio de arquitectura hexagonal deberia ir?
Buenas! Pues si son DTOs que comunican a la capa de infra con la de aplicacion, irian en la parte de la aplicacion, si son DTOs que comunican a la capa de dominio con cualquiera de las otras, iria en la de dominio, de esa manera nos aseguramos de que siempre cumplamos la regla de dependencia
Saludos, tengo una pregunta como seria la estructura cuando un domian se utilizan en varias infranstructura y applicaciones
Buenas! El domain puede ser usado tanto en infrastructura como en application, no habría ningún problema y la estructura seria la misma, un saludo!
@@AlbertHernandez Gracias
Hay algo que no entiendo. Por cada metodo en la interface UserRepository, genero un caso de uso. Hasta aca ok. Pero en el ejemplo no entiendo el controlador. El controlador recibe en el constructor el UserByIdFinder, y luego dentro del run() ejecuta este caso de uso. Y si quiero agregar otro metodo en la interface con su caso de uso, este controlador esta limitado a un caso de uso en el ejemplo del video. Por lo que veo en el ejemplo, necesitaria un nuevo controlador por cada caso de uso?, no seria mucho?. No es mejor un controlador con metodos que represente cada caso de uso?
Buenas! La parte del controlador depende mucho, eso ya es mas a nivel de gusto del equipo, a mi me suele gustar tener un único controlador por caso de uso para que así no tenga un controlador gigante que haga mucha lógica, pero lo dicho, va a depender mucho de la aplicación y del equipo. Hace tiempo hice un video donde explico porque a mi me gusta este enfoque, te lo paso a continuación por si quieres darle un vistazo: czcams.com/video/sxnUWWa5gPQ/video.html
@@AlbertHernandez Excelente muchas gracias!
Ese que estas usando es Fleet de Jetbrains como ide?
No, por ahora Fleet no va muy fino y estoy usando IntelliJ Idea
@@AlbertHernandez entiendo gracias , es queme gustó el como se ven tus carpetas y todo por eso preguntaba , pagas una suscripcion ? y de casualidad seguiras subiendo videos ? estan muy buenos !
Si, es modelo de subscripcion, asi que toca pagar eso es lo malo, y si como te comentaba en el otro comentario la idea es seguir dandole caña :)
@@AlbertHernandez dale compa , gracias