The Right way to write Nest.js & Typescript clean-code - SOLID

Sdílet
Vložit
  • čas přidán 31. 05. 2024
  • You should follow these 5 SOLID React Principles to write readable, maintainable and testable code. In this tutorial, we'll explore these 5 Principles and how to apply them in your Nest.js & Typescript code. The principles are inspired by clean-code books and architectures.
    ⭐ Timestamps ⭐
    00:00 Intro
    01:18 SRP - Single Responsibility Principle
    04:51 OCP - Open-Closed Principle
    08:20 LSP - Liskov Substitution Principle
    11:59 ISP - Interface Segregation Principle
    14:24 DIP - Dependency Inversion Principle
    ⚡️ S.O.L.I.D Principles implementation in Nest.js ✨
    github.com/ipenywis/nestjs-solid
    📕S.O.L.I.D blogs to get a better grasp on the principles
    / the-s-o-l-i-d-principl...
    -- Special Links
    ✨ Join Figma for Free and start designing now!
    psxid.figma.com/69wr7zzb1mxm
    👉 ✨ Join Figma For Professionals And Start Designing with your Team ✨
    psxid.figma.com/ucwkx28d18fo-...
    -- Watch More Videos
    🧭 Build Login/Register API Server w/ Authentication | JWT Express AUTH using Passport.JS and Sequelize
    • Build Login/Register A...
    🧭 Turn Design into React Code | From prototype to Full website in no time
    • Turn Design into React...
    🧭 Watch Tutorial on Designing the website on Figma
    • I Design a onecolor We...
    🧭 Watch Create a Modern React Login/Register Form with smooth Animations
    • Create a Modern React ...
    🧭 Debug React Apps Like a Pro | Master Debugging from Zero to Hero with Chrome DevTools
    • Debug React Apps Like ...
    🧭 Master React Like Pro w/ Redux, Typescript, and GraphQL | Beginner to Advanced in React
    • Master React Like Pro ...
    🧭 Learn Redux For Beginners | React Redux from Zero To Hero to build a real-world app
    • Debug React Apps Like ...
    🧭 Introduction to GraphQL with Apollo and React
    • Introduction to GraphQ...
    🐦 Follow me on Twitter: / ipenywis
    💻 Github Profile: github.com/ipenywis
    Made with 💗 by Coderone

