Duration 28:53
16+
Play
Video

RailsConf 2019 - Bug-Driven Development by Ylan Segal

Ylan Segal
Staff Software Engineer at Procore Technologies
  • Video
  • Table of contents
  • Video
RailsConf 2019
May 1, 2019, Minneapolis, USA
RailsConf 2019
Request Q&A
Video
RailsConf 2019 - Bug-Driven Development by Ylan Segal
Available
In cart
Free
Free
Free
Free
Free
Free
Free
Free
Add to favorites
432
I like 0
I dislike 0
Available
In cart
Free
Free
Free
Free
Free
Free
Free
Free
  • Description
  • Transcript
  • Discussion

About speaker

Ylan Segal
Staff Software Engineer at Procore Technologies

Software Engineer with 19+ years of experience, 9+ in Ruby and Rails. Practitioner and advocate of test-driven development; enthusiastic supporter of continuous improvement and clean, maintainable code. Proven performance as team member and leader. Focused primarily on back-end web-services and technologies. Ample experience in Object-Oriented programming and relational databases.

View the profile

About the talk

RailsConf 2019 - Bug-Driven Development by Ylan Segal


This is a sponsored talk by Procore.

Have you ever gotten a bug report that is hard to believe and seemingly impossible to reproduce? Fixing these type of bugs can be draining, but often improves your understanding of the system. Come and learn the nuts and bolts of writing a good regression test that exposes the bug at the right level of abstraction. We will pay close attention to the structure of our code after the bug fix. Through incremental changes, we will drive improvement. I’ll show you how you can have code that is simpler to understand, follows project conventions, and is easier to test.

Share

Lower everyone. Thank you for coming and it's my talk. My name is Elin originated from Mexico City. I've been a long time San Diego resident and I've been writing code in some form or another for the last 20 years real since about 2012 and 2009. Sorry. It's not tell you a story and hopefully we'll get something out of it weird about programming staff engineer at procor the software it to build the world a permission. We work on the code that we use that is used daily by thousands of construction professionals around the country and around the world to make their job better and have the

information they need at the moment that they need it on the job site in the rap on the web. I love working there. Values which are ownership openness and optimism even starting an R&D team in Sydney Australia. So if you are interested come to a booth and talk to us and thank you program for letting me speak. So this story starts with a bug report like many Story start staying active. But when I do on the web interface, it's not reflective directly in the API. The changes not sticking. All right, sounds easy enough. Let's

go to the volume and I try to fix it. I tried to recreate it. Sorry and it's like death. Make the change. It shows up in the public API support that received this and see what they say and they're like we were able to confirm this but just accounts on the European Union and now it's starting to look like so we have to deployment one in the US one of the European Union. This is not for broker. By the way. This was for a company previously broke or I and they were both like mirror images of each other

with the play the same code at the same time to both so now Well, maybe there was a bug in the front than that didn't deploy to correctly in the European Union when using Old Navy baby has to do with cash. Maybe I have no clue what's going on. But you know, I go down some rabbit holes and try to find the thing we can find it. I enlist rqa personality like you and I need you to help me represent this bug now, by the way at this point, we do not have any production taxes. If you have like

you can go into production open a real so so All right. Well as the company particular company I work for this was absolutely not allowed. You couldn't even actually because you know security restrictions and all that we couldn't do it. So there was a lot of you going through logs and see me like this but only with an Enterprise type of account not with like other types of work out. We have a you know, if like tears Pro accounting all of that is that has nothing to do it's like code that's

related at this point. We don't like what we have quite a stink bug. Don't know that there's a disclaimer from its original version. It has been formatted to fit this screen. It has been edited for Content. It looks like we have accounts we had users. We had user accounts, which is you do the many accounts for this. I think of it as a company or organization that has an account in the system. It has many users and there's some things that are part of a user record like, you know their name and

some things that are part of the user account record like there is Like they're sorry like the role which was the problem here and show you how hard is that? Probably won't be really entertaining and as much as miserable misery loves company. I think the So what are you doing on the controller? So or controller looks a little typified but it looks something like this. We had like some sort of placid, you know, nothing's job and goes in search for users. And then we take those users and decorate them, right? And by decorator issue is decorating

in the moment. There's something like the concept of a current account which is similar to current user many applications have this pattern somehow some other thing that happened to navigation controller loads the current account for us, but it's available in the context. And then we move into the user decorator which and some some some some places. This is like a presenter or a decorator a civilizer really job is to taking the user and then convert that use for sterilizing into a hash. So we have like ID first name last name Etc. And one of the things we have their eyes rolled and

