Guide on how to implement Clean Architecture in Next.js

แชร์
ฝัง
  • เผยแพร่เมื่อ 3 พ.ย. 2024

ความคิดเห็น • 142

  • @nikolovlazar
    @nikolovlazar  2 หลายเดือนก่อน +4

    Update: I refactored the app and now we're running on any runtime, including Vercel's Edge (hello middleware)! Check out my latest video to see the refactoring: th-cam.com/video/Yliaah4oiZY/w-d-xo.html
    This is the definitive guide on how to implement Clean Architecture in Next.js. It's almost an hour, so grab a coffee or tea and dive in. Hope you enjoy this video! Some of you pointed out that using Sentry directly is breaking CA’s rules, and you’re right! I had to take a shortcut there, but I forgot to mention that in the video. If you have any questions, don't hesitate to reach out to me in the comments, or in my Discord server: creatures.sh.
    🔗 Links from the video:
    👉 GitHub Repo: github.com/nikolovlazar/nextjs-clean-architecture
    👉 Demo: next-clean-arch.vercel.app/
    👉 Clean Architecture article: blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
    👉 My interpretation diagram: app.eraser.io/workspace/fAyjQlkBiC7AoAoYoPnw?origin=share
    👉 Configure Inversify in Next.js video: th-cam.com/video/2NVYG5VDmwQ/w-d-xo.html
    👉 Test case naming guide: www.epicweb.dev/talks/how-to-write-better-test-names

  • @carlpahuyo4482
    @carlpahuyo4482 2 หลายเดือนก่อน +7

    I'm a self-taught developer so I only really get these types of knowledge from tutorials or just follow how these techs' documentations do it. I've watched and read different tutorials about good and clean architecture to follow but most of them are just really opinionated and not really explain why. But THIS particular video really got me. It's clean and each type of file makes sense and does different isolated work. I think I'll implement this architecture in my next projects. I mostly use Supabase and I'm excited as to how I will implement this architecture with that tech :D Thank you so much for this video!

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน +4

      I'm glad you fount this useful! Here's an other project of mine that implements CA with Supabase: github.com/nikolovlazar/bife

  • @smeadkraftz
    @smeadkraftz หลายเดือนก่อน

    Bro, you saved my life! I'm struggled importing the reflect-metadata on NextJS all the time to implement dependency injection!

  •  17 วันที่ผ่านมา

    This is pure gold. Thank you so much!

  • @drosi1994
    @drosi1994 2 หลายเดือนก่อน

    One of the best and insightful videos that I have seen the last years in YT. Thank you man!

  • @0xmetalogica
    @0xmetalogica หลายเดือนก่อน

    Fantastic video. I’ve been searching for a pattern to help me apply domain driven design properly to next JS projects and this example is the inspiration I needed. So comprehensive!

  • @harshitsahu8704
    @harshitsahu8704 หลายเดือนก่อน

    Thanks for creating it. It blows my mind. Need such content more on your channel.

  • @BladesGamings
    @BladesGamings หลายเดือนก่อน +1

    this is what quality content look like. thanks!

    • @nikolovlazar
      @nikolovlazar  หลายเดือนก่อน +1

      Thank you! And thank you for becoming a member! 💖

  • @KirilGerovski
    @KirilGerovski หลายเดือนก่อน

    Изключително добре направено! Браво!

  • @steventabango4790
    @steventabango4790 2 หลายเดือนก่อน

    Thank you so much for this great video. I always heard about Clean Architecture and watched several videos, but I never truly understood it until now. After watching some videos that left me confused and even fearful of applying it, this one finally gave me a clear understanding to move forward. I love that it was demonstrated using Next.js because that's exactly what I'm learning.

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน

      Thank you! I'm glad that you found it useful!

  • @dunkpolice
    @dunkpolice 2 หลายเดือนก่อน +2

    По случайност ти намерих канала, точно преди седмичният stand up 😂 Keep up the quality content 👌

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน +1

      Thank you! Благодаря ви!

  • @kanogl
    @kanogl 2 หลายเดือนก่อน

    @nikolovlazar Amazing stuff... The bit on the presenter was a great thing to learn, security, ui friendlyness and performance from not shipping extra packages.

  • @werix_4776
    @werix_4776 2 หลายเดือนก่อน +5

    Having this clean architecture as boilerplate to start a new complex project, I think would be cool, with different packages like supabase etc

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน +2

      Definitely! I think the GitHub repo is simple enough that it potentially could be used as a boilerplate, but feel free to fork it and swap out the libraries you need.

  • @KingDebo-rm7gj
    @KingDebo-rm7gj 2 หลายเดือนก่อน

    Haven't watched the entire video yet but the diagram alone was SUPER helpful and needed, Thanks a lot. Wish I could give you multiple likes

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน

      Thanks a lot! Happy that you found it useful!

  • @didholipyan8227
    @didholipyan8227 2 หลายเดือนก่อน +11

    My brain is currently stop working🤯

  • @Evyweb
    @Evyweb 2 หลายเดือนก่อน +1

    Not finished the video yet but as someone using clean architecture and tdd most of the time I can say that you did it pretty well. You can also enforce these principles for new developers or for bigger teams with ts-arch.

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน +1

      Thank you! Someone on my live streams told me about ts-arch. I checked it out, but haven't used it yet.

  • @diegosk8bt
    @diegosk8bt หลายเดือนก่อน

    Awesome bro, we absolutely need more of this excellent content. subscribed for more of this! thank you!

  • @camchn3355
    @camchn3355 2 หลายเดือนก่อน

    Best Clean Architecture video ever, thank you 🙏🏻

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน

      Glad you liked it!

  • @cesar-brandon
    @cesar-brandon 2 หลายเดือนก่อน +1

    Great video, I needed it ✨, I would like to see it in a more committed project but it still helped me, I still don't understand clean architecture so I will come back again

  • @kiddienoob
    @kiddienoob 2 หลายเดือนก่อน

    Very clear explanations!
    A possible improvement:
    Instead of binding a test setup to the concrete implementation of your application's signInUseCase, you could create a wrapper for your tests like ```function authenticatedUser(): {sessionId: string} { return { sessionId: signInUseCase({user, password}).sessionId }```. That way if the meaning of what authenticated user actually is ever changes, you don't have to change it in all the test files.
    It's a bit abstract with a simple example like this, but it will make more sense when you are testing behavior that depends on a certain application state. For example: If you want to test that deleted todos cannot be updated, then you will have to first create one, then delete it, and only then you can test for what you are actually interested in. Here you could have a deletedTodo() function that takes care of that setup

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน

      Good point! Thanks!

  • @shaked1233
    @shaked1233 2 หลายเดือนก่อน

    This is a very detailed video about clean arch, very well made. thanks

  • @vonghesjonovan
    @vonghesjonovan 2 หลายเดือนก่อน

    WOW!! So much bonus in that video!! Thank you so much!!! You made life easy for JS dev! 🔥🔥🔥

  • @sidaliassoul408
    @sidaliassoul408 2 หลายเดือนก่อน

    Thanks for the great video lazar.
    Watched more than 5 streams then didn't have time to watch more glade that you dropped this one.

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน +1

      This video will save you HOURS 😂 thanks!

  • @sasquatch_devs
    @sasquatch_devs หลายเดือนก่อน +2

    Would love to see this applied for a React + Vite SPA application!

    • @nikolovlazar
      @nikolovlazar  หลายเดือนก่อน

      That would be an interesting topic. CA on the client side!

  • @PixeLabor
    @PixeLabor 26 วันที่ผ่านมา +1

    very good viedo. thanks! :)

  • @IkraamDev
    @IkraamDev 2 หลายเดือนก่อน

    Great video. Extra respect for Neovim.

  • @alwaisy
    @alwaisy หลายเดือนก่อน

    Mind blowing. I wish I was a backend engineer I had hope to learn Architecruee stuff. I'm thankful I am Frontend Engineer, I should be disgrateful but Backend is OP.

  • @MuhamadAzizPrasetyo
    @MuhamadAzizPrasetyo 2 หลายเดือนก่อน

    Very good stuff! Thank you

  • @lutzzdias
    @lutzzdias 28 วันที่ผ่านมา

    Great video and explanation of each layer. I have one next.js specific question: should we prioritize server actions over route handlers? Are there any benefits to be gained from choosing one over the other?

    • @nikolovlazar
      @nikolovlazar  27 วันที่ผ่านมา

      Thanks! Server Actions are faster to develop because they’re functions. Route Handlers are exposing an endpoint that can be triggered by any client, not just Next.js. I think when using Actions the app performs a rerender automatically to update the UI with the new data, so there’s that. If you’re building a Next.js app that will remain just a Next.js app (and not have other clients use your API) you can stick with actions. Even if you need to change in the future, you’ll just cut the try catch block that invoked the controller and refactor handling the return and exceptions.

  • @matyascsoti4400
    @matyascsoti4400 หลายเดือนก่อน +2

    QQ about input validation: Architecture wise ( looking good on a graph ), validation looks better in the controllers so both incoming ( from server ) and outgoing ( to server ) data is validated in the same place. But implementation wise validating your input data makes much more sense in the context of the form. Is the validation and form linked only by the form libraries, so its just getting used to it, or the proximity of the input to the form warrants its. Like you can validate the data without ever leaving the context of the form and calling a controller, vs calling the controller and returning the validation error in your onSubmit function and setting the errors explicitly from there ( as most form libs handle this explicitly ) ?

    • @nikolovlazar
      @nikolovlazar  หลายเดือนก่อน +1

      Good question! In my other project, I reuse the same Zod schema on the client-side to validate the form as well. Validating input is a *must* on the server-side, because it's easy to jump around the frontend and send data directly to the server without passing the validation mechanism. Validation on the frontend is good UX, validation on the backend is good security practice.

    • @matyascsoti4400
      @matyascsoti4400 หลายเดือนก่อน

      @@nikolovlazar Thank you for your time to response, I think I wasn't explicit enough with my question, the question was not 'to validate or not' but 'where to validate'. You validate your outgoing data inside your repository and sending back the validation error to the UI to handle it, most form libraries handle the validation in the context of the form and if the data is not valid it will never reach the repository ( repository call will never be reached in the onSubmit since the validation does not pass ). So my question is which one should be preferred as doing the latter feels good because of the proximity of the input to the form, the former makes sense in an 'architectural way' as the controller is the "gateguard" of the data 'correctness' of your application.

    • @nikolovlazar
      @nikolovlazar  หลายเดือนก่อน

      No I think I understood you. You should validate on both sides. As I mentioned, form validation is good UX, but you have to validate in the controller as well for security reasons. Validating in both places is a good practice. With Zod, you can even share the same validation schema. Here's how I do that in my other project:
      - Form: github.com/nikolovlazar/bife/blob/main/app/app/collections/create-collection.tsx#L38
      - Controller: github.com/nikolovlazar/bife/blob/main/src/interface-adapters/controllers/create-collection.controller.ts#L6

    • @matyascsoti4400
      @matyascsoti4400 หลายเดือนก่อน

      @@nikolovlazar lookin at the code indeed you are double validating your outgoing data, thanks for sharing, but now then I have to ask isn't double validating redundant? ( or it is in this case but there might be a situation when something can actually happen between your action and the controller, the current example is very straightforward you pass the validated data directly into your controller, where you validate it again, i am interpreting correctly )

    • @nikolovlazar
      @nikolovlazar  หลายเดือนก่อน +1

      Double validation is not redundant. The backend and the frontend are two separate things that can live independently from each other, so each part handles validation for separate reasons. You could refactor it down the line and split it, or build a new client (ex. mobile app, AI client, whatever that uses the backend you already have) so you’ll have to refactor the server actions into api handlers. Even now, you can’t risk not validating the data on the backend, let alone in a scenario like that. Consider the backend and the frontend as two separate parts and validate data at both places. There won’t be any significant performance overheads as well.

  • @BrandonNoad
    @BrandonNoad หลายเดือนก่อน

    Great video. Quick question. Isn't the `getInjection` helper function an example of the service locator anti-pattern that InversifyJS warns against?

    • @nikolovlazar
      @nikolovlazar  หลายเดือนก่อน +1

      I haven't read a lot on it being an anti-pattern, but thanks for bringing it to my attention. Looks like you're right. If you want to avoid it, you should either write everything as classes and do property injection, or export resolved services from within the DI and not the container itself. I haven't seen any issues of using the "getInjection" method in my app yet since implementing it, but I'll have this in mind. Thanks again!

  • @baptiste.famchon
    @baptiste.famchon 2 หลายเดือนก่อน

    Thanks for this video @nikolovlazar !
    In your codebase (25:20) you talk about user authorization in use-case. So if we want to get more infos on user (free / paid on your example), we should retrieve the user repository and get user in this same use-case right ?

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน +1

      Correct! You can use the repository to retrieve the user object, and then you can use a service that implements the authorization check logic, so you can test that logic individually later.

  • @NaniwaRocky
    @NaniwaRocky หลายเดือนก่อน

    Great content, thank you! I have a question regarding the sentry config included in your project. I have never used sentry, suppose i would like to do a code along with your tutorial, will a free sentry account be sufficient to apply the sentry features or is a paid subscription with them required ? Thanks!

    • @nikolovlazar
      @nikolovlazar  หลายเดือนก่อน +1

      Glad you like the content! Yep, the free Sentry account supports all SDK features, except the Insights modules (business+) and Dashboards (team+), but you'll be able to get alerts, capture exceptions, measure performance and use traces for debugging without issues on the free plan.

  • @foxwell_1108
    @foxwell_1108 หลายเดือนก่อน

    Thank you for the incredible amount of high quality information that you have packed into a hour long video! Very much appreciated 🙏 One question I would really like your opinion on and that is the choice for a DI library in TypeScript. You chose InversifyJS but there are others like TypeDI and tsyringe. All of them are not actively maintained for the past couple of years. Do you see any risks of implementing DI with these libraries, as is it part of the core of your codebase?

    • @nikolovlazar
      @nikolovlazar  หลายเดือนก่อน

      Glad you liked it! And that's a good question! I think the only thing forcing the libraries to push updates (once they achieved what they want to achieve) is the language itself. As TypeScript / JavaScript evolves and introduces breaking changes, they most likely would need to push an update. That doesn't happen as often, so that's why you don't see any activity on these repositories for an extended period of time. On the other hand, just like any other library dependency, there is always a risk of deprecation and refactoring.

  • @soaacademy
    @soaacademy 2 หลายเดือนก่อน

    Thanks for the great work!

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน

      Glad you like it!

  • @yourr_dude
    @yourr_dude 2 หลายเดือนก่อน

    Maan thank you for your work. Greetings from Ukraine

  • @zakir.nuriiev
    @zakir.nuriiev 2 หลายเดือนก่อน

    Thank you for the cool video! It was very interesting!

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน

      Glad you liked it!

  • @wrivera626
    @wrivera626 หลายเดือนก่อน

    Thank you Lazar for your big efforts in this topic, your are using Lucia in this example, I'm struggling to do something similar with Next Auth, is there a good article/video about this approach?

    • @nikolovlazar
      @nikolovlazar  หลายเดือนก่อน

      Thank you! Not sure if I’ve seen anything like that. Hop into creatures.sh and we can figure it out!

  • @НикитаВолошин-ь1ь
    @НикитаВолошин-ь1ь 2 หลายเดือนก่อน

    Like, awesome! Please, more videos on architecture topic

  • @SushantJadhav-b5h
    @SushantJadhav-b5h 2 หลายเดือนก่อน

    Awesome video, could you please extend cover below things in second part?
    In Clean Architecture
    Where/how will handle global state like zustand or redux toolkit?
    Where/how will handle constants and enums?
    Where/how will handle language translation (for errors)?
    Where/how will use
    Where/how to map the types (separate types for Infra other layer)

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน

      Thank you! These are good points. I'll definitely cover some of these in future.

  • @user-lt4tr2rm8q
    @user-lt4tr2rm8q หลายเดือนก่อน +1

    Hey, this is super interesting... however what I'm struggling with, is that in this approach frontend and backend is completely separated, which I get is the idea of this paradigm, however in practice the lines are not always clear. For example lets say I build a tax return form: I might want all the business logic structured as presented to nicely handle a submitted form on the server side but still show the user an estimated value while they are filling the form which doesn't need (and I think shouldn't) be calculated in the backend for every changed value. Same with validation: If I'm already using zod and frontend libraries, I don't have to deal with validation and displaying errors... this is taken care of in the frontend. I still need to perform the same checks on the backend but ideally a non-malicious user only submits validated data once everything is in order. A model might be fine to import from the frontend and use as my validation scheme but the calculator example its not quite clear to me how I would deal with such a scenario and where I would put the code/helper methods which perform the calculations in the end in order to maintain separation and allow reusability without risking to import code that is only meant for the server side (which might e.g. leak secrets) on the client side.
    Any help/ideas would be greatly apreciated!

    • @nikolovlazar
      @nikolovlazar  หลายเดือนก่อน

      Is the calculator logic plain javascript that can be used both on the frontend and backend? If it's something that you don't expect to change a lot, it's fine if there are two implementations of it (comments should note that as well). If not, see if you can isolate it in a shared function and how that would look like. You need to maintain testability, so try to follow the operation flow (contoller > use case(s) / service(s) > repository(ies)). You can have a use case that invokes the shared calculate function and use its output. That should be perfectly fine.

  • @viniciustomiokuboyama3706
    @viniciustomiokuboyama3706 2 หลายเดือนก่อน

    This is gold.

  • @PeterStJ
    @PeterStJ หลายเดือนก่อน +2

    Okay, nice explanation, looks great, only one thing bothers me, and it is a big big thing for me.. an __all__ layers you have the sentry calls.. on ALL layers. How does this fit into the clean architecture, clean maintainable code etc. I don't see it, sorry. Otherwise great explanation.

    • @nikolovlazar
      @nikolovlazar  หลายเดือนก่อน +1

      Thanks! I had to take a shortcut there. It's not CA-approved 😁 We should put that away in its own service and call the service instead.

  • @ericmaina7922
    @ericmaina7922 2 หลายเดือนก่อน

    Very educative video. Create a larger project implementing the same

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน +1

      Thanks! It’s not a seriously large project, but I have it implemented here as well: github.com/nikolovlazar/bife

  • @PixeLabor
    @PixeLabor 10 วันที่ผ่านมา

    did you ever try to implement this in a bigger project? i recently tried it and it was so much over head creating all the dtos. and especially if you have nested entities it is just a pain doing this. and for one small change i need to touch a lot of files. this seems more like a academic philosphising about architecture. maybe if you have a big team. but not as a solo dev.

    • @nikolovlazar
      @nikolovlazar  7 วันที่ผ่านมา

      I have a couple of shorts on my channel where I address this, but in short - yes. If you’re a solo dev and don’t care about testing or growing the team or the codebase, then you won’t see too much value in CA.

  • @Frim85
    @Frim85 2 หลายเดือนก่อน

    Love the vid, thnx!

  • @galenus_0
    @galenus_0 2 หลายเดือนก่อน

    What nvim theme are you using?
    Also, great video 🫡

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน +1

      Thanks! It’s cyberdream with a custom background. Check it out here: My Neovim Dev Workflow
      th-cam.com/video/G7-qUMKSH_Y/w-d-xo.html

  • @AndriusLau
    @AndriusLau 2 หลายเดือนก่อน +1

    basically a standard Rest API (repository, service, controller) plus UI :)

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน +1

      Pretty much 😁 with some additional rules on top

  • @issiagaconde
    @issiagaconde หลายเดือนก่อน

    Thank you very much for the enormous effort you put into making this tutorial. I really like how you configure vscode. Can you share it with us? THANKS

    • @nikolovlazar
      @nikolovlazar  หลายเดือนก่อน

      Thank you! This is not vscode, but neovim. Here’s my config video: th-cam.com/video/G7-qUMKSH_Y/w-d-xo.htmlsi=kq2lTPyJaQqa9JTl

  • @YevheniiViazovskyi
    @YevheniiViazovskyi 2 หลายเดือนก่อน

    Pleasant to watch bringing some order to usual Nextjs chaos. Really good ideas and realisation here.
    One thing i don't get fully is multiple controllers. Why is there createTodoController/getTodosForUserController/toggleTodoController (which acts like 3 different controllers) and not single TodoController with create/getTodosForUser/toggle methods?

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน

      Happy that you found it useful! In regards to the controller, you're talking about a class versus functions. Since we're in JavaScript, functions feel easier to work with so I went with functions. Classes need to be instantiated before you use them so it represents an extra step. If we utilized constructor injection for the DI, then we would've had to use a class.

    • @YevheniiViazovskyi
      @YevheniiViazovskyi 2 หลายเดือนก่อน

      @@nikolovlazar Thanks for the answer. Probably i'm just brain damaged by other MVC frameworks, hard to see a controller that is not an object 😅. The easiest way to avoid instantiation would be to have maybe index.js in the controller directory that reexports all functions in single object or single file that has only default export of an object containing all the methods.
      In theory static classes can also help to avoid instantiation but still allow extension. Some repeated logic (error handling for example) could live on the base Controller class. This will also allow to have decorators for methods, for example "Authenticatable" that could check sessionId and get the user.
      Thanks again for the content.

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน

      Oh that's a good point!

  • @Deus-lo-Vuilt
    @Deus-lo-Vuilt 2 หลายเดือนก่อน

    Wow , thanks ❤

  • @jekku123
    @jekku123 2 หลายเดือนก่อน

    Great video to explain clean arch! Im wondering that how to deal with stuff like internationalization etc that need middleware?

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน

      Thank you! I'm working on a different DI approach that would work in other runtimes and I'll most likely publish a separate video on it, so stick around for that one! Right now you'd have to patch things in the middleware function.

  • @iced2916
    @iced2916 2 หลายเดือนก่อน +1

    Using something like zsa would remove the need for input validation in the controller layer as it would be handled inside the action itself, maybe the session could also be validated inside the action and then the service would be called. This wouldn't be 100% compliant to clean arch because then the validation would belong in the framework layer and not in the interface adapters but It would be simpler to have the server action act as a controller

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน +2

      True! The issue with keeping that logic arises when you try to unit test that logic. Server actions should be plain functions in the test environment (haven’t checked though), but even if they are you’d have to handle ZSA-specific errors in your unit tests. If you ever need to refactor ZSA you’ll be in for a ride 😂

    • @iced2916
      @iced2916 2 หลายเดือนก่อน

      ​@@nikolovlazar Hey, I have another question, since drizzle is being used and we define all our database models there, in the entities/models the user definition is repeated and everytime we change something in the drizzle schema we need to go into the entites/models folder and change the zod schemas in order to match. I saw a library called drizzle-zod that allows zod schema generation from a drizzle table definition, maybe with this library we could define and export all the models and then in the application/entities/models we could have a class for the model and receive the it's model type in the constructor(coming from drizzle folder) and we could have access to all it's fields while also being able to define methods depending on the application's business logic. This way infrastructure concerns will be mixed up with application logic but I think this could work, what do you think about this approach?

    • @nikolovlazar
      @nikolovlazar  หลายเดือนก่อน

      I did use drizzle-zod briefly in this project, not sure why I didn't even mention it. Models should contain a certain amount of logic in them as well, which are basically the zod schemas. The approach you described is definitely valid, but limited to models defining their own methods, and to potentially simpler projects. In a lot of cases you would have operations that modify multiple models (tables) so that's why the isolation happens between the "business logic" and the "business rules". Logic is use cases and controllers. Rules are the models. Bigger projects would have more model classes that depend on each other, so you're very likely to run into all sorts of issues like dependency issues. Not to mention, once you start bringing in other model classes in one model class, you're starting to create a "god class" (a.k.a. "god object"), which is a code smell and something you should avoid.

  • @hug0er96
    @hug0er96 2 หลายเดือนก่อน

    Awesome work, thank you for the video lazar. I have a question. How would you handle Prisma transactions in this code structure?

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน

      Thank you! Everything Prisma related would be boxed in a Repository.

    • @hug0er96
      @hug0er96 2 หลายเดือนก่อน +1

      @@nikolovlazar Thanks for the early response. But what if the Prisma transaction needs to occur across two different entities? For example: updating the user table to deduct credits and simultaneously decreasing the stock of a product purchased with credits. I understand that products will have their own repository, and users will have their own repository. However, implementing this logic in a useCase without introducing Prisma in application layer will not allow for a Prisma transaction, and each query will run separately, causing us to lose atomicity in the operation.

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน

      ⁠​​⁠that would be two different use cases. Use cases are single operations. Updating a field in the users table is one use case. Deducing credits in a different table is another. You’ll have a controller that “orchestrates” those two use cases based on the input, user, etc… the controller will invoke them.

    • @FTheohu
      @FTheohu 2 หลายเดือนก่อน

      @@nikolovlazar I am not the person you are replying to, but I assume you mean that the controller will combine those two use cases in a transaction and thus make the transaction atomic?

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน

      @@FTheohuoooh I see now. If that’s the case then I guess it has to be part of a repository. If those two or more db operations happen every single time, it does make sense to put them in one transaction in a repository and invoke that.
      Another approach I could think of is splitting the query building from executing. This is a wild idea and I’m just thinking out loud, but what if the repositories just build your query(ies), and then you pass it off to a service that executes all of them in a single database transaction? I’m not sure of what side effects can that have on testing, but it’s something to think about 😁

  • @kanogl
    @kanogl 2 หลายเดือนก่อน

    Hey mate, question on your errors entities you have a type called ErrorOptions but its not being defined anywhere in the code and i dont see it as imported from an external package, where does that come from?
    Thanks!

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน +1

      The "ErrorOptions" interface is built-in the language actually, just like the "Error" one.

  • @mhdyousuf3392
    @mhdyousuf3392 2 หลายเดือนก่อน

    At last, Thank you

  • @DaveMacpherson
    @DaveMacpherson 2 หลายเดือนก่อน

    Are the objects returned by your presenters essentially DTO's?

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน

      Yep! Since you don't want to return entitie types, you create a UI-friendly object that contains the controller's results, which could be multiple entities as well. That's basically a DTO.

  • @seifmahdy4846
    @seifmahdy4846 2 หลายเดือนก่อน

    Great video!! I wonder how this can apply to TRPC specifically the T3 stack.

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน

      Thanks! Everything would fall into the Frameworks & Drivers layer. TRPC's queries (equivalent to Next.js Server Actions in a way) would be defined in the "app" directory alongside everything Next.js related, and they will invoke controllers. Exactly the same as the server actions I presented in this video.

    • @seifmahdy4846
      @seifmahdy4846 2 หลายเดือนก่อน

      @@nikolovlazar Thanks, this is really helpful!!

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน

      @@seifmahdy4846 You're welcome! If you have more questions don't hesitate to ask. I'm always around in my Discord server creatures.sh.

  • @devyb-cc
    @devyb-cc 2 หลายเดือนก่อน +2

    zod for entities should be the norm hahah

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน +2

      Right? 😂

    • @devyb-cc
      @devyb-cc 2 หลายเดือนก่อน +1

      @@nikolovlazar ofc!!

  • @nekotajni394
    @nekotajni394 2 หลายเดือนก่อน

    Hey friend, I have an application with a large userbase, over 300k. I find that Sentry captures so many random JS errors that are unhandled and I have no idea why/what they do. It's like missing 'a' in some random js bundle, or scrollEvent, or some extension stuff. It consumes so many of my error metrics and it does nothing for me, what do you suggest I do in this case? I only want to capture relevant errors.

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน +1

      Hey! You should check out the Filtering doc: docs.sentry.io/platforms/javascript/guides/nextjs/configuration/filtering/
      You can try the "thirdPartyErrorFilterIntegration" method. That way you "fingerprint" your codebase's bundles and only errors that originate from those bundles get reported, otherwise they get ignored. This + the "ignoreErrors" regex can significantly reduce issues noise. Let me know if this works for you!

  • @saveriomazza7781
    @saveriomazza7781 หลายเดือนก่อน

    Top!

  • @PauloRodrigues-d9j
    @PauloRodrigues-d9j 2 หลายเดือนก่อน

    Which browser are you using?

  • @starrynight72
    @starrynight72 16 ชั่วโมงที่ผ่านมา

    It seems way too angular-like which I don't really accept when I work on nextjs this kind of framework based on react...

  • @zomars
    @zomars หลายเดือนก่อน

    Can we hire you?

  • @patolorde
    @patolorde 2 หลายเดือนก่อน

    Awesom

  • @doloreslaflipoflopo2746
    @doloreslaflipoflopo2746 หลายเดือนก่อน

    what theme is this in nvim?

    • @nikolovlazar
      @nikolovlazar  หลายเดือนก่อน

      This is Cyberdream! github.com/nikolovlazar/dotfiles. I also have a video on my setup: th-cam.com/video/G7-qUMKSH_Y/w-d-xo.html

  • @yogithesymbian
    @yogithesymbian 2 หลายเดือนก่อน

    why we need sqllite instead mysql

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน

      I picked SQLite just to make the demo project simpler to run locally, no other reason.

    • @yogithesymbian
      @yogithesymbian 2 หลายเดือนก่อน

      @@nikolovlazar So if we use MySQL and hit an API, would it be challenging technically? Or do you have any suggestions?

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน

      Your codebase won't need to change too much (aside from your repository, which is the reason why you want to put away that implementation detail). If you want to use MySQL instead of SQLite, you'd need to start a mysql server alongside your app, and the easiest way to do that is to use Docker Compose. There's plenty of resources on how to get started with Docker and Docker Compose.

  • @김인욱-u5q
    @김인욱-u5q 2 หลายเดือนก่อน

    That's really cool, but it's also complicated :(

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน

      Step by step! It's important to understand the reasons why each layer exists, and why you want to split your app's codebase in layers.

    • @김인욱-u5q
      @김인욱-u5q 2 หลายเดือนก่อน

      @@nikolovlazar I watched this video without skipping anything. It helped me understand the structure, but the folder structure is too complicated and there are many libraries that I am using for the first time, so it is difficult to create a project from scratch and follow along. Still, I will try to follow along little by little.

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน +1

      @@김인욱-u5q A good rule of thumb is this:
      - if the library you use lives around the "consumer" part of the app (next.js, api handlers etc...) it belongs in the Frameworks layer.
      - if the library you use supplements the app's core logic (a database, auth, email service, APIs that your app uses...), it lives in the Infrastructure layer.
      It'll be either in Frameworks or Infra. There's no other place where you put third-party libraries.

    • @김인욱-u5q
      @김인욱-u5q 2 หลายเดือนก่อน

      @@nikolovlazar I'll keep that in mind. Thank you

    • @nikolovlazar
      @nikolovlazar  2 หลายเดือนก่อน

      @@김인욱-u5q Oh you meant there are many libraries in this video that you're using for the first time. Sorry I misunderstood your comment. Don't hesitate to ask me specific questions about the setup and libraries. If you want more real-time help, feel free to join my Discord server and we can discuss in there: creatures.sh.

  • @MerthanMerter
    @MerthanMerter 2 หลายเดือนก่อน

    this is nesxt js

  • @maxmurr
    @maxmurr 2 หลายเดือนก่อน

    First!

  • @ramirodondero7856
    @ramirodondero7856 2 หลายเดือนก่อน

    Genius!!!!!