"Cruddy by Design" - Adam Wathan - Laracon US 2017

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Forever my bedside video

πŸ‘οΈŽ︎ 7 πŸ‘€οΈŽ︎ u/leandrowf πŸ“…οΈŽ︎ Jan 03 2019 πŸ—«︎ replies

#oldbutgold

πŸ‘οΈŽ︎ 12 πŸ‘€οΈŽ︎ u/crypt0lover πŸ“…οΈŽ︎ Jan 03 2019 πŸ—«︎ replies

This video made my development so much better. After watching this video, I instantly went to refactor my entire Laravel app.

πŸ‘οΈŽ︎ 3 πŸ‘€οΈŽ︎ u/damcclean πŸ“…οΈŽ︎ Jan 04 2019 πŸ—«︎ replies

The old war. RPC(natural entities and natural verbs) vs REST(natural and pseudo-entities and 4-5 standard verbs).

From my point of view, the world is not Cruddy by design.

I just "publish" the podcast. Not create a publish-podcast pseudo-entity.

User "registers" self in some app. Not create.

The car just "moves" somewhere. Not creates a CarMovement pseudo-entity.

Reducing the methods amount in controllers is not a good target for refactoring. If methods are only 3-4 lines and almost never changed, you can have even 20+ methods in one controller. The application code will be better than several controllers with huge methods...

I can easily make only 1 method for each controller. There is a package for that - https://github.com/hivokas/laravel-handlers . It won't automatically make my code much better.