the naval flag those go from a user account. So we're decorating the user. So we're also passing for converting it to a house from passing an account. And this is really we're ultimately this is where we found the problem. So If you see here were iterating over all the user account and finding the correct one for the current account that we're looking except that we're not right. Well in this is this is the nature of the bug the bug was, you know, there was a missing character. We were not finding and making things equal. We were just assigning and

And if you go into the thing with the assignment at this time and just Ruthie because it Returns the same account ID. So we were basically just finding any the first user account that was loaded as opposed to finding the correct user account. So at this moment. I was terrified because we are Sending data in the scope of one account, but his release date of the belongs to a different account. Now the particular thing that we're standing here is roll and enabled. So the damn the date of the word leaking is whether a user is

has a different role in a different account. But the fact that we're looking some data between accounts it was you know, quite quite concerning and for the culture of a company was like weird thing. dumb Another thing that occurs to me that this woman is like why why was it is there the year first of all like why is this even happening? This car has been around for years literally was around for years and nobody has reported this we haven't noticed the issue. What why is it happening now? And why is it

hard to recreate? So there's like a Twist here in this particular system. We were not using numeric ID theft auto increment which is like the standard thing but we were using were using uuids the reason is not particularly important. But you do I degeneration has a particular property that it does not art. They're not sequential. So real sword of you know, when you love a user. User accounts in order them by ID. It didn't used to be this way yet so that you could always have like they load always in the same order. You straight like if you're using order increments that

the order is generally correlated to when they were created because you know, they're sequential numbers, but that is not the case with it which made it particularly hard to to to the bar because at some point she did have a notion that this may have been like from one account to the other but when they tried and they created two new accounts and a user belongs to both they couldn't recreate it. And the reason why they couldn't was because the second account actually came before, you know ordering with the ideas. So it was a little harder to to do

the recreate that the the bug sorry So what what are we doing now? So we have that we have about we know pretty much all we need to fix it. So you don't let's go go in right a failing tests. And what we need is you need to use her that looks multiple accounts. We know that's part of the issue. We need property values for rolls that are different in inner chest and this come from a user account and we need to make sure they're loaded in the correct order. So lit right aspect like this in R-Spec,

you know, we'll have some user and then will assert that the account that the specific role for the hassock we are creating is equal to Sumrall that we already know and that the enamel is equal to 2 to the flag that we already know now, I'm sorry, we could we can use it in different dealer project. We're using Factory girl and you know, we can create a user that has two accounts and we roll in an abled and set some values for those. And I hope to hear this is you know, relatively straightforward tested up

but then becomes interesting part is so we need an account. That's the second account in the way going to be loaded. Right? Not the first account. The second one's okay, we can grab the last account and then we all take that one until it gets back the correct saying but that's not a hundred percent enough to recreate this right because we need to make sure that the other account has a different role in a different enabled so that it fully exposes about so

this is some Not not this is regular set up but we know we have a failing test ready to go to PR and my thoughts of this moment turn to like why are we even doing the user account finding in Ruby? Right? Like we should let the date of his do the work is much faster that way so I whip up i-19 PR except for the tests, right so that the code and just see you instead of like finding any Ruby just do what we're in first. Then we're said, right Except that we're not so one of my co-workers

we could open a PR and he's like he was like that in the first place. I have a sinking feeling like did I miss something? He probably knows more about that than I do. All right. I don't know why it's different. but we digging a little bit fine. Commit message for the correct line and the person that wrote the original message rights an interesting thing because they they they they said we don't we we are doing is we're finally a correcting in Ruby for performance and we got a warning that like well

and if you do it now before we didn't have it, so this is more efficient to leave, you know doing the fighting and Ruby is unusual and they're sending us a warning to the Future developers that like, this is Bound for that but I did it for a reason which is great, right, but Puts it in the first place right leg. Why what's going on that smoke with me did not remember years later? I'm looking at it like this is a great job. But so, you know, it's like a double-edged thing because I was smart enough to leave me a message not smart

enough to check it. So I don't know what state of affairs at this moment. They're like, well I fixed a bug but I still have things that bother me about this whole thing. Right? First of all, it's telling me you know, where like I have to get the last use for modified and then get the first user and user account to modify that and then I can do my test. Like okay, that's a doctor tells me something this is nagging at me. Like why why are we why is loading more

things from the database faster this this this ghost is counter-intuitive to everything. I know because you know, there's going to be more data coming across a wire from the from the database more Ruben sensation, which is usually the slow part like why is the date of is not the passport like that that is usually the other way around right like do more stuff in the date of his two for perform is not less. so that's some that's that's telling me something and the next thing is that my decorator has like a weird shape. I haven't told you what the rest of the system

