The Intermediate Developer Trap

Поділитися
Вставка
  • Опубліковано 12 вер 2024
  • All it takes is one book about SOLID to radically transform the way you write code. Often, it's a transformation for the better. ...But not always. Let's chat about what I call the intermediate trap, or the tendency to turn a small handful of lines into a web of confusion. In this Larabit, we'll reverse-engineer our code for the better.
    Watch thousands of videos, track your progress, and participate in a massive Laravel community at Laracasts.com.
    Laracasts: laracasts.com
    Laracasts Twitter: / laracasts
    Jeffrey Way Twitter: / jeffrey_way

КОМЕНТАРІ • 102

  • @Laracastsofficial
    @Laracastsofficial  26 днів тому +2

    Watch thousands of videos on laracasts.com

  • @roberttudor_
    @roberttudor_ Місяць тому +24

    As a solo developer, I tried to stock to all the canonical practices, but soon realized that I'm overcomplicating my life simply because "this is the way". And the more events, the more listeners and more complicated the structure would be. I had days when I was navigating mindlessly through controller->event->listeners->actions/services.... until I found my own way, and now I'm refactoring events and listeners into actions and life is beautiful again.

  • @JiahuaCui-h8t
    @JiahuaCui-h8t Місяць тому +26

    This sparked a discussion within our team. One of the argument to this approach is that in a larger project, each listener often has many more than the 3 lines of code shown in this example and grouping all listeners logic together will result in a very bloated Action. More importantly, the code in the action is synchronous procedure meaning if one of them failed then the remaining won't execute whereas in the event and listener approach, you can simply make a directory and group the listeners together by event.

    • @2gbeh
      @2gbeh Місяць тому

      True

    • @perdanjam279
      @perdanjam279 Місяць тому +1

      Could catch exceptions to help with that.
      Could also argue that in many cases, you would want transactions and rollbacks if one thing fails, so having it in one file in that case is clearer.
      Your points are valid, but the main thing is that there are always arguments to both sides.

    • @joerushton886
      @joerushton886 Місяць тому +5

      You can and should split out actions into multiple actions, once an action starts to experience that "bloat" or when you find you need to re-use a subset of an actions logic in another action. You still retain the benefit, in this example, of being able to see all the side effects of marking a best reply, because you are invoking the logic explicitly from the MarkBestReply action.

    • @Pekz00r
      @Pekz00r 19 днів тому

      @@joerushton886 Yes, that is what I do as well, There is nothing wrong with calling another action inside your action.

    • @ward7576
      @ward7576 5 днів тому

      Yea, I don't really get it either. Even more so when you don't use auto-discovery for event listeners, you can simply do array key-value mapping in EventServiceProvider, making it plain and simple as to what happens on certain event. It's not much work and provides more visibility to side-effects.

  •  Місяць тому +12

    First of all, the videos are looking amazing!
    I agree with you on that example, but I wanted to add to the conversation (which I find very interesting): I think two of the most important things when it comes to event-driven functionality are 1) the failure model and 2) coupling.
    First, I think that if you can't justify doing something (e.g doing something because of SOLID, or because a book said so) yourself, this is problem itself.
    More often than not you have relatively complex processes - IIRC, on Modular Laravel I use e-commerce as an example: checking out a cart isn't just processing a payment and creating a record on orders: there is updating inventory and shipment to begin with, but more complex systems might also deal with warehouses, reaching out to distributors, shipping from different warehouses, cashback systems, etc., and in these situations the isolation/failure and decoupling model provided by events makes a lot of sense.
    By having each process independent from one another it's easier to deal with coupling between subsystems, handling non-catastrophic failures or gracefully fail, fault containment, observability, etc.
    Events also map closely to business requirements - they often go "when X happens, do Z", and events are a perfect narrative factor for that. By inspecting the commands and events of an application you can get a very nice overview of its capabilities.
    All in all, I agree with you - when we reach that intermediate level, it's easy to want to apply all the fancy techniques and patterns. Indirection always comes with a cost, so when implementing something, I think a fair question is: can we justify *why* we want to implement it in such a way, and can we describe the benefits and downsides of that?

  • @webpulseify
    @webpulseify 5 днів тому +1

    I am going to follow this approach. Thank you for these great insights! Keep it up; we love your content, Jeff!

  • @TimGavin
    @TimGavin Місяць тому +18

    Read a blog post by Freek a couple years ago about this; adopted it and never looked back. This is the way.

  • @zerthur
    @zerthur Місяць тому +2

    This idea of having a sort of "entry point class" that provides an overview of a given functionality, where you can easily see the flow based on the functions defined, is very clever. Coz in just one file, you get to see how everything is pieced together. Then, every other file after it, regardless if it's a mountain of code, we already have a pretty good idea of the path we're trying to navigate.

  • @victoronwe906
    @victoronwe906 Місяць тому +1

    I always break the rules, I often focus on how readable, and maintainable the codes are. You simply nailed it

  • @JordanHumbertodeSouza
    @JordanHumbertodeSouza Місяць тому +8

    This is such a great video. So much can be learned when you're not so SOLID minded and more like a "gut feeling" guy.

  • @bambamboole1
    @bambamboole1 Місяць тому +4

    100 with you. events are for comunication over boundaries like websockets / message bus / modules

  • @HkanAktas
    @HkanAktas Місяць тому +3

    I like code simplicity as much as the next guy. But it's another intermediate dev trap to think that our job as software developers is to implement the happy path and be done with it. The code _will_ face issues. The developer has to think about and write code for handling errors and doing them in a user friendly way (doesn't just mean showing a nice error message), keeping data integrity both by guarding against obvious problems and by thinking about recovery paths.
    If the app is anything but a simple todo or another learner's app, the code will get considerably more complex than this.
    This is *not* a jab at the video, but simply a reminder to everyone that what you see in the video is not the full story.

  • @znat5
    @znat5 27 днів тому +1

    More content like this please, Jeff😊

  • @khessamahmed7117
    @khessamahmed7117 4 дні тому

    after that amazing course of laravel we want another course about vuejs3 in laravel and livewire pls and thank you Laracasts for everything

  • @bbbbburton
    @bbbbburton Місяць тому +3

    I'd suggest putting all 3 side effects in queued jobs. The API consumer (user in most cases) doesn't directly care about any of those 3 side effects. The thing they are doing is marking a reply as "best." The other things can be eventually consistent, by means of queue.

    • @adeonabule1517
      @adeonabule1517 Місяць тому

      Depends on the importance of the side effects, for some use cases this might not be efficient

    • @princeani3929
      @princeani3929 Місяць тому

      I agree especially with scalability. But to his point, this lets you know what actions are part of the process. You can choose to queue instead of run the actions. But you still get one source of truth.

    • @MarkSnape
      @MarkSnape Місяць тому

      Depends on whether the order of side effects is important. Your notification might need the result of adding the experience for instance. You can still use the action in a queued job.

  • @mohamadnasir6437
    @mohamadnasir6437 Місяць тому +1

    I follow your video since codeigniter 2..thank you for your guidances

  • @netsudro
    @netsudro Місяць тому

    This really helps me refactor a messy project that is hard to understand every time I come back to it to make small changes or fix bugs. Even though I am the only person who build it, it still makes my brain hurt.

  • @techfuture-code-tv
    @techfuture-code-tv Місяць тому

    This is awesome. Thank you sir. I learned this simplicity

  • @popforall
    @popforall Місяць тому

    You have just solved my team's issues
    Thanks for making coding fun!

  • @Flankymanga
    @Flankymanga 29 днів тому +1

    Actions seems to be a similar to concept or service classes. You extract the advanced logic grouped arround the same topic out of the controller to a dedicated class.

  • @shaikhfoysal4426
    @shaikhfoysal4426 Місяць тому

    Great. I will do that to my project. This will help a lot. Thanks.

  • @ahmad-murery
    @ahmad-murery Місяць тому +1

    I use event listeners when the action to be taken is optional or when I need to trigger external functionality that is not directly affecting my app workflow usually in some kind of general utility classes
    Thanks Jeff!

  • @JT-mr3db
    @JT-mr3db Місяць тому +1

    I tend to return '$this' from these side effect type methods so I can chain them. It reads better IMO, and saves some characters and a few semicolons.

  • @enjibby
    @enjibby Місяць тому

    This is fundamentally a very similar principle to state pattern, transactions, or even activity log. I prefer to use Job as a base class in Laravel for these classes so they can be dispatched (synchronously or asynchronously) and I normally try to include a validation step (to ensure that e.g. the reply instance is in a valid state to be marked as best) but the benefits of this structure are obvious in hindsight. Audit logging of the execution of Action classes are also much more user friendly rather than the standard practice of audit logging database update statements.

  • @natenatters
    @natenatters 23 дні тому

    Great quality on your videos as always :D
    But I disagree 😅 This breaks on larger projects.
    On a larger projct, you need to mange this yourself:
    * Set the $reply->status('becoming-best')
    * Chain those 3 as jobs
    * Have a 4th job to "complete" the action and set the status as $reply->status('best')

  • @yasseralhassan4188
    @yasseralhassan4188 Місяць тому +2

    Absolutely logical

  • @steenrabol2378
    @steenrabol2378 Місяць тому

    One thing to remember is that time spent in an action is time a user is waiting

  • @AbderrahmanFodili
    @AbderrahmanFodili Місяць тому

    you were right, this pissed me off 😅
    i do use actions but for repeated actions only , and i use the event service provider to link events to listeners in order to not forget what tirgers what.

  • @shabxs
    @shabxs Місяць тому

    Thanks for the insights...

  • @ajyankee93
    @ajyankee93 Місяць тому +1

    I was watching the beginning of this video and thinking... "This seems like the 'right' way to do this with all the listeners, but in practice it can be so confusing and hard to follow" and then you said basically the same thing. This is how I would do it. And to be honest, I might even just leave it in the controller occasionally, depending on the size of the project and how many side effects of the action.

  • @brunoggdev6305
    @brunoggdev6305 Місяць тому

    Simply logical. Good stuff

  • @dr.adam.nielsen
    @dr.adam.nielsen Місяць тому

    I really enjoy these personal opinion-based videos-thanks for sharing, Jeff! Does that mean you don’t typically use events/listeners for your own code within your Laravel apps (other then as a package API)? If you do use them, I'd love to see an example where the event/listener approach is more maintainable for you compared to placing code in services or actions. I'm also curious if that means you're not a big fan of the techniques proposed in the "Modular Laravel" course from Laracasts.

  • @Jara47M
    @Jara47M 23 дні тому

    Hey! What editor or IDE he is using in the video? I like the clean design.

  • @farazsalehi9034
    @farazsalehi9034 Місяць тому

    yeah .. if readability is our priority this approach is the best. Still, if you think those actions will use in other places in the application, event listeners are a better approach, in my opinion, whoever uses laravel to create applications he/she must know about the framework feature.

  • @TLJAFAR
    @TLJAFAR Місяць тому

    It's a good one I'm using laravel action package this kind of thing.

  • @techietoons
    @techietoons Місяць тому

    I like this approach.

  • @joebashour
    @joebashour Місяць тому

    Such a great insight!

  • @kenjohnsiosan9707
    @kenjohnsiosan9707 22 дні тому

    Hi Jeff, is it a good practice to reuse listener as opposed to grouping it as it is shown when refactored? thanks

  • @MarkSnape
    @MarkSnape Місяць тому

    I've switched between both approaches. I like listeners for events that are triggered by an external resource, which is similar to your package example. Actions work better where the sequence is important. In your original code, if you wanted to notify the user that their XP had increased to nnnnn then its important that the increments XP code is executed first. In Laravel 11, the ability to order the listeners has been lost in favour of auto-discovery which probably requires juggling class names to set the order - fragile !!!

  • @ticorj
    @ticorj 17 днів тому

    So using a Service Class approach could the action class lead to a set of rules that is not present on the service?

  • @ericsan1561
    @ericsan1561 Місяць тому

    You still need an event listener to do an action after the async task is done. Example i have to log or update a status after the notification sent. If the notification failed to send i need to know.

  • @lassestube
    @lassestube 27 днів тому

    While i agree about the code organization etc. primary actions shouldn’t be put in listeners. But as soon as you have side effects for processing on the queue, or using cqrs you do need to use some sort of queuable events. So this is still within the intermediate trap in my opinion, since all you have done is extract from the controller into an action. No db transaction used, no knowing about failure etc. I was hoping for a more advanced level solution to see how do you make that step up…. I think this needs follow up with more gradual complexity.

  • @yadindominguez1027
    @yadindominguez1027 8 днів тому

    Hello, just one question since you do this, what stops you from putting it in the controller, wouldn't it be the same?

  • @MatteoPresot
    @MatteoPresot Місяць тому

    I follow pretty much the same approach (move from initial listeners to actions/jobs/pipelines). However my epiphany was driven by implementing transactions and dealing with race conditions rather than thinking about how it would look a year from now 😅

  • @pranithNP
    @pranithNP Місяць тому

    What is this theme and font name that you are using?

  • @xristosgr567
    @xristosgr567 Місяць тому +1

    I really like this way of coding, it's simple and elegant, but what if you need some kind of response from the action or truck any failures on the way?

    • @blessdarah1256
      @blessdarah1256 Місяць тому

      You can use an event or queue if you must trigger so many other things.

    • @EnriqueMunoz-no1fq
      @EnriqueMunoz-no1fq Місяць тому

      Was going to ask the same thing

    • @MarkSnape
      @MarkSnape Місяць тому

      throw an exception in the action and use try-catch in the controller if you expect there could be errors.

  • @techietoons
    @techietoons Місяць тому

    Please post some more such trap videos.

  • @louisevirtudazo2822
    @louisevirtudazo2822 Місяць тому

    Isn't it good practice to run these sides as queue? Where you could easily do using listeners.

  • @phpannotated
    @phpannotated Місяць тому

    I love this!

  • @SaiyanJin85
    @SaiyanJin85 Місяць тому

    I would like your opinion on event sourcing, it kinda enforce us to use the first approach. I don't mean on a microservices separated app. Thanks

  • @hiajayy
    @hiajayy Місяць тому

    I follow the same approach.

  • @GeorgeDrakakis78
    @GeorgeDrakakis78 Місяць тому

    this is the way indeed :)

  • @cookiebinary
    @cookiebinary Місяць тому +2

    I have been using Laravel since version 3. I'm still using this pattern, I never liked the listener and events.

  • @ReinhardtCagara
    @ReinhardtCagara Місяць тому

    What would you consider non-primary actions / sideeffects?

  • @brunoggdev6305
    @brunoggdev6305 Місяць тому

    Hey, where can I get that cool wallpaper?

  • @sarfrazqasim
    @sarfrazqasim Місяць тому

    Does action class also good for utility functions? which can be accessible in every controller of the app? Still learning Laravel so please dont get mad on my noob question.

  • @shofada
    @shofada Місяць тому

    This makes sense.

  • @mmelimahlobo7656
    @mmelimahlobo7656 8 днів тому

    Hie Jefrey what advice can you give to someone who wants to get a Job as a junior PHP developer I mean there is too much to learn when starting out.😢

  • @adelkazem8645
    @adelkazem8645 Місяць тому

    Awesome thanks

  • @PaphosLife
    @PaphosLife Місяць тому +1

    Most websites are massively over-engineered.

  • @mediopalodev
    @mediopalodev Місяць тому

    100% agreed!

  • @alexanderpotapov2774
    @alexanderpotapov2774 Місяць тому

    I'm curious how do you move code to just created function? :)

  • @obadaalzidi6452
    @obadaalzidi6452 Місяць тому

    Nice refactor, but in my opinion we are not concidering reusability here !
    I'm pretty sure that there are alot of other places where we need to record some kind of activity or increasing the user's experience by different values,
    So why not exracting those to their seperate actions also ?

  • @phusedallas3536
    @phusedallas3536 27 днів тому

    My colleagues always tell me to say "dump and die" instead of "die and dump". I always wondered why I say that..just realised while watching this video that Jeffery Way spoiled me lol

  • @seeking7662
    @seeking7662 Місяць тому

    Hi, what do you use for local development ? I need multiple version of PHP so I am using docker, but doing testing etc is bit harder.

  • @2gbeh
    @2gbeh Місяць тому

    I'd do the same except i'd move everything within the action handle method back to the invokeable controller. That's technically why they exist.

  • @homamal289
    @homamal289 Місяць тому

    Hi jeffrey whats your thought about repo and sercives pattern im using uaualy Actions + Services in my code and Thanks alot Mr best teacher in the world

  • @mayoryorma5048
    @mayoryorma5048 Місяць тому

    That’s the way, I would just add database transaction.

  • @IbrahimIsmail98
    @IbrahimIsmail98 Місяць тому

    Laravel beyond CRUD

  • @mihaes7172
    @mihaes7172 Місяць тому

    For some time now, I noticed you `whistle in the church` of so called best practices that choke the solving problem process. I'm in php since v4, I agree with you & I would like to see a more practical Laravel than 'smart'.

  • @kingstalker
    @kingstalker 23 дні тому

    ty nice vid , how did you do that 15:16 - 15:20

    • @Laracastsofficial
      @Laracastsofficial  15 днів тому

      On VS code, it's Command + Shift + L
      On PhpStorm Ctrl+Alt+Shift+J ( www.jetbrains.com/guide/java/tips/find-next-word/ )

    • @kingstalker
      @kingstalker 15 днів тому

      @@Laracastsofficial ty

  • @lukmannakib7497
    @lukmannakib7497 Місяць тому

    I need that wallpaper

  • @SergeiPakhomov0
    @SergeiPakhomov0 Місяць тому

    Why not to make one listener with all these private functions?

  • @joshhh4642
    @joshhh4642 Місяць тому

    To simplify, dont over architect things / complicate things. Just make your code more intuitive/straightforward as much as possible.

  • @Aalii6
    @Aalii6 Місяць тому

    👍👍

  • @prepped8551
    @prepped8551 Місяць тому

    In defo a controller stuffer….

  • @TeHzoAr
    @TeHzoAr Місяць тому

    Nobody is doing that

  • @facephonesy
    @facephonesy Місяць тому

    You guys always over engineer things, you are thinking like when someone comes back to the code he will be a complete idiot. And the solution you propose is to over complicate things so when this idiot comes he has to check 10 more files to figure out what the code does. I feel the weird urge to be over organized doesn't make any sense. But thank you for the video

    • @jeffreyway520
      @jeffreyway520 29 днів тому

      Did you watch the full video??

    • @facephonesy
      @facephonesy 29 днів тому

      @@jeffreyway520 no i didn't. When he started to sayvwe have to create a new file for each one of them. I stoped the video.

    • @Laracastsofficial
      @Laracastsofficial  29 днів тому

      Yes, but this is the exact issue Jeffrey is discussing in the video, he is doing that to show the issue in the first place, you need to watch full video :)

    • @facephonesy
      @facephonesy 27 днів тому

      @@Laracastsofficial lol, I judged really fast. Apologies. He is saying exactly what I am saying