πŸ‘οΈŽ︎ 5 πŸ‘€οΈŽ︎ u/Adelf32 πŸ“…οΈŽ︎ Jan 03 2019 πŸ—«︎ replies
Captions
all right hello everybody welcome to Larrick on 2017 how's everybody enjoying their time in New York so far so my name is Adam Raven and today I'm here to talk to you about making your applications cruddy by design so a few years ago I saw this tweet from DHH where he said a common problem that he sees in rails applications is people not creating enough controllers and that more controllers often eliminates the need for more sophisticated patterns so I saw this I thought to myself yeah you know that's a useful insight I agree with that and that kind of went on my merry way thinking that although I agreed within it sounded like a good idea I was already serve applying this thinking in my own code and it was not really much for me to dig deeper into here right a few years later right around this time Basecamp 3 came out DHH tweeted this these are the rake stats for the Basecamp 3 code base about three months after it came out which kind of details how many of each type of class they have in the application and how many lines of code there are on each one how many methods per class that sort of thing and when I saw this I sort of jumped out of my skin a little bit because they have 206 controllers in this application and not only that if you exclude tests and front-end stuff there's only about 450 classes in the entire app so 206 out of 450 classes were controllers almost half the entire app was controllers so when I saw this I realized pretty quickly you know maybe there was a little bit more to that original tweet than I thought maybe I'm not really applying this the way that I thought I was and maybe there's some more stuff to learn here so for the last year so I've been really kind of exploring this idea deeply trying to figure out ways to use more controllers to simplify my code and today I want to walk through a bunch of different examples to kind of share some of the lessons I've learned and hopefully give you some ideas that you can use to take home with you and apply in your work right away so that's basically it for slides so here's the demo application that we're going to be talking about it's called cast hacker and what cast hacker is it's like a platform for discovering and hosting podcasts specifically for programmers so you can see a bunch of popular programming podcasts you might recognize some here these are all podcasts I subscribe to you should check them out if you're a podcast fan but here you can like dive into a podcasts you can subscribe or unsubscribe to it you can see some recent episodes maybe view all the episodes you know dive into an episode and listen to it or check out the show notes you can even view a list of like all the episodes across all the podcasts on the platform so if you're looking for something new something recent you can check that out here and if you own a podcast well then you can control whether or not it's visible like published or not and you can also head into the settings and change some names and update the cover image that sort of thing okay so let's head over to the code side of things so here's a handful of routes that we're going to be working with as I go through this talk I have the font size is that okay for everybody cool alright so here you can see a bunch of routes that we've got hanging off of the podcast controller so we've got like an index view for listing all the podcasts a view for showing the forum for creating a podcast route that lets you submit that form to save a podcast showing an individual podcast edit form for a podcast submitting that edit form or archiving deleting a podcast and we've got a couple extra ones here like showing all the episodes for a podcast or replacing the cover image for a podcast with a new image allowing people to subscribe to the podcast unsubscribe allowing that owner of the podcasts to publish it or unpublish it and we've got some sort of basic crud actions for the episodes controller as well so before we go any further questions how many people here work on an application or have inherited an application where there are controllers with five or more methods like every single person okay how many people have seen an application where a controller had ten actions almost the same amount of people has anyone seen a controller with 15 actions on it before lots of people still okay perfect so one thing you notice that I should have mentioned we were looking at this stats here the controllers in Basecamp have an average of four methods per controller and I know from talking to Dave and myself that they often have between one and three private helper methods on their controllers - so this is really like maybe two or three actions per controller at best okay so here on the podcast controller we have 13 actions and on the episodes controller we have 6 actions so if we're trying to apply this idea of trying to write more controllers to simplify our code we need some sort of like heuristic or way to decide how to cut this controller up into more controllers right so I'm happy to say that after some careful experimentation and research the easiest way to do that is just to follow one very simple very basic rule I like to call that rule the NWC a rule all right which is never write custom actions on your controllers so what is a custom action it's looking at this list of Reds you can see these first seven are just kind of your standard resource actions right like if we went into the terminal here we went like artisan make controller boot controller resource you can see these are like the seven basic rest or crud actions that you get out-of-the-box right index create store show edit update and destroy and these are what I call standard actions and anything else is a custom action so list episodes is a custom action update cover image is a custom action subscribe unsubscribe publish publish these are all custom actions so in our journey to sort of figure out ways to cut up this controller and create more controllers the easiest way to do that in my experience is to avoid creating these custom actions and figuring out ways to remodel them as basic rest or basic crud actions so to get started what we want to do here is like draw a line in the sand between these first seven actions and then these other six so let's start with the list episodes one first so the way I like to start is by basically evaluating this current action against what our options are what okay so here's our seven basic crud actions right so list episodes which one fits best for listing episodes it's pretty simple one we could all probably agree pretty quickly that it's a public index action right index is used to show a list of some resource and here we're trying to show a list of episodes now it doesn't make sense for us to be the index action on the podcast controller because that's for listing podcasts but you might think okay well obviously what we should do here is use the index action on the episodes controller it's a list of episodes but if you scroll down and tried to do that you'd realize pretty quickly ah crap we already have an index method on the episodes controller has anyone run into this situation before where they want to list all of a resource and a nested resource and have to figure out where to put that stuff yeah so if we're forcing ourselves to just use an index action here we have to come up with some way to do it and one way that I've seen people do it that I think is a bit of an anti-pattern that I want to talk about quickly is trying to piggyback off of the existing index action so say we pulled this up here and instead of having a podcast controller lists episodes action we pointed this route at the episodes controller index action just like this one down here but this one has a parameter and this one doesn't so what I've seen people do is head into this controller have this take an optional ID and then you know you think okay so now all I basically have to do is check you know if there's an ID scope the episodes to a podcast there's a typo there but that's okay and you might think like that's as simple as it needs to be that's all you have to do but let's head over to the podcast controller for a second and look at the list episodes action and copy the body this and paste it over here so we can compare them and see how similar or dissimilar they really are so this is if there's an ID we do this if there's not ID we do this so if there's an ID we look for a podcast not for episodes but we preload the episodes we have this sort of authorization check to make sure that podcast is visible to the current user because it might be unpublished then we return this podcast list episodes template passing through the podcast in this case we're searching just for episodes we happen to be paginating them we're returning in episodes index view and we're passing episodes to it not a podcast so these are actually two totally different code paths so if we try to piggyback off this existing action and point two routes in it what we're doing is we're taking two routes we're funneling those down into a single action and then we're making it the controller's responsibility to sort of reverse-engineer the intent of the user and split that back up into two separate actions when you think about it that way it seems like an obviously stupid thing to do don't do that okay so if we don't want to do that what can we do instead it has to be an index action right we can't put it on the episodes controller so we need a new controller but what do we call this controller well what I like to try and think about is like what is the resource that we're trying to list you might think okay well we're trying to list episodes right but we're not just trying to list all episodes any episodes we're specifically trying to list a podcast episodes so what I do in this situation is I'd create a new resource called podcast episodes that's now we have a podcast episodes controller index action we can go artisan made controller podcast episodes controller head over to that controller with my cold fingers and paste well cut this action out of the podcast controller paste that in the podcast episodes controller called an index action you know and as long as we pull on our imports and stuff we'd be done here and we would have eliminated a custom action on the podcast controller and introduced a new controller to sort of simplify that a little bit there's an interesting side benefit to this as well so if you scroll down here to our episodes controller you can see this sort of two types of routes there's an index one that's kind of scoped to episodes show has also got episodes at the beginning edit and update have episodes at the beginning but creating store are scoped to a podcast because you want to create an episode for podcast right so if we look at the episodes controller you can see that we've got a show action that takes an ID and that's the ID of an episode but the create action also takes an ID but now if you have a podcast not episode that's a little bit confusing right and it's the same with store and then edit and update well now that we have a dedicated podcast episodes controller it's acts sort of as a magnet for these sorts of endpoints that are scoped to a podcast and you pull those out of the episodes controller point them at the podcast episodes controller cut those actions out of here so what's that a store or in create so you can rip those out of here paste those into the podcast episodes controller and now instead of having an episodes controller with six actions we have an episodes controller with four actions and a new podcast episode controller with three of its own actions and now in the podcast episodes controller every ID parameter is always the idea of a podcast instead of the ID of an episode so it's a little bit more consistent so tip number one that I want you to remember if you have a nested resource give it a dedicated controller if you have posts and comments and you want to add a comment to a post don't force yourself to decide okay should that be in the comments controllers that be in the post controller put it in the post comments controller and just be done just follow that convention and don't force yourself to make that decision anymore and you'll end up with more smaller controllers which will make your code kind of feel simpler and sort of make you feel less likely to want to reach for complicated patterns to solve some of these problems because your code or it kind of feels simpler next one I shouldn't have shouldn't close that that's okay now I gotta wait because it takes a while for kena its kind of load here but we'll be fine all right next custom action here let's move this new controller down here the next custom action we got to deal with is updating a cover image so updating cover image is when you head over to like a podcast here and you know we do something like let's make sure this is published so we can see it so we've got a form for editing the details for our podcasts which are kind of the basic columns but then we've got a separate form for updating the cover image so for red of reason the requirements dictated that we want to update the cover image separately from updating the rest of the details so we can go here and like replace full-stack radio with like a pink version of full static radio whatever cool and the way that we're exposing this is through a post request to an update cover image endpoint scope to a podcast pointed that an update cover image action on the podcast controller now if you look at the implementation it's pretty straightforward like update just takes a couple fields validates them and updates the corresponding fields on the podcast right updating a cover image all it does is save a file after doing some validation and update another column on the podcast so if we're trying to evaluate this actioning it's our list of rest actions it's pretty natural to think okay well this is updating right it says update right in the dam method name so this is going to be an update in some way shape or form so again you might be tempted to try and piggyback off of the existing update action and we might just say okay well let's just like save the file in there and we'll just use that one update action and we'll get rid of this custom action we end up with that same problem of taking two discreet user intentions funneling them into one controller and trying to reverse engineer it because it's not as simple as just adding the cover image here we have a title attribute that's acquired right well all of a sudden now it's required if we think they're trying to fill out the top form but it's not required if we think they're only trying to update the cover image things just get way unnecessarily complicated so what are you doing this case cover images it's not like a table right it's like a resource it's not an eloquent model but because we're exposing the ability to edit the cover image separately to the user we have to think about it as its own resource because to the end-user of the application it is its own resource we can let them manipulate it on its own so what I would do in this case is I would create yet another controller I would call it the podcast cover image controller and just give it an update action and then I would even go and change this route instead of being a post request you know and everyone just uses post when they have a custom action because they can't think of anything that really makes sense semantically right we could do a put and said so we're replacing the cover image and we can take the action out of the endpoint let the action live in the HTTP verb and now we're just putting a new cover image in this sort of nested sub resource so we could go ahead and make a new controller call the podcast cover image controller we can go to our podcast controller grab the update cover image action cut this out paste it in here rename it to just a put and then we'd be done okay so we've created another custom control or another new controller and we've eliminated a custom action on the podcast controller sorry I called it put it doesn't matter because we're not gonna run this code it looks like I'm doing live code right it looks like I'm like wow this guy's so awesome at coding on stage but doesn't matter you never run it's okay hope you broken okay so tip number two if you have some sort of property or field that's not a table but you expose the ability to manipulate it independently treat it as its own resource and give it its own controller stupid keno thing all right next one subscribe and unsubscribe things are getting a little bit more interesting now before we had list and update it's easy to map list and update to index um update right it's really natural but now that we're dealing with subscribe subscribe is like a totally different verb so trying to model this in a restful or like crud based way is a little bit more complicated so it's evaluated against our actions here it's not index it's not show creator store and that's possible editor update that's possible destroy and not destroying anything let's say a try and model it as a creator store action the way they like to do this is I try and phrase things to myself sort of like this if I have a user and that user subscribes to a new podcast what do I have now that I didn't have before and if I can make that mental model makes sense then I can model this as a create action so if a user subscribes to a podcast what do I have that I didn't have before I have a subscription to that podcast right so what I might do in this case is create a new controller called a subscriptions controller and give it a store action where we're storing a new subscription and I would go ahead and even change the endpoint right because if we're if we're trying to do this standardized sort of approach it's best if you can keep the endpoints sort of standardized too so normally when you do like a store action it just goes to the top level resource so let's just make a post request to subscriptions so let's go ahead and create this new controller and see what it looks like to port this over okay so we head over the podcast controller and grab the SUBSCRIBE method cut this out and paste it over here there's one difference here which is that we were getting the ID of the podcast to subscribe to as a right parameter before but if we're treating this as a top-level subscriptions resource we're not gonna get that ID coming through so instead we need to accept that as like a request to parameter so change this to store and this ID will actually just become requests podcast ID that's how I would do this right and the implementation is we have a belongs to many relationship between podcasts and users I'm using the attach method to insert a new row into that pivot table right that's kind of how we model subscribing to a podcast cool that one's done let's look at the next one unsubscribe okay well typically you know if if subscribing to a podcast is creating a subscription then unsubscribing would be destroying that subscription right so let's try and see what we get so typically for a destroying action or a delete request you have the resource name and then the idea of what you're trying to delete so we might have something like deletes subscriptions then an ID that appointed our subscriptions controller destroy a method yeah and I know this brat gets backwards again we're not going to run the code but you may look at this and think wait a second idea of what like subscriptions is like a pseudo resource that we've represented in our end points but it's it's not actually a real thing we don't have an ID of a subscription or do we if we head over to sequel Peru here you see I've got this podcast user table which is like the standard naming convention for a boring pivot table and laravel right it's just the name of both resources combined and that's how you kind of map them together it belongs to main relationship and each record here kind of maps a user to a podcast and that's how we know that users subscribe to that podcast well each one of these records has an ID and if you think about it a better name for this table might be subscriptions spelled correctly even now if we have a subscriptions table well then we could head over to our code we could look at our user model we could say that the user belongs to many subscribed podcasts through the subscriptions table now instead of through a default table name and then our podcasts you know has many subscribers or users through that same table as well well too many comments it's all good though alright so now we have a name for a table and now they have a table called subscriptions well maybe we want to go ahead and even create an eloquent model for that table artisan make model subscription and now we have a model that represents that table and now when our subscriptions controller instead of using this pivot table thing well we can just go ahead and create a subscription right we can say subscription creates and just specify the user that we're creating the subscription for and the podcasts and the nice thing about this is that now we actually get a subscription object back that has an ID we can even return the subscription from the send point so you could see the new subscription that you have and now that we have a subscription model that has an identifier it doesn't seem so far-fetched to expose the ability to destroy a subscription by passing in the ID of the subscription that you want to destroy so if we went over to the podcasts controller again here we could grab this unsubscribe method rip it out move that over to the subscriptions controller rename it to destroy and now instead of looking for a podcast through that ID what we might actually do is head over to our user class create a new relationship because now that a user has many podcasts through the subscriptions table the user also has many subscriptions and a podcast also has many subscriptions so you can kind of cut that relationship into two pieces and treat it separately if you want to so here in our user model we could do something like create a has many relationship to subscriptions and then in our subscriptions controller we can say something like off user subscriptions you know find or fail the idea of the one that we want to delete and then instead of like detaching that pivot record or whatever we can be more expressive in our code and say that we actually want to delete that subscription and then we're turning that t2o for response you know it still seems fine it's kind of an ajax request or whatever it's cool so that gives us the ability to kind of remove two more custom actions from our podcast controller so we can move those down here underneath our podcast image controller and that brings us to tip 3 here which is that if you have something that touches pivot records and creates new pivot records or deletes new pivot records try creating a new controller for that too and think of it as its own resource and you probably want to create a new model too something that I find very helpful when dealing with belongs too many relationships in my lower bound is to try and give that table a better name than the default name get myself a model for that table and then you have this nice side benefit of having a class that exists to sort of represent this relationship now what you'll find typically is you'll have all sorts of behaviors sort of emerging in your application where before you had to think should this go on the user's class or should just go on the podcast class and they're related to the subscription in some way but now that you actually have a subscription class you'll find this becoming sort of a magnet for behavior related to users being subscribed to podcasts so it helps you keep your user model simpler and the podcast model simpler just kind of nice I'm running a little bit faster than I expected so I want to show you one quick tip that I was gonna cut out before but it's really cool so something that I hate about creating these like pivot record relationship models this way it's sort of letting the ID columns leak out into my controller you might have done stuff in the past like you know post comments create to try and create a new related record without specifying the foreign key which is nice because then that foreign key only needs to be known by that model that actually holds that foreign key if you try and do this with a relationship where there's two foreign keys on it the best you can ever do by saving it to the relationship is eliminate just one of those foreign keys you always need to kind of choose which one you want to expose and which one you want to hide and that sort of sucks to me I hate when there's like two options and neither of them feel like I deal so trick that I've been using lately is you know with eloquent you have mutators right so people might do something like set password attribute on a user model that takes like a password and then you might want to automatically hash that password so you could do something like you know this attributes password equals bcrypt password sort of thing right sort of intercept the act of setting that property and manipulate it in some way it's useful for like lower casing things that come in if you want to normalize strings or trimming whitespace sorts of interesting things like that something that I don't see a lot of people doing that I think it's kind of interesting is you can use a mutator to set a totally different column it just sounds kind of crazy but here we're doing something like we're specifying the user ID and the podcast ID right well what if in our user class or sorry in our subscription class we created a mutator for setting the user attribute not the user ID and this takes a user now instead of trying to set a user property because there is no user property we can do something like this attributes user ID equals like a user get key and if you want to sort of simulate how Larry Bell's sort of relationship caching works you can even do something like this set relation user to be this user and that user be sort of pre-loaded so if we do that with both the user and the podcast all right lots of repetitive typing here but maybe I'll make it easier to follow and understand that's my excuse if you do something like this and we would have the user and podcast relationships defined here in this case right I'm going to skip that for the sake of time we're now in the subscriptions controller instead of setting the ID of each you could just set the user entirely to this whole user and the podcast to this whole user and now it feels like yeah I'm creating a subscription for this user in this podcast you're not letting the IDS leak out which is kind of cool it kind of gives you that nice relationship creation benefit for creating something that has multiple foreign keys I think it's kind of a cool trick alright last example that I want to go through is publish and unpublish so how do we map publish to a crud or arrest action if you look at the implementation in the podcast controller you can see that what publish does is it calls a publish method on the podcast and the publish method on the podcast just sets the published at column to be a new timestamp so really the act of publishing a podcast is just updating a field on the podcast table so it seems like it could just be an update action and unpublished is basically doing the same thing just in Reverse so again you might be tempted to take that route of trying to piggyback off the existing update action yeah so in the podcast controller you might think okay well why don't we just point publish an update and we'll just allow this to set the publish that timestamp as well the thing that sucks about that is the way that we're setting that column here is through this nice convenient expressive method that's saying publish this podcast which goes ahead and updates that column if we try to piggyback off this update action you'll find yourself tempted to specify publish to add equals fresh timestamp or equals the timestamp that came in from the request right here and that kind of sucks because what if I wanted to do something in the podcast like fire an event when the podcast was published like podcast was published in a dispatch this if I move this implementation right into my controller I don't have this ability to sort of like connect these two behaviors easily anymore right so my code is a little bit less flexible and you're just sort of like manipulating your code to make it things easier despite the fact that again there are two different intentions from the user publishes just a button on one screen and updating is like a whole format a whole other end point so no good oh boy wait so what can we do instead well we have this example for the cover image controller right where we're trying to put a new cover image resource there so you might think well maybe we have like a like a published sub resource for the podcast and maybe we put true there or something that feels kind of weird cuz like you're making a put request to publish you're passing in like published equals true it's duplicating it's just not really not interesting it can work but I think there's like another interesting approach that is worth talking about that'll teach you something new that we haven't covered yet what if we trying to model publishing as a create action instead of as an update or ended action getting back to that original idea of we have a podcast we publish it what do we have now that we didn't have before do we have anything new has there anything new that we have it's still just a podcast right well now we have a published podcast before we just had a plain old podcast now we have a published podcast so if we wanted to model this as a creator store action we could say that what we're creating is a published podcast and we're creating the raw materials for creating a published podcast is an existing unpublished podcast let's take a look at what that would actually look like if we implemented it so we could update this controller to be published podcasts controller changing action to be store and then change the URL to just be this top-level resource published podcasts okay let's make this controller and take a look okay so here we got to publish podcast controller let's grab our publish action and move this over so now instead of publishing an existing podcast what we're doing is we're storing a new published podcast we lose that route parameter right so we have to accept that in the request instead which honestly I think makes sense because if you look at what it takes to create a regular podcast the raw materials for creating that podcast come in the request not through the routes or anything right so when we're creating a new podcast the raw materials are a title a description and a website and we kind of bundle those up to create a new podcast but when we're publishing a podcast or creating a new published podcast the raw materials are the identifier for an existing podcast so now we have like a dedicated controller for publishing podcasts and instead of returning this empty response which kind of seemed like the most natural thing to do when we were using a published action maybe we want to return this podcast is JSON now so that the consumer can kind of see okay it's got a published equals true JSON attribute set or something that I can use to update my view in some interesting way so if we're gonna use store for creating a new published podcast then unpublishing a podcast naturally would be destroying the published podcast this one is probably the biggest stretch and sort of your imagination and sort of mapping it because we're not deleting a podcast but we are taking a published podcast and we're making it not exist anymore instead we have a regular podcast so I like the idea of modeling that as like a destroy action on a published podcast so now we can change this URL to be published podcasts and then the ID of the published podcast which you know just happens to be the same idea is the regular podcast because they are the same entity they're just being modeled as separate resources and then in our podcast controller we can take this unpublished action cut that out move that over to the published podcast rename it to destroy if we wanted to here we could even scope this based on published right to make sure that we can only unpublished podcasts that are published we unpublish it and then you could either return an empty response but what I find to be more practical most of the time is to return kind of the deleted podcast in its new kind of representation that seems to be more practical for my front end most of the time so let's move those down as well and kind of see what we're left with at the end of the day after all this work that we did so now I've got a podcast controller which just has the standard crud or rest actions for working with a podcast right just the seven basic ones and if I'm being honest this is a pretty big controller right it's still seven actions we were going for like an average of four but the nice thing about using this rule this constraint of only use standard rest actions or standard crud actions is that this is the absolute upper limit in actions for any controller you'll ever create so we know it can never get bigger than this and most of the time honestly I don't find myself needing all seven actions for most resources in my application most the time it's two or three especially when you start creating these new controllers for you know different things and before we go any further I should show that one final tip like this so what we were doing with the published podcast is if you have a resource that's transitioning state as a result of some action you can often treat that resource in that state as its own dedicated resource it's like published podcasts can be different from podcasts even something like popular episodes can be different from episodes instead of having all these query parameters and trying to do all this finagling in your controller in one controller to figure that all out just point them at different controllers that makes things a lot simpler so if something's transitioning stay or is filtered in some way a lot of time you can treat the filtered version of that or that specific state has its own resource and give it its own controller did it again so we got this big controller with seven actions not the end of the world but now we have a dedicated podcast episodes controller for nested resources and it only has three actions and that's like all we'll probably ever need here which is great that's a nice little controller got the podcast cover image controller so we're treating the cover image is a separate resource because it's exposed independently through the UI and the nice thing about this too if you look at it say for whatever reason like uploading and saving this file was like a little bit more complicated and that laravel was like a worse framework it didn't make this like brain-dead easy for you if we needed to add to private methods to this controller to support this and make it easier we wouldn't feel like we had some big bloated out-of-control controller it's one action with two private methods imagine we have to add those two private methods to the original controller that had 13 actions that's when you start thinking oh I need a command bus or something you know what I mean so the next thing but moving these things to dedicated controllers is it just it kind of removes that pressure to come up with other more sophisticated ways to simplify your controller code subscriptions controller this one is cool because by forcing ourselves to use this constraint of crud we actually like uncovered a new like domain concept in our application like thinking in terms of crud enriched our domain which sounds like counterintuitive a lot of time but crud is a powerful thing and then we have published podcasts so we're treating published podcasts as its own resource this filtered version of a podcast of a specific state and now we're able to move that custom publish and custom unpublished action out to its own controller again just two actions our episodes controller even got smaller because we were able to move two of those actions out to the podcast episodes controller so let's check this out now let's see how many actions do we have in total and how many controllers do we have in total so it looks like we have 19 actions one two three four five six controllers nineteen actions spread over six controllers is an average of three point one six actions per controller instead of what we had before which was nineteen actions split over two controllers which is nine point five actions per controller so now we're actually doing better than base camps so to kind of finish things off next time you're working on an application and you find yourself with a big controller that you want to try and simplify in some way instead of looking at the individual actions in that controller and trying to figure out how can I make this action shorter by extracting a form request or creating a service object or introducing god-forbid of command bus instead trying to figure out ways to cut that controller up into more controllers and if you can make that work I think you'll often find that you don't need to go any further than that because everything is crud with a little imagination that's all I got thanks for coming to lair Con and checking out my talk I hope you enjoyed it
Info
Channel: Adam Wathan
Views: 54,028
Rating: undefined out of 5
Keywords:
Id: MF0jFKvS4SI
Channel Id: undefined
Length: 40min 30sec (2430 seconds)
Published: Mon Aug 28 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.