looks like, but The Decorator itself most other decorators in the system have a you know, something object decorator near when you passing some things and then to H on it not to itch with a note to Edgewood passing something else it so that's also a little unusual, you know, it's not terrible it's different but it's weird. So at this point, I'm like a hundred percent happy with how this looks but I don't know where to go. Like, I don't know where to proceed but I figured that this last part is relatively easy to fix because we like we can make that

two H not receive an argument then make it feel like the older ones that have no are you So would you go if we go back to original decorator? This is what it looks like. You don't we have a user and they would have the to which the account and we see realize that so let's start working on that. Right? So I want to make a change and it's not strictly ever factoring because I am changing their public API of this particular decorator, but at this point, I don't know where to go in and make this overall better, but this might be something so we're passing we make some

changes so we can pass it into the account in addition to the user. And then why is like the store that inside the object and then make it remove the need for the argument from the twitch? So, okay. Now we have it in the irregular shape are we can we can make this a little bit super too because we're doing we were doing two things in your in your 2H method. We're finding the correct user account and we're also just constructing the hash. So maybe we can do that a little bit and just move it to the bottom and then you know, it's it's it's way over there it

it's the finding of a user account is one thing which is another thing looks a little cleaner. South I-5 successfully change the API of the Arctic a little bit made it possibly a little better to work with but I think the teacher was like there's there's another thing here. That's that's that's even more meaningful. Will read it. So I am initializing a user decorator and I'm passing it a user which makes sense. But I'm also passing it in the account. So really like a juicer in an account together. We

already have a account so we might as well just use that right so maybe we don't need to decorate as user. We maybe you need to decorate a user account. Right? And then how does that look like? Well, you know user account you're passing a user can we store it and they would go to H&H. Some things are come from the user something's going from user account. But basically we simplify this thing and we're now decorating the same object now noticed that because we're already passing to user account Oh My My My Pain about finding the user

is now gone from this decorator now, it's not even the same decorator. This is a user account the Creator. So, let's see if we can what happens in the control room or a list of users and then we mapped over them and called twitch on it. Now we want to try to use her new decorator, which is our user account decorator, but now that takes a user account but we don't have it user account. So we're sort of have to have like the same code that we had before and move it up to the controller. Now that is worse

than we had before because we're doing the same thing. But now we moved it to the controller and we're before we had a controller that use if you don't have relatively need no logic like doing stuff in your application and then convert it to something that goes out now it has all this stuff about bears like well We can right now out there same. There's something I I had not show you before and then I wasn't going to what happens in the search users part of this but our whole trouble started because search users read

down there somewhere was doing the equivalent of pre-loading the user account. So we had a class. It was called search users and it was bringing back a list of users. But each of those users already had all its user accounts loaded. This is the source of the original problem because if I already have all the user accounts loaded that enabled us to have a bug where we were using the wrong user account, but we were loading more than we should be in the first place. So if We can we can

continue in our train of thought that says you don't we have we had a user decorator, but we turned it into a user account decorator. But now we have search users. We can just change it to search user account and this brings back. So this is basically what we did here is just change from the user accounts in only this is responsible for loading. The usual. Which is what we need now for a decorator not just users and then we can plug back in two or more or decorator and This sort of brings back, you know a little bit of symmetry to what we

had before and we're decorating user accounts all seems like it flows in that in a naturally. There's a bloke close by Sarah me cold five Factor testing like all the different reasons why we write test. If you haven't read it, it's it's fantastic. You should read it. I noted along every time I read it and I keep it handy because I send it to people a lot when we talk about testing. Body particular one of the factors that she goes to one of the reasons why we test is

to prevent future regressions. So Remember regression test like her first as when we started and we put it in the decorator and we know we did all this complicated set up and then when we had it, so what happens to it now? We're not even using that decorate your anymore. We don't want that. This doesn't exist. So where do we put it? So one one place to put it now is we can put it in the controller, right? We're or request spec nowadays, I guess but which means from the outside make sure that you know, if there's a user has two accounts

do all these things when the responses he gets is the correct one and he's getting the correct date on I think this is a good place to put it that is where I put it in the beginning but it sounded you were testing at the wrong level of abstraction having a regression tested make sure the business and having the future is not unreasonable. So whether you know, you need to have it or not is up to you guys, but I think it's a it's a trade-off. You don't what's one more test. Maybe the fence

if it's really slow. Another place where we can put this right so we talked about how we create a new user accounts class. So this class is really about searching user accounts or loading them from the database. You take some parameters in that the user sent in and now we need to load them. So I think this is a good place to put in the test and it's a relatively simple test in which you don't create the glossing over a few of the details, but you know, we're going to create a user with two accounts and then we have we're going to check that. We that

