 Can you guys hear me? Does it amplify? That's for the recording, right? Yeah. Okay. Yep. Can you guys see? Okay. You can hear me. Definitely. Okay. So everyone, yep. As Wing Ding said, I'm Kenneth from Grain. And today I want to share with you some of the things that I've learned over the past few months reading and writing production code. Well, for myself, I'm currently a junior software engineer at Grain. I have no idea how I got hired there. And today my boss is here. I wasn't planning on him being here. So hopefully by the end of this talk, he won't change his mind. I learned Ruby on Rails at Alpha Camp. The main things that I work with at Grain are Rails, GraphQL, Node, and View. And before this, I was also in investment banking, started a business, worked on an accelerator, fun hybrid. So the boring stuff you can read up on LinkedIn. Yep. So the first thing I learned just being at Grain was that it seems that production code really just seems to be code that I write. And it kind of seems to work. And someone else has agreed it's working, sort of, maybe. And that person decided to either approve the pull request or add the name to the pull request. And hopefully somewhere in between someone else has written a test or I've written a test to cover the code. So basically I'm here to talk about, yeah, what's happened to me over the last two months. And I don't think it's going to be 100% accurate just because I'm super new to this. Yeah. But I think there's two groups of people who are going to benefit from this talk. So the first group of people are people who are exactly like myself. You're probably just completely new to the whole programming world. And hopefully some of these tips will be new to you. And for the rest of you who have a lot more experience, it might help you along with people who join your team. So these are kind of the things that would really help them as they join the team. Yeah. So things I wanted to talk about. And yeah, I will be stealing a lot from the internet as I have over the past few months. I think that's really the best way to learn. Yeah. And I think that's one of the first things that I picked up was that what I picked up in Alpha Camp wouldn't really be enough. It's just stack over flow, right? I think we're joking one day that if stack over flow went down, our productivity level would drop by like half. Yeah. Okay. So the first thing is safe navigation. So I think this is something that's pretty new. Like in the past, what would happen was you would see something a lot more similar to this, like the dot try. And there'd be a whole series of like dot tries. I think that looked really, really bad. So one day when I found this safe navigation operator, I was like, why have we not been using this? Oh yeah. And this too. This pattern is pretty common. The end-end thing. So generally I tend to use this when I'm receiving like a JSON response. And it comes as basically a long chain where it tends to come from something where I'm exposing an endpoint perhaps and someone is posting to me and I have no idea what's going to come. And sometimes there's some missing information. And also the other thing is oh yeah, APIs also processing responses. So basically anytime you don't have enough information to don't have enough information about the shape of the data that's coming in, that's a good time to use safe navigation. But there's a couple of gotchas. So it doesn't work for false. And it also doesn't prevent errors when the method's not available. So it's mostly, like I said, for no responses. So other things that I use are 2i, blank or present. And I also like to use dig for hashes. So these are pretty useful. And the next thing is concerns. Yeah, so this is basically what a concern should look like. This is not what a lot of the concerns that we write look like. Yep. And basically what it does is it moves stuff that can be in your model and it moves out into a different part. The main goal is separation of concerns and stuff like that. But to me it just seems like if there's a logical block of code that you can take out of your model, then you can use this. And I think on the internet you see a lot of like arguments about oh, don't use real concerns. They're horrible. But let's just use it, OK? And it's pretty clear that the instance methods, they're just kind of in the main block. And then the class methods, it's just in a special block. That's supposed to be here, actually. I just didn't have space. And then that's how you would add the mix-in in the model itself. Yeah. And actually this is something else that I didn't really know. I got a class method was. I think when the Senior Program actually showed me concerns, I was like oh, why are there two separate areas? I'm these all just methods. But to me this is my basic understanding of a class method where you can just use something that tends to be not specific to one instance. And so you would use it as a class method. And this is how I practically move my code. Initially all my code was in the controller. And so I actually moved it to the model first. And I realized that hey, it's actually still working. It's pretty surprising, but it's still working. And then finally I moved it from the model to a concern. So these are the couple of examples where we used concerns. So I think we were starting out with Kafka. And yeah, because I was completely unfamiliar with Kafka, I decided to just process the data as it came in. I came in from the controller. So I was like oh, okay. Let me just start adding information to Redis. Let me start calling a database from here, blah, blah, blah. And when my Senior and the Valder told me, why is this all here? What is this all doing here? So I had to move it. And the second thing was our huge state machine that we also moved. And the last note is just about when to use concerns. I think if you look on the internet, it's a couple of good examples of how you name concerns. And I think that is kind of a good idea of what it should be useful. It should be something that would be useful for multiple models. And that's why you would want to pull it out into concern and use it for different models. Yep. Oh, and I was also supposed to talk about a side note about this whole thing about fat models and slim controllers. Because I think the senior engineer just dropped this on me. He was like, oh, you know, obviously we had to do this because of this principle, blah, blah. And I was like, yeah, I totally knew that. But yeah, I did it. So apparently it's this thing where because model code is a lot easier to test than controller code. So that's why you would try to move it over to the model. And the other thing is also that I guess because it's a very opinionated framework, you kind of want to have, oh, this is where this thing should be and this is where this should be. There's a whole MBC thing, blah, blah, blah. But to me it's okay. If it's easier to test, I'll do it. Okay, the next thing is single table inheritance. Yeah, so I first saw this when I was working on a GraphQL API that we were doing. And I basically was given this list of stuff that I had to create. So a bunch of models to create and then expose the API. And I think I must have been writing some R specs. And then Rails basically told me, oh, type is a reserve keyword on the database. And I was like, huh, maybe the senior engineer made a mistake. Maybe it should be a category instead. And so I changed to the category. And then after that I went to ask him, oh, why was it named type? And he was like, oh, because it's STI, duh. And I was like, huh, STI. I'm thinking of two different things that STI could be and neither of them has related to programming. So I was like, okay, in order and just went back and Googled it. And I was like, ah, okay, got it now. Yeah, so anyway, the reason why we even had them there is that we have kind of many different kinds of orders at grain. And so some of these methods we don't, I mean, a lot of the methods that we do have on there are shared. The state machine is shared, that kind of thing. But some parts are specific to in order. For example, in this case, the on-demand order, where we have to call another API. So that's where you would use STI. Yep. Model callbacks. Yeah. So this, okay, yeah. So for this, I think I had to use it again in relation to the order. And this is an actual piece of code, I think. When after an order was saved, I would basically assign it if these pre-conditions were existed, yeah. And so you would tend to use this when you are trying to create or modify an object in your database. And you need to do something after that. For example, you want to verify it some other way, perhaps outside of active record validations. Perhaps you want to, I don't know, in this case, assign someone, talk to another model. That kind of stuff. All right. And SQL transactions. Yes. So this was something awesome that I discovered. It's kind of related to the stuff that you would see in controllers, where sometimes when you do, like, a create action, or a create action, sometimes when you run a create on the model and you realize that some part of that failed, you usually do like a different render, right? So in the same way, I think, I think it's the same way. This is something that you would tend to do more on the model site and you would wrap everything in a transaction, kind of in a conditional, so that if something does fail, then you will end up, yeah, basically being able to roll back all of that, because when you can't roll back all of that, then you realize that, oh, if only the process happened, but the user wasn't charged, then now I have this order that's already being on its way to fulfillment. But yeah, I haven't charged a person. I have to somehow reverse it. So the cool part about this is that, yeah, you're actually able to do this automatically just by wrapping the entire thing in a transaction block. So definitely use it. Oh yeah, and I found this random fact while I was preparing for this talk. It seems that Rails actually wraps the save and destroy methods in their own transactions, which is cool, and it kind of explains why sometimes when I do mess up with saving, creating my objects, it rolls back, and no idea what else was happening, but now I do. RSpecTips. Yeah, so these are some things that I figured out while looking at the RSpec at grain, because I realized that our test suite is huge and this laptop is like five years old. So I think RSpec takes like seven minutes to run on my laptop, which I think is not a super long time, but I think when you're at my level and you're making mistakes all the time, that's a really long time to wait for the specs to pass. So what Focus True does is that it allows you to only run that specific test. It's pretty cool, and then my boss actually showed me that you can add the F to your described blocks to your id blocks, and that will actually also just run that. So it's a lot easier. Stub Model. Yeah, so I think this was something else I also learned at grain. Before that I was building factories for everything, and that was always kind of a waste of time for me. I was like, why am I declaring this factory and using it once? And you know how factories are like, oh, in real, you have to name them correctly, blah, blah, blah. So yes, Stub Model saves you a lot of time when you're doing that. And this. Yeah, so this is pretty cool as well. I think this might not be newest to everyone, but it was definitely new to me. And I think being able to test different contexts very quickly definitely helps. I think it's related to the previous point about stubbing the model, because what I would do in the past was just create a different factory, perhaps with a different trade, and basically have one of them be a failing test, a failing context. But with this I was able to, you know, in one line completely change the result of the test and save a lot of time in the process. Okay. Yeah, so I think I'm done with the main bulk of it and the rest of it just are super random. So this is the part where, more than five. Yeah, so definitely use Robocop and also use Lintas in general for other languages because they'll save you a lot of time. Because I think for myself, I do find that when I make a typo or something like that, Robocop is a lot quicker to catch it than a failing test later. And the other thing is, I think when you're working with a bigger team, then you realize that oh, everyone else has a different standard for how they indent and how they arrange their code. So when you just force lint it, right, then you will, yeah, it's a lot easier to study the code and figure out where things went wrong. Params in different formats. So this is something I recently discovered. So I was writing, what was I doing? Oh yeah, I was writing a service that was calling a class. Sorry, no. I was writing a few shared classes that would be called either by a service or a controller. And I realized that the controller params come in a different format. News to me as well. So what I did was I actually just did this to figure out whether they were parameters and then if they were, I would just convert them to a hash so that I could use them just the same way as the information from a service. And also sometimes I deep symbolize the keys. The senior engineer actually told me that oh, this is the more real way to do it because I think before that I was doing string access which didn't look that good and git. Yes, this happens to me all the time by the way. I hope I'm not the only one. But yeah, I'm doing a git ad. Okay, now this one I kind of knew beforehand. These two though, these are pretty crucial when you are working with like a ton of punches and yeah, when you push it to the wrong place git push production. Another random tip. And only for people who use atom, not vim and not probably not sublime, right? Yeah, so I think the first time I saw it I was having a lot of trouble doing something that seemed really simple to me. I was like why can't my regex work? And then I realized that oh, atom is JavaScript so this regex syntax is JavaScript as well. Okay, and bash scripts. Yeah, so this was one other thing that actually saved me a huge amount of time that I didn't realize I could do back in Alpha camp. So, actually when I say bash script I think everyone's familiar with it or should I talk a bit more about it? Okay, I'll talk more about it because basically I just have to edit my dot bash profile and these are the lines that I add to it. So I think this happens sometimes to me when my real server crashes but it doesn't crash properly in some way and I'm always finding myself googling like oh, so how do I find a stuck port? Or how do I find a port that's being blocked? Or how do I find a server that seems to be running but that I didn't start? And so I found these online and then this basically just accepts an argument after that and passes it into here so you can just in your terminal just type find server 3000 for example and that basically allows you to find the block thing and then kill server you have to type in the PID that you found from the first step. I think you'll find that a lot of the stuff that I write is very hackish because I'm not super familiar with it but it seems to work So at any point if you guys figure out that oh my gosh you should not be doing that or something like that just totally tell me after this because I think that will really help me too and this also helped me a lot because I was realizing that I was typing the same thing every single day and I was like there has to be a way to set some default home page kind of thing This is my hack so far and then this is for one of our apps so there's quite a few things that we need to start at the same time so I decided to kind of add this in So first I have to stop all the local services because they're blocking the ports and then I get into the directory I start the docker image and then I have to start the webpack dev server as well and then the real server and so what these am I blocking the screen? what these will do is start as a daemon and put it in the background so you can actually still run real ses and see all the output that you normally see which is pretty helpful because I think before that we were trying to use 4man and that would kind of launch everything and it all overlap and I could not see any of the output that I wanted yeah anyway oh that's it that's all I have for you guys so this is actually a lie they're not available yet but they will be so yeah they will be yep any questions for me and any glaring mistakes that I should definitely correct right now a few slides ago there was a regular expression so you're looking for something that's not a single parenthesis and you're looking for one of them oh ok this is this is quite ridiculous actually so what was happening was that I was trying to oh remember earlier when I did a deep symbolize keys so I think I did that on some piece of code and then I had to replace all of these string keys with symbol keys oh I see and then I was like oh this is a really simple thing to do so I wrote out the ruby regex and kind of ran it oh it's not working and I realized that it's because it's javascript so some things are missing like they don't have the I think the look behind but this is just a random thing super random case any other questions? please leave a hand to Canada again