Komentáře • 83

  • @cheng6630
    @cheng6630 Před 8 měsíci +41

    I think logic is not handled on the controller, the controller only forwards requests from view to service and receives response and forwards to view.

    • @justfromnowhere
      @justfromnowhere Před 4 měsíci

      I thought it was a bit abstract but he ended up saying it should be handled in another layer, rather than the service (this layer can communicate between different services and will be called from the controller). But he gave an example from the controller so you feel it's not quite right. But I understand what he thinks.

    • @TMANandMAISON991
      @TMANandMAISON991 Před 3 měsíci +4

      Bruh all this stuff is just opinions. There is no correct answer

    • @petertran141
      @petertran141 Před měsícem

      @@justfromnowhere well then what is the correct answer for this? if you have more class to just serve a small function, your project will become very very big.

  • @ivanvelinov4630
    @ivanvelinov4630 Před 10 měsíci +37

    Loved the explanations and everything. Quick thing to add and probably a lot of users do it differently. Using your service as the "Business layer" doesn't mean you write bad code or not clean code. My humble opinion is that, "controllers" should take care only for input and output of the application, nothing else. Service is actually the business part and the clean code should be there. You have to think also about the architecture and controllers should not do business logic. Ofc repository,dao or whatever for the data layer.
    Keep with the great stuff :)

    • @mundoprogramado3106
      @mundoprogramado3106 Před 9 měsíci +1

      I was two days ago trying to pass the repository linked with the interface in usecase. Find out at 10:43 that it needs @Inject

    • @tuanpham6162
      @tuanpham6162 Před 3 měsíci +1

      Yes, I agree, too. I also think it is fine if we let service handle its business logic instead of laying it on controller. I don't want to split my controllers just because it is too long to handle like he recommends for the SRP :(

    • @SebastianKravetz
      @SebastianKravetz Před 2 měsíci

      yes! this is very important from an architecture's perspective, let's say for example ports and adapters architecture, where you should encourage such decoupling that even you can switch the controller implementation (from example moving from a rest controller to a kakfa topic subscriber) and the business logic should stay the same.

  • @permanar_
    @permanar_ Před 11 měsíci +12

    I really love this NestJS series. Please keep going!!

  • @TheBeastDispenser
    @TheBeastDispenser Před 8 měsíci +9

    Thank you for including good and bad examples! By far the best way for me to learn

  • @reidyoung298
    @reidyoung298 Před 4 měsíci

    Fantastic way of teaching these concepts and one I have hoped to see for years now: real world issues people create constantly, why they are mistakenly created, how to avoid them, and how best practices (SOLID, etc.) guide us to avoid making such mistakes along the way to creating more composable code. Thank you for the video!

  • @CharlesDv
    @CharlesDv Před 10 měsíci +9

    Excelente video. Just a comment, at 4:09 ordersService should only receive a DTO, how the service implements the solution is not concern to the controller.

  • @abolfazljalildoost766
    @abolfazljalildoost766 Před 5 měsíci +2

    that was facinating. please provide more nestjs videos

  • @miguecast
    @miguecast Před 5 měsíci

    It's the first time I see an exemple of Record type in real world, thank you!

  • @MichelVersianiDev
    @MichelVersianiDev Před 11 měsíci

    Amazing as always, thanks for the tips!

  • @MAVrikrrr
    @MAVrikrrr Před 11 měsíci +7

    Don't get the implements against extends part. "extends" is not bad thing and it still covers Liskov principle. If you want to force one (or several) of methods to be implemented in children, you just make the base class abstract and make those methods abstract as well (just like you did in open-close example). "implements" is good when you combine multiple interfaces in one class implementation. But "extends" allows you exactly *extend* something (not re-implement from scratch). Good overview though.

  • @georgy2763
    @georgy2763 Před 11 měsíci +6

    I am confused with example on GitHub for open closed principle. Should we call registerPaymentGateway in controller? Will this object (paymentGateway) always have only 1 payment method at a time? I thought paymentGateways (the one in paymentService) should have all our relative payments options inside the object, so that when we call processPayment it checks payment method against the one we have. I am just confused the way it’s organised in your GitHub repo) I didn’t even see where you are calling processPayment Method in your code

  • @user-wf4mo3mx2k
    @user-wf4mo3mx2k Před 11 měsíci +1

    nice bro please keep updating us with your awesome knowledge about backend specially nest js

  • @juneroyd.quinimon495
    @juneroyd.quinimon495 Před 11 měsíci

    Amazing tutorial, thank you!

  • @yohanneskindu8794
    @yohanneskindu8794 Před 10 měsíci +2

    Dude you are very amazing developer, I was just looking around to improve my coding structure and make it more readable, reusable and maintainable, This is the video anyone who wants to look first before writing nest js code. Thank you!!

  • @mohamedsba4185
    @mohamedsba4185 Před 4 měsíci +1

    very helpful. thank you and keep doing great stuff

  • @SabujArefin
    @SabujArefin Před 19 dny

    Great explanation. Thanks

  • @danielosariemen3824
    @danielosariemen3824 Před 4 měsíci

    Great content, really learnt alot from this video

  • @eminaliyev4953
    @eminaliyev4953 Před 11 měsíci

    Very helpful!

  • @geebsayshi
    @geebsayshi Před 8 měsíci +1

    In OCP you can extend if the subclass is the same as the base class but with an added functionality. e.g A cock is a bird that can crow. Cock class can extend the bird class which has the fly functionality and then implement its own crow functionality.

  • @belkocik
    @belkocik Před 2 měsíci

    Would love to see a good course of Nest.js with these clean-code - SOLID principles.

  • @beodan9219
    @beodan9219 Před 9 měsíci

    great video
    thank for your sharing

  • @EstebanHelgueroCardiff
    @EstebanHelgueroCardiff Před 10 měsíci

    Really good video!

  • @ubonginyang1889
    @ubonginyang1889 Před 8 měsíci +2

    Nice video man. However, I prefer to use extend, and then make the method in the base class an abstract method as well.

  • @codeliam
    @codeliam Před 8 měsíci

    Very awesome. Thx

  • @The14Some1
    @The14Some1 Před 7 měsíci +6

    hey @CoderOne, don't you think that on 4:00 your controller does too much of logic? I've been taught, that controllers should only transfer the data from view to services and back.
    What would you do if there will be addtitional logic between creating order and sending it? For example, let's imagine you must create orders without restrictions, but send action should be applied only after some filtering. would you add this logic right in your controller between two service calls?

    • @vinimaciel
      @vinimaciel Před 5 měsíci

      It has no logic operations, just calling functions, if you need to check another thing, maybe process data or validate it, you'll have another service

    • @tuanpham6162
      @tuanpham6162 Před 3 měsíci

      @@vinimaciel I don't think so, because sometimes, we also need to check the other service call is fine or have errors to process next steps .
      Do you have ideas when we face this case ?

  • @RdozeTV
    @RdozeTV Před 6 měsíci +1

    In single responsibility principle you could also use events to decouple

  • @user-sy5cj9wz5c
    @user-sy5cj9wz5c Před 11 měsíci

    great tips keep going

  • @andyheld3136
    @andyheld3136 Před 4 měsíci

    Thanks for that video.
    How do you recommend injecting all implementations of services in one array with the dependency inversion principle? In your Scenario you have 2 Service implementations and let's say you want to inject List services. One method is: Module factory methods or the use Value in the module file. But it becomes more complicated when the service implementations are in different modules - i do not want to import all the modules, which implement them, just for defining an array of services. What i do currently is a service provider module with an abstract ServiceProvider class with a registerService(service: T), and a getServices():T[] method from a ServiceProviderModule. It holds a list of instances of type T. All Implementations of these service providers define their abstract type, in your case it would be class StorageServiceProvider extends ServiceProvider. The service implementations just inject the StorageServiceProvider and in the constructor they just register themself with storageServiceProvider.registerService(this). A consumer service, which needs all storage implementations injects the StorageServiceProvider and calls getServices() method and can iterate over them.
    I am coming from the java spring world and there it is already handled implicitly. Is there a in house solution in nest for handling list of services with the dependency inversion principle? :) Thx

  • @s1dev
    @s1dev Před 7 měsíci

    soo good, would you make more videos on nestjs design concepts

  • @neallahiany2213
    @neallahiany2213 Před 3 měsíci

    Hello, what's theme were you using on the video ? Thank you

  • @ODAIR_SCTY_OFC
    @ODAIR_SCTY_OFC Před 9 měsíci +1

    good video, like from brazil.

  • @muhammadsalmanagustian75
    @muhammadsalmanagustian75 Před 9 měsíci

    amazing, thanks for the tips. +1 subs

  • @-_-unseen-_-
    @-_-unseen-_- Před 3 měsíci

    Single responsibility means that your controller is not responsible for sending emails. Controllers are only responsible for handling the http request / response and invoking the business logic layer. In frameworks like nestJs that includes all the validation and transformation of the endpoint input as well. If you remove the presentation layer from your solution can it still orchestrate the use case?

  • @DenNivAs
    @DenNivAs Před 10 měsíci +8

    The controller can be replaced with another method because it should not contain business rules. Controllers are responsible for handling requests and delegating the processing to other components. By keeping controllers lightweight and decoupled from business logic, it allows for flexibility and easier replacement with alternative methods or technologies.

    • @martonvalentin7386
      @martonvalentin7386 Před 10 měsíci +3

      That's right, but I'm always wondering how and where should I put these wrapper implementations.. How do you use it usually? For example when you have to save something and also sending notification, you should not put both different service calls into the controller (as you mentioned), but how would you call that service that wraps the business logic? I would usually inject my abstract notification service into the service that saves the data, and call the sendNoti method inside the "saving" method

    • @DenNivAs
      @DenNivAs Před 10 měsíci +8

      @@martonvalentin7386 This is a very used solution, mainly by frameworks.
      Another option is to create an event within your service/use case to make this call more decoupled. Then the event of sending the notification will be responsible for sending it, being able to put it in a queue and not depending on the flow of the notification to confirm the creation. Imagine that your notification throws an exception, it would break your creation which is another case, thus breaking the single responsibility principle.

  • @patel5532
    @patel5532 Před měsícem

    Can we structure nest js project similar to Spring boot? I mean separate the files in Controllers, Service, Models etc folders. Is it good idea or practice?

  • @NofaceAndrew
    @NofaceAndrew Před 11 měsíci +1

    Why are you using Abstract class with abstract method Payment Gateway instead of interface in 7:19?

  • @gamingwolf3385
    @gamingwolf3385 Před 11 měsíci

    The last time i want to learn more about this framework , but i didn't get a large community as other frameworks

  • @nhatnguyenhuu7822
    @nhatnguyenhuu7822 Před 6 měsíci

    I have a doubt about the S principle, if do it like this, the code in the controller is quite long, and corresponds to business, somehow it is not good for reusable functionality right? Just kinda view from mine! Anyone can help me on it? Or do we have to make trade-offs?

  • @jonamep
    @jonamep Před 8 měsíci

    I thought a concrete class should only implement interfaces not abstract classes. Why ts allows that ? Inheritance from class to class I normally use extends. If I want to enforce contract I would use implement from class to an interface

  • @TGamer2209
    @TGamer2209 Před 6 měsíci

    very good video =))

  • @-_-unseen-_-
    @-_-unseen-_- Před 3 měsíci

    If your code inside your service method throws an error, does the email still get sent? In your case no but it's because you don't have any error handling not because it's part of the use case. You would have to add some additional business logic to your controller in order to decide if the email should get sent. Oh, and your product manager just asked you to send a certain type of email based on the response from the database when adding a new order. Now you have to add even more business logic to your presentation layer because your business logic layer does not complete the use case. As the use case grows so do your problems given your implementation.

  • @ulrichmbouna4091
    @ulrichmbouna4091 Před měsícem

    How do you Handle Money in such situation?
    In Laravel they use moneyphp

  • @Mak-Henry
    @Mak-Henry Před 11 měsíci

    a genius

  • @carpamon
    @carpamon Před 9 měsíci +1

    Doesn't StorageFetcher breaks LSP?

  • @slahomar1497
    @slahomar1497 Před 7 měsíci

    in 8.17, when you're filling the paymentGateways ?

  • @isi1044
    @isi1044 Před dnem

    talking about giving urself extra work

  • @jo.repossi
    @jo.repossi Před 10 měsíci

    Can you create a nestjs tutorial serie?

  • @-_-unseen-_-
    @-_-unseen-_- Před 3 měsíci

    The Open / Close Principle (Objects or entities should be open for extension but closed for modification.) has nothing to do with DI. The "D" in SOLID is where IOC or DI would come into play. Open / Close is more about coding against a contract rather than a concrete implementation. So in other words, use interfaces and abstract classes.

  • @dksss1
    @dksss1 Před 6 měsíci

    Hey great video, why the storage fecther is an abstract class and not an interface

  • @DanielNistrean
    @DanielNistrean Před 4 měsíci

    What is user can select any of the payment providers ? Your solution doesn't include that.

  • @josephjoey3904
    @josephjoey3904 Před 11 měsíci

    How does this architecture work with state management sayusing context api or redux toolkit?

    • @lardosian
      @lardosian Před 11 měsíci

      This is a backend framework, does not deal with state management

    • @josephjoey3904
      @josephjoey3904 Před 11 měsíci +1

      @@lardosian oh, I read that as Nextjs either way, very informative video

    • @lardosian
      @lardosian Před 11 měsíci

      @@josephjoey3904 Easily done, but lots of videos covering what your after - eg React Query for example..

  • @adiathasan
    @adiathasan Před 11 měsíci

    🚀

  • @davidchavez4054
    @davidchavez4054 Před 9 měsíci +1

    Is there any reason for using abstract classes instead of interfaces?

    • @jamilbenselma1577
      @jamilbenselma1577 Před 7 měsíci

      Very good question but no answer ! too bad.. I would like to get answer, really !

    • @thomass9802
      @thomass9802 Před 7 měsíci +1

      Interfaces do not exist at runtime in Typescript, so it is not possible to resolve dependencies by interfaces (unless you use a String token that has the same name as your interface and use the @inject() decorator in your constructor)

  • @seghirissam2662
    @seghirissam2662 Před 2 měsíci

    please what the theme name you use in vscode ?

    • @CoderOne
      @CoderOne  Před 2 měsíci

      Halcyon! I need to do a video about it soon 😅

  • @sitdownandcode
    @sitdownandcode Před 4 měsíci +3

    "Make no mistake, there is a principle like that. A function should do one, and
    only one, thing. We use that principle when we are refactoring large functions
    into smaller functions; we use it at the lowest levels. But it is not one of the
    SOLID principles-it is not the SRP." page 62 of Clean Architecture by Robert C. Martin

  • @staspanyukov4822
    @staspanyukov4822 Před 6 měsíci

    Unfortunately not many js developer are even noticed about these principles

  • @balasuar
    @balasuar Před 3 měsíci

    Aren't these just basic OOP patterns rebranded for javascript devs?

    • @jongjong2x
      @jongjong2x Před měsícem

      i definitely agree, they're just trying to do java in typescript :D

  • @miguecast
    @miguecast Před 5 měsíci

    If you want to call othe method from another service inside a service and avoid to inject this another service, you just can emmit an event and put this other method listen to it.

  • @surenmatinyan3699
    @surenmatinyan3699 Před 3 měsíci

    The domain logic should not be inside the application layer in your case you show that when you call the email method inside the controller of orders!
    There can be a lot of logic from other modules so what you will do in that case is all the logic will be both of them in controllers and in services that's the antipattern
    That's wrong!

  • @albertlabarentojr1625
    @albertlabarentojr1625 Před měsícem

    Naming a class suffixed with "Service" doesn't make SRP easier, class named as per its responsibility not only enforces the developer to write code in SRP but also for readability, there's no need to name a class called "StorageS3FetcherService" if you can name it as "StorageS3Fetcher"

  • @-_-unseen-_-
    @-_-unseen-_- Před 3 měsíci

    You totally shot yourself in the foot when you decided to add the sendOrderEmail() in the controller. Sending a notification, in this case an email is part of your business use case. Your service class is responsible for orchestrating the use case. Look at it this way. If you remove the API presentation layer (controllers) can your app still orchestrate the use case? In your case no. You can imagine there may be a number of things you could put in place of the API presentation layer like going from REST to GraphQL or a grpc microservice or even a CLI. Your implementation does not scale given your decision to put business logic inside the controller. Your giving bad advice here ( czcams.com/video/vE74gnv4VlY/video.html ). The service class that handles the submitOrder use case should invoke the process of sending an email. If you really want to look like a senior dev then you would suggest dispatching an event once the order is created successfully and allow any number of operations to subscribe to that event one of which may be sending an email.

  • @TheAdnanZaib
    @TheAdnanZaib Před 4 měsíci +2

    This guy is using coding structures that junior developers use till they learn how to properly code. This video is a waste of time in my opinion.

  • @-_-unseen-_-
    @-_-unseen-_- Před 3 měsíci

    czcams.com/video/vE74gnv4VlY/video.html "you can change the pricing strategy without changing any code", but you changed code to use the other strategy! What you need is a factory that will provide you with the desired pricing strategy based on some context or other condition.