the parameters particular account ID. We're going to check that the results to come back including user account, but don't include the other one. So we are like testing at the correct level, right? This is the right level to test because it's it's this class is all about loading users. so A a particular after bit like in reality. We dream just only kept this test because we felt this was like this was provided enough of a safety net to 21 in the future will be prevented from surfacing about a similar bug again.

So read my thoughts on this was the bug was an opportunity for you to improve the system. Yes, we could have just picked up but it was also an opportunity gave us a little bit more understanding of what's going on. It is surfaced a few different things one was that or naming was a little bit off and that the concept that we were using the Domaine not if we're not really the ones we should be using. My my contention is that we ended up with a little that. The design of the resulting code is better

than the design of the initial why I think it's a is better. Well a few things one. It's almost patterns, right it fit better with the rest of the system and buy batteries. I mean, you know or decorator has the same maybe I like boobs are all the other decorators has and this is good because any other developer working on it as lesser prizes. It's easier to extract away its convention over configuration, which region Essences shared understanding right? Like there's there's there's something that we get from real to self. And this is one of the great powers and there's

something that we have as a team. But following them the the the the greatness of following his convention says that we all have a shared understanding and we know how it's supposed to look and we have lesser prices. I also think that we ended up with a smaller pieces right although maybe smaller pieces, but easier to understand so Why are these your do understand because they're sticking to their own responsibilities. The part about loading is about loading the part about. Is that the part about decorating is about

decorating in the part about taking an HTTP and converting it back to some other agent to be like a request in person responds to controller is also easier to understand now and I also think we created better abstractions not just in Direction. So we're before controller to breathe and you know, there's just one thing and do think there's were two classes that we were in time cheating and using more of The Decorator but do many of the same class but there was something in there that there was causing some looks like if you looked at The Decorator we were left

with like all I have a decorator, but it's loading a user account that the user has you know, and it's passing the current account. There was a lot more it was a lot more noise there. Then than it needed to be so those things like the difference between a good abstraction in a golden direction is indirection just hide stuff attraction. Let's it clears your mental load illithid, put it out of your mind. So now you're working on The Decorator and you are adding new things or or I don't know changing the format. It's only about that and when you were looking at the part that

loads at it's only about load and you can sort of put it out of your mind and not think about it if it's Justin directions and it's more things that you need to keep in the back of your head. So for that I think it's because it's easier to go to work. Framework of testing I think about testing a lot. I think I'll show you more arsenic code than the regular coat. And and the reason for that is that testing HealthSource here in a few ways one with the regression testing, but it also has about reforming or design

sort of complicated something about our design right and told us like, well, there's there's something here. That's the going against the grain. It shouldn't be hard to have your setup. So also Having a good test with you allowed us to change the internal structure of the code and well internal we did change the API of someone to retain some object around but from the outside of the system within you change the behavior we did because we took the bug but you know, we didn't really change anything. You know, where

had the same parameters coming in Json response coming out. So from my perspective, I'm calling it a refectory, but the fact that we had a good test weed around the other things and wherever else this code was used gave us like a safety to be able to do it. In conclusion, I think I want you to take something about it. So, you know you have a The takeaway I wanted to get is 1 a bug is an opportunity to Improvement in tells you something about the system that you didn't know before and you can always learn something about your

system even system that you wrote, you know make them it's about but it also is someone into testing is there to help you. Sometimes it feels like we're fighting or testing framework in the end in the end. It's really hard. But you know, if you improve your skills in testing it'll it'll it'll help you design better code.

Cackle comments for the website

Buy this talk

Access to the talk “RailsConf 2019 - Bug-Driven Development by Ylan Segal”
Available
In cart
Free
Free
Free
Free
Free
Free
Free
Free

Access to all the recordings of the event

Get access to all videos “RailsConf 2019”
Available
In cart
Free
Free
Free
Free
Free
Free
Free
Free
Ticket

Interested in topic “IT & Technology”?

You might be interested in videos from this event

September 28, 2018
Moscow
16
173
app store, apps, development, google play, mobile, soft

Similar talks

Chris Salzberg
VP Engineering at Self-employed
Available
In cart
Free
Free
Free
Free
Free
Free
Free
Free
Jason Swett
Software Engineer, Teacher, Writer, Speaker, Podcaster at Secret Business
Available
In cart
Free
Free
Free
Free
Free
Free
Free
Free
Sonja Peterson
Senior Software Engineer at ActBlue Technical Services
Available
In cart
Free
Free
Free
Free
Free
Free
Free
Free

Buy this video

Video

Access to the talk “RailsConf 2019 - Bug-Driven Development by Ylan Segal”
Available
In cart
Free
Free
Free
Free
Free
Free
Free
Free

Conference Cast

With ConferenceCast.tv, you get access to our library of the world's best conference talks.

Conference Cast
646 conferences
26471 speakers
9831 hours of content