The Bike Shed

Follow The Bike Shed
Share on
Copy link to clipboard

On The Bike Shed, hosts Chris Toomey & Steph Viccari discuss their development experience and challenges at thoughtbot with Ruby, Rails, JavaScript, and whatever else is drawing their attention, admiration, or ire this week.

thoughtbot

Donate to The Bike Shed


    • Jan 18, 2022 LATEST EPISODE
    • every other week NEW EPISODES
    • 40m AVG DURATION
    • 322 EPISODES

    Listeners of The Bike Shed that love the show mention: thoughtbot, ruby, rails, fixed, developers, technical, code, programming, development, always interesting, great to hear, i've learned, balance, dive, learn something, discussion, deep, practical, highly recommend, topics.



    Search for episodes from The Bike Shed with a specific topic:

    Latest episodes from The Bike Shed

    322: Toxic Traits

    Play Episode Listen Later Jan 18, 2022 35:21

    Happy New Year (for real)! Chris and Steph both took some end-of-year time off to rest and recharge. Steph talks about some books she enjoyed, recipes she tried, and trail-walking adventures with her dog, Utah. Chris' company is now in a good position to actually start hiring within the engineering team. He's excited about that and will probably delve into more around the hiring process in the coming weeks. Since they aren't really big on New Year's Eve resolutions, Steph and Chris answer a listener question regarding toxic traits inspired by the listener question related to large pull requests and reflect on their own. The Midnight Library by Matt Haig (http://www.matthaig.com/books/midnight-library/) Tim Urban on Twitter (https://twitter.com/waitbutwhy/status/1367871165319049221) How to Stop Time by Matt Haig (http://www.matthaig.com/how-to-stop-time/) Do the Next Right Thing (https://daverupert.com/2020/09/do-the-next-right-thing/) Debugging Why Your Specs Have Slowed Down (https://thoughtbot.com/blog/debugging-why-your-specs-have-slowed-down) test-prof (https://github.com/test-prof/test-prof) Tests Oddly Slow Might Be Bcrypt (https://collectiveidea.com/blog/archives/2012/11/12/tests-oddly-slow-might-be-bcrypt) Transcript: STEPH: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Steph Viccari. CHRIS: And I'm Chris Toomey. STEPH: And together, we're here to share a bit of what we've learned along the way. So, hey, Chris, what's new in your world? CHRIS: What's new in my world? Well, spoiler, we actually may have lied in a previous episode when we said, "Hey, happy New Year," because, for us, it was not actually the new year. But this, in fact, is the first episode of the new year that we're recording, that you're hearing. Anyway, this is enough breaking the fourth wall. Sorry, listener. STEPH: [laughs] CHRIS: Inside baseball, yadda, yadda. I'm doing great. First week back. I took some amount of vacation over the holidays, which was great, recharging, all those sorts of things. But now we're hitting the ground running. And I'm actually really enjoying just getting back into the flow of things and, frankly, trying to ramp everything up, which we can probably talk about more in a moment. But how about you? How's your new year kicking off? STEPH: I like how much we plan the episodes around when it's going to release, and we're very thoughtful about this is going to be released for the new year or around Christmas time, and happy holidays to everybody. And then we get back, and we're like, yeah, yeah, yeah, we can totally drop the facade. [laughs] We're finally back from vacation. And this is us, and this is real. CHRIS: Date math is so hard. It just drains me entirely to even try and figure out when episodes are going to actually land. And then when we get here, also, you know, I want to talk about the fact that there was vacation and things, and the realities of the work, and the ebb and flow of life. So here we are. STEPH: Same. Yeah, I love it. Because I'm in a similar spot where I took two weeks off, which was phenomenal. That's actually sticking to one of the things we talked about, for one of the things I'm looking to do is where I take just more time off. And so having the two weeks was wonderful. It was also really helpful because the client team that I'm working with also shut down around the end of the year. So they took ten days off as well. So I was like, well, that's a really good sign of encouragement that I should also just shut down since I can. So it's been delightful. And I have very little tech stuff to share because I've just been doing lots of other fun things and reading fiction, and catching up with friends and family, and trying out new recipes. That's been pretty much my last two weeks. Oh, and walks with Utah. His training is going so well where we're starting to walk off-leash on trails. And that's been awesome. CHRIS: Wow, that's a big upgrade right there. STEPH: Yeah, we're still working on that moving perimeter so he knows how far he can go. Before then, he needs to stop and check on me. But he's getting pretty good where he'll bolt ahead, but then he'll stop, and he'll look at me, and then he'll wait till I catch up. And then he'll bolt ahead again. It's really fun. CHRIS: I like that that's the version of it that we're going for. This is not like you're going to walk alongside me on the trail; it's you're obviously going to run some distance out. As long as you check back in once every 20 feet, we're good; that's fine. Any particularly good books, or recipes, or talks with friends to go with that category? But that one's probably a little more specific to you. STEPH: [laughs] Yes. There are two really good books that I read over the holidays. They're both by the same author. So I get a lot of books from my mom. She'll often pick up a book, and once she's done with it, she'll drop it off to me or vice versa. So the one that she shared with me is called The Midnight Library. It's written by Matt Haig, H-A-I-G. And it's a very interesting story. It's a bit sad where it's about a woman who decides that she no longer wants to live. And then, when she moves in that direction to go ahead and end her life, she ends up in this library. And in the library, every time she has made a different decision or made a decision in life, then there is a new book written about what that life is like. So then she has an opportunity to go explore all of these lives and see if there's a better life out there for her. It is really interesting. I highly recommend it. CHRIS: Wow. I mean, that started with, I'm going to be honest, a very heavy premise. But then the idea that's super interesting. I would, actually...I think I might read that. I tend to just read sci-fi. This is broadly in the space, but that is super interesting. There's an image that comes to mind actually as you described that. It's from Tim Urban, who's also known as Wait But Why. I think he posts under that both on Twitter, and then I think he has a blog or something to that effect. But the image is basically like, all of the timelines that you could have followed in your life. And everybody thinks about like, from this moment today. Man, I think about all of the different versions of me that could exist today. But we don't think about the same thing moving forward in time. Like, what are all the possibilities in front of me? And what you're describing of this person walking around in a library and each book represents a different fork in the road from moving forward is such an interesting idea. And I think a positive reframing of any form of regret or looking back and being like, what if I had gone the other way? It's like, yeah, but forward in time, though. I'm very intrigued by this book. STEPH: Yeah, it's really good. It definitely has a strong It's a Wonderful Life vibe. Have you ever watched that movie? CHRIS: Yes, I have. STEPH: So there's a lot of that idea of regret. And what if I had lived differently and then getting to explore? But in it's A Wonderful Life, he just explores the one version. And in the book, she's exploring many versions. So it's really neat to be like, well, what if I'd pursued this when I was younger, had done this differently? Or what if I got coffee instead of tea? There are even small, little choices that then might impact you being a different person at a point in time. The other book that I read is by the same author because I enjoyed Midnight Library so much that I happened to see one of his other books. So I picked it up. And it's called How to Stop Time. And it's about an individual who essentially lives a very long time. And there are several people in the world that are like this, but he lives for centuries. But he doesn't age, or he ages incredibly slowly, at a rate that where say that he's 100 years old, but he'll still look 16 years old. And it's very good. It's very interesting. It's a bit more sad and melancholy than I typically like to read. So that one's good. But I will add that even though I described the first one, it has a sad premise; I found The Midnight Library a little more interesting and uplifting versus the other one I found a bit more sad. CHRIS: All right. Excellent additional notes in the reading list here. So you can opt like, do you want a little bit more somber, or do you want to go a little more uplifting? Yeah, It's a Wonderful Life path being like, starts in a complicated place but don't worry, we'll get you there in the end. STEPH: But I've learned I have to be careful with the books that I pick up because I will absorb the emotions that are going on in that book. And it will legit affect me through the week or as I'm reading that book. So I have to be careful of the books that I'm reading. [laughs] Is that weird? Do you have the same thing happen for when you're reading books? CHRIS: It's interesting. I don't think of it with books as much. But I do think of it with TV shows. And so my wife and I have been very intentional when we've watched certain television shows to be like, we're going to need something to cut the intensity of this show. And the most pointed example we had was we were watching Breaking Bad, which is one of the greatest television shows of all time but also just incredibly heavy and dark at times, kind of throughout. And so we would watch an episode of Breaking Bad. And then, as a palate cleanser, we would watch an episode of Malcolm in the Middle. And so we saw the same actor but in very different facets of his performance arc and just really softened things and allowed us to, frankly, go to bed after that be able to sleep and whatnot but less so with reading. So I find it interesting that I have that distinction there. STEPH: Yeah, that is interesting. Although I definitely feel that with movies and shows as well. Or if I watch something heavy, I'm like, great, what's on Disney? [laughs] I need to wash away some of that so I can watch something happy and go to sleep. You also asked about recipes because I mentioned that's something I've been doing as well. There's a lot of plant-based books that I've picked up because that's really my favorite type of thing to make. So that's been a lot of fun. So yeah, a lot of cooking, a lot of reading. How about you? What else is going on in your world? CHRIS: Well, actually, it's a super exciting time for Sagewell Financial, the company that I've joined. We are closing our seed financing round, which the whole world of venture capital is a novel thing that I'm still not super involved in that part of the process. But it has been really interesting to watch it progress, and evolve, and take shape. But at this point, we are closing our seed round. Things have gone really well. And so we're in a position to actually start hiring, which is a whole thing to do, in particular, within the engineering group. We're hiring, I think, throughout the company, but my focus now will be bringing a few folks into the engineering team. And yeah, just trying to do that and do that well, do that intentionally, especially for the size of the team that we have now, the sort of work that we're doing, et cetera, et cetera. But if anyone out there is listening, we are looking for great folks to join the team. We are Ruby on Rails, Inertia, TypeScript. If you've listened to the show anytime recently, you've heard me talk about the tech stack plenty. But I think we're trying to do something very meaningful and help seniors manage finance, which is a complicated and, frankly, very underserved space. So it's work that I deeply believe in, and I think we're doing a good job at it. And I hope to do even a better job over time. So if that's at all interesting, definitely reach out to me. But probably in the coming weeks, you'll hear me talk more and more about hiring and technical interviews and all of those sorts of things. I got to ramp myself back up on that entire world, which is really one of those things that you should always be doing is the thought that I have in my head. Now that I'm in a position to be hiring, I wish I'd been half-hiring for the past three months, but I'll figure it out. It'll be fine. STEPH: That's such a big undertaking. Everything you're saying resonates, but also, it's like that's a lot of hard work. So if you're not in that state of really being ramped up for hiring, I understand why that would be on the backburner. And yeah, I'm excited to hear more. I've gotten to hear some more of the product details about Sagewell, but I don't think we've really talked about those features here on the show. So I would love it if we brought some more of the feature work and talked about specifically what the application does. I am intrigued speaking of how much energy goes into hiring. Where are you at in terms of how much...like, are there any particular job boards that you're going for? Or what's your current approach to hiring? CHRIS: Oh, that's a great question. I have tweeted once into the world. I have a draft of a LinkedIn post. This is very much I'm figuring out as I go. It's sort of the nature of a startup as we have so many different things to do. And frankly, even finding the time to start thinking about hiring means I'm taking time away from building features and growing out other aspects. So it's definitely a necessary thing that we're doing at this point in time. But basically, everything we're doing is just in time compiling and figuring out what are the things that are semi-urgent right now? And to be honest, I like that energy overall. I've always had in the back of my mind that I like this sort of work and this space, especially if you can do it intentionally. It shouldn't feel like everything's on fire all the time, but it should feel like a lot of constraints that force you to make decisions quickly, which, if we're being honest, I think that's something that is not my strongest suit. So it's something that I'm excited to grow that muscle as part of this work. But so, with that in mind, at this point, my goal is to just start getting the word out there into the world that we are looking to hire and get people interested and then, from there, build out what's the interview process going to look like? I will let you know when we get there; I will. I will figure that out. But it's not something that I've...I haven't actually very intentionally thought about all of this. Because if I were to do that, it would delay the amount of time until I actually say into the world, "Hey, we're hiring." So I very purposely was like, I just need to say this into the world and then continue doing the next steps in that process. I'm prone to the perfect is the enemy of the good just trying to like, I want to have a complete plan and a 27-step checklist, and a Gantt chart, and a burndown. And before I take any first action and really trying to push back, I'm going to be like, no, no, just do something, just take a step in the right direction. There's actually a blog post that comes to mind, which is by Dave Rupert, who is a former guest on this podcast. It was wonderful getting to interview him. But he wrote a blog post. The title of it is Do the Next Right, which is a line from a song in the movie Frozen 2, I believe. He is like, all right, stick with me here. And I know this is a movie for kids, maybe. But also, this is a very meaningful song. And he framed it in a way that actually was surprisingly impactful to me. And it's that idea that I'm holding on to of you can't do it all, and you can't do it perfectly. Just do the next right thing. That's what you're going to do. So we'll link to that blog post in the show notes. But that's kind of where I'm at. STEPH: I love that. I'm looking forward to reading that because that has been huge for me. I used to be held back by that idea of perfection. But then I realized other people were getting more work done more quickly. And so I was like, huh, maybe there's something to this just doing the next thing versus waiting for perfection that is really the right path. So, how do folks reach out to you? Should they reach out to you on Twitter or email? What's best for you? CHRIS: Oh yeah, Twitter. This is all probably going to be said at the end of the show as well. But Twitter @christoomey. ctoomey.com is my blog. I'm on GitHub. I make it very easy to contact me because I haven't regretted that up to this point in my life. So basically, anywhere you find me on the internet, you will be able to email me or DM me or any of the things. I'm going to see how long I can hold on to that. I want to hold on to that forever. I want just a very open-door policy. So that's where I'm at right now, but any of those starting points. And bikeshed.fm website will somehow link to me in any of the various forums, and they're all kind of linked to each other, so any of those are fine. I will happily take inquiries via any of the channels. STEPH: Cool. Well, I'm excited to hear about how it goes. CHRIS: Me too, frankly. But in a very small bit of little tech news or tech happenings from my holiday time, this was actually just before I started to go on break for the holidays. I had noticed that the test suite was getting very slow, like very, very slow but on my machine. It was getting a little bit slow on CI, but the normal amount where we just keep adding new things. And we're adding a lot of feature specs because we want to have that holistic coverage over the whole application, and we can, so for now, we're doing that. But our spec suite had gotten up to six-ish minutes on CI and had a couple of other things. We have some linting and some TypeScript and things like that. But on my machine, it was very slow. So I hadn't run the full spec suite in a long time. But I knew that running any individual spec took surprising amounts of time. And in the back of my head, I was like; I guess I hadn't configured Spring. That seems weird. I probably would have done that, but whatever. And I'd never pushed on it more until one day I ran the specs. I ran one model spec, and it took 30 seconds or something like that. And I was like, well, that's absurd. And so I started to look into it. I did some scanning around the internet. There was a wonderful post on the Giant Robots blog about how to look through things from Mike Wenger, a wonderful former thoughtboter. Unfortunately, none of the tips in there were anything meaningful for me. Everything was as I expected it to be. So I set it down. And there were a couple of times that this happened to me where I'd be like, this is frustrating. I need to look into this a little bit more, but it was never worth investing more time. But I mentioned it in passing to one of the other developers on the team. And as a holiday gift to me, this person discovered the solution. So let me describe a little bit more of what we've got working on here. On CI, which in theory is less powerful than my new, fancy M1 MacBook, on CI, we take about six minutes for the test suite. On my computer, it was taking 28 minutes and 30 seconds. So that's what we're working with. The factories are all doing normal things. We're not creating way too many database records or anything like that. So any thoughts, anything that you would inspect here? STEPH: Ooh, you've already listed a number of good things that I would check. CHRIS: Yeah, I took all the easy ones off the list. So this is a hard question at this point. To be clear, I had no ideas. STEPH: Could you tell if there's a difference if it's like the boot-up time versus the actual test running? CHRIS: Did that check; it is not the boot-up time. It is something that is happening in the process of running an individual spec. STEPH: No, I'm drawing a blank. I can't think of what else I would check from there. CHRIS: It's basically where I was at. Let me give you one additional piece of data, see if it does anything for you. I noticed that it happened basically whenever executing any factory. So I'd watch the logs. And if I create this record, it would do roughly what I expect it to. It would create the record and maybe one or two associated records because that's how Factory Bot works. But it wasn't creating a giant cascade or waterfall of records under the hood. If we create a product, the product should have an associated user. So we'll see a product and a user insert. But for some reason, that line create whatever database record was very, very slow. STEPH: Yeah, it's a good point, looking at factories because that's something I've noticed in triaging other tests is that I will often check to see how many records are created at a certain point because I've noticed there's a test where I think only one record is created, but I'll see 20. And that's an interesting artifact. But you're not running into that. But it sounds like there's more either some callback or transaction or something that's getting hung up and causing things to be slow. CHRIS: I love those ideas. I didn't even know those were sort of ideas in the back of my head. I didn't know how to even try and chase that down. There was nothing in the logs. I couldn't see anything. And again, I just kept giving up. But again, this other developer on the team found the answer. But at this point, I'll just share the answer because I think we've run out of the good bits of the trivia. It turns out bcrypt was the answer. So password-hashing was incredibly slow on my machine. What was interesting is I mentioned this to the other developer because they also have an M1. But there are three of us working on the project. The third developer does not have the M1 architecture. So that was an interesting thing. I was like, I feel like this maybe is a thing because we're both experiencing this, but the other developer isn't. So it turns out bcrypt is wildly slow on the M1 architecture, which is sort of interesting as an artifact of like, what is password hashing, and how does it work? And in normal setups, I think the way it works is Devise will say by default, "We're going to do 12 runs of bcrypt." So like take the password, put it into the hashing algorithm, take the output, put it back into the hashing algorithm, and do that loop 12 times or whatever. In test mode, it often will configure it to just run once, but it will still use the password hashing. Turns out even that was too slow for us. So we in test mode enabled it so that the password hashing algorithm was just the password. Don't do anything. Just return it directly. Turn off bcrypt; it's too painful for us. But it was very interesting to see that that was the case. STEPH: Yeah, I don't like that answer. [laughs] I'm not a fan. That is interesting and tricky. And I feel like the only way I would have found that...I'm curious how they found it because I feel like at that point, I would have started outputting something to figure out, okay, where is the slow process? What's the thing that's taking so long to return? And if I can't see tailing the test logs, then I would start just using a PUT statement to figure out what's taking a long time? And start trying to troubleshoot from there. So I'm curious, do you know how they identified that was the core issue? CHRIS: Yes, actually. I'm looking back at the pull requests right now. And I'm mentioning that this was related to the M1 architecture, but I don't think that's actually true because the blog post that they're linking to is Collective Idea blog post: Tests Oddly Slow? Might be bcrypt. And then there's a related Rails issue. They used TestProf, which is a process that you can run that will examine, I think the stack trace and say where are we spending the most time? And from that, they were able to see it looks like it's at the point where we're doing bcrypt. And so that's the answer. As an aside, my test suite went from 28 minutes and 30 seconds to 1 minute and 30 seconds with this magical speed up. STEPH: Nice. That's a great idea, TestProf. I don't know if I've used that tool. It rings a bell. But that's an awesome sales pitch for using TestProf. CHRIS: Similarly, I don't think I'd ever use it before. But it truly was this wonderful holiday gift. Because the minute I switched over to this branch, I was like, oh my God, the tests are so fast. I have one of those fancy, new fast computers, [laughs] and now they're so fast. STEPH: Wait, you had to switch to a branch? I figured it was something that you had to do special on your machine. So I'm intrigued how they fixed it for you, and then you switched to a branch and saw the speed increase. CHRIS: So they opened a pull request. And that pull request had the change in the code. So it was a code-level configuration to say, "Hey, Devise, when you do the password hashing thing, maybe just don't, maybe be easy for a moment," [laughter] but only in the test configuration. So all I had to do was check out the branch, and then that configuration was part of the Rails helper setup, and then we were good to go from there. I added an extra let me be terrified about this because the idea of not hashing passwords in production is terrifying. So let me raise...I put a couple of different guards against like, this should only ever run in test. I know it's in the spec support directory, so it shouldn't. Let me just add some other guards here just to superduper make sure we still hash passwords in production. STEPH: Devise has a bcrypt chill mode. Good to know. [laughs] And I like all the guards you put in place too. CHRIS: Yeah, it was really frankly such a relief to get that back to normal, is how I would describe it. But yeah, that's a fun little testing, and password hashing, and little adventure that I get to go on. Mid-roll Ad And now a quick break to hear from today's sponsor, Scout APM. Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more. Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform. See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed. STEPH: So I have something that I've been wanting to ask you, and it's not tech-related. But we can make this personal and work however we want to tackle it. But there is a previous episode where we read a listener question from Brian about their self-diagnosed toxic trait being large pull requests. And Brian was being playful with the use of the term toxic trait. But it got me thinking, it's like, well, what is my toxic trait? And it seems like a fun twist on you, and I aren't really big on New Year's Eve resolutions. And in fact, I think you and I are more like if we're interested in achieving a goal, we'd rather focus on building a habit versus this specific, ambiguous we're going to publish ten blogs this year. But rather, I'd rather sit down and write for 15 minutes each day. And it seemed like a fun twist instead of thinking about what are my toxic traits, personal, at work? Large pull request is a really fun example. So I'll let you choose. I can go first, or you can go first, but I'm excited to hear your thoughts on this one. CHRIS: I think I've been talking too much. So let's have you go first at this point/ also, I want a few more seconds to think about my toxic trait. STEPH: [laughs] All right, I have a couple. So that's an interesting point start there [laughs], but here we are. So I was even bold because I asked other people. Because I'm like, well, if I'm going to be fully self-aware, I can't just...I might lie to myself. So I'm going to have to ask some other people. So I asked other folks. And my personal toxic trait is I am tardy. I am that person who I love to show up 5, 10, 15 minutes late. It's who I am. I don't find it a problem, but it often bothers other people. So that is my informed toxic trait. That might be a strong term for it. But that's the one that gives people the most grief. CHRIS: Interesting. I do find the framing of I don't find my own tardiness to be a problem as a really interesting sort of lens on it. But okay, it's okay. STEPH: I see it as long as I'm getting really good quality time with someone; if I'm five minutes late, I'm five minutes late. I think the voice going high means I'm a little defensive. [laughs] CHRIS: But at least you're self-aware about all of these aspects. [laughs] That's critical. STEPH: I am self-aware, and most of the people in my life are also self-aware, although I do correct that behavior for work. That feels more important that I be on time for everything because I don't want anyone to feel that I am not valuing their time. But when it comes to friends and family, they thankfully accept me for who I am. But then, on the work note, I started thinking about toxic traits there. And the one I came up with is that I'm a pretty empathetic person. And there's something that I learned that's called toxic empathy. And it's when you let people's emotions hijack your own emotions, or you'll prioritize someone else's physical or mental health over your own. So, for example, it could be letting another person's anxiety and stress keep you from getting your current tasks and responsibilities done. And there's a really funny tweet that I saw where someone says, "Hey, can I vent to you about something?" And the first person telling it from their perspective they're crying in the middle of a breakdown. And they're like, "Yeah, sure, what's up?" And I felt seen by that tweet. I was like, yeah; this seems like something I would do. [laughs] So over time, as something I'm aware of about myself, I've learned to set more boundaries and only keep relationships where equal support is given to both individuals. And this circles back to the book anecdote that I shared where I had to be careful about the books that I read because they can really affect my mood based on how the characters are doing in that book. So yeah, that's mine. I have one other one that I want to talk about. But I'm going to pause there so you can go. CHRIS: Okay, fun. [laughs] This is fun. And it is a challenging mental exercise. But it is also, I don't know, vulnerable, and you have to look inside and all that. I think I poked at one earlier on as we were talking, but the idea of perfect is the enemy of the good. And I don't mean this in the terrible like; what's your worst trait in a job interview? And you're like, "I'm a perfectionist." I don't mean it in that way. I mean, I have at times struggled to make progress because so much of me wants to build the complete plan, and then very meticulously worked through in exactly the order that I define, sort of like a waterfall versus agile sort of thing. And it is an ongoing very intentional body of work for me to try and break myself off those habits to try and accept what's the best thing that I can do? How can I move forward? How can I identify things that I will regret later versus things that are probably fine? They're little messes that I can clean up, that sort of thing. And even that construing it as like there's a good choice and a bad choice, and I'm trying to find the perfect choice. It's like almost nothing in the world actually falls into that shape. So perfect is the enemy of the good is a really useful phrase that I've held onto that helps me. And it's like, aiming for that perfection will cause you to miss the good that is available. And so, trying to be very intentional with that is the work that I'm doing. But that I think is a toxic trait that I have. STEPH: I really like what you just said about being able to identify regrets. That feels huge. If you can look at a moment and say, "I really want to get all this done. I will regret if I don't do this, but the rest of it can wait," that feels really significant. So the other one that I wanted to talk about is actually one that I feel like I've overcome. So this one makes me happy because I feel like I'm in a much better space with it, but it's negative self-talk. And it's essentially just how you treat yourself when you make a mistake. Or what's your internal dialogue throughout the day? And I used to be harsh on myself. If I made a mistake, I was upset, I was annoyed with myself, and I wouldn't have a kind voice. And I don't know if I've shared this with you. But over time, I've gotten much better at that. And what has really helped me with it is instead of talking to myself in an unkind voice, I talk to myself how someone who loves me will talk to me. I'm not going to talk to a friend in a really terrible, mean voice, and I wouldn't expect them to talk to me. So I channel someone that I know is very positive and supportive of me. And I will frame it in that context. So then, when I make a mistake, it's not a big deal. And I just will say kind things to myself or laugh about it and move through it. And I found that has been very helpful and also funny and maybe a little embarrassing at times because when pairing, I will talk out loud to myself. And so I'll do something silly, and I'll laugh. I'm like, "Oh, Stephanie," that was silly. And the other person hears me say that. [laughs] So it's a little entertainment for them too, I suppose. CHRIS: Having observed it, it is charming. STEPH: It's something that I've noticed that a lot of people do, and we don't talk about a lot. I mean, there's imposter syndrome. People will talk about that. But we don't often talk about how critical we are of ourselves. It's something that I will talk to people who I highly admire and just think they're incredibly good at what they do. And then when they give me a glimpse into how they think about themselves at times or how they will berate themselves for something they have done or because they didn't sit down for that 15 minutes and write per day, then it really highlights. And I hope that if we talk about this more, the fact that people tend to have such a negative inner critical voice, that maybe we can encourage people to start filtering that voice to a more kind voice and more supportive voice, and not have this unhelpful energy that's holding us back from really enjoying our work and being our best self. CHRIS: That's so interesting to hear you say all of that for one of your traits because it's very similar to the last one for myself, which is I find that I do not feel safe unless (This is going to sound perhaps boastful, and I definitely do not mean it as boastful.) but unless I'm perfect. I guess the standard that I hold myself to versus the standard that I hold others to are wildly different. Of course, for other people, yes, bugs will get into the code, or they may misunderstand something, or they may miss communicate something, or they may forget something. But if I do that, I feel unsafe, which is a thing that I've slowly come to recognize. I'm like, well, that shouldn't be true because that's definitely not how I feel about other people. That's not a reasonable standard to hold. But that needing to be perfectly secured on all fronts and have just this very defensible like, yeah, I did the work, and it's great, and that's all that's true in the world. That's not reasonable. I'm never going to achieve that. And so, for a long time, there have been moments where I just don't feel great as a result of this, as a result of the standard that I'm trying to hold myself to. But very similarly, I have brought voices into my head. In my case, I've actually identified a board of directors which are random actual people from my world but then also celebrities or fake people, and I will have conversations with them in my head. And that is a true thing about me that I'm now saying on the internet, here we are. STEPH: [laughs] CHRIS: And I'm going to throw it out there. It is fantastic. It is one of my favorite things that I have in my world. As a pointed example of a time that I did this, I was running a race at one point, which I occasionally will run road races. I am not good at it at all. But I was running this particular race. It was a five-mile January race a couple of years back. And I was getting towards the end, and I was just going way faster than I normally do. I was at the four-mile mark, and I was well ahead of pace. I was like, what is this? I was on track to get a personal record. I was like, this is exciting. But I didn't know if I could finish. And so I started to consult the board of directors and just check in with them and see what they would think about this. And I got weirdly emotional, and it was weirdly real is the thing that was very interesting, not like I actually believed that these people were running with me or anything of that nature. But the emotions and the feelings that I was able to build up in that moment were so real and so powerful and useful to me that it was just like, oh, okay, yeah, that's a neat trick. I'm going to hold on to that one. And it has been continuously useful moving forward from that of like, yeah, I can just have random conversations with anyone and find useful things in that and then use that to feel better about how I'm working. STEPH: I so love this idea. And I'm now thinking about who to put on my board of directors. [laughs] CHRIS: I'm telling you, everybody should have one. As I'm saying this, there is definitely a portion of me that is very self-conscious that I'm saying this on the internet because this is probably one of the weirdest things that I do. STEPH: [laughs] CHRIS: But it is so valuable. And it's one of those like; I like getting over that hump of like, well, this is an odd little habit that I have, but the utility that I get from it and the value is great. So highly recommend it. It's a fun game of who gets to go on your board. You can change it out every year. And it is interesting because the more formed picture that you have of the individual, the more you can have a real conversation with them, and that's fun. STEPH: So, as I'm working on forming a board of directors, how do you separate? Is it based on one person is running work and one is finance? How does each person have a role? CHRIS: So there are no rules in this game. [laughs] This is a ridiculous thing that I do. But I find value in it's sort of vaguely the same collection of individuals. Some of them are truly archetypal, even fictitious characters. As long as I can have a picture in my head of them and say, "What would they say in a situation?" If you're considering, say, moving jobs? What would Arnold Schwarzenegger have to say about that? And you'd be surprised the minute you ask it in your head; your brain is surprisingly good at these things. And it's like, let me paint The Terminator yelling at you to get the new job. STEPH: [laughs] CHRIS: Not get to the chopper, but get the new job. And it's surprisingly effective. And so I don't have a compartmentalized like, this is my work crew, this is my life crew. It's a nonsense collection of fake people in my head that I get to talk to. I'm saying this on the internet; here we are. [laughs] STEPH: That makes sense to me, though, because as you're describing that situation, I do something similar, but I've just never thought about it in these concrete terms where I have someone in mind, and it's a real person in my life who are my confidence person. They're the one that I know they are very confident. They're going to push for the best deal for themselves. They're going to look out for themselves. They're going to look out for me. They're going to support me. I have that person. And so, even if I can't talk to them in reality, then I will still channel that energy. And then I have someone else who's like my kind filter, and they're the person that's going to be very supportive. And you make mistakes, and it's not a big deal, and you learn, and you move on. And so I have those different...and in my mind, I just saw them as coaches. Instead of board of directors, I just see them as different things that I don't see as strong in my character. And so I have these coaches in those particular areas that then I will pull energy from to then bolster myself in a particular way or skill. This was fun. I'm so glad we talked about this because that is very insightful to you, and for me as well, and to myself. CHRIS: Yeah, we went deep on this episode. STEPH: No tech but lots of deep personal insight. CHRIS: I talked a little bit about bcrypt. [laughs] You can't stop me from talking about tech for an entire episode. But then I also talked about my board of directors and the conversations I have with myself, so I feel like I rounded it out pretty good. STEPH: It's a very round episode. CHRIS: Yeah, I agree. And with that roundedness, should we wrap up? STEPH: Let's wrap up. CHRIS: The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review on iTunes, as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey. STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Byeeeeeeeeee!!! Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.

    321: Leaving Breadcrumbs

    Play Episode Listen Later Jan 11, 2022 40:20

    Steph tells a cute story about escape artist huskies, and on a technical note, shares a journey in regards to class variables and modules inheritance. Chris talks about how he's starting to pursue analytics and one of the things that he's struggling with that he's always historically struggled with is the idea of historical data. He's also noticed a lack of formalization of certain things and is working with his team to remedy that. This episode is brought to you by ScoutAPM (https://scoutapm.com/bikeshed). Give Scout a try for free today and Scout will donate $5 to the open source project of your choice when you deploy. Mike Burns: How to Skim a Pull Request (https://thoughtbot.com/blog/a-smelly-list) RSpec Documentation (https://rspec.info/documentation/) Don't Let the Internet Dupe You, Event Sourcing is Hard (https://chriskiehl.com/article/event-sourcing-is-hard) Datomic (https://www.datomic.com/) timefora_boolean (https://github.com/calebhearth/time_for_a_boolean) Sentry (https://sentry.io/) Become a Sponsor (https://thoughtbot.com/sponsorship) of The Bike Shed! Transcript: CHRIS: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey. STEPH: And I'm Steph Viccari. CHRIS: And together, we're here to share a bit of what we've learned along the way. So, Steph, it's an entirely new year. What is new in your new year? STEPH: Well, the year is off to an interesting start because we helped rescue a husky. CHRIS: Rescue as in now this is your dog or rescue as in the dog was trapped in a well, and another dog told you about the dog being trapped in a well, and then you helped the trapped? [laughs] Which of those situations are we working with? STEPH: [laughs] I'm really wishing it was the second version [laughs] where there's a dog that tells me about another dog trapped in a well. No, this is a third version where there was a husky that was wandering around the gym that we go to. And so Tim, my husband, called and said that "There's this husky, and he's super sweet, but he seems very lost." And our gym is located near a major road, and so we were worried that he was going to wander about and get hit. So I hopped into our car and took a crate and a leash, and he hopped right in. Clearly, he belonged to somebody; he'd just escaped. So he hops right in, and then we bring him home. But I put him in the backyard because I want to keep him separate from our dog, Utah, just because I don't know this dog, and I want to keep him safe. And I go back inside to grab a few things. I come back out, and the husky is gone. And I'm like, well, shit. [laughs] Now I'm starting to understand why this husky is missing or why this husky seemed lost. So then I started looking for the husky, and Tim comes home. He's helping me look for the husky. And it was one of those awful moments where we live near...it's not a major road, but people tend to speed on it. And the husky and I happen to see each other across the road. And so the husky was like, oh, human friend and starts coming across the road towards me. And there's this large SUV that's also coming from the other direction. I'm like, oh, this is it. This is my nightmare. This is becoming real. This dog is about to get hit. Thankfully, the driver saw the husky and stopped in time, so everything was fine. And the husky just finished trotting across the road to me, brought him in, kept him in the kennel in the garage. We didn't have any backyard adventures after that. The husky then thanked us by howling most of the night. [laughs] So this poor husky has had an adventure. We've had an adventure. And then, around 4:30 in the morning, I go out because I'm checking on the husky and going to let him out. And I'm scrolling on the app called Nextdoor. And I see that someone posted a picture of this exact husky that's like, "Please help me find my dog." And I was like, yes. Because we were going to have to take him to a county shelter or at least go see if he had a chip so then we could return him. But thankfully, we found the owner. I found out the husky's name is Sebastian. And then we had him for a few more hours, and then we had a wonderful husky and human reunion. CHRIS: That story had everything. It had ups; it had downs; it had huskies. It had escape artist huskies, in fact. I have...this is only through Reddit because that's how people learn about things in the world, but huskies are a rather vocal dog breed. So when you say the dog was howling, huskies have a particular way of almost singing, and it kind of sounds like yelling rather than more traditional dog sounds. Was that the experience you had? STEPH: Luckily, it wasn't too bad. His howling was more just; he didn't want to be in the crate. He seems like an indoor dog. So he's like, what am I doing outside in the garage? I should be indoors. And so he wasn't too loud. It was more he was just bemoaning his situation. But our dog Utah could hear him upset in the garage. And so that was also getting Utah upset because he didn't understand why there was a dog so close. And that was what led to the sleepless night because we couldn't get both of them to calm down. Because then, as soon as one of them calm down, the other one would get the other one riled. CHRIS: As it so often happens. STEPH: I'm so grateful that it turned out to be a happy story, though. That part was wonderful. And if we see the husky again, now we know his name is Sebastian and that he'll just come home with us. [chuckles] And we'll know how to return him since he seems to be an escape artist. CHRIS: And we were best friends forever. STEPH: On a more technical note, I have quite the journey to share in regards to class variables and modules inheritance. But before I dive in, I'm curious, what's new in your world? CHRIS: Oh. Well, I'm excited to dig into that story. But I've got two smaller things in my world this week that are top of mind. I don't really have answers on them. I have more questions. One is we're starting to pursue analytics. We want to try and understand our system a little bit better. What is the experience of our users? How are they coming into the system? What are they doing? How long does it take them to do the things that we want them to do? All those sorts of questions you want to be able to answer about your application. And one of the things that I'm struggling with that I've always historically struggled with is the idea of historical data. So data changes over time, and often we actually want to know about those transition points. We want to know about the different states that a user or any record in the system has been in. And I'm finding myself feeling the same pain that I felt many times and starting to think again about the relevant options out there in the world. To give a slightly more pointed example of what we're dealing with, users come in, and then there are a few steps for them to actually sign up for the application. And so their user record or their application, if you will, will go through a couple of different states. So they can be basically approved directly, and now they're an active user of the system, that's one option. But they can also end up in a state where they're pending review. And then eventually, depending on the outcome of that review, whether it's manual or someone intervenes or what have you, then eventually they can transition to either being denied or being accepted. And then they'll again be an active user. And so there's a question now of how many of the users that end up in that pending state end up transitioning into active. And as I looked at the database, I was like, I do not have this information right now. I know their current state. And the logs could tell me all of this. We don't have proper log archiving right now. And I also don't have a system for, like, let me pull down gigabytes of logs and try and sift through that to understand the answer, especially for something domain level like this. But this is one specific example that represents a category of things in my mind. The stuff that I've looked at in this space otherwise is Event Sourcing. So the idea that rather than having a discrete representation of the state of your application, you store every event as an individual log, essentially of like user did X, thing happened, Y occurred. And then, at any given point, you need to know about the state of your system; you just reduce all of those events through some magical reducer that produces the current state. I also very recently read an article called Event sourcing is Hard. So I have that in my head as a counterpoint. This seems like a thing that is non-trivial to do, makes sense for a certain scale. But of course, like anything else, it has its trade-offs. Another thing that I've looked at and never really pursued mostly because it's in a different ecosystem, is Datomic, D-A-T-O-M-I-C, which I think I've mentioned before. But it's a database that actually stores data in this historical format. And so you can ask for the current value, but then you can also ask for what are all the states that this user has been in? And what are the timestamps of those changes? One small thing that we do have that I really like...so this is one example of us; I think leaning into wanting to have more information, higher fidelity information, is often we want to know something like was this ticket paid? Did someone pay for this ticket? And so paid is a BooleanProperty on this ticket record within our system. So the ticket can be held for a little while and eventually gets paid. And now, yes, it has been paid for. It is good. You can use it. But often, we want to know not just that it's paid but when it was paid. And so there's a gem that we are using on the project called timeforaboolean by former thoughtboter, Caleb Hearth. And it does a wonderful job of basically instead of storing a Boolean value in the database, you store a timestamp. But then the Boolean can be inferred. If there is a value, if there's a timestamp for that record in the database, then there are a bunch of helper methods that get introduced that say, like, paid? That's now a method that I can ask, and it will tell us that. But we can also find the paidat, paid_at value. And so we have this higher fidelity data when we need it, but we can also collapse it down to the simpler representation. Because most often, all we need to know is, have they paid for it? Cool, then they're good. They can come into the concert, that sort of thing. But yeah, this is a broader question that I don't have a great answer to. I think Postgres and Rails and just the nature of how we approach these applications pushes us in a certain direction. Another thing I'm exploring is downstream analytic systems. What if I send a bunch of events to them, and they act as a half-event sourcing type thing? But yeah, this is going to be, I think, an open question for me for a while. STEPH: Yeah, you said a lot of really good options. When you're talking about in our ecosystem, we get pushed in one direction or the other that makes me think of the projects that I've been on. Typically, what they'll reach for first is something like a Papertrail. So then, that way, they can check for the historical versions of an object and how it was changed and see who changed it. That's one way to track the logs. I like the idea that if you can outsource it and send all of those events to a logging system and then essentially ask for that data back as you need it. You made me think of a recent project as well where we needed to track the state. So it was a patient matching system. And we really needed to know when a patient match was created or disconnected and then who did that and perhaps for what reason. And to ensure that we had as much information as possible, we took that opportunity to just create a record for it. So we had a patient match record or...I forgot the name of the other one where we created where a patient did not have a match. But we were creating a record every time someone did that. Granted, probably that's not going to happen nearly as often as someone paying for an event or the situations that you're describing. This was ideally infrequently that someone was going to unmatch a patient because it meant that our system had matched people that shouldn't be matched, and then a human had intervened. But yeah, it's interesting the space that you're in. And you listed all the good things that I would have thought of. CHRIS: I think you listed Papertrail, which is one that I hadn't actually thought of yet for this particular instance. This only came up earlier today also. So this is new in my head that I'm really being pushed in this direction. But I think Papertrail could be a good solution for where we're at. But it is one of those where you often don't know the thing you want to know. And I'm terrified of losing data of like; I had the data. I knew it at one point in time, but now I can't reknow it in the future because I didn't write it down. That's one of the things that I just don't want to happen in the world. And so finding those ways of like, how can we architect a system so that we can do the normal, straightforward, boring things most of the time but then when we need to expand out the analytics dimension of the system that we're working on...and trying to thread that needle and find the ideal optimization on both sides is a tricky one. But yeah, I'll definitely take another look at Papertrail and see if that...at a minimum, I think that's a good solution for where we're at now. And then this is going to be a thought that's going to roll around in the back of my head for a while. So if I come up with anything else, perhaps a grander solution, I'll certainly bring that back to The Bike Shed. But yeah, what else is up in your world? I want to hear the story of the class variables. STEPH: Well, it is quite a journey. So I hope you're ready. Specifically, I was pairing with Joël, who was working on fixing a test that had been marked as being skipped for a while. We weren't really sure why. We figured maybe because it's flaky. But then, as Joël had restored that test, he realized it was actually failing consistently. So it was a test that was failing for a reason folks maybe didn't understand, but they decided to cancel or to skip that test. But they didn't actually want to get rid of it because it seemed like a pretty important test based on the description. So Joël saw it and got excited because it seemed very relevant to some of the work he was already doing. So then, he is now investigating why this test is failing consistently. So in this story, we have four main characters: we have a class, two modules, and a class variable. So enter the class stage left. All right, so this class defines a class variable which I have to say is not something I work with very much in Ruby. So class variables kind of felt a bit novel and diving back into like, oh yeah, these are a thing. So the class defines a class variable that's called cache and assigns this variable to an instance of a cache. So then this class includes two modules who we'll call Module A and Module B. And we'll enter them stage right. And both of these models look to see if cache is already set. And if it's not, they also set the cache class variable. So with that information, in our test, we don't want to exercise the real cache just because then if other tests are reading from that cache, which is proving to be a source of flakiness for these tests, then they are overriding each other's expectations, and it's causing some of the tests to flake. So instead, we want to use a fake cache, just like an in-memory cache. So the test and its setup is already overriding. It's setting that class variable to say, hey, I want you to be a fake cache, just be in-memory. However, while executing that test, one of the modules is checking to see if that cache is set, which is being set in our test setup. So test setup sets the value. We're running the test but then in the module, the model checks to see if it's set, and it's suddenly nil instead of using the cache that we had set. So now it's defaulting back to say, "Oh, it's unset. So let me go back and set it to the real cache," which is exactly what we're trying to avoid. So then the question became, if we're setting the class variable in our class, why is it being populated in one of the modules but it's not being populated in the other module? So one of them has it set to the in-memory cache, but the other one does not. So I'm going to gloss over some of the details because this stuff is pretty tangling. But essentially, when the test is running, and it's loading the class, and we are overriding that class variable, it's getting shared with one of the modules because as soon as one of the models does set that class variable, there's a bidirectional link that gets set between the parent class which is the module in this case, and the class itself. And as soon as that module sets the class variable, then they're going to talk to each other, and they're going to reference the same value. However, this only seems to happen for one of the parents. You can't do this for both. So if you have two parents that are trying to share a class variable with the same class, that doesn't work. So that's a particular bug that we were running into. I do have some good news because if anybody is very nervous about the situation that I'm describing, I feel you. The good news is that in Ruby 3, they actually warn when this is happening and have introduced an error. So you don't have this inheritance confusion that can come out of the fact that these parent classes are also trying to share a class variable with this child class. So in Ruby 3, if you are writing a class variable in that class but then you try to overwrite that class variable in the parent of that class or by the module that's being included, then an error is going to be raised. So it's going to warn you if you're creating this bidirectional link between those two class variables and that you shouldn't be overriding the child's ownership of that class variable. Instead, if you're going to use class variables, which, one, is not my cup of tea, but if you're going to use class variables, it should be defined in the parent class, and then it can be shared downstream in the inheritance versus trying to go upstream and then having your ancestors essentially override some of those class variables. So all of that is to say we were on a very interesting journey of understanding how class variables work, how the inheritance works, how that bidirectional link is getting established, and then how Ruby 3 comes in to warn us if something funky is happening. CHRIS: Oh, that is interesting. And I'm now going to catalog that as a piece of information that my brain will retain for roughly the amount of time that we are recording this podcast and then immediately forget. STEPH: As you should. [laughs] CHRIS: It's one of the reasons that I try to avoid inheritance. And I try to avoid class variables as much as possible because of this category of problem, a very subtle bug that you have to try and really hone in. And you have to be very smart to debug this sort of thing. I don't want to be that smart. I want to code in a way that I can be less smart on any given Thursday. That's my goal in life. I will ask one other question, though. So there's just a cache that this class and pair of modules are hanging around with, and then you want to swap it out for in-memory. This sounds remarkably like the Rails cache. Is this cache distinct special? Could it not just be backed by rails.cache, THE cache within the rails context, which can be backed by Memcached, or Redis, or in-memory when you're in tests, or the NullStore, which I think is the default in development is probably how that goes? Is there a particular reason? Is this a special cache? Is there additional behavior that this cache has beyond the normal thing? Or is it just like, at some point, someone's like, oh, I need a cache. I'm just going to use a class variable, that'll be easy, which it definitely is, but then you run into complexities. And caches are one of those hard things to get right. So it's one where I would immediately be like, whoa, whoa, I would love to not make up our own cache here. So I'm wondering, is there a distinct reason, or is it just this happened, and here we are? STEPH: So I think we are using a custom cache that we are pointing to. So it is another service. It's not a Rails cache or an abstraction that we can point to and use. It is a different cache that we are using. And I'm trying to think back to the exact code. But there is a method that essentially checks to say, hey, should I use the real cache? Should I use the in-memory cache? And that is something that we've explored to find a way to make this more global for the test suite because we really want to control this for all the tests. Because it's very easy to not realize in the test that you should avoid using that shared global cache. And so that way, the tests don't interact with each other but instead always use an individualized cache for each test to make sure that it is self-sufficient and independent. But we haven't gotten that far yet in figuring out how we can take a more global approach with this. CHRIS: Gotcha. So I don't know the details. I assume there are reasons here. But just to play this out, if we find ourselves saying we have a reason to have a distinct cache, to have a special cache over here, but it's a cache...and caches fundamentally, that word always will raise my attention. It will be like, okay, this is a place that bugs will come and aggregate. And we need a distinct one that has special behavior as an external service, or that is just something like in... There's a wonderful blog post that Mike Burns wrote at one point that was about...I think it was something like things that will make me look at your pull request in more detail. And I really loved it because it did capsulate all of these like, yeah, there are good reasons to do everything on this list. But if you do any of them, I will look at your pull requests and be like, oh, that's interesting. Why are we doing that, though? Do we have to do that? Are you sure? Are you triple sure we have to do that? And this is definitely one of those things where caches automatically catch my attention. Even if we're using the built-in cache, I'm like, do we need to? Is that a definite thing? And then all the more so when we're using a custom bespoke one. Again, I assume that there are reasons that there's something special that's going on here. Perhaps the caching behavior is distinct from just it's Redis, and we throw data. And if it falls out the backside, that's fine. Maybe you need entirely different behavior here. But it is something that I would poke at a bunch. STEPH: Yeah, you're asking a lot of good questions. I will have to go back and look at some of the code because we spent enough time in Ruby specifics that I didn't pay as much attention to the cache. Because right now, as we are working on these tests, we're trying to fix just the test without changing the application code, one, because that feels like a safer space. And if the test is flaky, we're just trying to change the test first. But some of these tests we're starting to realize I'm not sure we can fix the test without also changing some of the application code, or the way that we do have to fix the test is really an incentive to back up and say maybe now's the time that we look at some of the application code. Because another question that comes to mind is why use a class variable, and does this need to be shared by the class and the modules? And there's a part of me that suspects that maybe some of this logic was extracted to a module, but then it wasn't cleaned up in the other places. And so that's why we still have a reference. And it's essentially then being shared and set and unset and reset in those different places. So I think you ask some good questions, and I have some more questions of my own when we have time to revisit that portion of the test and application. As another example of some of the tests that I've been working on, one of the tests that I...because we have a list, we can usually tell some of the tests that are flaky. So one of the ones that I was investigating was a similar issue where there was a shared resource, and someone had tried to mock it out. So they had taken the time to say, hey, I don't actually want to use that real resource that's over there; instead, I want to just return the scanned value. But instead, they'd accidentally stubbed out a class-level method instead of the instance-level method. And so it was running, but it wasn't actually stubbing anything else since that's the method that's not getting called. So that was just an oversight for that test. So I fixed that test. But I noticed that we were using allow any instance of, so then I did take the time to go through that file and change and move away from the use of allow any instance of. And for folks that are less familiar with allow any instance of, RSpec has some really great docs that talk about how it's very helpful for dealing with legacy code. But essentially, it is a code smell that you're using; allow any instance of because you are saying that my test is or my code is so complex that I can't really mock out the specific instances that I want to and then return specific behavior. So instead, I'm having to use this more global approach to say, hey, any instance of this method, I want you to mock it out versus this very specific instance that I know that I'm working with. But we can include a link in the show notes because there's a nice write-up that talks about some of the reasons that allow any instance of is not recommended. So that's been kind of fun. There's been a little bit of joy to get to refactor away from that and actually stub out a specific instance. Part of the work, too, that I'm noticing as Joël and I are going through these tests is leaving breadcrumbs for other developers as well because they have a very large team. And they're very junior friendly, which is just incredible. I love that so much about this company. And because they do hire a lot of juniors, then it is a tough codebase. It's a fairly old codebase. So as these juniors are coming in, they're seeing a lot of these patterns. And they're propagating these old patterns that aren't necessarily the best patterns to propagate. But they're doing their best, and then they are reusing what they're seeing. So part of the work as we are revising these tests, my hope is that people will see some of these newer patterns and use those instead of following some of the older patterns. CHRIS: I can only imagine that you're writing borderline novels in your pull request descriptions and commit messages there. I do wonder, is there an index of those that you're collecting? So there's like, here's the test remediation examples list, and you're slowly adding to them. This was a weird one with a class variable. And this was a weird one that had flakiness due to waiting or asynchronous behavior. And gathering examples of those, but specifically from the codebase. I could see that being a really useful artifact because I happily traverse through git blame all the time. But I don't know that that's always a thing. And frankly, I have to work for it sometimes. So if there is that list of here are pull requests that specifically did X, Y, and Z, I think that could be super useful. STEPH: Yeah, that's a great idea. And yes, they have some shared team documentation that speaks to specifically flaky tests because they're aware that this is a problem. They are working together to address this. And they have documentation that states ways to avoid flaky tests. If you encounter a flaky test, here are some of the ways that you can triage to find out what's wrong. So as Joël and I have been finding good examples, then we've been contributing to that document. And they also have team meetings. So our plan is to attend some of those meetings and be like, "Hey, this is just some of the stuff that we've seen this week, some of the things that we improved and changed," and share the progress that we're making. Since everyone is aware that there are these developers that are working hard to improve the test suite, but then share that information with the rest of the team so they too can feel...one, they can just see the changes that are taking place. But they too can also benefit and apply those strategies themselves when they see a flaky test. Oh, but you did just remind me of a thing. So one of the tests that I was going through...I'm very intentionally going through and making the smallest change possible. So I will do the gross, ugly fix whatever it is to get something to pass, and then I will commit it. And then I'll think about okay, well, how can I make this better? So essentially, I have the fix, whether it's pretty or not. And then, after that, I start to have other commits that make it prettier. And so, I had a pull request that had four commits that told the story that I was very happy about and progressed along in a more positive direction. And I issued that, and I discovered that Gerrit, when it sees four commits, it split all of them into their own change request. And so, instead of having what I thought would be this nice story, now got split across these four change requests. And I thought, well, that's less helpful. So I ended up squashing two of them, but I still kept three of them because they stood alone, and each told a story. But that's something that I've learned about Gerrit. CHRIS: Always so interesting how our tools shape our work. STEPH: And it made me think back to the listener who asked the question about ensuring that CI runs for each commit. Well, here you go, Gerrit. [chuckles] Gerrit does it for you. It ensures that every commit gets split into its own change request. CHRIS: I mean, as you said earlier, not my cup of tea but... [laughs] STEPH: Yeah, I'm still lukewarm. I'm still discovering Gerrit and how we get along. Mid-roll Ad And now a quick break to hear from today's sponsor, Scout APM. Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more. Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform. See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed. What else is going on in your world? CHRIS: In my world, we keep adding new users to the system. We keep doing more stuff. These are all wonderful things, the direction you certainly want to be heading. But as we're doing that, I've recognized that we had a lack of process and a lack of formalization of certain things. And a lot of the noise of the work was just coming to me because I was the person that everybody knew. I can ask a question; Chris will know the answer, et cetera. And then there were things that we needed to keep an eye on. But because it was everyone's job, it was no one's job. So we've introduced the idea of a point person on the engineering team. So this is a role that will rotate each week. I think you and I have worked on a handful of projects that had something similar to this. There was a team that we worked with that had an ad hoc list, which were just little tasks that needed to be done by developers. So there was one person who would run with that. I've heard it called captain before, the sprint captain. We're not really doing sprints. So for various reasons, that title didn't work for me. But point person is what I went with here. And so the idea is rather than having product management or anyone else in the organization just individually reaching out to developers, we want to try and choke that off, have a single point of communication. And so just today, I introduced into Slack, a group, but it's a group of one person. So @pointdev is technically the handle for this person. It's a group in Slack. And each week, we'll rotate who the members of that team are. And technically, you could add multiple, but the idea is this is just one person. So we'll rotate the person. And what ends up happening is if anyone...say the product manager says, "@pointdev, what's the status on..." blah, blah, blah, that will notify the person who is the point person that week. So that's a nice feature in Slack so that we can condense it down and say rather than asking individuals, ask this alias. We're introducing one layer of abstraction in our communication tools, much like we do in our software. So I'm drafting now the list of like, here's all the stuff that I think this person...because we're trying to push all of the quote, unquote, "other work" the non-product feature development work into this person's purview for a given week. So it's monitor Sentry for any new errors as they come up, triage them, and figure out what we want to do. Ideally, and this is perhaps aspirational, I would like to keep inbox zero in Sentry. I know how you feel about that more generally and perhaps even more specifically within the world of errors, but that's my dream. We're going to see how it goes. STEPH: I don't know if people know I am the opposite of inbox zero. This is the life that I'm living. CHRIS: What about with errors, though? What about something like Sentry? STEPH: I want to say that I would be a better human with my email. But I'm going, to be honest [laughs] and say that I would probably have the same approach where I am not an inbox zero person. I've come to terms with it. I used to really strive and think I needed to change. But I have reached a point of comfort with this is who I am. There are many like us, so shout out to all y'all. CHRIS: Oh yeah, by far the more common approach, I think. So specifically with the errors, I struggle a bit with it because what ends up happening is we are implicitly ignoring the errors. And if we're doing that, I would rather just sit around and have a conversation and be like, let's just explicitly ignore them. There's a button in the UI. We can ignore them. If this is not a real error, we can add it to the list of things that we do not report on. We can ignore that error. We can ignore it for a week and add a card to Trello that has a due date that says, "Hey, we got to work on this." But let's take that implicit indifference to that particular error mode of our application and make it explicit. Let's draw that line in the sand such that when I see a new error pop up, I'm like, oh, that seems like something I should do something about. I really want high signal-to-noise when I'm seeing errors coming. And so I'm willing to work for that. But it is a trade-off, and it does take effort. And it's noisy, especially browser extensions, and whatnot, just fighting the page. Facebook showed up one day. I don't know how Facebook got in there. Someone was browsing our website from within Facebook's browser, which I didn't know was a thing, but they had their own thing. And it fires a bunch of events, and Sentry was just like, let me slurp all of those up. Those seem fun. That was noisy. So we had to turn those off, but we explicitly turned them off. STEPH: I do like the approach that you're taking where it's one person, and then it's a rotating shift because I think that makes it more reasonable for someone's who's like, hey, this is going to be noisy for a week. And then you're going to look through these emails and check all these errors, and then either silence them because you don't think that they're interesting or mute them for now. Or if you're going to convert it into a ticket, set a due date, whatever the triage approach is going to be. But that feels more achievable versus inbox zero for life is just exhausting. But I feel like if you're doing it rotating week by week, that seems like a nice approach and also easier to keep it at inbox zero because that way, you are keeping up with all the errors. Because I agree; otherwise, what's the point of tracking all the errors if you're just going to ignore them? CHRIS: Yeah, definitely the rotating, I think, is critical. I think the other thing that's been critical specifically on the error front is we've had now a handful of meetings where we triage the backlog together, the backlog of errors. So like, what all is coming into Sentry? What's going on? And we go through the process of determining is this a real thing? Should we fix this? Should we ignore it? And we do that together so that it becomes not just one person's intuition about whether or not this is important or not or what the source of it might be but a shared intuition such that now any one of us, when it's our week, can ideally represent the team in that way and be like, never mind, never tell us about this again because it's very easy to silence things in Sentry that you would actually like to know about when they become real. But right now, we have this edge case that is an ignorable version. So trying to get there that's been fun. But yeah, once again, Sentry, that's one of the things on this person's list. There are ad hoc support tickets for our operations team. So anything that needs to happen on a user's behalf that currently needs a developer to console, let's funnel all of those to this one individual, respond to any new questions. So this is where that Slack handle will be useful. Check for any stuck jobs in Sidekiq. So is there anything that's been retrying for a while? Because it probably shouldn't. Maybe one or two retries is cool, but past that, something has gone wrong. And we should either get in there and fix it or just kill that job because it's never going to succeed, which is quite often the case but go in there and keep an eye on those and then look for anything. We're starting to use due dates within Trello, which is currently our project management system. We'll see. Someday we're definitely going to grow out of that. But for now, it's good enough and checking for anything that's overdue or coming up in the next week in terms of due dates and just making sure that we're being responsive to that. And so, I really like the idea of having this be a named set of things and a singular focus for one individual. Because again, that idea of like, if it's everybody's job, it's nobody's job. Or if it's nobody's job, then it's my job, and I don't want it to exclusively be my job. [chuckles] So I'm trying to make it not exclusively my job and to share the knowledge about it and make sure that these are skills that we all have and ideas and et cetera. But also, I would be fine to answer fewer questions in Slack each day. STEPH: I have to admit, as soon as you were telling me that you had established this role, I was quietly congratulating you on helping delegate some of these responsibilities to the team. Because like you said, you are then the person that takes on all these tasks. CHRIS: There's a laziness to that. Like, it's easy for me to just answer the questions. It's harder for me to put up a wall and say, "No, no, we have a process for this." And quite possibly, what's going to happen behind the scenes is that questions are going to come in to whoever is this point person. They're not going to know the answer. They're going to reach out to me, and then that conversation is still going to happen. But even by doing that now, now that person will see that answer, will understand the thinking or the background, the context that I have. And so it's that weird thing of like, it would be so much easier for me to just answer one question. But to answer all the questions, well, I can't do that. And so I'm working to try and do more of the delegation to try and hand things off when they're in a known state and to identify this sort of stuff so that the team broadly can be stronger and better able to support everyone else in the organization. So that's the dream. We'll see how it goes. STEPH: Yeah, I love that approach. I'm also thinking how interesting this role is because I'm imagining a mix between someone who is like the front point person at like an ER. So like, things are coming in, and they're in a tragic state and need help and need to be diagnosed. But at the same time, you mentioned they're going around. They're checking Sidekiq. They're looking at some email errors. So they're also that night shift guard that's walking around with a flashlight just poking in each room. So it seems like a very stressful and low-key role all at the same time, all mixed up into one week. That person probably needs a beer at the end of the week. CHRIS: There is a version of the story in my head that is...I wouldn't say this feels like a failure mode, but I would rather this not have to exist at all. I would rather things to be calmly humming along and not require a dedicated person each week to deal with the noise. I don't think that's realistic, certainly not as early on as we are in our organization. But I do wonder, is this a crutch? Is this something that we should be paying more attention to? And I know in teams that you and I have worked with in the past that has been a recognition of like, this is a crutch. But it's a costly crutch. Like, we're taking an entire...in our case, it's not requiring the entirety of a developer's week. They're able to do this pretty easily and then still get a bunch...like, 75% of their time is still feature work. But we're just choking down who's the person that will be responding to questions when they pop up so that fewer individuals are interrupted? But I have seen organizations where this definitely filled an entire week and spilled out more than. And then there was the recognition of that and the addition of another person that comes along and tries to fix stuff along the way as opposed to just responding. And so I want to make sure this isn't a band-aid but is, in fact, a necessary layer that we then try and shore up, you know, we should have fewer errors. That feels true. Okay, cool. Let's fix the bugs in the app. And these ad hoc things that an admin needs to have done can that be a button in the UI? Can they actually self-serve in those cases? And we're slowly moving towards those. Ideally, fewer jobs get stuck in Sidekiq. And so, my hope is that this isn't a job that gets harder and harder over time. It's a job that potentially, if we're being honest, probably stays about this hard. I don't think it's ever going to be just like, nope, nobody needs to do anything. The app just runs, and it's great. And it never has bugs. But that is a question in my mind as I start to embrace this thing of like one person is dedicated for a week to this. And if right now it's only 25% of their time, okay, that's probably fine. But if suddenly it's 50% of their time or 75% or 100% of their time for that whole week, that becomes too high of a bar in my mind. And I want to keep a close eye on it and make sure it's not trending in that direction. And I will be one of the people on the rotation. So I'll get to be in the trenches. STEPH: I appreciate all the thoughtfulness that you're putting into it. And I'm thinking back on a project where we had a similar rotation because we had an issue Slack channel. And so anytime there was an issue, then it would get posted in there. And before, it was going out to everyone, or there was one particular person that was always picking it up and then trying to delegate it to others as they needed to. But then we started a similar rotation. And one of the key benefits that I found from that is it signaled to the team, hey, this person might get pulled away. They can pick another ticket or two, but we need to give them lower priority tickets because there's a chance that they're going to get pulled away to work on something else. And that's okay, and we're going to plan for it. Versus without this role in mind, then you had people all taking on high priority tickets, but then someone had to be the one that's like, well, I'm going to punt on my high priority and feel stressed about the fact that I've got this other thing to deal with. But then, I didn't actually do the work that I planned for. So I feel like you're helping introduce calmness into the week, even if it is a stressful role. But then there's the goal that this becomes less of a stressful role, and if you see it trending in the opposite direction, then that's something to investigate. But I also feel like triage and communication is such an important part of being a developer that it also feels very relevant upskilling for the whole team to go through. So there's also that benefit of where this approach also empowers the rest of the team to also experiences, build empathy, look for additional fixes, and then also build these important skills. Overall, I really applaud your thoughtfulness. And I think it's a really good idea. And it will be interesting to see which direction that this role trends if it gets easier or if it's getting harder over time. CHRIS: Well, thanks. I appreciate that. And I'll certainly report back as we develop this but hopefully, it stays about where it is. That feels right. And I think I'll probably...that's one of those things that I will monitor. And if I feel it moving in the wrong direction, then step in and try and get it back to this space because this feels like a maintainable reasonable amount. And we shouldn't be fixing every bug and adding every button to the UI. That's just actually not how it works, unfortunately, would love to. That's not true. You shouldn't have every button in the UI. That's so many buttons. But broadly, I hope we can maintain roughly this, and I think identifying it and laying it out now I'm feeling good about having that structure. So yeah, we'll see how it goes. Will report back. But again, thank you for the kind words. With that tour of a bunch of different things, should we wrap up? STEPH: Let's wrap up. CHRIS: The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review on iTunes as it really helps other people find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey. STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Byeeeeeeeee!!!!! Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.

    320: Remember The Fun: 2021 Recap

    Play Episode Listen Later Dec 21, 2021 34:02

    Steph and Chris recap their favorite things of 2019 and 2020 and share their 2021 list. Happy Holidays, y'all! Steph: * Feature flags and calm deploys * Creating observable systems * Debugging * Working in seasons * Don't forget the fun “The longer I'm in the software game, the more I want things to be calm” - Steph Chris: * Pushing logic back to the server * Svelte (https://svelte.dev/) * Remote work (but maybe hybrid!) * Vim * Joining a startup as CTO This episode is brought to you by ScoutAPM (https://scoutapm.com/bikeshed). Give Scout a try for free today and Scout will donate $5 to the open source project of your choice when you deploy. Listen to episodes from 2020 and 2019

    319: Wins & Losses

    Play Episode Listen Later Dec 14, 2021 35:20

    Steph started a new project and shares details about the new tools she's using, including working on a remote dev environment. Chris shares a journey with Lograge and Rails flash messages as he strives to capture user-facing errors. They also discuss "silencing" flaky tests, using Graphviz to visualize data dependencies, and porting Devise views to use Inertia and Svelte. It's also interesting how different their paths have been this year! This episode is brought to you by ScoutAPM (https://scoutapm.com/bikeshed). Give Scout a try for free today and Scout will donate $5 to the open source project of your choice when you deploy. Joel Quenneville (https://twitter.com/joelquen) GitHub - roidrage/lograge: An attempt to tame Rails' default policy to log everything (https://github.com/roidrage/lograge) Graphviz (https://graphviz.org/) Become a Sponsor (https://thoughtbot.com/sponsorship) of The Bike Shed! Transcript: CHRIS: Tech talk nonsense and songs, that's what people come to The Bike Shed for, variations on the Jurassic Park theme song, you know, normal stuff. Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey. STEPH: And I'm Steph Viccari. CHRIS: And together, we're here to share a bit of what we've learned along the way. So, Steph, what's new in your world? STEPH: Hey, Chris. Let's see. So I've started a new project. So frankly, there's a ton of new stuff in my world. And I've been on the project for about a week and a half now. I started over the holiday, and it's been going really well. Still in that whole early stage with getting to know the application, the codebase, the processes, the team, all the dynamics. It's a large company. So I'm working with a small group of individuals, but there are about over 100 developers that work at this company. And they do have a lot of documentation, which has been very helpful. But there's a lot to learn in terms of setup and processes, specifically. So they have provided a laptop that I'm using to access their codebase. So I'm using their laptop. And then, I am also using a dev machine, a remote dev machine, that they have set up for me. So I need to be on their VPN and SSH into that dev machine. So that's novel as well. CHRIS: Ooh, I'm very intrigued by that bit, not that they gave you a laptop bit but the dev machine. This is in the cloud sort of thing? What is this? I'm very intrigued. STEPH: I don't know if I have concrete answers for you. But yes, for me to be able to access their codebase, I have to go into the dev machine. And then that's where then I can do my normal development work. CHRIS: So is this like an EC2 instance or something like that that you're SSH-ing into, and then you can run processes on it? Or is it closer to the GitHub dev containers thing that they just released? Or are you running with your local Vim? Is it a remote Vim? Are you using Vim? Is it VS Code? I have so many questions. STEPH: [laughs] I think it's more like the first version, although I don't know the backbone of it. I don't know specifically if it's an EC2 instance or exactly how it's being hosted and how I have access to it. But I did have to set everything up on it. So they started the dev machine up for me. Their DevOps team started an environment where then I could access, and then I did need to cultivate it to my own habits. So I had to install several things. I had to install Brew and Vim and also the tmux and all those configurations that I'd really like to have. They do have a really nice Confluence document that walks you through how to set up a connection between VS Code and the remote environment. So then that way, you can really just hang out in VS Code all day. And initially, I was like, okay, I could do this. And immediately, I was like, no, I love Vim. I'm going back to it even if I have to spend the 20, 30 minutes setting it up. I'm so comfortable with Vim and tmux that I stuck to my roots, and I didn't branch out into VS Code. But I think VS Code is one of the more popular tools that they're using. So that way, it feels more local versus having to work in a remote machine. I think I answered some of your questions. I don't think I answered all of them. CHRIS: Yes. I think you did answer all the questions. But just for clarification, the Vim and tmux and whatnot setup is that you're running SSH, and then on the remote machine, you are using Vim and tmux? Or is it a local Vim that is doing…I think Vim has some remote editing capabilities but not anywhere near what VS Code can do. STEPH: It's the first setup. So I am SSH-ed in. And then I have Vim and tmux running on that remote machine. CHRIS: Gotcha. Novel. STEPH: Yeah, it's a thing. It's working. So that's good. And it feels cozy. I feel like I'm at home. I feel like I can be productive. So that's great as well. Some of the other tools that I'm also new to, so they use Zeus, which is used to then speed up the booting of your application. And you can also use it for speeding up test runs. So very similar to Spring, which I think we've had some discussions about Spring and who loves it and who doesn't. [laughs] CHRIS: I don't know. I'm not...[chuckles] I feel like I remember Zeus. But Zeus is like three iterations ago of this preloader thing. I'm intrigued by that. I thought Spring had fully supplanted it in the Rails ecosystem but maybe not. STEPH: So this company has been around for a very long time. So there are a number of tools that I think they're using because that was the tool to use the day when they got started. And then it just hasn't been a need to move on to one of the newer tools to use Spring. So at least that's my current explanation for why we're using Zeus. And also, Zeus works most of the time. I'm frankly still getting comfortable with it. [laughs] I still have gripes about Spring too. CHRIS: 60% of the time, they work most of the time. STEPH: [laughs] So, Zeus is another new tool that I'm adding to my tool belt during this engagement. Another new tool that I'm using is Gerrit. And so they use Gerrit…it is used for managing their Git repositories. It is used for code reviews. And being as accustomed and familiar with GitHub as I am, that one has been a little tricky to then navigate and change the whole UI that I'm used to when it comes to pushing up code, reviewing code, asking for feedback on changes. And at one point, I was reviewing a change request for someone else. And there's a button on there where I was adding comments, but they were in draft mode. And I'm trying to figure out how to get them out of draft mode so that they're actually submitted, and the other person could see it. And I saw a submit button. I was like, cool. So I hit the submit button. And then it said something in red text about ready to be merged into main. [laughs] I was like, oh, no, I mean, maybe, but that's not what I meant to do. So I had to reach out to that person and be like, "Hey, I'm new to Gerrit. I don't know what I did. I hit a button. I hope everything's fine. Here's my review. Best of luck. [laughs] I think everything is fine. Nothing dramatic came out of it. But I had my own little dramatic moment. CHRIS: Wow, that is a bunch of new stuff. It's interesting. On the one hand, I totally understand projects get started, and there's a certain set of tools that are current at that point, and so then you're using them. And then, over time, it takes a very active effort to try and keep up with the new current, that new-new as we call it. But the trade-off there is really interesting because, at any given time, it never feels like the right investment to pursue the new thing to just upgrade for upgrading sake. But then the counterpoint is the cost to someone like you coming onto the project. And it's like, it's a bunch of new stuff. It's kind of old stuff. It's new for me, but it is old, and less documented, and less familiar. And it's also certainly less compatible with other things that are going on, almost certainly. And so, how to stay on top of those updates is always the thing that's really intriguing to me. I say as someone who started a project recently, and I have not thought about upgrading anything at this point. And we have bundler-audit I want to say is the one thing that we have in there. So if there's a CVE for a gem, then security-wise, we will be upgrading those. But otherwise, I haven't thought about upgrading our Ruby version or anything. And I think we're on 2.6 or something like that, which is a couple back at this point. And so it's something that's in the back of my mind. I feel like I should have a formal answer to this. Like, company-wide, how do we think about the process of upgrading? And Dependabot and things like that answers some of it, but that doesn't tell me when to upgrade Ruby, I don't think. It could. That would be annoying. I don't want that. But it's one of those many things that depends and is subtle. And you have to decide where you put the trade-offs and whatnot. So just an interesting thing. And to observe you now going into this project building and being like, there's a bunch of new stuff. STEPH: I think it really takes passion or pain. Those are the two things that then prompt us to upgrade. Either it's pain, and you need to change it to get rid of that, or it's passion. So you're really excited about the next version of Ruby or the next version of Rails. And I think that's fine. I think that's fine that those are often our drivers. But yeah, that is interesting. I hadn't really thought about that in terms of there's often no real strict process around when we upgrade except those are then the natural human catalyst. CHRIS: I think you're right that those are the catalysts. But I think quite often those cannot be sufficient to push us to do the work. And so what do you do in the absence of that? It's not really painful. And I'm not really passionate about it. But I probably should do it is the 80% of the time middle space that we live in. And so yeah, I don't have an answer to it. I'm more observing the question. But like so many other things, I feel like often we just exist in that awkward middle and got to find a way through, so how like life. STEPH: I was having a conversation with someone earlier a bit about these life cycles that we live in. Specifically, we were talking about consulting and how changing from project to project is so daunting. Because you go from I'm accustomed to this project, I'm accustomed to the team. And then all of a sudden you jump into this new project and with all these new things it can be really interesting. But then there's also this feeling of like, wait, I used to be smart, and I knew everything that was going on. And the team knew me, and I knew all the team processes, and I felt good. And now I'm in this totally new space, and I have to relearn, and I have to reprove myself and relearn all the company politics. And there's always that initial jumping from a sure space over to a very new space that always makes me then question and be like, yeah, I can do this, right? I can do this. And then I have to keep letting that voice build until about two weeks in. And I'm like, oh okay, I'm back in a good spot. I said two weeks; it's probably more like four. But there's still that grace period of a new project where you're leveling up on all the things and learning the new team. And as daunting as it is; apparently, it's what I like. Apparently, I like that roller coaster ride that comes from jumping from one project to the next. So on that note of a bit of novel insight into myself, what's new in your world? CHRIS: What is new in my world? Let's see. I think I've got two updates, two anecdotes to share. One, I lost the battle, one I won the battle. So we'll go with the lost battle first because that seems fun. So we have Lograge on this application, which Lograge, for anyone that's not familiar, is a library that helps with producing more structured and more complete log lines from a Rails application. You can tell it to do JSON log lines, which is useful for many of the tools that will receive your logs. And then with it, you can say grab me the controller name and the params but sanitized and this and that. And so, you aggregate a bunch more data than would traditionally be in the logs. In general, I've just found it to be a much better foundation. I find the logs to be more readable, and more informative, more useful, all those lovely things. But slowly, I've been looking at what's the other stuff that I want to have in here? What else would be nice to know? So one example is we use Inertia on this project. And Inertia has a particular way in which errors get mapped back to the front end. And it's an interesting little trick that involves the session, but that's sort of an aside. Basically, this is something that the user will see that I would love to know about. So how many users are hitting their head against the wall? Because typically, whenever these errors happen, that means this is a flash message or something like that we're going to show to the user. So we were able to add that into our log lines. Now we can see those. We can aggregate on them. We can do counts. We can do alerting and monitoring, all those kinds of fun things. So cool. That was great. That worked well. I then specifically…I mentioned the flash a second ago, but that's actually not…the Inertia messages will not show up in the flash. They end up in forms inline on certain inputs or whatnot. But we do also use the flash message pretty regularly as a way to communicate to the user success or failure or what have you. And I really wanted to get those into the logs. And I tried very hard, and I failed. I gave up. I threw in the towel. I raised the white flag. So the nature of the flash, which is something that knew in the back of my mind but I had never really experienced as pointedly as this, is the flash is a magic value within the Rails ecosystem that can be written to and then once read clears itself. That's the nature of how the flash is supposed to work. And it persists across requests. So it's doing some fun stuff there, which I assume is tunneling through the session or maybe putting it into a cookie. I'm not actually sure. But there's some way that you post to an endpoint, and then you get redirected to the show page. And on the show page, we actually display that flash value. But the flash is set on the controller endpoint that is handling the POST request. So this value spans across two request-response life cycles, which is interesting. And so the manner in which that works is Rails is managing that on our behalf. We write to it on the one side. And then, when we do the subsequent requests, if there's a value in the flash, we show it to the user, which is why occasionally you'll see those weird things where that flash message shouldn't show up. But it's like a sticky value that was left in the system that didn't get cleared via one thing or another. But I really wanted to put those into the logs. Like, what are we saying to the user is the thing I want to know. This is that question of like, what's my system doing at runtime? I understand what it's doing. I can read the code and understand what should happen. But what actually happened? Are users seeing this flash message way more than they should? That's a question I want to be able to answer. And I have lost the battle. I cannot find a way to read the flash value, put it into my loglines, but then also have it persist through. The first attempt I did, I was able to get it into my loglines, but then it didn't show to the user, which is a bad outcome. Because now I've read the value, Rails clears it, cool, that's fine. There is a flash.keep method. And that I thought would do the thing I wanted, which is like, oh, I want to read this value. I want to tap this value, I want to observe it, I want to peek at it. And I thought this keep method would do the thing that I wanted. It did not. It just caused the flash to be persistent. So now, anywhere I went had the same flash message for forever, which was not the behavior that I was looking for. I then tried, like, all right, just for exploration purposes, what if I reach inside and read the instance variables of the flash objects? Also did not work. Everything I tried did not work. And it had these fun failure modes that just made me very sad. Thankfully, we had feature specs that told me about this failure mode because I would not have known about it otherwise. This was not obvious to me on first implementation. But yeah, I lost, and I feel sad. And then I did the thing that we do, which is I searched Google, and there's nothing. I cannot find…This is one of those cases where like, I can't be the first person who wants to know what's in the flash. I can't be breaking new ground here. And yet I couldn't find anything on the internet. So that's where I'm at. STEPH: That's interesting. Yeah, I'm trying to think…I think I'm one of those people. I don't think I've ever tried to peek into the flash and see what's there ahead of time. And it makes me wonder if it's partially…so we can't peek into the flash. You've exhausted several examples or tries there. When you're setting the value of the flash, it makes me wonder if there's an order of operations that you have to pursue. So before you set the flash, you know what messages that you're going to share. So you send that off to the logs, but then also share that to the flash. So instead of writing the message directly to the flash and then having to check the flash, if you just stored that value elsewhere and shared it to the logs first. Is that a reasonable approach? CHRIS: It definitely could work. But that was in the space of this is getting weird enough. I thought about things like that, but I didn't want to do anything weird. And part of the benefit that I get from using Lograge is rather than having multiple lines for each request…so a request came in and rendered this partial and did this thing. It gets constructed such that there's a single logline, which is one big JSON object that contains all of the data about that request. And I really liked that structure because then everything's correlated like, oh, did we 404, or did we 302? And what was the message that we said to the user? And what were the params? It's all there in one line. I found that to be really useful. So I wanted to do that. I could just separately log it. But then I'm also worried of there is a statefulness there. Because again, the flash is written on one side and read on the…it's like a Hail Mary to ourselves between requests. Look at me with a sports reference. And so, I didn't want to try anything out of the ordinary. I really just wanted to find a way to just like; I just want to read this value but not like Heisenberg uncertainty principle observing changes in the system. I found myself in that space, and I was like, can't there be a way that I can just flash.peek? And I just want to take a quick look. I don't want to mess with anything. You do your normal thing, flash. Just let me know. And I do not have an answer for it yet. And for now, this is one of those nice to have, not an absolute requirement. So I wasn't yet in the position of okay, fine, let's do some out-of-the-box ideas here. So I'm still in the in the box phase, I would say, but who knows? Maybe down the road, I'll be like; I would really love to know what the flash message was for that request because this user is seeing stuff that we do not understand. And that information would tell us the answer. So we're not there yet. But I was surprised by how thoroughly I was defeated by Rails and the flash message on this adventure. STEPH: I am equally surprised. I wouldn't have thought that particular achievement would have or is proving to be that hard or, frankly, not doable. So yeah, I'm intrigued to see if anybody has thoughts on it or if you do find a different solution because Lograge is one that I haven't used. But I would be surprised if other people haven't had a similar request of like; I want to be able to store what's in the flash message. Because like you said, that seems super helpful. CHRIS: Well, certainly, if I do figure anything out, then I will share that with the world. But yes, part of this is putting it out there into the universe. And if the universe happens to send me back an answer, I will happily accept that. But yeah, again, I had two stories, and that was the one where I lost. I'm going to send it back over to you because I'm interested in anything else that's up in your world. And later, I'll tell the story of a victory. Mid-roll Ad And now a quick break to hear from today's sponsor, Scout APM. Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more. Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform. See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed. STEPH: I have a victory that I can share as well, and I'm excited to hear about yours. So to share a bit more context about the project that I'm on, we are focused very heavily on improving their test suite, not only the time that it takes to run the test suite but predominantly addressing a lot of the flaky tests that they have. Because that is a huge pain point for the team and often leads to the team having to rerun tests. And so, there are a couple of areas that we're very excited to make some contributions. The first part is that we are just looking at those flaky tests to figure out what is going on and how can we address these? And one of the nice things, one of the tools that they're using TeamCity is the tooling that they're using to run their automated test suite. And TeamCity will let you mute tests, so then that way, if you do encounter a flaky test, you can mute it. So then, at least it's not impacting other people. I say this with some asterisks that go along with it because, for people who can't see, Chris is making a very interesting face. I think you have thoughts on this. And the other thing that they will show is a flip rate for the flaky tests, which is really nice, too, because then you can see which tests are flaky the most. So then that helps us prioritize which ones we want to look into. All right, I'm going to pause so you can respond to that comment I made about muting tests. CHRIS: I'm intrigued. I talked in a recent episode about adding RSpec::Retry. So the idea of flakiness being a thing that exists and trying to decide how much engineering effort to apply to fixing it. But the idea of muting it and especially muting it in the UI, not in the test suite or not having that be something that's committed, there's something about that that caught my attention, and thus apparently, my eyebrows raised. You saw that. [laughs] But I don't actually know how I feel about it. This is such a complicated, murky area that I wish I had a stronger set of beliefs around. It was interesting when we talked about the RSpec::Retry thing. I think you rightly pushed back on me, and you were like, that's interesting, maybe don't do that. And I was like, that's a fair point. [laughs] And so now hearing you're in the quagmire of flaky tests, and yeah, it's an interesting space. STEPH: Well, I think my hard belief is that muting tests is a thing that we shouldn't do. It's going to lead to more problems, and you're not really addressing the issue that you have. It is a temporary solution to a much bigger problem that you have. And so it is a tool that you can use to then buy you some more time. And so that is the space that this team is in where they have used this particular tool to buy them more time and to be able to keep shipping changes while realizing that they do still need to address these underlying issues. So it is a tricky space to be in where essentially, you've gotten to the point that you do have these muted tests. It is a way to help you keep going forward, but you are going to have to come back to it at some point. And so that's the space that I'm in right now joining the team is that we have been brought in to help some of their engineers specifically address this issue while ideally letting the rest of the team continue to focus on shipping changes while we address the test. Although I really think there's going to be two angles that we've talked about in how we're going to help this particular codebase. One of them is that we are going to address a flaky test. But the other one is empowering people that they feel like they have the time and the knowledge that they can address a flaky test and also not contribute more flaky tests to the codebase. But I appreciate that you called me on that a bit because we've had those conversations around when we should actually address something versus muted, all the interesting trade-offs that come along with that conversation. So this particular flaky test that we addressed earlier this week is specific to hard coding primary IDs. The short version is that it's bad, don't do it. The longer version is that they were having a test that was failing intermittently because it would pass the first two runs, but then it would start to fail for all future runs. And the reason it would pass for the first two runs is because when they were setting the ID for a record that the test setup is creating, they were looking for existing records and saying, "Hey, what's your latest ID?" And then I'm going to guess the next ID. I'm going to add one to that to figure out what the next ID should be. Some additional context, when the tests boot up, there's some data that's being created before the test run. So then that's why they're checking to see, okay, what records already exist? And then let's add one to that. The reason that fails sometimes is because then once the tests have run, the Postgres IDs aren't being reset, so they're using a truncate approach. So then, when the test runs once or twice, that works. But then, at some point, there's a collision between those IDs where they tried to guess the next ID, but then Postgres is also on that same ID, and it ends up failing. There are also some callbacks. There's some trickery afoot. It took a little while [chuckles] to work through these tests to understand why they're failing. But the short version is that we thought we had to restructure the data in a way that no longer required us to guess what the next primary key should be for a record. We could actually use Factory Bot to generate that record, and then ask Postgres, okay, what ID did you assign? And we're going to pass that in. And that part was really challenging when you're in a new codebase, and you are learning the domain knowledge and exactly how data should be structured. So that was one challenge of it. The other part was that a lot of the data relies on each other. So then figuring out the right hierarchy in which we could create the data. So we didn't have a circular reference at some point. It took some time. And Joël Quenneville, who's on the project with me, used a tool that I found very helpful. It's called Dataviz. He went through and documented the let statements, the data that's being created, and then it generated a nice tree structure that shows you okay; these are your dependencies. This is the test setup that you're using. And then from there, just by changing a few lines in that particular file that used to generate that Dataviz tree, he would move it around. And we could simulate what we were already mentally trying to construct in our head. So as programmers, we're already thinking, okay, I know this record needs that data. And that data needs that data before I can build this. But this actually turned it into a concrete visualization where we could see it. And I was really struggling. And he was like, "Hey, I got it into a visual form that we can look at. And there's a circular reference. That's why this keeps happening and why we're not making progress." So then, using that, we were able to then reformat some of the dependencies, look at the graph, see that we didn't have that circular reference anymore. And then we could implement that in code. And it really helped me to be able to walk through that visual aspect because then I could say, okay, this is all the stuff that I'm trying to mentally hold on to, but instead, I can just look at this and know it's going to work. I don't have a circular reference. It also helped concretely show why the previous efforts were failing and why we kept running into some issues. So I'm really interested now in Dataviz because I found it very helpful in this particular case. And I'm very intrigued to see if I can apply this to more tests that I'm trying to fix and to see if I can start out with here's the current structure. Here's where I'm trying to go. And then essentially build that graph first before I start changing the code around. I would love to have that optimization. And I feel like it would speed up the process. CHRIS: It was funny as you started to say that I had observed some tweets going out into the world recently. And I was like, this is Joël. This is definitely Joël talking about these things. As an aside, for anyone who doesn't follow Joël Quenneville on Twitter, @joelquen, I would highly recommend it. We can include a link to Joël's Twitter in the show notes. Joël is one of the clearest thinkers and communicators about programming that I have ever worked with. And in particular, what you're describing of the data visualization is something that I think he does incredibly well. Often he'll make blog posts, but they'll include just simple little visualizations, little images, or diagrams, or flowcharts that just so concretely encapsulate an idea and express it so much better than text ever could. And so, in so many ways, I look to Joël's writing, both on Twitter, in the blog, in many places. And I just appreciate so much what he puts out there and the manner in which he does it. So I was by no means surprised when you said, "Oh, and I'm working with Joël on this project." I was like, yes, I bet you are. That sounds true, and in particular, some of the conversations about flaky tests and determinism and all of that. So yeah, the visualization stuff is also particularly interesting in taking a system that it's very hard to hold all of this in our heads. But that visualization, the tree and/or graph thing at play, having that in a picture and being like, oh, look, there's a cycle now. There we go. Can't have those. That's not okay. That's a really interesting solution that's just very cool to hear about and presumably led to a good outcome where you were able to break that cycle. And now you're happy and deterministic in your tests. STEPH: Yeah, it's one of those approaches where I wonder if it was helpful afterwards and how can I make it helpful beforehand? Because it felt like a confirmation of the pain in the process that we had been through. And I'm eager to see if now I can apply it ahead of time and save myself some of that pain. That's where I get really excited. But yes, it was a successful outcome. And we have fixed that particular flaky test. But I'm very excited to hear about your victory from the week. CHRIS: It's a shared victory. It was a team victory, just to be clear. But we are working in a system that is using Inertia. Inertia.js is a project that I've talked about a number of times on the show. I'm a huge fan of it. It is the core architecture of how we're building our application. But as a very brief revisiting of what it is, on the server-side, we have Rails, and Rails is acting in a pretty traditional way. We do not have an API. And on the front end, we have Svelte, which is a JavaScript view layer framework. Inertia sits between them and binds the traditional Rails MVC architecture and the Svelte front end. So again, there's no API in the traditional sense of this is a REST endpoint, and we hit it, and we get some data, and then the front end holds on to that in a store. None of that is going on. Inertia does a wonderful job of marrying these two concepts and allowing us to use familiar programming techniques on the server-side but then also have a more future-friendly front end. Animations and transitions and things like that are now totally possible while not throwing away the entirety of our programming model that we've had in Rails server-side applications. That's all well and good. Almost all of the UI in our application is rendered via Inertia and Svelte. That's great. We love it. The one caveat is Devise. So we have Devise on this project, and Devise comes with a lot of views built-in. And we have both an admin and a user model. So we have sign in and sign up, and confirm registration, and forgot password and all of these different views and flows and things that Devise just gives you out of the box. And being an early-stage startup, it was not a good time to revisit any of that or to try and build it from scratch or any of that. We just wanted to build on the good known trusted foundation that Devise gives us. But the trade-off there is that now all of our Devise logic lives in this uncanny valley. It's the only stuff that is in ERB views. Our styling, thankfully, we're using Tailwind, and so we are able to have some consistency between the styling. But recently, we redesigned the flash messages on the client-side in our Svelte pages. But on the server-side, they are a little on the Devise-side because Devise is the only pages that are being rendered truly server-side. They look a little different. And this is a pain that we felt, that inconsistency or that mismatch between the Devise views. And then the rest of the application is a pain that we felt but one that we consistently were like, I don't think it's worth the effort to try and change this. Finally, this week, we've been doing a lot of work on our user onboarding funnel. So the initial signup flow going through it's a progressive form screen where you go in between different pages. And a majority of it is implemented in the Inertia and Svelte side of things. And it's very nice and very fun to work with. But the signup form, the user signup form, is in Devise, and it's a traditional Rails server-rendered post, and then all the normal stuff happens. We finally decided to bite the bullet this week and see how painful it would be to port that over to Inertia and Svelte. And spoiler, it was awesome. It was very straightforward, and coming out of it, immediately, the page was largely the same. The server-side code was largely the same. But now we had things like when you submit this form, if there's a validation error, we don't clear out your passwords because we're staying on that page on the client-side. We're taking advantage of the way Inertia's error flow works. That's a subtlety of how Inertia works. That's probably more detail than we want to get into here, but it's an awesome thing that works and is great. And so immediately, this page just got better. We got inline errors for each of the fields. We were able to very easily add a library called Mailcheck, which I've talked about on an episode a while back. But this is a thing where if you have a typo in your email address, we can say, "Hey, you have a typo in your email address. And if you click this link where we suggest the alternative, we'll just replace it inline." That would have been really awkward to wire up in our Devise view. It would have been some jQuery-esque script tag at the bottom of the view page that doesn't stop…We don't have jQuery actually at this point. We wouldn't have jQuery. And we could certainly, but it would only be for that view. And it would be weird and different in a fundamentally different programming model. It was trivial to do in the Inertia and Svelte world once we had made that port over. This was always my hope. This was the dream that I had in mind. And it speaks to the architecture of Inertia. And Inertia is a really great abstraction that is very minimally leaky. I won't say it has zero leaks because no abstraction does. But this was my hope is I think the server-side should mostly stay the same. And I think the client-side, we just take an ERB template, turn it into a Svelte template, and we're good to go. And that has largely been the case. But suddenly, this page is so much more. There are subtle animations as things come in. And there are just lots of nice features that were trivial to add now and that fit with the rest of the programming model that we have throughout it. So that was awesome. STEPH: That is awesome. I love these styles of updates where there's like, oh, I had a loss this week. But I also had this really great win because that feels just so representative of a typical week. So I love this back and forth. CHRIS: It's also that sequence is how the week went. So the loss happened earlier in the week, and then the win happened later in the week, which is how I would prefer it because now I'm going into the weekend with a win. Like, cool, I'll take it. Had it gone in the other direction, I would have been like, oh man, Rails beat me. But I guess it's the weekend now. I'll forget about it for a little while. STEPH: Yeah, that definitely helps to end on a positive note. CHRIS: But yeah, I don't think too much more to say about that beyond it was both really nice to get the added functionality to get the better, more user-friendly behavior in this view that naturally falls out of this programming model. But also to have that reinforcement of my belief in Inertia as a good architecture. Not only did we get some really nice stuff out of doing this port, but it was also pretty straightforward because Inertia sits so comfortably between the pieces. And that's a story that I really like. I want more of that in my programming world, where to change this thing requires changing everything in our app. Oh no, this is sad. No, this was a great example of we were able to very minimally change things and get a much better experience out of it. So once again, I am very pro Inertia.js STEPH: It's interesting to me how different our paths have been this year where I have been working on applications that are brought on thoughtbot to then help out with some of the concerns that they have, either their application is going down, or they have a test suite that they need to improve, or there's a lot of triage that's involved. And so it makes me very excited to hear that, when you are building stuff, and it's going really well and how awesome that is. Because then I feel like most of my world has definitely been more in the triage space, which is a very interesting and fun space to be. But it brings me a lot of joy to hear about wins from let's build new stuff and hearing it be built from the ground up and how well that's going. CHRIS: Well, I'm definitely happy to provide that. But also, I want to be realistic and be like, I'm just writing next year's legacy code right now, let's be honest. I'm very happy with where we're at in this moment. But I also know how early I am in the project that I'm working on. And I'm burdened with the knowledge that I'm certain one decision that I'm making of the many that are being made I will deeply regret a year from now. I just know that that's true, and I can't let it slow me down. I got to just keep making decisions and do stuff. But I know that there's going to be one. I know that a year from now, I'm going to be like, why did we choose that option? But it's sort of the game. STEPH: [singing] We'll just know that there's something strange and your code won't change. Who are you gonna call? thoughtboters! CHRIS: Well, yes. I will definitely be calling you when I find myself in the uncertain times of legacy code of my own creation. So I look forward to that, frankly. But that's a problem for a year; I don't know, maybe two years from now. Who knows? But for now, what do you think? Let's wrap up. STEPH: Let's wrap up. The show notes for this episode can be found at bikeshed.fm. CHRIS: This show is produced and edited by Mandy Moore. STEPH: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or a review in iTunes as it really helps other people find the show. CHRIS: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed on Twitter, and I'm @christoomey. STEPH: And I'm @SViccari. CHRIS: Or you can email us at hosts@bikeshed.fm STEPH: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Byeeeeeeeeee!!! Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.

    318: Successful Skills with Edward Loveall

    Play Episode Listen Later Dec 7, 2021 44:05

    Fellow thoughtboter Edward Loveall joins Steph to cohost and talk about alternative frontends and his own that he created: scribe.rip: an alternative frontend to Medium, learning about what it's like to be a manager/non-IC, and helps answer a listener question re: how do you think about empathy in your work? This episode is brought to you by ScoutAPM (https://scoutapm.com/bikeshed). Give Scout a try for free today and Scout will donate $5 to the open source project of your choice when you deploy. Empathy Online: Edward Loveall (https://thoughtbot.com/blog/empathy-online) Scribe (https://scribe.rip/) GitHub - mendel5/alternative-front-ends: Overview of alternative open source front-ends for popular internet platforms (e.g. YouTube, Twitter, etc.) (https://github.com/mendel5/alternative-front-ends) Become a Sponsor (https://thoughtbot.com/sponsorship) of The Bike Shed! Transcript: STEPH: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Steph Viccari. And this week, Chris is taking a quick break. But while he's away, we have a guest on today's show. Today's guest is fellow thoughtboter, and wonderful friend, and British accent enthusiast Edward Loveall. EDWARD: Oh, hello, Steph. It is lovely to meet...No; this is not my real accent. Anyway, hi, friends. [chuckles] STEPH: [laughs] Hello, British Edward. I am so excited to be chatting with you today. Are you going to maintain that accent throughout the whole episode? EDWARD: No. There's no way I could do that. I need a lot more professional actor training to be able to maintain quality of that level, I think. STEPH: That's fair. I won't hold you to that standard. I was reflecting on preparation for this chat. I've been thinking about all the fun that we've had together, the time that we have worked together at thoughtbot, all the remote coffee walks that we have gone on together as we've talked through consulting challenges or coding challenges. And I realized that we have never worked on a project together, which is wild to me. EDWARD: Huh. Yeah, I think you're right. That is wild. Because I've been here three and a half years, and you've been here even longer than me. So in three and a half years of overlap, we've never done that. STEPH: And yet we've still always found ways to hang out. EDWARD: We make it a priority, you know. STEPH: I think we need to...we might have to bribe somebody for us to get on a project together. EDWARD: I'm pretty sure we know the person to bribe. STEPH: We do. EDWARD: We can go talk to our boss and make that happen. One thing we've both done in our career here at thoughtbot, too, is we have gone from individual contributor to being a manager, which is a cool transition. STEPH: That's a really good point. That is fun that we have embarked on that journey together. I was very much encouraged to become a team lead, and that was very helpful. Because I'm the type of person where I'm not sure I would have put myself up for that role. I'm very thankful that others encouraged me to do so because I really love it. There are certainly challenges with being a team lead. But overall, I have very much enjoyed the role. Just to provide some context for being a team lead a thoughtbot, because I feel like those management roles tend to differ from company to company as to the level of responsibilities that you have. So for us in particular, it's really focused on leading a team of developers, usually two to three developers, and conducting regular one-on-ones to ensure that they are fulfilled and are successful in their projects and their growth at thoughtbot. And then helping them become senior developers if they're not already and essentially coaching them through difficult development and consulting scenarios. EDWARD: Yeah, there is still an expectation that you are an individual contributor in some form on client projects. It is not just a management position. STEPH: Yeah, that's a good point. For me, that context switching is often what makes it challenging but yet also helps me still feel that I can coach somebody and that I can have one-on-ones because I am still in the trenches. I'm still contributing to client projects. And so, it really helps me still stay in touch with the work that's being done and the struggles that people will face. Let me say again I am positive I wouldn't have pursued this path if I lost my IC status. I really like that part of the role. That's really a split. How about you? EDWARD: Yeah, and I still do. We've been experimenting. So thoughtbot generally does four days a week on many projects. So we do four days a week with our client, and then we do one day a week as investment. And team leads, at least on the team that we are on, have been experimenting with just doing three days a week on a client, one day dedicated towards team lead, and then one day for investment. I like that split so far. We're still seeing how it goes, still pretty early on in that experiment. But I've enjoyed continuing to be in the trenches, as it were, and working sometimes with the people that report to me so that we can really grow in the same way. There's a lot of context shared there. And that's been really wonderful. STEPH: Yeah, I have some specific questions I'd love to ask you about that shift in schedule. Because in some of our meetings, there has been discussion about that ability to context switch between I'm only billing three days now instead of my typical four. And I now have more time to focus on team lead priorities, but then that also means I lose a day with client work. And so there's that battle going back and forth between focusing on client work and also focusing on team lead work. So I'm going to leave that as just a teaser because I want to come back to that. But I'd really love to circle back to earlier in the year when you were thinking about becoming a team lead and correct me if I'm wrong, but I think you were pretty hesitant about it. And you were still deciding if it was something you wanted to do. Do you recall what helped you make up your mind as to which path you wanted to take and why you chose this one? EDWARD: Yeah, that's a great question. I did also get some encouragement, a pretty light encouragement from a previous co-worker. And that was helpful, but I turned it down initially. Someone asked, "Hey, are you interested in this?" And I said, "Nope, definitely not." And, I don't know, a year-ish later, I then ended up applying. And I think what happened in the intervening year was that I started to naturally do some of the work of a team lead primarily, checking in with people and talking with them, pairing with them on things more regularly. So I felt as if I was already doing some of the work, not exactly running a one-on-one, not getting people promoted necessarily. But I cared about the people I was working with and wanted to see them grow and be happy and thrive. That realization helped me think, oh yeah, I'm just kind of doing this. And I should maybe apply for this role. STEPH: Wow, that resonates so much. I've heard that from other folks, too, as they have progressed into team lead or other management roles is it was often they already felt like they had started doing some of the work, or there was some natural inclination to start taking over those activities. And so then it felt right to then actually acquire that title and take on those responsibilities officially. Well, how's it been going? You had almost a year now. So you had some of those hesitations at the beginning. How's it been? What do you think of being a team lead? EDWARD: Yeah, I'm really enjoying it. It is a challenge like you said. But that's every job, right? Every job should be a bit of a stretch. So I did come into it with some natural inclinations of wanting to talk to people and check in with them. But there are all these other pieces that I wasn't good at. One thing that has been really challenging is instead of completing things myself, being that individual contributor, is trying to coach and sponsor people to do something that I would do. And I think the hardest part about that is they may not be as far along in their career as you are. And so it is hard to watch someone struggle in the way that you used to struggle without saying, "Oh, here, let me just do that for you.” And I think what I started to realize is that the efforts that I'm putting in I can really be a force multiplier and end up effecting more change than what I could do by myself. Like, if you think about it, I have four reports right now, and they're all really smart and talented people. But let's just say they were half as good as I was. That is definitely not true but just go with the numbers here for a second. If I could teach them to do what I do, even if they were half as fast as me, because there are four of them, they can get two times the work done. The math adds up in a way where if I can unblock those people, help them just get to the next one little step, do whatever it is that they need, they're going to do way more than I could by myself. And really wrapping your head around that and the advantages there is so hard but so rewarding once you figure it out and get it going. STEPH: Do you feel like anybody told you that up front going into taking on some more management responsibilities? Or is that something you learned as you went? EDWARD: I definitely learned that as I went. I got some great advice from Josh Clayton, who we work with, and he's been a manager for a long time. And that's a lot of how he thinks about it. And he encouraged me to do things like pairing with everybody on the team or running little workshops to teach, to fill in knowledge gaps for people asking questions, instead of giving answers, to help them find their own answer. And that's all been really, really helpful. STEPH: Yeah, that's one of the things that I have valued very much about our culture. I've seen some other companies struggle with is that when someone does get elevated into a management role that they still need support. They still need to be coached. And they also need room to make mistakes and grow. And at thoughtbot, I feel that we have been very supported and where there's someone that I can still get mentoring and coaching from. And I can learn to be a manager on the job versus I'm not just put in a position where I'm going to fail or just put there without the expectation that I still need to grow as a manager and as a person as well. So that has helped me out tremendously as well. You highlighted the idea of pairing more with others and then asking more questions around providing answers. And as you're learning those skills or as you've acquired those skills for being a team lead at thoughtbot, have you found those skills also transition well to client work? EDWARD: Yeah, they do. There's a lot of overlap, especially around gaining trust with somebody. I'm gaining trust in one-on-ones, but I'm also gaining trust with my client or helping my client understand something. This gets a little more into the client-side of it. But a lot of times in client work, I'm looking to bridge a gap. I understand something because of my consulting experience, and they want my knowledge and consulting experience. But it's hard to just go in and say, "Do X or do Y." And in the same way, with somebody who's reporting to me or who we're having a one-on-one, it's not usually very helpful to just say, "Do this, do that." You want to help them understand the why and bridge that knowledge gap to get to where you want them to be and where you think they should be. Those really do go hand in hand, and I have used a lot of the same skills. Giving feedback also has been a huge thing to share. It's really, really hard to give critical feedback to somebody. It's very easy for them to shut down and not take the feedback, which is the opposite of what you're trying to do. And the same can be with clients. Like, they've gotten to where they've gotten to because of whatever they've done in the past, and trying to show them why what some of the things they're doing is maybe not ideal is really tricky without triggering that flight or fight response. So yeah, there are lots and lots of crossover to answer your question. [chuckles] STEPH: I get so excited when clients that have brought on thoughtboters recognize that we are there temporarily, that we bring an outsider perspective. And they will set up essentially reoccurring; maybe it's weekly, maybe it's monthly to say, "Hey, give us feedback. Let us know what are you seeing? What do you think about the team? What do you think about our processes? What would you like to change?" And I don't mean just in a retro setting that you're having with the team, but it may be meeting with leadership of that company to give them that feedback directly. And that's awesome. It's rare because, I mean, that takes confidence on their part to be able to say, "Hey, give us all of your feedback, constructive, positive, whatever it may be." But I feel like they get so much value out of doing that where they really get to leverage the fact that they have brought in these external members. And they get to hear from them as to how things are going and insights that they may be missing or not hearing from their people otherwise. EDWARD: Agreed. STEPH: Circling back to the manager IC path for a moment, I have a question for you because I often find myself asking this question to me or sometimes other people asking this question. But how do I know which path to follow? How should I explore do I want to be a manager? Do I want to continue and invest in my individual contributor skills and really lean into that path? Have you found any resources that have really helped you or ways that you coach others through that scenario? EDWARD: I probably don't have a very interesting answer just because I'm going to mostly repeat what I think I said. But I think it's still so relevant and valid, which is, do you find yourself doing some of the work that a manager does? And it doesn't necessarily have to be the thing that I did, which was reaching out to people and checking up on them and seeing how they're doing. It could be that you really, really like running big team meetings or something like that. You just get a kick out of doing that kind of work. Or maybe you really enjoy working less on yourself and more on the group around you. That could also point to more of a technical leader. It doesn't have to be a person leader. So I think I would look for where you find yourself wanting to effect change and figuring out if that fits into a manager role or not. And I've had people tell me they definitely do not want to be a manager, and they know that for sure and people that are on the fence. And I think that's another useful thing is to ask your manager what they do as the job and see if that's interesting. See if any of those things spark joy for you, as it were. STEPH: I love the approach of just flat out asking your manager or someone that you see where perhaps you would like their role and saying, "Hey, what's your day like? What do you do? And can I be part of more of your day just to see if I would be interested in this type of work? Essentially, can I shadow some of the meetings that you're in?" I really like that idea. And I think in the past, I would have been more hesitant about this approach. And it certainly depends on your company's culture. But there's a part of me that's like, just try it out. Like, if someone is encouraging you to go for a management role or to go for maybe it's a stronger individual contributor role, maybe it's being a principal engineer or something else, but if there's someone that's already there encouraging you or if it's just yourself and you are your own cheerleader, then go for it. Try it out. See if you like it. Take some notes. See if what you thought the job was going to be like actually matches reality. Because then, at the end of the day, you can always decide to change your path. And if you are at a company that supports that type of experimentation, then you can step back to your current role if you decide that you don't like it. Or you might find that there's a really nice mix in there. But I feel like, with time, I'm getting a bit more bold with strategies in terms of just trying things out, even when it comes for technical challenges as well. Like if there's something that you're really nervous about or there's some big technical problem or something that the team is working on, and you're really skittish and nervous about it, just go ahead and say, "I'll do it, or I'd love to work with somebody on it," and then try it out and take some notes, see how it goes. EDWARD: You could be really sneaky too. You can say to a colleague, "Hey. You want to get lunch?" And like you turn that into a secret one-on-one. Or you offer to run the retro board during retro, or you step up for doing a bunch of pull requests that week or something like that. You can try these little test things without even having to let somebody know or committing to anything publicly or even privately. Just really internally to yourself, you can try to take some of those steps. STEPH: I like the sneaky success ladder. People won't talk about that one as much. [laughs] That's how I definitely found out that I didn't want to do sales. There was someone that I was talking to that was interested in working with thoughtbot, and Josh Clayton was very supportive of like, "Do you want to come along and be part of the conversation?" I was like, "Yeah, sure." And so I went along, and it was fun. But I definitely walked away like, yep, I don't want to be part of sales. I really like everything else minus this part. [laughs] EDWARD: Yeah, it's good to know. It's good to know. STEPH: Circling back just a bit to something you said earlier, you had mentioned that as you were becoming a team lead, you realized that helping others be successful at their job was really then what led to you feeling successful as well and that you could be a force multiplier. And you'd mentioned that a lot of that work comes down to bridging knowledge gaps. And I'm really curious because this is something that we're always working on at thoughtbot. We are looking to identify what skills people would really like to learn. How can we help people learn those skills? And I'd love to know more. How do you go about this? How are you helping people bridge those knowledge gaps? EDWARD: Yeah, so that is a doozy of a question. I have a couple of different answers. First is something I talked about before, building trust. And there's a bunch of different ways to do that. And I see trust as the foundation of almost everything in consulting. If you don't have that trust, it's really hard to deliver feedback like we talked about. It's hard to bridge that knowledge gap. Because effectively, nobody knows who you are, and what you're doing, what's going on, why you are coming to talk to them. It's really strange. And we can come back to how to build trust. But once you've built that trust, I approach bridging that knowledge gap in a couple of different ways. One is asking questions instead of giving answers. The goal behind this is I want them to think about their goals. And that will often help lead them to some answer to bridge that gap that we have. I have some idea. They have another idea. If I can ask the right open-ended question, they will walk themselves across and get to where I want. Now, that doesn't always work. Another strategy I've found is outlining a bunch of different possible solutions and their pros and cons. That has done two things. One, it helps them understand where I'm coming from, what my goals are in relation to what they're trying to do. And another one is that actually tends to gain a lot of trust. In the meantime, you're showing your expertise. You're showing that you're really considering all their problems. Because almost every solution has trade-offs, there's very rarely a silver bullet. And so it's really helpful to say, "Well, here's the pros, here's the cons. Here's where I think you should go, but you know your business better than I do. And I've outlined all the things here. So whichever way you want to go forward on this, let's do that. And let me help you get there." Joël and I, a colleague that we both cherish dearly, we did that on a project recently, and it was really, really successful. We put a lot of work in and helped them get to a really difficult architecture decision. And it could have gone one of, I think, four different ways. And we were sort of vying for one. They were vying for another. And we found a couple more in the middle, and I believe we went more towards the middle. And we were both pretty happy with how that turned out. STEPH: I really, really like how that approach gives someone so much autonomy, and they're part of that decision. So you're not just saying, "Hey, you need to do this," and then just following through with it. But instead, it's saying, "I think I've heard everything. I think I understand the different problems that we're facing. Here are my suggestions, but you still have more context. What do you think, or which option would you like to pursue? I really like that option." EDWARD: Yeah, because you're always writing this line as a consultant of like, they did bring you in for your skills and expertise and theory. But you really want to level them up so that they can make the right choices because that ultimately is...like, their success is your success as a consultant. That's the job in a lot of ways. And so yeah, giving them the tools they need to make the right decision is so often the job. And I think that can get lost in the shuffle of, oh no, we have to meet these sprint goals. Or I got to get this ticket done or this bug fixed or something. And stepping back to get them to a better place is another goal that you can get to down the line. It's not to say shipping tickets is bad [laughs] or getting the sprint goals is bad. It's just another facet. Have you had any aha moments in consulting? STEPH: Oh my gosh, I have had so many aha moments. I think most of them, for good or for worse, are here on The Bike Shed, or at least they've been shared here on The Bike Shed. [laughs] EDWARD: Yeah, you should write a book of them all. STEPH: Could we just grab the...I'm lazy. Can we grab the transcripts? We'll just turn that into a book. EDWARD: [laughs] Yeah, just put it all together, call it The Bike Shed Diaries. STEPH: Yeah. Oh, I like it. Okay, all right, that'll be next week's task. We'll publish The Bike Shed Diaries. [laughter] Specifically, in terms of bridging aha moments for helping someone bridge knowledge gaps or even for myself is I will often focus on what skills do you need today to make your job easier? What challenges are you facing? And also, what skills would you like to have six months from now? So that way, you are meeting the needs and the requirements that you really need today to fulfill your job. But then also six months out, we're still looking towards the future. Maybe that's also more job requirements related, or maybe it's just for personal growth, or the areas that you're really excited about. You really want to contribute to an Elixir, open-source project, or something more specific that contributes to your fulfillment. So when it comes to knowledge gaps, those are often the questions that I'm asking are, what do you need this week to make your job easier and to make your life easier? And then where would you like to be in terms of what skills would you like to have six months from now or what concepts? It may even be too lofty to say what skills because that could be huge to say that I want a whole new skill to be able to work in a language. So maybe it's something that's more specific of like, I'd really like to understand forms a bit better six months from now, or I'd really like to feel a little more confident with SQL, or maybe you'd like to take a look at Arel, things like that. And then set those targets and then check in to say, "How's it going? How do you plan to learn these skills? Would you like help learning these skills? What are some resources?" Because I am not always the person that can help someone acquire that knowledge. So in that role, I'm often a facilitator where I will say, "Cool, you want this. You're interested in this particular skill. I don't know that skill. But I do know someone else who's really good at this. So let's get you all connected, and then you can work together on this." EDWARD: And to dovetail a little bit with that manager individual contributor piece we were talking about before, that's another piece we didn't really talk about, which sounds like sponsoring. It's not just you doing the thing for your report or even coaching them necessarily. It's how can I get my report into a situation where they can exercise that skill or connect them with somebody who can help them with that thing? I'm still working on that one, honestly. That's a really, really difficult one. That's not something that comes naturally. STEPH: When you say that's the part that's still challenging for you, is it the connecting of one person to someone else to learn a skill? I'm curious to hear more about which part of that is challenging for you. EDWARD: I think I don't always think of sponsorship as a tool that I can lean on. It just doesn't come to mind as naturally. I think the very natural thing to do is mentor first, which is like, here's what you should do. It's kind of giving somebody a fish. Coaching then is more like teaching them how to fish. And then I don't know if we're going to extend this analogy farther. Sponsoring is like you're going to open up your own fishing teaching school or something. [laughs] And that just doesn't always occur to me. I don't necessarily think like, oh yeah, like my friend over here could totally teach you about this technical skill that you're trying to learn or set you up to speak at a conference or something like that. It's a much different level of being a manager that I'm just not used to yet. I'm getting better at it. But it doesn't come naturally. STEPH: Yeah, that's a very powerful form of managing someone as well because then you are helping that person go beyond their current bubble of who is their manager in their team and then helping them shine in other circles. And that's incredible and also something that I am always working on getting better at. EDWARD: Let's get better at it together. STEPH: We can do it. Also, when you mentioned opening a fishing school, I definitely pictured fish in a school in front of a chalkboard and someone's writing on that board and little fish in their school seats learning. EDWARD: [laughs] A little Finding Nemo action. STEPH: You got it. [laughs] You know your fishing school. You got to learn to stay away from those hooks. Mid-roll Ad And now a quick break to hear from today's sponsor, Scout APM. Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more. Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform. See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed. STEPH: So pivoting just a bit on a slightly more technical note, you've been working on a side project called scribe.rip R-I-P. And I've heard a bit about it, but I would love to hear more. Could you tell me more about that project that you're working on? EDWARD: Yeah, sure. So Scribe is what I would call an alternative frontend. And specifically, it is an alternative frontend for medium.com. The goal of the project is to give people a tool to read the Medium articles, not on medium.com, which might sound like a strange goal. [laughs] I'm happy to go into a little bit of a lie there. But that is the tool. And yeah, the domain is scribe.rip, mostly because that was a cheap domain. [laughs] So I got it and put my project there. STEPH: I like that phrasing that you're using, alternative frontends because I think when you had first mentioned that, when I'd heard that in other conversations, I was like, oh, what is that? And I didn't know what it meant. But now, when you put it into some context, that makes all sense. I am intrigued. Why would someone be interested in using an alternative frontend versus, say like, there's an article on Medium; I'll just read it there. What might inspire me to want to use Scribe instead? EDWARD: Definitely. There's a bunch of different reasons. The alternative frontends cover a pretty broad ground. But I'd say the most common reasons that someone might want to use one are privacy if they're worried about the main service, whatever that might be. Let's say Medium, in this case, is doing something with their user data that they'd rather they not do, potentially a better experience on that service. If you don't like the way Medium's articles look, you might want to see them in a different way. It can also be a way to vote with your actions, saying that this is the kind of web that I want to see if you don't like in general what a platform is doing. And if you think a platform is potentially even harmful, it can be a way to say I don't want to support that platform, but sometimes I find myself needing to interact with it in some way. The alternative frontends can be a tool for that. On the very cynical angle, you can also go to you don't want to see ads. And sometimes, these are ad-supported platforms. Alternative frontends can get rid of those ads. And so that's another way too. I'm conflicted more about that one. We can dive into that. But those are the most common reasons I've seen that people want to use alternative frontends. And to be clear, Scribe is not the only alternative frontend out there. There are frontends for YouTube, for Twitter, for Instagram, for Reddit. There's a huge list of a bunch of them, but those are some popular ones. STEPH: Oh, that's really cool. I've never used any of those before. Will be sure to include some links in the show notes so people can check those out. And you listed some really interesting reasons for why folks might want to use an alternative frontend. I'm curious, to make this possible, though, does it mean that the service that is hosting that content do they have an open API into which then you can pull that content? How is an alternative frontend possible? EDWARD: It is possible through APIs almost always. In some form or another, the APIs aren't necessarily open. One interesting side effect to many of the JavaScript rendered apps is that they often talk to some API in the background. And that can often be used to get the content in a more computer-friendly way. And so, with Medium, in particular, they don't really have an open API. So I ended up trying to figure out their API in the background that they're using to fetch articles and was able to get the content and display it in a different way. STEPH: So everything you're describing sounds really interesting. I feel like I do have to ask the question, is it okay that these alternative frontends are taking content and are essentially rendering content but then not using the original service in which the content was published? How do you feel about that aspect? EDWARD: Yeah, it's a really interesting question. There's a bit of a moral argument here, and I think everybody has to make that call for themselves. I think every platform if it gets large enough, is going to have people that don't want it to exist for some reason. I think, in some ways, providing alternative frontends is a bit of a release valve for that platform. Not to say that the alternative frontend explicitly helps that platform, but I imagine it gives people literally an alternative to then use instead and can make a peaceful, neutral ground in a way. So instead of being forced to use only the official platform, you can now use it at least in a limited fashion outside of that, which may alleviate whatever concerns you have and therefore keep everybody happy. And I think honestly, in the long run and in practice, most platforms will not particularly notice the impact of these alternative frontends. Overall, we're talking very, very small potatoes. YouTube is not going after Invidious, the alternative frontend for YouTube, because it's probably a drop in the bucket. Nitter is not getting cease and desist from Twitter. Instagram is not sending a cease and desist to Bibliogram. These are some of these alternative frontends. And I think that's just because it's okay. They don't mind. It's so small. And it's giving people what they want in a way that is not harmful enough for it to really matter in the long run for them. STEPH: Interesting. Because yeah, as you'd mentioned earlier, I think most people are going to continue to use that main service because that's what they see advertised. And it's more well-known, and it's frankly easier to go to. But then for folks who do want a little bit more control over their experience and they still want to access someone's content. So it is interesting. You still want to ensure that the person who created that content always gets recognition and ownership of the content that they have. And in this case, that very much still applies. If I wrote an article on, say, Medium, but then I'm using Scribe to be able to read that content, it's still known who wrote the article. But this way, you are perhaps opting out of something else that service is doing, maybe if they have some type of tracking or something that you're not comfortable with. But you still want to be able to appreciate that person's content, even though they're perhaps only able to publish on Medium for right now. Or they're still looking for more ways to publish their content for folks who would like alternative ways to consume their information. Yeah, it's an interesting spot. EDWARD: Right. And some ways that I think Scribe can provide a slightly better experience are trying to highlight the author more than the platform. The only time it says Scribe on the website is on the homepage. If you go into an actual article, I don't put branding or anything like that. Because I think I really want people to have their work speak for the author, not for the platform, and that's really important to me personally. And that might not be important to you, and that's okay. Maybe you use scribe because it supports dark mode or something like that, and that's totally fine too. I don't mind at all. There are many aspects on which an alternative frontend can provide for people that the official platform doesn't. In some ways, it's augmenting their features, but in some ways, it's just giving people a bit more choice. And I think that's important. STEPH: I have found since you'd mentioned the side project, that I've started using it more to read content. And I have found it helpful because it really silences all the noise because a lot of services want you to see ads, and they do want you to click on more articles that are related to the thing that you're reading. And so, I do appreciate the simplicity that it brings to the content. So then I can really just focus on that one article that someone has written. Overall, it seems like a really neat project. EDWARD: Yeah, thanks. I'm glad you enjoyed it. STEPH: Pivoting just a bit, I would love to go on a slight adventure and answer a listener question with you. What do you think? EDWARD: Yeah, let's do it. STEPH: All right. So this listener question focuses on empathy in your work, and this person writes in, "I'm curious how you all think about and notice empathy from yourselves and others around you. Empathy is so helpful and critical for making and maintaining healthy, productive relationships. I've noticed that the way you frame your client engagements, empathy sounds to be at the heart of them. For myself, I've noticed I'm better at it in certain contexts and certain times and with specific personalities, more so than others. More concretely, how do you stay empathetic with your clients and with cross-functional teams like product or design or even yourself? Can you teach or increase your empathy? And if so, what have you found successful in these situations? So, Edward, this seems really on topic for some of the things that we were discussing earlier. So I'm going to hand it over to you first and get some of your thoughts. EDWARD: This is a really great question. There's a lot to unpack. And one question they asked was, can you teach or increase your empathy, and if so, what have you found successful in what situations? I have found that being vulnerable both publicly and being empathetic publicly is a really useful tool. A lot of teams don't communicate very publicly; it's a lot of stuff in private messages. Being vulnerable publicly in a big team channel can really open the door to letting other people be vulnerable and see what other people are doing, understand what people are feeling. And that's really at the heart of empathy is understanding someone else's point of view. I've also found that starting small, like, just do it with your close co-worker. Maybe try to effect just change with them. And then once you've gotten them on board, broaden it to two other people, and then two more people, and then two more people, because it's really hard to take that leap of faith and be vulnerable by yourself. So I totally get that. And also trying to take this on really early in someone's career or someone's tenure at a job. Offer to help new people to your team. Work with them, so they just start off with a very empathetic experience. And that can grow into a more empathetic team as a whole. Encourage team members to update documentation on their first day because they're learning so much in those first few days. Once they've learned it, the only reason they want to document it is because they have empathy for that next person. And so, just like setting that baseline and that boundary, I think is super helpful. What do you think? STEPH: Yeah, I think those are some great examples. I really love that one way to acquire more empathy is to go on a journey with someone else. So if you have someone new that's joining the team, be their onboarding buddy. Go through that journey with them so you can understand what they're going through, what challenges they are facing. And that will boost the knowledge that you have and will likely also boost then the empathy that you have for people that are new to the team or for future onboarding buddies if you realize that there are some processes that really need to be smoothed out. I also think it's worth highlighting that I don't think empathy is a single skill. I think it's a number of things. It can be the ability to feel someone else's emotions, so you can understand what someone else is feeling at that moment. It could be reasoning about another person's perspective, or it could be just, frankly, wanting to help. So I think there are a number of ways that we can demonstrate empathy to someone else. And it's going to depend on the situation as to which one of those skills is going to be helpful. For how you stay empathetic with clients, that one is a really interesting one just because the way we work with clients; we do get to go on that journey with them. We are with them in making decisions around priority and technical decisions and what pain points they are feeling. So I think going, as you described earlier, going on that journey with someone is what helps us stay empathetic with our clients. And I think that's true for cross-functional teams. So if you are working with someone that's maybe on customer support or on the design team, it could be grabbing lunch with them and saying, "Hey, what's your day like? What challenges are you facing?" Maybe it's your company has rotations where you actually are part of the customer service team for a day. So you get to respond to tickets and have more of an understanding. I'm realizing there's a theme here. I feel like a lot of it comes down to stepping into someone else's shoes and seeing the world from their perspective and not just seeing it but experiencing the world from their perspective. EDWARD: Yeah. And another way to do that...because that can also take a lot of time. It's a hard ask potentially to say, "I'm going to go be a customer service rep for a day," if your job is also, I'm going to be a programmer and ship features or fix bugs. That's hard to do. And I think there are ways to do that, to experience what someone else is experiencing by trying to take on not necessarily the role of the other person but just trying to support the other person in their role. So, for example, we see teams become really siloed where the product is solely responsible for writing tickets, development is solely responsible for understanding what makes the code work or fixing a bug, and design is only responsible for user interactions. I found it really, really helpful to try to approach design and say, "What's the goal here with this user interaction?" I don't know. I'm not a designer. And so, how can I ask them and again bridge my own knowledge gap? Because that can really help you get to that point and help them understand maybe what you're going for and say, "I wasn't going implement it like that because I thought X, Y, and Z." And they go like, "Oh, I see what you're saying." And then now you're making those barriers…or maybe when you're working with products, they're like, "I see what you're trying to do here. But in my experience, I've seen websites like this. How do you feel about that?" And it's not to say that you're just trying to steamroll over them. It's that you're trying to share your experience and get on the same page and trying to get them on your page so that you're all making the decision together, not just handing it back and forth across the wall. STEPH: Yeah, and that was really well said where I think the more that you do collaborate with others and the more that you make decisions with others, the more context you're going to have for why someone else is making a decision, what challenges they're facing. And so again, it comes down to having more information about what that person is going through to then help you be able to be empathetic because I don't think this is a skill you can just turn on. If you don't know anything about somebody, you don't know anything about what they're going through. Being empathetic is going to be incredibly hard. And in this question, they mentioned that they're better at it in some contexts, at certain times with certain personalities. And I think that makes sense because anyone that's more like you, I think you're going to find it easier to be more empathetic. And anyone that has had similar situations, ones that you can relate to, you're going to naturally be more empathetic to. Also, timing is important. Maybe it's the end of the day, and you have already used up your empathy bucket, and you have nothing left to give. And that's just something to be aware of. You may have reached that threshold. And with practice, maybe that bucket will get bigger, and you will have more empathy to give throughout the day. But just be aware when you've also hit that threshold, and maybe you don't have any more to give in that moment. But I do think it's very much a skill that you build with a lot of practice. EDWARD: Yeah, it's absolutely a muscle. You're totally right. You are trying to do it, and the first time you do, it will be very hard. You will be very drained. And you need to recognize that that's okay. You can step away and come back the next day, and it will get a little better. But that's a wonderful point. STEPH: There is a really nice example that you have captured in a thoughtbot blog post that will be sure to link to in the show notes that highlights how difficult it can be to communicate the tone of voice and even how impactful that can be for someone who is reading that message that you have sent, and they don't understand that tone of voice. EDWARD: Yeah, that post was very focused on trying to bring in emotion to a more or less emotionless conversation, which is often text. It's very hard to understand when someone is being sarcastic or angry or bubbly or whatever. Just even silly things like adding emojis can really help in that process of bringing in more emotion and getting that tone across. And I'd say finally to this person who asked the question that the fact that you're thinking about it is already an empathetic thing. Just the fact that you want to get better at this shows that you're already empathetic, and that's really great to hear. STEPH: Yeah, I think that's a really great observation, and I think that's a perfect note for us to end on. So thank you so much to the person that shared this question with us. It is a very interesting question. And I applaud you for being so thoughtful about how to be empathetic with everyone around you. Edward, thank you again for being a guest on the show. For those that are interested in following more of your work or checking out your alternative frontend, where can they find out more about the life of Edward Loveall? EDWARD: You can find the alternative frontend called Scribe; it's scribe.rip. You can find me at edwardloveall.com. And I have links to various social media or email if you want to email me or whatever. And yeah, it's been a pleasure. Thanks for having me, Steph. STEPH: Thanks so much. On that note, shall we wrap up? EDWARD: Let's wrap up. Ta-ta, Stephanie. CHRIS: The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes, as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Byeeeeeeeeeeee! Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.

    317: Burn The Ships!

    Play Episode Listen Later Nov 30, 2021 41:41

    Steph gives an update about RSpec focus and how she often forgets to remove the focus feature from tests. She figured out two solutions: one using Rubocop, and the other from a Twitter user, suggesting using a GitHub gist. She also suggests that if you're one of those people who misses being in an office environment, you check out soundofcolleagues.com for ambient office noise selection. Chris has been struggling to actually do any coding and is adjusting to doing more product management and shares some strategies that have been helping him. They answer a listener question about dealing with large pull requests and how it's hard to recognize a good seam to break them up when you are in the thick of one. This episode is brought to you by ScoutAPM (https://scoutapm.com/bikeshed). Give Scout a try for free today and Scout will donate $5 to the open source project of your choice when you deploy. Twitter note re: rspec-retry (https://twitter.com/jasonrudolph/status/1458416077726158852) soundofcolleagues.com (https://soundofcolleagues.com) mailcheck (https://github.com/mailcheck/mailcheck) Inertia.js (https://inertiajs.com/) Svelte (https://svelte.dev/) devise (https://github.com/heartcombo/devise) clearance (https://github.com/thoughtbot/clearance) Become a Sponsor (https://thoughtbot.com/sponsorship) of The Bike Shed! Transcript: CHRIS: One day, I'll grow up. It's fine. I look forward to that day. But today, I don't think it's that day. Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey. STEPH: And I'm Steph Viccari. CHRIS: And together, we're here to share a bit of what we've learned along the way. So, Steph, what's new in your world? STEPH: Hey, Chris. Well, in some fun news, Utah started his professional training as of this morning, which I'm very excited about. Because we've been working with him to work on being good with walking on a leash, FYI, he's not, [laughs] and also being good about not jumping on people. And essentially, being a really good roommate. And he started training today, and we are using an e-collar, which initially I was really hesitant about because I don't want it to hurt him in any way. But now that I have felt the e-collar myself and we've had a first day with it, it's going super well. I'm very excited for where this is headed. CHRIS: That's very exciting. When does he start paying rent? STEPH: Ooh. I'll have to check with him, or I guess I have set those boundaries. That's my job. CHRIS: I just figured that's a core part of being a good roommate. But maybe we've got baby steps or doggy steps to get there. But that's exciting. I'm glad [laughs] that the first day of training is going well. STEPH: Yeah, it's going great. And the place that we're going to the trainer they have horses, and mules, and goats. And so now I have a very cute video of him trying to play with a goat, and the goat was having none of it. But it's still all very cute. In tech-related news, I have an update for when you and I were recently chatting about the RSpec focus and how I mentioned that I often forget to remove the focus feature from tests. And so then that goes up to a PR, and I have to rely on a kind human to let me know, and then I remove it. Or worst-case scenario, it gets merged into the main branch. And for anyone that's not on Twitter, I just wanted to share an update because I also shared something there. But the resolution for what I was looking for there's already a rule that's written into Rubocop, but it's specifically written in the Rubocop RSpec codebase. And with that rule, you can essentially just say, hey, let me know anytime that a test is using the focus metadata, and then make sure to let me know and fail. And then if you don't want to actually include all of Rubocop into your project because Rubocop is pretty opinionated, you can still add Rubocop to your project, but you can specifically add Rubocop RSpec, and then you can say, hey, all other rules disabled by default, but then you can enable that specific rule. So then, that way, you will catch all of your focus tests. There's also another approach that someone on Twitter shared with us recently from Marz Drel. And Marz shared specifically a really nice simple GitHub Gist that documents or exemplifies that you can add an environment variable that checks to say, hey, if we're in CI mode, then add a before hook. And then that before hook will look for any examples that are using that focus metadata, and then it's going to raise. And then if we're not in CI mode, then don't do anything, don't raise, and carry on. And that's just a really nice simple addition if someone didn't want to pull in Rubocop into their project. CHRIS: Both of those definitely sound like great options. I don't think we have Rubocop on the current project that I'm working on. But I think the RSpec focus thing, the metadata one, seems like it'll work great. More generally, I just want to thank folks out there who listen to the show and then write back in like, "Hey, this is probably what you want." There was a similar thread that someone shared around the RSpec::Retry stuff that I was talking about recently and the failure mode there and trying to get that into the Junit Reporter. And so they had some suggestions around that. Jason Rudolph on Twitter reached out, sharing just his initial exploration and thoughts on how it might be possible to extend the XML reports that are generated and capture a flaky test in that way. So that's really interesting. And again, just really love that folks are listening to the things that we say and then even adding on to them and continuing the conversation. So thanks to everybody for sharing those things. STEPH: Yeah, it's incredibly helpful. And then one other fun thing that I'd love to share, and I found this out from someone else at thoughtbot because they had shared it recently. But it's a neat website called soundofcolleagues.com. And I know you've got your laptop in front of you. So if you'll go visit it, it'll be neat to see as we're talking through it. For anyone else that wants to pull it up, too, we'll include a link in the show notes. But it's a neat project that someone started where you can bump up the sounds that you would normally hear in an office. So maybe you want to bump up background noise of people or an open window. There's one specifically for printers and a coffee machine, and keyboards are on there as well. [laughs] I have discovered I am partial open window and partial rain, although rain is just always my go-to. I like the sound of rain for when I'm working. CHRIS: Gentle rain is definitely nice white noise in general. I've seen this for coffee shops, but I haven't seen the particular one. Also, yes, I definitely know how to spell the word colleague on the first of three tries. Definitely didn't have to rely on Google for that one. But yeah, nice site there. I enjoy that. STEPH: I tried the keyboard option that's on there because I was like, oh yeah, I'm totally going to be into this. This is going to be my jam. I don't think it is because I realized that I'm very biased. I like the sound of my own keyboard. So I had to shush the other one and just listen to the rain and the open window. But that's some of the fun things that are going on in my world today. What's new in your world? CHRIS: I'm just now spending a moment with the keyboard sound. It's a very muted keyboard. I want a little more clackety. STEPH: A little more clackety? CHRIS: I was assuming it would be too much clackety, and that would be the problem. But it sounds more mushy. Maybe we can pipe in some of the sound here [laughs] at this point. Or we can link to these sounds, and everyone can dial up the keyboards to 100. But I, too, am partial to the sounds of my own keyboard. But what's new in my world? This past week and I think probably even a little bit more of the prior week, I've been noticing that I've been struggling to actually do any coding, which has been interesting to observe. And again, trying to observe it, not necessarily judge it, although if that's not the thing that we want to be doing, then try and improve that. But mostly trying to observe what's going on, what is taking my time. A lot of it is product management type work. So I am spending a good amount of time trying to gather the different voices and understand what is the work to be done, and then shape that into the backlog and make sure that that's clear and ready for the team to pick up. And then, thankfully, the other two developers that are working on the project are fantastically prolific. So they're often very quickly working through the work that has been set up in front of them. And so I'm trying to then be proactive and respond to the code. But there's almost a cycle to it where I'm just staying out in front of them, but they're catching up with everything that's going on. So it's something that I'm trying again to be intentional about, name, share some of that back up with the group. If there are things that I'm doing that I don't uniquely need to be doing, then let's share as much of that knowledge as possible. But one thing that I will say is the product management, shaping the backlog work is exhausting. I am astonished by just how drained I am at the end of the day. And I'm like, I don't even really feel like I did anything. I didn't write any code, but I am just completely spent. And there really is something to when the work is clear, just doing the work, I can actually find energizing. And it's fun, and I can get in flow state. And sometimes, I'll be drained in a certain way. But the work of taking a bunch of different slack threads, and communications, and meetings, and synthesizing that down, and then determining what the work needs to look like moving forward, and providing enough clarity but then not over constraining and not providing too much clarity. And there are so many micro-decisions that are being made in there. And I'm just spent at the end of the day, and I have so much...I've always had a lot of respect for product managers and folks that are existing in that interstitial space and trying to make sense of the noise, especially of a growing company, but all the more so this week as I've been feeling some of that myself. STEPH: I totally agree. I have felt that having a strong product manager really makes or breaks a project for me where even though having technical leadership is really nice, I'd prefer someone that's really strong at the product knowledge and then helping direct where the product is headed. That is incredibly helpful. Like you mentioned, the work is exhausting. There's someone that joined the thoughtbot team fairly recently, and I was chatting with them about what type of projects they would be interested in working on. And one of their responses was, "I'd love to work on a project with a strong product manager because I have been doing that a fair amount for recent years. And I would love to get back to just focusing on coding." And so I think they enjoyed some of the work, but they just recognize it's exhausting. And I'd really like to just get back to writing code for a while. CHRIS: Yeah, I'm definitely in that space. And I think there's a ton of value to spending a little bit of time, like having any developer at some point in their career spend a little bit of time managing the backlog, and you will learn a bunch from that. But I'm also in the space of I would love to just turn on some music and code for a while. That sounds fun. There's a lot of work to be done right now. I'd love to just be in there doing the work. But sometimes, out of necessity, the defining of the work is the thing that's important. And so, I think I've been correctly assessing the most important thing. And that that has consistently for a while now been the defining and responding to the work that's in process as opposed to doing it myself. But, man, I really hope I get to dive back into the code sometime and use my clackety keyboard to its fullest extent. STEPH: Have you found any particular strategies that really help you with the product management work? CHRIS: I will say that I think this is a competency. This is a skillset and a career path that...again, I've been at plenty of organizations that I don't think respected the role as much as it should be. But it's an incredibly hard role and multidisciplinary communication at the core of it. And so I don't think I'm great at it is the thing that I'll say. So everything that follows is just to be clear; I'm not saying that I'm great at this, but I have been doing some of it. So here are some thoughts that I have. I think a lot of it is in reaction to where I felt like the work was clear. So I have a sense of what it looks like when I can go to the backlog, trust that it is in a roughly solid priority order, pick up a piece of work and immediately go to work on it. And understand what are the end-user implications of this piece of work? Where would I start on it like, how technically? What's a rough approach that I would have? And getting that level of specificity just right. So it's not overconstrained, but it's not under constrained. So having experienced that on the developer side, I try and then use that to shape some of the guidance that I'm putting into, say, the Trello tickets that I'm writing up here. We recently introduced Trello epics, which is I want to say like an add-on. And that allows us just the tiniest bit of product management, like one level up. So instead of just having cards and a list that is like, here's the work to be done, we now have an epics list that is separate to it, and it links between a card and its associated epics. So it's like project and action within that project. And just that little touch of structure there has been really, really useful to help look at like, okay, what are the big pieces that we're trying to move? And then how do they break down into the smaller pieces? So a tiny, tiny bit of fanciness in our product management tool, not Jira-like not going in that direction yet for as long as I cannot. But that little bit of structure. And then thinking about what has been useful to me as I pick up tickets. And then, as always, trying to just always be cognizant of what is the user's experience here? What problem am I trying to solve for them? What is their experience going to be? How will they know how to work with this feature? And just always asking that and then framing the work to be done in the context of that. STEPH: I like how you're adamant about a little bit of fanciness but not all the way to Jira-like. I also like how you highlighted end-users. All of that, I think, is awesome when developers are able to expand their role to experience all the other facets of building software. CHRIS: Yeah, definitely. I think that whole list of all of the different facets of where our work interacts with different groups. The more empathy or, the more experience that you can have there, the better that you'll be able to understand how to communicate there, how to express things in terms, et cetera, et cetera. So a huge fan of all of those ideas. I am ready to just get back in the code for a few minutes, though. But for now, for as long as necessary, I'll do some of this work. But I am trying to find my way to other things. In terms of actual feature work that we're working on, one of the things that we're doing right now is restructuring our onboarding. So when a user comes and signs up to the website and then subsequently has to fill out a handful of other forms, there's actually an external system that we've been working with that houses some of the core data of our application. And they have a hosted application form. So we can send the user over to them, and the user fills out the rest of the application on this other system's site. And then they get redirected back to us. And everything's got nice DNS entries for a particular subdomain and whatnot. So it looks roughly consistent. There's some branding. But it's still someone else's UI, essentially. And we were feeling enough pain from that experience. We were like; you know what? It's time. We're going to bring this back in-house. We're going to do all the forms ourselves. We're going to do a nice progressive little progress bar. You can see all the steps as you're going through onboarding. We're just going to own that more because that's a core part of the experience that we're building here. So biting the bullet, deciding to do that. But there's an interesting edge case that we run into, which is we are using Devise for authentication. Totally makes sense. We're in Rails context; there we go. It's the thing to use. But Devise exists in truly the Rails world. So like HTML ERB templates, the controllers have certain expectations as to what's going on. So thus far, we've just let that exist in that world and everything else we're building in Inertia and Svelte. But we're just now starting to feel enough of the pain, and that Devise exists in this other context. And for a while, we just kept saying, "You know what? It's not worth the effort to port it over. It's fine." Because we're using Tailwind, we have a consistent design language that we can use across them. That said, the components are drifting a little bit. And it's like, oh, this one's got a rounded corner like this, and that one's got this color. And we don't have the disabled style. But it is nice that it's not completely distinct. But we have finally decided it is time. We need to port this thing over because we feel like the onboarding and authentication type flows; they're actually a big part of the user experience or at least the first run user experience when someone's signing up to our site. So we want to own that a little bit more. One of the things that I ran into as I was trying to introduce Mailcheck, which is a library that I've talked about, I think in a previous episode...but basically, you can have it observe a field and if someone types in like, user@gmaip.com, you can like, did you mean gmail.com? And then go from there. And I think there's more subtlety. They can maybe even look up MX records and things like that. But basically validate an email address heuristically and offer the nice, very friendly to a user, "Hey, did you mean this instead?" So not a full validation that says, "No, you cannot put your email address," because maybe you have a weird one that sounds like Gmail but isn't. But that's a little bit trickier to implement both on the Devise side and then in any other place that we have an email input. And so what we want to do is port over to Inertia and Svelte, and then everything's in our nice, happy context with all our components and all the other work that we're doing. And it really does just highlight how much I've come to enjoy working with Inertia and Svelte. They are fantastic technologies. And now I just want absolutely everything to be in them. So we're finally going to bite the bullet, and I think port those over a little bit after we get the current batch of work done. But soon, soon, that's the goal. STEPH: I'm having a bit of déjà vu where I feel like there was a project that you were working on that was using Devise, and then removing Devise and replacing it with something else was a challenge. Does that ring a bell? CHRIS: Yes, that is accurate. So I had a project that I worked on where we had both Devise and Clearance was actually what was going on. There were basically two different applications that existed; one was using Clearance, the later one used Devise. But then we folded those two applications back together. And by virtue of that, I tried to unify the authentication schemes, and it was like, nope, not going to happen. And then we didn't. STEPH: And then we didn't. [laughs] I like that ending. CHRIS: Well, sometimes you don't. [laughs] STEPH: Yeah, I love that ending because it reflects reality. Sometimes that just happens. In fact, I'm going to segue for just a moment because you're reminding me that there's something I don't think I've shared with you yet. On my previous project, there was a particular feature. It was a big feature that someone had picked up and worked on. And at one point, we were essentially playing hot potato with this feature because we hadn't gotten it to the point that it was merged. There was too much that was happening in that pull request, although then we ended up merging it. But then we found lots of bugs. And it was just one of those features that we couldn't really get across the finish line. There was always something else that was wrong with it or needed to be done or needed to be considered. And we'd reach that point where Chad Pytel, who is on the project, was like, "We're either going to finish this, or we're going to throw it away." And I felt a little guilty saying this, and I was like, "I vote we throw it away. I have lots of concerns about this. We are essentially reimplementing another complex workflow. But now, we are implementing it pretty differently in another portion of the application. It's going to be hard to manage. The cost of adding this and maintaining this is a really high concern." And so he talked with the rest of the team and came back, and he's like, "Yep, we're going to throw it away." And so then he issued a PR, and we removed it. And it was one of those moments of like; this isn't great because then we have invested hours into this, and now we are taking it away. But it also felt really good that that's always an option. And that was the better option because it was either we're going to continue sinking more time into this, or we can stop it now. And then we can move on to more important work. CHRIS: Sunk costs and all that. STEPH: Yeah. I feel like it's so rare when that really happens because then we just feel dedicated to like, well, we're going to make this valuable to somebody. We're going to keep this. And in this case, we just threw it away. It's very nice. CHRIS: There's a similar anecdote that I remember. Actually, I think it's happened more than once. But very particularly, we were working on a system. And this was with our friend, Matt Sumner, a friend of the show, as well been on a few times. And Matt was working on the project. And we got to a point where we had two competing implementations of a given workflow, and we were opting to go with the new one. But there were folks that were saying, "Let's keep the code around for the old one." And Matt was like, "Absolutely not. If we do that, we might go...no, this will be bad. Then we have to maintain that code. We need to burn the ships," as he said. And he actually named the pull request burn the ships where he just removed all the code. And I was like, I like your style, man. You made a decision here. We collectively made a decision. And then this is a classic Matt Sumner move. But he did the thing that we said we were going to do. And he just held that line. And I really appreciated it. And it's a voice that I have in the back of my head often now, which is just like, no, burn the ships. If we need it, it'll be in Git history. We can recover it. But it's going to need to be handled in the interim. We don't want to have to support that code right now and for however long until we actually decide to remove it from the codebase. So let's get rid of it. And if we really need it, well, then we'll resurrect it, but for now, burn the ships. And I like that. STEPH: I like that too. I think it's one of those areas where it takes experience to feel that pain too. If you're pretty new to writing code, you're going to think, well, we can keep it around. There's no harm. And so it often has to be that sage, that person who's been around long enough and felt some pain from making that decision in prior centuries or years. And he's like, "No, we're not going to do this." The WE collective of developers who have experienced the pain from this understand that that's not a good choice. And so we're going to burn the ships instead. But it is one of those that if you're newer, you won't think that way. And I think that's totally reasonable that you wouldn't think that immediately. CHRIS: I think that tacit knowledge that oh, I've gone through this before, and I've experienced the pain, and now let me tell you about that. And let me try and share that with you because there's always the cost-benefit trade-off. Because if that code stays in the codebase, then we know it works because we've kept it around for that whole time. And so there's a nicety to that, but there's a cost, that maintenance cost. And being able to express that well and being able to say, "I've been here, and let me tell you a tale," but do it in a way that doesn't sound overly condescending or explainy or things like that. I think that's a very subtle skill and a very important one, and frankly, really hard one to get right. I'm not sure I always hit the mark on that where I'm just like, "No, can't do it. It's bad." I think it's very easy to end up in a space where you're just like, "No, it's bad." And they're like, "But why?" And you're like, "Because it's bad. Trust me." It's like, well, I feel like you do need to be able to explain the stories, the experiences that you've had in the past, the anecdotes that you've heard, the blog posts that you've read that have really informed your thinking. But I think that is a big part of what it means to continue on in this profession and be able to do the work and make those subtle trade-offs, and the it depends because, at the end of the day, it all depends. STEPH: Or you just issue a pull request and title it burn the ships. [laughs] CHRIS: Burn the ships. Indeed, that is, in fact an option. And actually, while we're on the topic of pull requests, this might be a perfect segue into a listener question that we have. Mid-roll Ad And now a quick break to hear from today's sponsor, Scout APM. Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more. Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform. See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed. CHRIS: As always, thanks to everyone who sends in listener questions. We so appreciate getting them. They help direct the conversation and give us something to chat about. So this question comes in from Bryan Robles. And Bryan writes in about large pull requests. And Bryan writes in with, "My toxic trait is large pull requests. Any tips on when you get into a place where you're fixing or refactoring something, and it ends up cascading to many more changes than you want it to? I sometimes can go back and break it up. But it's hard to recognize a good seam when you're in the thick of it." So, Steph, what do you think? Large pull requests and finding yourself in them after [laughs] certain amounts of time. STEPH: Yeah, speaking of that knowledge that often comes from experience, this is something that I'm certainly always striving to get better at. I think it does take practice. There are some things that I do that I can share. And I categorize them really into a before, and I guess midway. So there's the before I set sail and set off to deeper waters list that I will think through as I'm starting a new task, and then there's the I'm lost at sea. And then, I need to figure out how I'm going to organize this change. So in the first category, when I'm first starting off a task, I consider what sort of changes need to be made, and are there any obvious roadblocks? So an obvious roadblock may be changing or updating a model that has one relationship, and I need to change it to has many relationships. Or perhaps there's a part of the application that is untested. And before I make any changes, I need to document that existing behavior. And that really falls neatly within Kent Beck's advice where he said, "First make the change easy (warning: this might be hard) and then make the easy change." So I try to think upfront what are some of the small, incremental changes that I can make first that will then make the final change easy? And then I separate that mentally into PRs. Or I may separate it into tickets, whatever is going to help me stay organized and communicate how I'm breaking up that work. And then the other thing that I'll do is I'll consider what's my MVP? So what's my minimum viable pull request? What set of changes include just enough changes to be helpful to users or to other developers? Which, by the way, is also a helpful mindset to have when you're breaking down work into tickets. So, as an example, let's say that I need to fix some bad data that's causing a site to error. So my first step could be to write a task to fix the bad data. And then, step two, prevent bad data from being created. And then probably step three, I need to rerun the task to fix data that was created during step two. But I can think through each of those steps and separate them into different pull requests. And then there may also be the question of well, how small is too small? Like you're saying, what's a minimum viable pull request? How do I know if I am not delivering value? And that one gets a little trickier and vague. But ultimately, I will think, does it pass CI? Is this change deployable? And then I do have to define what value I'm delivering. And I think that's a common area that folks struggle because we'll think of delivering value as delivering a whole new feature or adding complete test coverage for an untested interface. But delivering value doesn't have to represent that end goal. It may be that you added one test for an untested interface. And that's still delivering really great value to your team, same for delivering a feature to a user. You may be able to speak with that wonderful product manager and find what's the smallest bit of value that you can deliver instead of the whole feature set? I think the smallest PR I can think of that I've issued is either fixing a typo or removing a focus metadata from an RSpec test. So that's my starting point. That's the before I set sail. Those are some of the things I think about. I have more for the I'm lost at sea. But what are your thoughts? CHRIS: First, that was a great summary that you gave. So I totally agree with everything that you just said. I think part of the question I would have...So Bryan wrote this in and described this as his toxic trait. So he's identifying this as something that seemingly consistently plagues him. So I would ask, is there a way that you can introduce something? Like, are there natural breaks in your day? And can you ask the question at those breaks? Like, hey, I've been working on a thing for a little while. Is there a version that I could...like, could I close off a body of work at this moment? When you break for lunch, if you go grab coffee in the morning, when you're leaving at the end of the day, use those natural breakpoints. I'm not sure exactly what you mean when you say large pull requests. But if those are spanning multiple days, in my mind, if anything starts to span more than a day, I will start to ask that question to myself. And that's a reflex that I built up over time by feeling the pain of large pull requests and putting it up, and feeling apologetic. And then having my colleagues gently, professionally kindly ask me to break it down into smaller pieces. And me saying, "I really don't want it. All right, fine, fine, fine, I'll do it." And then I do it. And it's one of those things that I never want to do in the first place, but I'm always happy to have done after the fact. But it is work. And so, if I can get better at pulling that thinking and pulling that question earlier in the process, that I think is really useful. Similarly, I will try to, again, as friendly as I can; if I notice someone mentioning the same body of work at stand up for a few days, I might gently ask, "Hey, is there a way that we can find a shippable version of a portion of that of a subset? Can we put it up behind a feature flag and get something out there just to try and keep the PR small, et cetera?" And so gently nudge in that direction. And then I think the other side of that is being very okay with one character PRs. Like, that's it. We changed one character. It turns out we need to pluralize that word, or we need one-line changes are great. That's fine. And more pull requests, in my mind, are better than fewer, larger pull requests. And so really embracing that and having that be part of the core conversation and demonstrating that throughout the team is a way to share this idea. So that's perhaps more in the process or person point of view on this as opposed to the technical, but that's part of the consideration that I would have. I am interested, and I'll bounce back to, Steph, what you were saying of now that you're out at sea, what do you do? STEPH: So I need to react positively to some of the things that you just said because you made me think of two things. One of them is I've never had someone say, "Hey, Steph, that PR is too small. Could you add some more changes to it? Could you do some more work?" I have had people say, "Hey, that PR was hard to review." But even then, sometimes getting that feedback from folks is hard because nobody really wants to say, "I had a hard time reviewing your PR." That's something that, over time, you may become really comfortable saying to someone. But I think initially, people don't want to say, "Hey, that was hard to review," or "There were a lot of changes in that. Would you break it down?" Because that's a lot of complex emotions and discussion to have there. But yeah, I just figured I'd share that I have never had someone complain that a PR is too small, and I've issued a single character change. And then I love, love how much you asked the question of what's the problem we're trying to solve? And so there's this ambiguous idea of a large PR. But what does that mean? What are the pain points? What are we actually looking to change about our behavior? And then how is that going to impact or benefit the team or benefit ourselves? And so, going back to the question of how do we measure this? How do I know I'm starting to break up my changes in a helpful way? We may need to circle back to that because I don't have answers to it. But I just really like asking that question. As for the I'm lost at sea part, or maybe you're not lost at sea, but you've caught too many fish, and the fish warden is going to fuss at you if you bring too many fish back to dock. I don't think this is a real nautical example. But here we are. CHRIS: Was that the fish warden? STEPH: Yeah, the fish warden. You know, the fish warden. [laughs] CHRIS: Sure, I do, yeah. Yeah, I know about that, well-versed in fish law. STEPH: [laughs] Got to know your fish law. If we're going to talk about pull requests, you got to introduce fish law. But I'm actually going to quote Joël Quenneville, a fellow thoughtboter, because they shared a thoughtful thread on Twitter that talks a lot about breaking up your changes and how to break up your pull requests and your commits. And I'll be sure to include a link in the show notes because it's really worth reading as there's a lot of knowledge in that thread. But one of the things that Joël says is get comfortable with Git, and it makes a world of difference. In particular, you want to get really good at git add --patch, git reset, and git rebase interactive. And that is so true for me. Once I have gotten really good at using those commands, then I feel like I can break up anything. Because often when I am helping someone break something up, it's often they want to, but they're like, "I don't know how. And this is going to take so much of my time. It doesn't feel efficient and the right thing to do." And they're probably right. If you don't know how to break it up, then it may take you too long. And maybe it's not worth it at that point. But if you can ask a friend, and they can help walk you through this process, or if you can learn on your own, that's going to be a game-changer because you will start to think about how can I separate these commits? And I can reorder them, and then issue separate PRs, or just keep them in separate commits, whatever process you're looking to improve. In fact, there's a really great course on Upcase called Mastering Git written by someone who is co-host of this podcast. And it has a lot of great videos and tutorials that will help you get really good at these Git commands and then will help you split up your commits. CHRIS: Oh yeah, I did do that. Warning: it's like three and a half hours long. But it is broken up into, I believe, 10 or 11 videos. So you can find just the ones that you want. There's a couple in the middle that I think are particularly useful talking about the object model of Git. Git is weird, unfortunately. And so I spent a bunch of time in that course. Also, thank you for the kind words, Steph. [laughs] But I spent a bunch of time in that course trying to make Git less weird or understandable. If you look under the hood, it starts to make more sense. But if you really want to get comfortable with manipulating Git history, which I think is a really useful skill for this conversation that we're having, that's the only way I found to do it, just memorizing the steps. It's always going to feel a little bit foreign. But once you understand the stuff under the hood, that's a really useful thing for being able to manipulate and tease apart a pull request and break it into different things, and port things from one branch to another, and all those fun activities. Yeah, man, that was a bunch of years ago too. I wonder what I look like in it. Huh. STEPH: I really liked that episode, the one you just mentioned, the Git Object Model. Now that you've mentioned it, I remember watching it, and it's very interesting. So yeah, thank you for making all this helpful content for folks. There's also a blog post that we can include in the show notes as well that is a really nice overview of using git interactive, and rebase, and squash and amend those types of behaviors as well. So will be sure to include both so folks can check those out. And then to round things out, one of the other things that I will do is I will ask a friend. I will ask someone for help. So we've talked about some of these behaviors, or some of these processes that we have are really built up from experience and practice. And you can watch a lot of helpful content, and you can read blog posts. But sometimes, it really just takes time to get good at it. I know, as I'd mentioned earlier, I am always still looking to improve this particular skill because I think it's so valuable. And one of the ways I do that is I will just phone a friend. And I'll say, "Hey, can we chat for a bit? I would like to show you my changes. I want to hear from you if you see something in here that's valuable that you think can be shipped independently, so that way we can get it delivered faster." Or it may be a change that's just like a test improvement or something. And we can go ahead and get that immediately released to the team, and it will benefit them. Or you may want to do this at the start of a ticket. If I am new to a project or when I am new to a project, I will often ask someone to break down a ticket with me if I'm feeling a little bit uncertain. Or just say, "Hey, do you see any clean lines of division here? I feel like there's a lot in this ticket. You're more familiar with the codebase. What would you ship? How would you ship this incrementally?" and have someone else walk through the process with you. CHRIS: Yep, the phone a friend and/or, as always, pairing is a wonderful tool in these sorts of situations. The one other thing that comes to mind for me is part of the question was about sometimes it's difficult to find a clear parting line within a larger body of work, within a larger change. And that can definitely be true. I think there are certain standouts of like is this a refactoring that can be shipped separately? Is this a test change that would be useful on its own? Is there a model change that we could break out and have just that go out? So there's a bunch of mechanical questions that we can ask and say; here's categories of things that might fit that bill. But to flip this to the other side, the question was asked by Bryan very much as an I struggle with this thing. This is my toxic trait is the phrase that he used, which I thought was really interesting. And that can be true. This can be something that if you're consistently and uniquely within the team producing these giant PRs and then folks find that difficult to review, then I think that is absolutely something to work on. But if this is something that is happening between members like, other members of the team are also finding that they keep ending up with PRs that are bigger than they expected and taking longer and harder to review, there is a question of is the codebase actually in a shape that makes it harder to do small changes? There's the phrase shotgun surgery, which refers to a codebase that is so entangled and coupled that any change requires modifying ten files just to make one small alteration. And I think that's a worthwhile question to step back and ask, actually, is it not me? Is it actually the codebase? It could be both certainly. But there is a version of your codebase is coupled in a way that means that any even small, tiny change requires touching so many different places in the code. And if that's true, that's at least worth naming and worth highlighting and maybe talking about in retro and saying, hey, this feels like it's true. So maybe we start to get intentional about refactoring, and breaking out, and starting to add those dividing lines within the code such that hopefully, down the road, small changes can, in fact, be small changes. So that is the one last thing that I would consider here. Also, anecdotally, this is just a thing that came to mind. As I've worked with strongly-typed languages, systems that have a compiler, and have a type system, and the ability for the compiler to keep an eye on the whole codebase, I've noticed that it's very easy to do this sort of thing where I just start with one small data model change, and then the compiler is like, oh, you got to go fix it here, and here, and here, and here. And I found that because the compiler is your friend and will just point you to all the places you need to make the change, it is very easy to just keep going because some of that mechanical work is happening on your behalf. And it's a wonderful facet of typed languages and of having a compiler and being able to have that conversation with the compiler. But I found that for me, it is much easier to end up in this mode where I'm like, oh no, this PR is way too large. When I'm working in a system that has types, that has a compiler, that frankly makes it a little bit easier to chase down all the places you need to make a change. So that's also a consideration. It's not necessarily a good or a bad thing, just something that I've observed that feels like it's adjacent to this conversation. But yeah, I think those are my thoughts. STEPH: Yeah, those are great points. I've certainly worked on projects where that felt very true where it's a small change, but it would cascade throughout the project. And all the changes were necessary. It wasn't something that I could split into smaller PRs. So checking if it is the codebase that's really making it hard to have small PRS is a really great idea. CHRIS: Who'd have thunk such a little question could get us rambling for so long? Oh, wait, I would have thunk that. STEPH: And so far, reflecting on the things that we've talked about so far, I think I've talked a good game of where I'm saying, "Oh, I identify the seams upfront, and then I organize and create different tickets." And that is very much not the case. That's the really ideal outcome. But often, I am in the thick of things where like you just said...and it's this moment of, oh, I've done a lot in this PR. And how can I break this up? And that does take time. And it becomes a conversation of trade-off, which is why those Git skills really come in handy because then it will lower the cost of then splitting things out for others. But for people that are struggling with creating smaller PRs, I do think it's very fair to ask your team for help. I think it's also fair that if you issued a large pull request and folks have already reviewed it, and it's gotten approved, and someone makes a comment like, "Oh, this would be great as two PRs instead of one," to say, "Awesome, thank you for letting me know. I will take that forward with me, but I'm not going to do it for this PR." I wouldn't recommend making that a habit. But just know that that is something that you can say to someone to say, "I think this one is good to go at this point. But I will keep that in mind for future PRs. And I may even reach out to you for help if I feel like I'm having trouble splitting up a PR." And bring that person into your progress and use them as an accountability buddy. They can be someone that helps you down that path towards smaller PRs. CHRIS: Yeah, I definitely agree with that, although it becomes a very subtle line. Saying, "Thank you, but no thank you," in a pull request or to feedback is delicate. It's difficult. That's a whole thing. But I agree there have been times where I have either been the one making that decision or suggesting that or being like, "We probably should have broken this up. But we're far enough along now. Let's get this merged. And then we'll iterate on it after the fact." One last thing, actually. I thought I was done, but I have one more thing, which is I feel like there's a strong parallel between test-driven development and this question in that, often, I hear folks saying, "I don't know how to write tests upfront. I don't know how to do that. I know after the fact I can write tests, and I can add them after." And that can definitely be true. It can become more obvious after you've written the code how you could then write a test that would constrain that behavior that would interact with the system. But I think the useful thing that you can do there is take a moment and pause there and say, "Okay, now that I have written the test, what would it look like if I had written this in the first place?" Or if you really want to go for it, throw away the code, try again. Start with the test first and then rebuild it. That's maybe a little much. But that thing of taking these moments of maybe you don't know upfront how to break the work into smaller pieces, but then you get to the end, and you have that conversation with someone. And they highlight where some parting lines would be, or you figure it out after the fact. Stay there in that moment. Meditate on it a bit and try and internalize that knowledge because that's how moving forward, you might know how to do this in the future. So take those moments, whether it be with TDD or with pull requests, or breaking up a ticket into smaller tickets, anything like that. And spend a moment there and try and internalize that knowledge so that you have it proactively moving forward. STEPH: You know how Slack has status? I really like the idea of there being a status that's meditating on...and you can fill it in. And the example that you just provided, meditating on splitting up a pull request or meditating on how to write a test first, [laughs] I think that would be delightful. CHRIS: I, too, think that would be delightful. But with that long, adventurous answer to what seemed like a simple question, and they always do, but here we are, shall we wrap up? STEPH: Let's wrap up. CHRIS: The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes, as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Byeeeeeeeeeee! Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.

    315: Emotions Are A Pendulum

    Play Episode Listen Later Nov 9, 2021 41:23

    Steph talks about starting a new project and identifying "focused" tests while Chris shares his latest strategy for managing flaky tests. They also ponder the squishy "it depends" side of software and respond to a listener question about testing all commits in a pull request. This episode is brought to you by ScoutAPM (https://scoutapm.com/bikeshed). Give Scout a try for free today and Scout will donate $5 to the open source project of your choice when you deploy. rspec-retry (https://github.com/NoRedInk/rspec-retry) Cassidy Williams - It Depends - GitHub Universe 2021 (https://www.youtube.com/watch?v=aMWh2uLO9OM) Say No To More Process (https://thoughtbot.com/blog/say-no-to-more-process-say-yes-to-trust) StandardRB (https://github.com/testdouble/standard) Become a Sponsor (https://thoughtbot.com/sponsorship) of The Bike Shed! Transcript: CHRIS: My new computer is due on the fourth. I'm so close. STEPH: On the fourth? CHRIS: On the fourth. STEPH: That's so exciting. CHRIS: And I'm very excited. But no, I don't want to upgrade any software on this computer anymore. Never again shall I update a piece of software on this computer. STEPH: [laughs] CHRIS: This is its final state. And then I will take its soul and move it into the new computer, and we'll go from there. [chuckles] STEPH: Take its soul. [laughs] CHRIS: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey. STEPH: And I'm Steph Viccari. CHRIS: And together, we're here to share a bit of what we learn along the way. So, Steph, what's new in your world? STEPH: Hey, Chris. Let's see. It's been kind of a busy week. It's been a busy family week. Utah, my dog, hasn't been feeling well as you know because you and I have chatted off-mic about that a bit. So he is still recovering from something, I don't know what. He's still on most days his normal captain chaos self, but then other days, he's not feeling well. So I'm just keeping a close eye on him. And then I also got some other family illnesses going on. So it has been a busy family week for sure. On the more technical project side, I am wrapping up my current project. So I have one more week, and then I will shift into a new project, which I'm very excited about. And you and I have chatted about this several times. So there's always just that interesting phase where you're trying to wrap up and hand things off and then accomplish last-minute wishlist items for a project before then you start with a new one. So I am currently in that phase. CHRIS: How long were you on this project for? STEPH: It'll be a total of I think eight months. CHRIS: Eight months, that's healthy. That's a bunch. It's always interesting to be on a project for that long but then not longer. There were plenty of three and four-month projects that I did. And you can definitely get a large body of work done. You can look back at it and proudly stare at the code that you have written. But that length of time is always interesting to me because you end up really...for me, when I've had projects that went that long but then not longer, I always found that to be an interesting breaking point. How are you feeling moving on from it? Are you ready for something new? Are you sad to be moving on? Do you feel attached to things? STEPH: It's always a mix. I'm definitely attached to the team, and then there are always lots of things that I'd still love to work on with that team. But then, I am also excited to start something new. That's why I love this role of consulting because then I get to hop around and see new projects and challenges and work with new people. I'm thinking seven to eight months might be a sweet spot for me in terms of the length of a project. Because I find that first month with a project, I'm really still ramping up, I'm getting comfortable, I'm getting in the groove, and I'm contributing within a short amount of time. But I still feel like that first month; I'm getting really comfortable with this new environment that I'm in. And so then I have that first month. And then, at six months, I have more of heads-down time. And I get to really focus and work with a team. And then there's that transition period, and it's nice to know when that's coming up for several weeks, so then I have a couple of weeks to then start working on that transition phase. So eight months might be perfect because then it's like a month for onboarding, ramping up, getting comfortable. And then six months of focus, and then another month of just focusing on what needs to be transitioned so then I can transition off the team. CHRIS: All right. Well, now we've defined it - eight months is the perfect length of a project. STEPH: That's one of the things I like about the Boost team is because we typically have longer engagements. So that was one of the reasons when we were splitting up the teams in thoughtbot that I chose the Boost team because I was like, yeah, I like the six-month-plus project. Speaking of that wishlist, there are little things that I've wanted to make improvements on but haven't really had time to do. There's one that's currently on my mind that I figured I'd share with you in case you have thoughts on it. But I am a big proponent of using the RSpec focus filter for when running tests. So that way, I can just prefix a context it block or describe block with F, and then RSpec I can just run all the tests. But RSpec will only run the tests that I've prefixed with that F focus command., and I love it. But we are running into some challenges with it because right now, there's nothing that catches that in a pull request. So if you commit that focus filter on some of your tests, and then that gets pushed up, if someone doesn't notice it while reviewing your pull request, then that gets merged into main. And all of the tests are still green, but it's only a subset of the tests that are actually running. And so it's been on my mind that I'd love something that's going to notice that, that's going to catch it, something that is not just us humans doing our best but something that's automated that's going to notice it for us. And I have some thoughts. But I'm curious, have you run into something like this? Do you have a way that you avoid things like that from sneaking into the main branch? CHRIS: Interestingly, I have not run into this particular problem with RSpec, and that's because of the way that I run RSpec tests. I almost never use the focus functionality where you actually change the code file to say, instead of it, it is now fit to focus that it. I tend to lean into the functionality where RSpec you can pass it the line number just say, file: and then line number. And RSpec will automatically figure out which either spec or context block or entire file. And also, I have Vim stuff that allows me to do that very easily from the file. It's very rare that I would want to run more than one file. So basically, with that, I have all of the flexibility I need. And it doesn't require any changes to the file. So that's almost always how I'm working in that mode. I really love that. And it makes me so sad when I go to JavaScript test runners because they don't have that. That said, I've definitely felt a very similar thing with ESLint and ESLint yelling at me for having a console.log. And I'm like, ESLint, I'm working here. I got to debug some stuff, so if you could just calm down for a minute. And what I would like is a differentiation between these are checks that should only run in CI but definitely need to run in CI. And so I think an equivalent would be there's probably a RuboCop rule that says disallow fit or disallow any of the focus versions for RSpec. But I only want those to run in CI. And this has been a pain point that I felt a bunch of times. And it's never been painful enough that I put in the effort to fix it. But I really dislike particularly that version of I'm in my editor, and I almost always want there to be no warnings within the editor. I love that TypeScript or ESLint, or other things can run within the editor and tell me what's going on. But I want them to be contextually aware. And that's the dream I've yet to get there. STEPH: I like the idea of ESLint having a work mode where you're like, back off, I am in work mode right now. [chuckles] I understand that I won't commit this. CHRIS: I'm working here. [laughter] STEPH: And I like the idea of a RuboCop. So that's where my mind went initially is like, well, maybe there's a custom cop, or maybe there's an existing one, and I just haven't noticed it yet. But so I'm adding a rule that says, hey, if you do see an fcontext, fdescribe, ffit, something like that, please fail. Please let us know, so we don't merge this in. So that's on my wishlist, not my to-don't list. That one is on my to-do list. CHRIS: I'm also intrigued, though, because the particular failure mode that you're describing is you take what is an entire spec suite, and instead, you focus down to one context block within a given file. So previously, there were 700 specs that ran, and now there are 12. And that's actually something that I would love for Circle or whatever platform you're running your tests on to be like, hey, just as a note, you had been slowly creeping up and had hit a high watermark of roughly 700 specs. And then today, we're down to 12. So either you did some aggressive grooming, or something's wrong. But a heuristic analysis of like, I know sometimes people delete specs, and that's a thing that's okay but probably not this many. So maybe something went wrong there. STEPH: I feel like we're turning CI into this friend at the bar that's like, "Hey, you've had a couple of drinks. I just wanted to check in with you to make sure that you're good." [laughs] CHRIS: Yes. STEPH: "You've had 100 tests that were running and now only 50. Hey, friend, how are you? What's going on?" CHRIS: "This doesn't sound like you. You're normally a little more level-headed." [laughs] And that's the CI that is my friend that keeps me honest. It's like, "Wait, you promised never to overspend anymore, and yet you're overspending." I'm like, "Thank you, CI. You're right; I did say I want the test to pass." STEPH: [laughs] I love it. I'll keep you posted if I figure something out; if I either turn CI into that friend, that lets me know when my behavior has changed in a concerning way, and an intervention is needed. Or, more likely, I will see if there's a RuboCop or some other process that I can apply that will check for this, which I imagine will be fast. I mean, we're very mindful about ensuring our test suite doesn't slow down as we're running it. But I'm just thinking about this out loud. If we add that additional cop, I imagine that will be fast. So I don't think that's too much of an overhead to add to our CI process. CHRIS: If you've already got RuboCop in there, I'm guessing the incremental cost of one additional cop is very small. But yeah, it is interesting. That general thing of I want CI to go fast; I definitely feel that feel. And we're slowly creeping up on the project I'm working on. I think we're at about somewhere between five to six minutes, but we've gotten there pretty quickly where not that long ago; it was only three minutes. We're adding a lot of features specs, and so they are definitely accruing slowdowns in our CI. And they're worth it; I think, because they're so valuable. And they test the whole integration of everything, but it's a thing that I'm very closely watching. And I have a long list of things that I might pursue when I decide it's time for CI to get a haircut, as it were. STEPH: I have a very hot tip for a way to speed up your test, and that is to check if any of your tests have a very long sleep in them. That came up recently [chuckles] this week where someone was working in a test and found some relic that had been added a while back that then wasn't caught. And I think it was a sleep 30. And they were like, "Hey, I just sped up our test by 30 seconds." I was like, ooh, we should grep now to see if there's anything else like that. [laughs] CHRIS: Oh, I love the sentence we should grep now. [laughter] The correct response to this is to grep immediately. I thought you were going to go with the pro tip of you can just focus down to one context block. And then the specs will run so much faster because you're ignoring most of them, but we don't want to do that. The sleep, though, that's a pro tip. And that does feel like a thing that there could be a cop for, like, never sleep more than...frankly, let's try not to sleep at all but also, add a sleep in our specs. We can sleep in life; it's important, but anyway. [chuckles] STEPH: [laughs] That was the second hot tip, and you got it. CHRIS: Lots of hot tips. Well, I'm going to put this in the category of good idea, terrible idea. I won't call it a hot tip. It's a thing we're trying. So much as we have tried to build a spec suite that is consistent and deterministic and tells us only the truth, feature specs, even in our best efforts, still end up flaking from time to time. We'll have feature specs that fail, and then eventually, on a subsequent rerun, they will pass. And I am of the mindset that A, we should try and look into those and see if there is a real cause to it. But sometimes, just the machinery of feature specs, there's so much going on there. We've got the additional overhead of we're running it within a JavaScript context. There's just so much there that...let me say what I did, and then we can talk more about the context. So there's a gem called RSpec::Retry. It comes from the wonderful folks over at NoRedInk, a well-known Elm shop for anyone out there in the Elm world. But RSpec::Retry does basically what it says in the name. If the spec fails, you can annotate specs. In our case, we've only enabled this for the feature specs. And you can tell it to retry, and you can say, "Retry up to this many times," and et cetera, et cetera. So I have enabled this for our feature specs. And I've only enabled it on CI. That's an important distinction. This does not run locally. So if you run a feature spec and it fails locally, that's a good chance for us to intervene and look at whether or not there's some flakiness there. But on CI, I particularly don't want the case where we have a pull request, everything's great, and we merge that pull request, and then the subsequent rebuild, which again, as a note, I would rather that Circle not rebuild it because we've already built that one. But that is another topic that I have talked about in the past, and we'll probably talk about it again in the future. But setting that aside, Circle will rebuild on the main branch when we merge in, and sometimes we'll see failures there. And that's where it's most painful. Like, this is now the deploy queue. This is trying to get this out into whatever environment we're deploying to. And it is very sad when that fails. And I have to go in and manually say, hey, rebuild. I know that this works because it just worked in the pull request, and it's the same commit hash. So I know deterministically for reasons that this should work. And then it does work on a rebuild. So we introduced RSpec::Retry. We have wrapped it around our feature specs. And so now I believe we have three possible retries. So if it fails once, it'll try it again, and then it'll try it a third time. So far, we've seen each time that it has had to step in; it will pass on the subsequent run. But I don't know; there was some very gentle pushback or concerns; let's call them when I introduced this pull request from another developer on the team, saying, "I don't know, though, I feel like this is something that we should solve at the root layer. The failures are a symptom of flaky tests, or inconsistency or et cetera, and so I'd rather not do this." And I said, "Yeah, I know. But I'm going to merge it," and then I merged it. We had a better conversation about that. I didn't just broadly overrule. But I said, "I get it, but I don't see the obvious place to shore this up. I don't see where we're doing weird inconsistent things in our code. This is just, I think, inherent complexity of feature specs." So I did it, but yeah, good idea, terrible idea. What do you think, Steph? Maybe terrible is too strong of a word. Good idea, mediocre idea. STEPH: I like the original branding. I like the good idea, terrible idea. Although you're right, that terrible is a very strong branding. So I am biased right now, so I'm going to lead in answering your question by stating that because our current project has that problem as well where we have these flaky tests. And it's one of those that, yes, we need to look at them. And we have fixed a large number of them, but there are still more of them. And it becomes a question of are we actually doing something wrong here that then we need to fix? Or, like you said, is it just the nature of these features-specs? Some of them are going to occasionally fail. What reasonable improvements can we make to address this at the root cause? I'm interested enough that I haven't heard of RSpec::Retry that I want to check it out because when you add that, you annotate a test. When a test fails, does it run the entire build, or will it rerun just that test? Do you happen to know? CHRIS: Just the test. So it's configured as in a round block on the feature specs. And so you tell it like, for any feature spec, it's like config.include for feature specs RSpec::Retry or whatever. So it's just going to rerun the one feature spec that failed when and if that happens. So it's very, very precise as well in that sense where when we have a failure merging into the main branch, I have to rebuild the whole thing. So that's five or six minutes plus whatever latency for me to notice it, et cetera, whereas this is two more seconds in our CI runtime. So that's great. But again, the question is, am I hiding? Am I dealing with the symptoms and not the root cause, et cetera? STEPH: Is there a report that's provided at the end that does show these are the tests that failed and we had to rerun them? CHRIS: I believe no-ish. You can configure it to output, but it's just going to be outputting to standard out, I believe. So along with the sea of green dots, you'll see had to retry this one. So it is visible, but it's not aggregated. And the particular thing is there's the JUnit reporter that we're using. So the XML common format for this is how long our tests took to run, and these ones passed and failed. So Circle, as a particular example, has platform-level insights for that kind of stuff. And they can tell you these are your tests that fail most commonly. These are the tests that take the longest run, et cetera. I would love to get it integrated into that such that retried and then surface this to Circle. Circle could then surface it to us. But right now, I don't believe that's happening. So it is truly I will not see it unless I actively go search for it. To be truly honest, I'm probably not doing that. STEPH: Yeah, that's a good, fair, honest answer. You mentioned earlier that if you want a test to retry, you have to annotate the test. Does that mean that you get to highlight specific tests that you're marking those to say, "Hey, I know that these are flaky. I'm okay with that. Please retry them." Or does it apply to all of them? CHRIS: I think there are different ways that you can configure it. You could go the granular route of we know this is a flaky spec, so we're going to only put the retry logic around it. And that would be a normal RSpec annotation sort of tagging the spec, I think, is the terminology there. But we've configured it globally for all feature specs. So in a spec support file, we just say config.include Rspec::Retry where type is a feature. And so every feature spec now has the possibility to retry. If they pass on the first pass, which is the hope most of the time, then they will not be tried. But if they don't, if they fail, then they'll be retried up to three times or up to two additional times, I think is the total. STEPH: Okay, cool. That's helpful. So then I think I have my answer. I really think it's a good idea to automate retrying tests that we have identified that are flaky. We've tried to address the root, and our resolution was this is fine. This happens sometimes. We don't have a great way to improve this, and we want to keep the test. So we're going to highlight that this test we want to retry. And then I'm going to say it's not a great idea to turn it on for all of them just because then I have that same fear about you're now hiding any flaky tests that get introduced into the system. And nobody reasonably is going to go and read through to see which tests are going to get retried, so that part makes me nervous. CHRIS: I like it. I think it's a balanced and reasonable set of good and terrible idea. Ooh, it's perfect. I don't think we've had a balanced answer on that yet. STEPH: I don't think so. CHRIS: This is a new outcome for this segment. I agree. Ideally, in my mind, it would be getting into that XML format, the output from the tests, so that we now have this artifact, we can see which ones are flaky and eventually apply effort there. What you're saying feels totally right of we should be more particular and granular. But at the same time, the failure mode and the thing that I'm trying, I want to keep deploys going. And I only want to stop deploys if something's really broken. And if a spec retries, then I'm fine with it is where I've landed, particularly because we haven't had any real solutions where there was anything weird in our code. Like, there's just flakiness sometimes. As I say it, I feel like I'm just giving up. [laughs] And I can hear this tone of stuff's just hard sometimes, and so I've taken the easy way out. And I guess that's where I'm at right now. But I think what you're saying is a good, balanced answer here. I like it. I don't know if I'm going to do anything about it, but...[laughter] STEPH: Well, going back to when I was saying that I'm biased, our team is feeling this pain because we have flaky tests. And we're creating tickets, and we're trying to do all the right things. We create a ticket. We have that. So it's public. So people know it's been acknowledged. If someone's working on it, we let the team know; hey, I'm working on this. So we're not duplicating efforts. And so, we are trying to address all of them. But then some of them don't feel like a great investment of our time trying to improve. So that's what I really do like about the RSpec::Retry is then you can still have a resolution. Because it's either right now your resolution is to fix it or to change the code, so then maybe you can test it in a different way. There's not really a good medium step there. And so the retry feels like an additional good outcome to add to your tool bag to say, hey, I've triaged this, and this feels reasonable that we want to retry this. But then there's also that concern of we don't want to hide all of these flaky tests from ourselves in case we have done it and there is an opportunity for us to improve it. So I think that's what I do really like about it because right now, for us, when a test fails, we have to rerun the entire build, and that's painful. So if tests are taking about 20 minutes right now, then one spec fails, and then you have to wait another 20 minutes. CHRIS: I would have turned this on years ago with a 20-minute build time. [chuckles] STEPH: [laughs] Yeah, you're not wrong. But also, I didn't actually know about RSpec::Retry until today. So that may be something that we introduce into our application or something that I bring up to the team to see if it's something that we want to add. But it is interesting that initial sort of ooh kind of feeling that the team will give you introducing because it feels bad. It feels wrong to be like, hey, we're just going to let these flaky tests live on, and we're going to automate retrying them to at least speed us up. And it's just a very interesting conversation around where we want to invest our time and between the risk and pay off. And I had a similar experience this week where I had that conversation, but this one was more with myself where I was working through a particular issue where we have a state in the application where something weird was done in the past that led us to a weird state. And so someone raised a very good question where it's like, well, if what you're saying is technically an impossible state, we should make it impossible, like at the database layer. And I love that phrase. And yet, there was a part of me that was like, yes, but also doing that is not a trivial investment. And we're here because of a very weird thing that happened before. It felt one of those interesting, like, do we want to pursue the more aggressive, like, let's make this impossible for the future? Or do we want to address it for now and see if it comes back up, and then we can invest more time in it? And I had a hard time walking myself through that because my initial response was, well, yeah, totally, we should make it impossible. But then I walked through all the steps that it would take to make that happen, and it was not very trivial. And so it was one of those; it felt like the change that we ended up with was still an improvement. It was going to prevent users from seeing an error. It was still going to communicate that this state is an odd state for the application to be in. But it didn't go as far as to then add in all of the safety measures. And I felt good about it. But I had to convince myself to feel good about it. CHRIS: What you're describing there, the whole thought sequence, really feels like the encapsulation of it depends. And that being part of the journey of learning how to do software development and what it means. And you actually shared a wonderful video with me yesterday, and it was Cassidy Williams at GitHub Universe. And it was her talking to her younger self, and just it depends, and it was so true. So we will include a link to that in the show note because that was a wonderful thing for you to share. And it really does encapsulate this thing. And from the outside, before I started doing software development, I'm like, it's cool. I'm going to learn how to sling code and fix the stuff and hack, and it'll be great, and obvious, and correct, and knowable. And now I'm like, oh man, squishy nonsense. That's all it is. STEPH: [laughs] CHRIS: Fun squishy, and I like it. It's so good. But it depends. Exactly that one where you're like, I know that there's a way to get to correctness here but is it worth the effort? And looping back to...I'm surprised at the stance that I've taken where I'm just like, yeah, I'm putting in RSpec::Retry. This feels like the right thing. I feel good about this decision. And so I've tried to poke at it a tiny bit. And I think what matters to me deeply in a list of priorities is number one correctness. I care deeply that our system behaves correctly as intended and that we are able to verify that. I want to know if the system is not behaving correctly. And that's what we've talked about, like, if the test suite is green, I want to be able to deploy. I want to feel confident in that. Flaky specs exist in this interesting space where if there is a real underlying issue, if we've architected our system in a way that causes this flakiness and that a user may ever experience that, then that is a broken system. That is an incorrect system, and I want to resolve that. But that's not the case with what we're experiencing. We're happy with the architecture of our system. And when we're resolving it, we're not even really resolving them. We're just rerunning manually at this point. We're just like, oh, that spec flaked. And there's nothing to do here because sometimes that just happens. So we're re-running manually. And so my belief is if I see all green, if the specs all pass, I know that I can deploy to production. And so if occasionally a spec is going to flake and retrying it will make it pass (and I know that pass doesn't mean oh, this time it happened to pass; it's that is the correct outcome) and we have a false negative before, then I'm happy to instrument the system in a way that hides that from me because, at this point, it does feel like noise. I'm not doing anything else with the failures when we were looking at them more pointedly. I'm not resolving those flaky specs. There are no changes that we've made to the underlying system. And they don't represent a failure mode or an incorrectness that an end-user might see. So I honestly want to paper over and hide it from myself. And that's why I've chosen this. But you can see I need to defend my actions here because I feel weird. I feel a little off about this. But as I talk through it, that is the hierarchy. I care about correctness. And then, the next thing I care about is maintaining the deployment pipeline. I want that to be as quick and as efficient as possible. And I've talked a bunch about explorations into the world of observability and trying to figure out how to do continuous deployment because I think that really encourages overall better engineering outcomes. And so first is correctness. Second is velocity. And flaky specs impact velocity heavily, but they don't actually impact correctness in the particular mode that we're experiencing them here. They definitely can. But in this case, as I look at the code, I'm like, nah, that was just noise in the system. That was just too much complexity stacked up in trying to run a feature spec that simulates a browser and a user clicking in JavaScript and all this stuff and the things. But again, [laughs] here I am. I am very defensive about this apparently. STEPH: Well, I can certainly relate because I was defending my answer to myself earlier. And it is really interesting what you're pointing out. I like how you appreciate correctness and then velocity, that those are the two things that you're going after. And flaky tests often don't highlight an incorrect system. It is highlighting that maybe our code or our tests are not as performant as we would like them to be, but the behavior is correct. So I think that's a really important thing to recognize. The part where I get squishy is where we have encountered on this project some flaky tests that did highlight that we had incorrect behavior, and there's only been maybe one or two. It was rare that it happened, but it at least has happened once or twice where it highlighted something to us that when tests were run...I think there's a whole lot of context. I won't get into it. But essentially, when tests were being run in a particular way that made them look like a flaky test, it was actually telling us something truthful about the system, that something was behaving in a way that we didn't want it to behave. So that's why I still like that triage that you have to go through. But I also agree that if you're trying to get out at a deploy, you don't want to have to deal with flaky tests. There's a time to eat your vegetables, and I don't know if it's when you've got a deploy that needs to go out. That might not be the right time to be like, oh, we've got a flaky test. We should really address this. It's like, yes; you should note to yourself, hey, have a couple of vegetables tomorrow, make a ticket, and address that flaky test but not right now. That's not the time. So I think you've struck a good balance. But I also do like the idea of annotating specific tests instead of just retrying all of them, so you don't hide anything from yourself. CHRIS: Yeah. And now that I'm saying it and now that I'm circling back around, what I'm saying is true of everything we've done so far. But it is possible that now this new mode that the system behaves in where it will essentially hide flaky specs on CI means that any new flaky regressions, as it were, will be hidden from us. And thus far, almost all or I think all of the flakiness that we've seen has basically been related to timeouts. So a different way to solve this would potentially be to up the Capybara wait time. So there are occasionally times where the system's churning through, and the various layers of the feature specs just take a little bit longer. And so they miss...I forget what it is, but it's like two seconds right now or something like that. And I can just bump that up and say it's 10 seconds. And that's a mode that if eventually, the system ends in the state that we want, I'm happy to wait a little longer to see that, and that's fine. But there are...to name some of the ways that flaky tests can actually highlight truly incorrect things; race conditions are a pretty common one where this behaves fine most of the time. But if the background job happens to succeed before the subsequent request happens, then you'll go to the page. That's a thing that a real user may experience, and in fact, it might even be more likely in production because production has differential performance characteristics on your background jobs versus your actual application. And so that's the sort of thing that would definitely be worth keeping in mind. Additionally, if there are order issues within your spec suite if the randomize...I think actually RSpec::Retry wouldn't fix this, though, because it's going to retry within the same order. So that's a case that I think would be still highlighted. It would fail three times and then move on. But those we should definitely deal with. That's a test-related thing. But the first one, race conditions, that's totally a thing. They come up all the time. And I think I've potentially hidden that from myself now. And so, I might need to lock back what I said earlier because I feel like it's been true thus far that that has not been the failure mode, but it could be moving forward. And so I really want to find out if we got flaky specs. I don't know; I feel like I've said enough about this. So I'm going to stop saying anything new. [laughs] Do you have any other thoughts on this topic? STEPH: Our emotions are a pendulum. We swing hard one way, and then we have to wait till we come back and settle in the middle. But there's that initial passion play where you're really frustrated by something, and then you swing, and you settle back towards something that's a little more neutral. CHRIS: I don't trust anyone who pretends like their opinions never change. It doesn't feel like a good way to be. STEPH: Oh, I hope that...Do people say that? I hope that's not true. I hope we are all changing our opinions as we get more information. CHRIS: Me too. Mid-roll Ad And now a quick break to hear from today's sponsor, Scout APM. Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more. Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform. See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed. CHRIS: Well, shifting only ever so slightly because it turns out it's a very related question, but we have a listener question. As always, thank you so much to everyone who sends in listener questions. We really appreciate them. And today's question comes from Mikhail, and he writes in, "Regarding the discussion in Episode 311 on requiring commits merged to be tested, I have a question on how you view multi commit PRs. Do you think all the commits in a PR should be tested or only the last one? If you test all commits in a PR, do you have any good tips on setups for that? Would you want all commits to pass all tests? For one, it helps a lot when using Git bisect. It is also a question of keeping the history clean and understandable. As a background on the project I currently work on, we have the opinion that all commits should be tested and working. We have now decided on single commit PRs only since this is the only way that we can currently get the setup reasonably on our CI. I would like to sometimes make PRs with more than one commit since I want to make commits as small as possible. In order to do that, we would have to find a way to make sure all commits in the PR are tested. There seems to be some hacky ways to accomplish this, but there is not much talk about it. Also, we are strict in requiring a linear history in all our projects. Kind regards, Mikhail." So, Steph, what do you think? STEPH: I remember reading this question when it came in. And I have an experience this week that is relevant to this mainly because I had seen this question, and I was thinking about it. And off the cuff, I haven't really thought about this. I haven't been very concerned about ensuring every single commit passes because I want to ensure that, ultimately, the final commit that I have is going in. But I also rarely have more than one commit in a PR. So that's often my default mode. There are a couple of times that I'll have two, maybe three commits, but I think that's pretty rare for me. I'll typically have just one commit. So I haven't thought about this heavily. And it's not something that frankly I've been concerned about or that I've run into issues with. From their perspective about using Git bisect, I could see how that could be troublesome, like if you're looking at a commit and you realize there's a particular commit that's already merged and that fails. The other area that I could think of where this could be problematic is if you're trying to roll back to a specific commit. And if you accidentally roll back to a commit that is technically broken, but you didn't know that because it was not the final commit as was getting tested on CI, that could happen. I haven't seen that happen. I haven't experienced it. So while that does seem like a legitimate concern, it's also one that I frankly just haven't had. But because I read this question from this person earlier this week, I actually thought about it when I was crafting a PR that had several commits in it, which is kind of unusual for me since I'm usually one or two commits in a PR. But for this one, I had several because we use standard RB in our project to handle all the formatting. And right now, we have one of those standard to-do files because we added it to the project. But there are still a number of manual fixes that need to be applied. So we just have this list of files that still need to be formatted. And as someone touches that file, we will format it, and then we'll take it out of that to-do list. So then standard RB will include it as it's linting all of our files. And I decided to do that for all of our spec files. Because I was like, well, this was the safest chunk of files to format that will require the least amount of review from folks. So I just want to address all of them in one go. But I separated the more interesting changes into different commits just to make others aware of, like, hey, this is something standard RB wants. And it was interesting enough that I thought I would point it out. So my first commit removed all the files from that to-do list, but then my other commits are the ones that made actual changes to some of those files that needed to be corrected. So technically, one or two of my middle commits didn't pass the standard RB linting. But because CI was only running that final commit, it didn't notice that. And I thought about this question, and so I intentionally went back and made sure each of those commits were correct at that point in time. And I feel good about that. But I still don't feel the need to add more process around ensuring each commit is going to be green. I think I would lean more in favor of let's keep our PR small to one or two commits. But I don't know; it's something I haven't really run into. It's an interesting question. How about you? What are your experiences, or what are your thoughts on this, Chris? CHRIS: When this question came through, I thought it was such an interesting example of considering the cost of process changes. And to once again reference one of our favorite blog posts by German Velasco, the Say No to More Process post, which we will, of course, link in the show notes. This is such a great example of there was likely a small amount of pain that was felt at one point where someone tried to run git bisect. They ran into a troublesome commit, and they were like, oh no, this happened. We need to add processes, add automation, add control to make sure this never happens again. Personally, I run git bisect very rarely. When I do, it's always a heroic moment just to get it started and to even know which is the good and which is the bad. It's always a thing anyway. So it would be sad if I ran into one of these commits. But I think this is a pretty rare outcome. I think in the particular case that you're talking about, there's probably a way to actually tease that apart. I think it sounds like you fixed those commits knowing this, maybe because you just put it in your head. But the idea that the process that this team is working on has been changed such that they only now allow single commit PRs feels like too much process in my mind. I think I'm probably 80%, maybe 90% of the time; it's only a single commit in a PR for me. But occasionally, I really value having the ability to break it out into discrete steps, like these are all logically grouped in one changeset that I want to send through. But they're discrete steps that I want to break apart so that the team can more easily review it so that we have granular separation, and I can highlight this as a reference. That's often something that I'll do is I want this commit to standalone because I want it to be referenced later on. I don't want to just fold it into the broader context in which it happened, but it's pretty rare. And so to say that we can't do that feels like we're adding process where it may not be worth it, where the cost of that process change is too high relative to the value that we're getting, which is speculatively being able to run git bisect and not hit something problematic in the future. There's also the more purist, dogmatic view of well, all commits should be passing, of course. Yeah, I totally agree with that. But what's it worth to you? How much are you willing to spend to achieve that goal? I care deeply about the correctness of my system but only the current correctness. I don't care about historical correctness as much, some. I think I'm diminishing this more than I mean to. But really back to that core question of yes, this thing has value, but is it worth the cost that we have to pay in terms of process, in terms of automation and maintenance of that automation over time, et cetera or whatever the outcome is? Is it worth that cost? And in this case, for me, this would not be worth the cost. And I would not want to adopt a workflow that says we can only ever have single commit PRs, or all commits must be run on CI or any of those variants. STEPH: This is an interesting situation where I very much agree with everything you're saying. But I actually feel like what Mikhail wants in this world; I want it too. I think it's correct in the way that I do want all the commits to pass, and I do want to know that. And I think since I do fall into the default, like you mentioned, 80%, 90% of my PRs are one commit. I just already have that. And the fact that they're enforcing that with their team is interesting. And I'm trying to think through why that feels cumbersome to enforce that. And I'm with you where I'll maybe have a refactor commit or something that goes before. And it's like, well, what's wrong with splitting that out into a separate PR? What's the pain point of that? And I think the pain point is the fact that one, you have two PRs that are stacked on each other. So you have the first one that you need to get reviewed, and then the second one; there's that bit of having to hop between the two if there's some shared context that someone can't just easily review in one pull request. But then there's also, as we just mentioned, there's CI that has to run. And so now it's running on both of them, even though maybe that's a good thing because it's running on both commits. I like the idea that every commit is tested, and every commit is green. But I actually feel like it's some of our other processes that make it cumbersome and hard to get there. And if CI did run on every commit, I think it would be ideal, but then we are increasing our CI time by running it on every commit. And then it comes down to essentially what you said, what's the risk? So if we do merge in a commit that doesn't work or has something that's failing about it but then the next commit after that fixes it, what's the risk that we're going to roll back to that one specific commit that was broken? If that's a high risk for you and your team, then adding this process is probably the really wise thing to do because you want to make sure the app doesn't go down for users. That's incredibly important. If that's not a high risk for your team, then I wouldn't add the process. CHRIS: Yeah, I totally agree. And to clarify my stances, for me, this change, this process change would not be worth the trade-off. I love the idea. I love the goal of it. But it is not worth the process change, and that's partly because I haven't particularly felt the pain. CI is not an inexhaustible resource I have learned. I'm actually somewhat proud our very small team that is working on the project that we're working on; we just recently ran out of our CI budget, and Circle was like, "Hey, we got to charge you more." And I was like, "Cool, do that." But it was like, there is cost both in terms of the time, clock time, and each PR running and all of those. We have to consider all of these different things. And hopefully, we did a useful job of framing the conversation, because as always, it depends, but it depends on what. And in this case, there's a good outcome that we want to get to, but there's an associated cost. And for any individual team, how you weigh the positive of the outcome versus how you weigh the cost will alter the decision that you make. But that's I think, critically, the thing that we have to consider. I've also noticed I've seen this conversation play out within teams where one individual may acutely feel the pain, and therefore they're anchored in that side. And the cost is irrelevant to them because they're like, I feel this pain so acutely, but other people on the team aren't working in that part of the codebase or aren't dealing with bug triage in the same way that that other developer is. And so, even within a team, there may be different levels of how you measure that. And being able to have meaningful conversations around that and productively come to a group decision and own that and move forward with that is the hard work but the important work that we have to do. STEPH: Yeah. I think that's a great summary; it depends. On that note, shall we wrap up? CHRIS: Let's wrap up. The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes, as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Byeeeeeeeeee! Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.

    314: Communication, Testing, and Accountability

    Play Episode Listen Later Oct 26, 2021 40:55

    Chris regains several of his developer merit badges and embarks on a perilous CSRF (Cross-Site Request Forgery) adventure. Steph shares highlights from Plucky, a management training course, including ways we can "click" and "break apart" from our current role, and how to have hard conversations. They also discuss how software development processes change at different team sizes, processes that break down as teams grow, and processes that are resilient at any team size. This episode is brought to you by ScoutAPM (https://scoutapm.com/bikeshed). Give Scout a try for free today and Scout will donate $5 to the open source project of your choice when you deploy The Nightmare Before Christmas - What's This (https://youtu.be/QLvvkTbHjHI) Giant Robots Smashing into other Giant Robots - Plucky with Jen Dary (https://www.giantrobots.fm/search?utf8=%E2%9C%93&term=plucky) Plucky (https://www.beplucky.com/) Services are Not a Silver Bullet (https://thoughtbot.com/blog/services-are-not-a-silver-bullet) Become a Sponsor (https://thoughtbot.com/sponsorship) of The Bike Shed! Transcript: STEPH: Boom. I'm recording. Magic is happening. [singing] What's this? What's this? It's a Bike Shed episode. What's this? What's this? CHRIS: You did that on the mic. [laughter] So you just started recording too, so it's not like you're like, "Oh, I forgot I was recording." STEPH: Oh, I didn't have a finishing line that rhymes with shed. CHRIS: Head, dead, bread, spread. STEPH: [singing] Is TDD dead? I don't know. [laughs] CHRIS: Cool. I liked it. STEPH: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Steph Viccari. CHRIS: And I'm Chris Toomey. STEPH: And together, we're here to share a bit of what we've learned along the way. Hey, Chris, what's new in your world? CHRIS: What's new? I had a fun experience over the past week or two of regaining some of my developer merit badges, which is always enjoyable. So one was I had to configure AWS, specifically S3 and IAM such that I could upload files to an S3 bucket, which seems like one of those things that a developer should be able to do, and it's just not that hard. And, man, I failed so many times, and I stared at the screen. And the ARNs I think that's another acronym that I had to try and figure out what it means and fight against. Anyway, I got there. So that's one merit badge earned. I really hope [laughs] I correctly and securely configured access to an S3 bucket such that we could upload files in our Rails app. Cool, neat. Moving on, the next merit badge that I went for was restoring the sea of green dots. Our RSpec output had gathered some noise. There was a whole bunch of noise across a variety of things. There were some dev tools that were dumping some stuff in there. And there was something related to apparition, which is the...I want to say it's the Capybara feature spec driver that we're using now, which sits on top of ChromeDriver or something like that. I don't really understand the details, but it was complaining about something. And I found a fix, and then I fixed it and whatnot. But it was one of those. I did this on a Saturday because I was just like, you know what? This will be cathartic and healing. And then I got to the sea of green dots, and I was so happy to get to it. STEPH: This is me...I'm giving you a round of applause. CHRIS: Well, thank you. Arguable whether it delivered any real value to users, but again, this was Saturday effort, so I was allowed to indulge my fastidious caretaker of the code role. STEPH: Sorry, before we move on to more serious, can we pause to talk about developer merit badges? I really, really want cute felt badges that we can...I mean, I can't design them. I don't have the talent. But I think between us and other folks, we could design amazing merit badges, and then people could collect those. I'm very much in love with that idea. CHRIS: I love the idea. I am now certain that if we were to really pursue this, that we would fall into the deepest of bike sheds as we try and define well; what are all the merit badges? And what are the different levels? STEPH: [laughs] CHRIS: And how many do you need to collect before you can get to what are the different...There are just so many different taxonomies that we could introduce, and, oh man, I could spend a couple of weeks on that. STEPH: [laughs] It has a very strong Pokémon vibe too of you got to catch them all. CHRIS: Absolutely. STEPH: Okay. All right. We won't digress into bikeshedding merit badges, but I'm still very, very interested in that idea. CHRIS: Indeed. If anyone out there in the listener space wants to just make these, that would be great. This is the way that I avoid bikeshedding now is I just say I'm not allowed to make these decisions or even think about it. But if these happened into the world, I would be happy about that. STEPH: Oh, I just remembered we do have something similar at thoughtbot. They're not physical where you can hold them, but I think we've talked about turning them into physical badges. But we have our internal tool hub that we used to track our schedules. And one of the fun Ralphapalooza events that we had, a team came up with the idea of introducing badges in the tool hub, so then you could award people badges. You could give people badges. And it's very cute. So they could probably help us with the taxonomy. They've probably already figured out a number of badges we could get started with. CHRIS: And of course, this is where my brain went initially to like, oh, what would the taxonomy be? But I think that's how this goes bad. And if we just keep it in the this is cute and fun, and what are all the possible merit badges, but they're all equal, and the points are made up anyway, and then it's just a fun thing, then I'm like, I'm super into this. Let's do that. Have you used a regular expression to parse HTML? Congratulations, you get a merit badge. Have you not used regular expressions to parse HTML? You get a different merit badge. [chuckles] STEPH: [laughs] I feel very positive that I could be chief of cute and fun. I could manage that department. CHRIS: Yes, that feels like definitely a role that you could really excel at. But shifting around ever so slightly, I did run into a fun bug this week. And it was a mystery tour of, I'm going to say, sadness and then eventual learning and understanding, and I think we've come to a better place. But I want to tell a story, take us on a quick tour of the adventure that I went through. So we recently saw a handful of exceptions come through in our exception monitoring service and then piped into Slack, where we see those around CSRF token expiry. So this occasionally happens in a Rails app. The CSRF token that was on the page gets rotated. And therefore, when someone...if they have an older version of the page open and they try and submit a form or something like that, then CSRF protection is going to kick in. And you do get some false negatives there or some cases where like, nope, this is actually a fine user, this is not hacking, this is nothing bad. It's just that that user had a tab open or something like that. I'll be honest; I want to understand better the timeline of expiry and how Rails expires those and whatnot. But it's one of those things; it's deep enough in Rails that I trust that they are doing a very reasonable thing. And I think the failures that we're seeing that's part of the game. And so, mostly, we wanted to add a nicer handling around that. So thankfully, Inertia actually has a really wonderful page in their docs about handling Cross-Site Request Forgery expiration token, this whole thing. This is a particular failure mode that your app might have. And so it's nice to be able to provide a nicer user experience. And so what we ended up doing is if we catch that exception, we have a rescue_from in our application controller that will instead of having this be a 500 and just a full, like, something went wrong error page, we instead respond in an Inertia-like way to basically show a flash message that says, "This page has expired. Please refresh the page to continue." And if the user just refreshes the page, then they will get a new CSRF token. And from there, everything is going to be fine. So it's not ideal. But it is, I think, both secure and now a nicer user experience. STEPH: Yeah, that sounds really nice. When they refresh the page, do they lose all that form data? I'm curious how painful of a flow that is for the user. CHRIS: Currently, yes. Inertia actually has a really nice feature for remembering form data. If you've ever been on GitHub and you're filling in a box, and then you go away to a different tab, and you come back, and it's still there, and you're happy about that, it's that sort of thing. So we could configure that. At this point, we don't have...most of our forms are pretty small. So this is not something that we opted to do proactive management around. But that is definitely something that we could add but not something that's default or anything like that. STEPH: Cool. Yeah, that makes sense. I was just curious because yeah, either small form doesn't really matter, or also, this may be just a small enough error that only a handful of people are experiencing it that it's also just not that big of a deal. CHRIS: Yes, this definitely should be an edge case. And we've also recently been working on functionality to log folks out after a period of inactivity, which would also, I think, obviate this in a different way. So all total, this shouldn't be a big deal. And this was basically a quick, little snippet of code that we thought we could just drop in, and everything would be great because it shouldn't happen much. But then I was testing out a different feature on staging, and everything I tried to do was popping up this little alert flash message that was like, "Hey, your page is expired." And I was like, that seems bad. And then I realized literally every action, any non-GET request, was getting this response that the CSRF token didn't match. And I was like, well, this seems bad. Luckily, it was only on staging and hadn't made it to production. But it had made it to staging, which meant it had gotten through CI, which was very concerning because we have a pretty robust set of feature specs at this point. We built up a bunch of fakes for all of the external data systems that we're interacting with. And we're really putting the app through its paces and trying to do so in a very production-like way. And so I was like, this is such a deep fundamental breakage. I don't know what's going on here. And so I started to investigate. And it turns out that in a recent commit, I had started using Axios, which is a little wrapper around the Fetch API. They may not actually use the Fetch API under the hood, but it allows you to have a nicer interface to make XHRs. And we implicitly had that in our package already by virtue of Inertia. Inertia uses it under the hood, but I wanted to make it explicit because now I was using it directly. So I figured that's cool. I will yarn add Axios, and then I will continue on with my day. And I worked on my feature and everything was great. And then I pushed it up into a pull request, and everything was great, and CI passed. And I got it onto staging, and everything was very sad. So then I started on the adventure of like, what is going on here? It turns out that somewhere between version 0.21.1 of Axios and 0.23.0, which there's a bunch of things about those version numbers that make me uncomfortable but here we are, somehow the behavior where you can configure the XSRF header name, which is what they're calling it on their side, the configuration stopped working. And so our override that says this is what our CSRF or XSRF token should be called when it's sent back up to the server in a header that was getting lost. And so they were falling back to their default name, Axios was. And, therefore, Rails was like, "There's no CSRF token here. So this is going to be a no for me. I'm going to reject all of the requests." So the fix was relatively easy to roll back and to pin the version of Axios to the previous version that we had been using. I didn't actually intend to upgrade it. I just intended to make it an explicit dependency. But by doing that, I accidentally upgraded it. I don't love that there was this pretty deep breakage in that. I haven't done the good work of trying to open an issue. I still want to scan through and see if there is an open issue or a conversation around this before I start making any noise. But I think if I don't find anything, this is the sort of thing that should be reported because I can't imagine I'm the only one running into this. Likewise, I was very sad that my test suite did not find this. Turns out in Rails, CSRF protection is just turned off in test mode, which may be overall makes sense. But for feature specs, in particular, I definitely want to have it. And so, it was nice that I was able to find the relevant configuration. And we introduced an RSpec configuration that says, "If it's a feature spec, save off the existing configuration and enable CSRF. And then after the spec, go back to whatever the previous was." So now all feature specs run with CSRF. And I did make sure to push up that as a singular change to CI, and CI was very unhappy with me. Many, many features-specs failed, which was good. That was what we were going for. They failed for the right reason because things were fundamentally broken. And then, I was able to update the package-lock or the package.json on the yarn lock, pin the version, fix everything. But man, there was this period of like, oh man, the app is broken in such a fundamental way. Users just can't do stuff anymore. They can view anything, but they couldn't change any data. And it just snuck through CI. And that feeling is the worst feeling. We had, at this point, built up a lot of trust in our test suite. It was really telling us when stuff was wrong, and if it was green, I felt very good merging. And suddenly, this just really shook me to my core on that front. STEPH: I love these journeys that you take us on. I mean, they're painful for you, and I am sorry to hear that. But I love these journeys that you take us on. [chuckles] CHRIS: I usually only take us on them when I've figured out the answer. And I'm like, all right, here's where we're at. It was rough for a little while, but now we are happy. And thankfully, the one configuration of saying, hey, Rails, also, please include this as part of our production like, configuration for test mode. So I feel better that moving forward, this breakage won't happen again. STEPH: We should add that as another merit badge for telling a bug story. All right, I'm taking off my hat of chief of fun and cuteness. So this may not be terribly relevant to all the things that you just shared. But I am curious where you mentioned that with Axios because you'd specified the name of the token, and then that overriding behavior is what then broke. And so then that's what led to this whole adventure that you went on. I'm curious, why did y'all customize the name of that token? CHRIS: A, this is a great question. B, I'm not super sure. C, I think the reason is because we were trying to align to Rails. So we have a little middleware on the Rails side that will serialize the CSRF token into a cookie. And then that cookie value gets read by Axios and sent back up as a header on the request. So this is the way that with Inertia CSRF just kind of works and is good. And it's different than Rails' normal. We put a hidden input into any form. And so Rails holistically knows about both sides of that, and everything works fine. But now I have to manually round trip the CSRF token. And Axio's default configuration is a header name X-XSRF-TOKEN, and we needed X-CSRF-TOKEN because that's what Rails is looking for. I probably could have configured it the other way on the Rails side. But one way or another, I had to get Rails and Axios to come to an agreement, to meet at a table, and to agree to collectively protect the app. And so I had to mediate that discussion, and that's what ended us here. STEPH: A meeting of the minds. [chuckles] Cool, cool, cool. Yeah, that makes sense. I was just curious because then that would have changed the whole journey. But yeah, that is super interesting. And I definitely resonate with the idea of when you've really invested in your test suite, and you trust it that then when it doesn't catch something that obviously breaks the application, then that feels like something worth prioritizing and digging into and then figuring out how to bring back that parity. I don't know that I've turned on enable CSRF for feature spec. So I'm also very interested in looking at that configuration and considering if I need that for any of my future client projects if that's something that I need to remember for the future because that's very niche but good to know about. CHRIS: I feel like this only really comes up if you're working in the...it's called the odd middle ground that Inertia ends up occupying. If you're in a traditional Rails app that is generating HTML server-side, forms are generated. They got the CSRF token inlined there in a hidden input. And then when you post that form, it's coming back up. The names automatically are going to match. You don't need to worry about it. And it's probably fine to not have it included in test mode. And if you're at the other end of the spectrum and you've got API interaction, and that's the way you're doing everything, then you have a different auth mechanism and cookies, and whatnot just don't apply in the same way. And so it won't really matter on that side but for a different reason. And it's only because we're in this interesting middle ground, which, again, I really love. And it's the thing that I love about Inertia. But this is a rare case where it's like, oh, we do have to bring the two sides to meet in the middle. And this is a case where, unfortunately, due to a very subtle breakage on a minor release of...a package that we're using silently broke so, yeah. But yeah, thankfully, everything is back to working. And again, we've been able to enhance the test suite in that little way that I feel confident again because this won't sneak in another time. We have coverage around this. We're good to go. So while I was very scared when this initially happened, I feel better now. I'm happy to go into the weekend feeling better about this. But that's my story. What's new in your world? STEPH: So I feel like I've been having one of those weeks where I have less code adventures. In fact, it's one of those days where I went to thoughtbot's daily sync...because we often have our client daily syncs, but then we still have a thoughtbot sync as well. And I went to the group, and I was like, I get to write code today. It's going to be a great day. All the other things I'm doing are also interesting, but I get particularly excited when I get some maker's time and get to write some code. So I feel like I've had less coding adventures recently and more hiring and process-related adventures. And specifically, I just completed the Plucky Manager Training, which is a program that's founded and led by Jen Dary, who was recently on thoughbot's podcast, The Giant Robots Smashing Into Other Giant Robots. I'll be sure to include a link in the show notes for anyone that's interested. CHRIS: I believe this was the third time she was on. It's at least the second, possibly the third. And all of them are great listens, just as an aside, so we should include links to all of them. STEPH: Yes, I think she's one of the rare guests that has been on the show three times. And I think I've only listened to the first couple minutes of that episode. But I think they talk about the fact that this is her third episode, which is really, really cool. And I'm still frankly synthesizing all the information and the ideas that I've collected from the course. But I do have a few quick takes that I'm interested in sharing with you. So the first one is my cohort...we were the Panda Cohort, so go, Pandas. And some of the things that we talked about were…, and I think that this may have been the first day. So it was three days, and it was three hours for those three days. And they're spread out over a couple of weeks, which is really nice because then you show up for those three hours of the class, but then you leave with some ideas and some things to experiment with. You get a week to then try out an experiment and then come back to class next time and talk about this is how it went; it went to wonderful, or it went terrible. And you get to share that with others and work through it. And in the first class, we talked about coaching versus managing, which I found just a helpful definition to review. So managing is more direct, and telling someone what to do while coaching is encouraging someone to determine their own path and find their own solution. And I find that as a team lead at thoughtbot, I'm very often more in that coaching space than I am in that managing space. I think it's frankly pretty rare that I actually need to put on a manager's hat. And I often feel like I'm wearing my coaching hat instead. And some of the other things we talked about one of them is what is work? Which is a fun question to ask. And Jen had an analogy for this speaking about imagine that you have a plastic Easter egg. So it's got two sides, and side one is all the skills and desires and things that you're fulfilled by. And side two is a company that needs those skills. And it's great when those line up and click together, like when you take a job or get a promotion. Have you ever played...do you know what I'm talking about? Those little plastic Easter eggs. Have you ever played with those as a kid? CHRIS: Yes, certainly. STEPH: [laughs] I realize I just launched into that analogy. [chuckles] And then Jen goes on to say that's totally normal for then those sides to unclick. And Jen continues to say that it's totally normal for them to unclick. So maybe the company changes direction, the company is acquired. You've fallen out of love with something that you do about your job, or you have kids, and that has changed the things that you are fulfilled by and what you're looking for. And that's not necessarily bad. So it can be like, hey, you are working on x now, and you're not fulfilled by that anymore. But then another company comes along and says, "Hey, we're working on this, and you are fulfilled by that." So then another click happens. And essentially, it's a nice analogy to represent someone's career path and the ways that we are going to shift and re-prioritize what we're interested in. But it's also a really nice way to help it feel less personal because both sides are allowed to change. The company can change. You, as an employee, can change. And then you can look for that next click that is going to match up with a company that meets your skills and things that help you feel fulfilled. One of the other topics that we talked about are hard conversations, which I love that we dug into this one because that's certainly one that I struggle with or...I mean, we all get that feeling if you have to confront someone if you have to have that uncomfortable discussion with someone. It is a very hard thing to do. And so we had some very honest conversations around what is a hard conversation? What does that represent? And essentially, they represent that there is stalled progress and something can be improved. So Jen likens a hard conversation to a tool. It's something that you can use to then help something move forward again if something feels stalled or if there's something that needs to change. And during those hard conversations, you may not get to the resolution that you're looking for. So you may be looking for a specific outcome. But you also have another person that needs time to respond and to take in everything that you have said and process that information. So when you have a hard conversation, you may actually only move forward an inch. So if you had a lofty goal of we're going to talk and then we're going to have this hard conversation, and we're going to get to this space...But instead, you actually just make incremental progress. Like, okay, at least this person is now aware of this concern. That might be your win for the hard conversation versus actually tackling; how are we going to address it? I just want them to be aware of this concern. And it's a very vulnerable conversation, and they often take time before you can get to that ideal resolution. But essentially, the idea is get in the game, start the conversation, and then have follow-up conversations for that hard conversation. And I really appreciated that framing because I often will think of hard conversations of oh, we have to have this hard conversation and get to this specific outcome. But if you shift the goal line to be like, no, I really just need to at least make this person aware of a concern, that makes it a lot more approachable. And then also probably yields more fruitful outcomes because that gives the other person time to think about what you've shared to also come to the table with their own ideas and then work together to then get to that ideal resolution. CHRIS: I like that framing a lot. I can definitely see the case where you, as someone who has recognized something that needs to change (perhaps you're a manager),lineup you've now thought about that a good bit; you've observed it, but the individual that you're bringing that to this may be novel. This may be a surprise for them. And so if you come into that interaction both about to share this information but then also trying to resolve it and trying to get to I need you to internalize it, and I need you to fundamentally change your behavior as a result of this conversation we're going to have, that's quite possibly not a realistic outcome. And if you're trying for that, it might inherently lead to just a bad outcome because that individual is not in a position to do that. But they are potentially ready to hear it. And so you can just achieve step one and then later have step two. So I like that a lot. STEPH: Yeah, in general, I found the course incredibly helpful, very insightful. It was also really nice to hear from other managers that are facing similar problems or perhaps novel problems and then getting to weigh in and help each other. So it's a wonderful course. I'll be sure to include a link in the show notes for anyone that is interested. And I'll probably come back with some more insights from the class because it's really...we just wrapped up. So I'm sure I still have some ideas that will percolate over time, and I want to come back and share those with the group. Mid-roll Ad And now a quick break to hear from today's sponsor, Scout APM. Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more. Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform. See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed. STEPH: Pivoting just a bit, we have a listener question that I'm excited to dive into. This question comes from the one and only, the Edward Loveall, fellow thoughtboter. And Edward wrote in, "How does the process of software development change at different team sizes? What's a process that breaks down soon after the team starts growing? What's a process that is resilient at all sizes? And by process, I mean anything that involves other people including organizing tasks, code review, deployment, or anything else that isn't you alone writing code in a vacuum." I'm really excited about this question because I think there's a lot here. And there's actually one part that I'm struggling with a bit, so I'm curious to see what you think, Chris, about it. But I'm going to start off with saying that I think there are a number of management processes that definitely break down as a team grows. But in the spirit of Edward's question, I'm going to focus more on the software development process and how those might need to change and what starts to break as your team grows. So starting off with processes that break after the team starts growing, this one, frankly, what really starts to break is not a process specifically, but it's the lack of process that really starts to become visible and painful. So, how do we track work? Before, maybe the product manager or someone would just send you a message and say, "Hey, can you work on this?" or "Hey, can you fix this thing?" And how does code need to be reviewed before being merged? Does it need to be reviewed? Are people just merging as they get stuff done? How are deploys performed? Oh, we have a super urgent production fix that needs to go out, and the only person that knows how to deploy is out sick today? Cool. That's the type of process that I think that really breaks down, or at least you start to notice when the team starts to grow. What are your thoughts? CHRIS: I definitely feel that first one very strongly. We're feeling it right now on the team, which is still very small. There are only three developers working on the project, and then we have a product manager. And each week, we're slowly iterating, and tweaking, and honing, and trying to introduce just enough process in terms of how we define the work to be done, communicate the status of it, all of that fun stuff. We started with Trello. And we just had a board with some columns, and then we had more columns, and then we got rid of a few of them. And then we recently added a Power-Up to the Trello board, which allows for epics. So there are cards which are epics which tie to sub cards. And I'm staring at it, and I'm like, how long until we're Jira? How long can I hold out here and not be Jira? But it does feel like we're slowly iterating towards a more useful process for this team rather than process for process' sake, which I feel like is a really useful distinction. There's also a question of like, what can be known or what can be adequately measured and whatnot versus what can't be? So we've talked many a time on the show about estimation and velocity and trying to track that and the pitfalls inherent with that. And so there's, in my mind, two different camps. There's the process we want to avoid. And again, to reference German Velasco's wonderful blog post, Say No To More Process. And I really feel like there is a tendency often when things go wrong to then try and paper over that with process. Oh, this team didn't use the design system. So we need to write ESLint rules to make sure you can't import from the directories that aren't the thing. And it's like, we can do that, and I've definitely done that. And I will do that again in the future. But I always have the lens of do we need this? Is it worth the trade-off, the cost, the overhead, the complexity that it's bringing in? But definitely, organizing and communicating tasks is one of the ones that becomes really difficult. The more people that are working on something, the more you need probably more than one person staying out in front of them and trying to define the next bit of work that needs to be done after that. Code review feels like it probably should stay similar, with the exception that I lose the ability to review all code at some point. Right now, I'm trying to review every single PR that goes through or close to it. At some point, I'm just going to have to give up on that. But for now, that's my goal. But fundamentally, code review, I think, will hopefully take the same shape. Deployment, similarly, like, I've talked about the merge queue thing. I want to get a little bit of process in there but not too much. There is definitely some necessity for change. But I definitely want to resist the urge to change everything and to just say, like, slowly over time; we're going to have to be a big Byzantine organization with lots of rules and standard operating procedures and all of that. I've heard anecdotally, and I don't know if this is true, so maybe someone out there on the internet can correct me if I'm wrong, but my understanding is that at Google, they're pretty tight in terms of what languages and frameworks can be used and what processes, and workflows, and build tools and all of that whereas Facebook, as a counterpoint, is relatively lax. Obviously, React is used very heavily on the core web application. But there's some flexibility in terms of different languages and frameworks and things for sub-projects or small individual teams having a little bit more autonomy. And I think that's a really interesting thing of are you one large, cohesive, organized company or do you try to act like a bunch of small disparate but roughly connected teams that share good ideas but can work independently? And that changes how I would think about this question. STEPH: I really like how you're describing the addition of process. It sounds like a just-in-time process. So as you're learning that something needs to be added, then that's when you look for answers. And then you sprinkle on a bit of process that everyone agrees that feels very helpful within also the right to review and see if that still makes sense for the team. There's one additional area where I think the lack of process really shines through in addition to the number of ways that you've mentioned is also onboarding. So if you have a very small team and you are onboarding, it's likely that...Chris, you can let me know if I'm wrong, but when someone's joining the team, there's probably a good chance that they get to pair with you at some point, or they even get welcomed by you to the team. And then, they get an overview of the product and the codebase. And there's probably this really nice session where they get to ask you questions, and then they have that onboarding session. Does that sound about right? CHRIS: Yes. But I would go so far as to say it's not just a day or a session, but it's probably a couple of days. So yes, and. STEPH: That's even better. And with some of the smaller teams that I've seen, that onboarding process is where they are pairing with that lead person on the team. And that's going well until suddenly that lead person can't pair with everybody. And nobody has really thought about how to streamline that onboarding or how to coach or teach someone else to be a really good onboarding pair. And I have strong feelings about this area because we often focus so much on hiring, but then we drop the ball when it comes to onboarding that new, wonderful colleague that we've worked so hard to recruit. And at the end of that day, someone's going to reach out to them and say, "Hey, how was your first day?" And it makes a big difference for that person's retention as to how those first couple of days ago. So I think onboarding is another really important part that when you're a smaller team, you probably don't need much process because you have more of that personable onboarding experience. But as the team grows, there needs to be more of a process to help other teammates join the team. CHRIS: It's interesting. I think I totally agree with you that over time, there is a necessity to be more intentional and to have a little bit more structure in the process. And I don't think you're saying this, but I just want to make sure we are saying the thing that I think we believe, which is that shouldn't replace the human that helps you onboard. Like, I still like the idea that everybody gets a pair for some amount of time when they start at a new company. And you're working together on a feature, or you're working together on bug fixes. You're shipping to production as soon as possible. But you're not doing that based on some guides in a wiki. You're doing that with another human that's helping you. There should also be guides, and a wiki, and documentation, and formalization as the organization grows but not in place of having another person that you get to talk to. STEPH: We're just going to send you a little yellow rubber duck and then with a little Post-It note that says, "Good luck [laughs] with your onboarding process." Definitely. I agree with everything you said. It does not replace that human element where there's someone that's helping you onboard. I just see that onboarding is one of those things that gets forgotten, or we often point someone to a README which I do think is great because then it is battle-testing our README. But then there still needs to be someone that is readily there to say, "Hey, how's it going? What are you struggling with? Can I pair with you?" There still has to be that human element that is helping guide you through the process. And I think smaller teams may forget that they actually need to assign somebody to you to make sure that you have someone that you know. Like, hey, this is who I can reach out to with all my questions. Because they're probably not going to be comfortable posting in the company channel at that point or a larger communication to say, "Hey, I'm stuck on something." CHRIS: There's one other area that comes to mind, or I guess it's more of an anecdote that I have heard, but it speaks back to GitHub's early, early days. And they were somewhat famous for being very flat in terms of the organization and very self-organized, and everybody's figuring it out, and you're working on the thing that's most important in your mind. And for a long time, this was a celebrated facet of the company and a thing that they talked about rather publicly. And then I think there was this collective recognition, and maybe they reached a tipping point where that just didn't work anymore. Or maybe it actually hadn't been working for a bit, and there was just the collective realization of that. But it was interesting to watch from the outside as GitHub added more formalization, more structure, more managers, and hierarchy, and career ladders, and things of that nature. And I think there's a way to do all of those things in a complicated, overloaded, heavy way. But I think a different version of it is...like, you were using the word coaching earlier. Having formal structures within your organization to encourage people on their career path, to help them grow, to have structure around that, I think is a really difficult thing to get right. But I think it is critical, and I think just not having it can't be the answer past a certain probably pretty small size. So that is an interesting one where I think you do need to introduce some process and formalization around how you think about the group of people and how they work together within your organization. STEPH: I agree. I think where some folks may see a lack of hierarchy; others feel a lack of support. And adding levels of management should really be focused on the outcome is that we're helping people feel supported. So even getting feedback as you're adding those different levels of management, like, hey, did we make your life better? Did we make your life worse? I think that's a great question for management to ask as they're exploring a less flat structure. CHRIS: So, Steph, I have a question for you now on a variant of this topic. In general, we seem to be fans of having a codebase. Probably a Rails app that's got a database behind it, and that's where you put the data. Everybody commits to that same repository. It's all kind of one collected thing. And often, organizations grow to a certain size, and they're like, this is untenable. We cannot have this many people working on this same codebase. So we shall do the logical thing, which is we will break it up into small pieces. And those pieces will communicate over HTTP, and it will be great because then our teams can be separate from each other and can manage their little piece of the world. What do you think about that? Is there truth there? Is it not true at all? What do you think? STEPH: All right, so your team is getting too big, and to the point that you feel like you need to split it out so then you can have small teams, and they can all work independently on different parts and services of the codebase. I don't love the idea. I'm trying to think through because I feel like there's a lot of nuance here. But I don't love the idea that that's the driving force as to why are we making the change? And that is often a question that comes to mind whenever we are making a big change, either architecture or process-related is like, what's driving this? And then how are we going to measure it? And if we are driving it just because we have a large team, let's talk more. Why are people blocked? Why can't people work together? What's preventing people from being able to contribute to the same codebase? Are people blocked for a long time because they're having to wait on someone else to complete that work? I have a lot of questions that I don't know if I can fully answer your question. But my instinct is to say let's not break up the architecture just because our team grew in size. CHRIS: Yeah, I think I definitely agree with that. There's probably a breaking point where it's just too many individuals, and there'll be too much contention. But I think resisting that or at least naming that as like, okay, that's what we're saying but is that really what's true? Or are we actually feeling that this system is so deeply coupled that there's no way to change some small piece of the code without impacting other parts of it? Like, is the CSS completely untenable because we're just using global class names, and it's leaking everywhere? Okay, do we need a different solution there? And then it's actually fine. We don't need to have different services that have their own different style sheets. We just need a different approach to CSS. That's a particularly easy one to go for because there's inherently a global namespace there. But the same thing is true in a lot of different contexts. So services are a way to break things apart and enforce those boundaries. But if inherently coupling is your problem, then you're just going to be coupled over HTTP, and I think it's going to be difficult. There's a wonderful blog post by Josh Clayton, which I think does a better job than I'm doing in this moment of highlighting some of the questions I would want to ask. The blog post is titled Services are Not a Silver Bullet. And so Josh goes through and enumerates a bunch of the different versions of the story that he's heard throughout the years of well, we need to go to services because x, because our test suite is slow because pull requests are constantly having merge conflicts and whatnot, because the code is very deeply coupled and any change here affects everything else. And a fix over here broke something over there. This is no good. And so he does a really good job of presenting alternatives or at least questions that you can ask to say, like, is this the problem, or is this a symptom? And we need to address the more underlying cause. And so I think there is a point where you just can't have 1,000 people trying to commit to the same Rails codebase. That feels like it's maybe too big. But it takes a while to get to 1,000 people. And there will be times where extracting a service makes sense or integrating with an external service that exists. Like, I've talked about Stripe before as my canonical like, yeah, it's actually deeply intertwined with the data model, but they're just dealing with such a distinct complexity set over there. And they have such expertise on that that I'm happy to accept the overhead of the fact that that service lives outside of my core application, and I need to deal with synchronizing state and all of that. I will take on that complexity, but it's not worth it for everything, and it's not a silver bullet. Again, to reference the name of Josh's blog post there, Services are Not a Silver Bullet. And so, coming back to Edward's original question, I would say that having a monolithic codebase works for a really long time, but there is probably a breaking point somewhere well along, but fight it for as long as you can. I think. STEPH: I really like how you touched on coupling because it really helps ask those questions to get to the heart of what are the pain points that you are feeling? And it is less of a decision that is based on people and process but more if you're going to split out a portion of your architecture. It is in response to an actual business need and a business value versus some other pain points that you're trying to fix. A particular example might be like maybe you have a portion of your application that really just needs to spend a lot of time crunching data. And it's really not as specific to your application; it's something that can happen on its own. And then it's beneficial to move that outside so it can scale and relate it to the work that it needs to perform versus keeping it in-house with the application. I do want to circle back to another question that Edward included which is what's a process that is resilient at all sizes? And the ones that really come to mind for me...and these are a bit amorphous intentionally because it will look different for each company. But three areas that are very resilient at all sizes, whether you are 1 to 2 employees versus you've got hundreds or thousands it's communication, testing, and accountability. So communication, where are we headed, and how do we know what we're working on? For testing, it's how do we test our changes? Do we write tests? Do we use QA? Do we have a staging environment? What does that look like? What's our parity between staging and production? And then how do we know what's in progress, and how do we know when it's done? Those are three core areas that, regardless of your team size,,I think are very crucial to the team success. What do you think? What are some of the processes that are resilient at all sizes? CHRIS: I actually really like the list that you just provided. That is a wonderful trifecta, and I think it will take you very far, so probably not much to add from me. But I guess on that note, should we wrap up? STEPH: Let's wrap up. CHRIS: The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes, as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Byeeeeeeeeeee! Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.

    313: Forty-Seven Percent

    Play Episode Listen Later Oct 19, 2021 42:05

    Steph talks about binging a few Things Worth Learning podcast episodes and particularly enjoyed an episode that featured one of thoughtbot's design directors, Sameera Kapila. Sam shared her expertise about management and inclusion, and Steph shares her favorite parts. Chris shares the story of a surprising error and the resulting journey through database transactions and Sidekiq that eventually resolved the issue. He also shares some follow up on the broken build and the merging process changes they introduced (spoiler, the process changes have been rolled back). Leading Inclusively, with Sameera Kapila - Things Worth Learning Podcast (https://www.youtube.com/watch?v=eiV6_3pZFc0) How to Skim a Pull Request (https://thoughtbot.com/blog/a-smelly-list) Isolator (https://github.com/palkan/isolator) aftercommiteverywhere (https://github.com/Envek/after_commit_everywhere) timefora_boolean (https://github.com/calebhearth/time_for_a_boolean) Transcript: STEPH: Oh man, I'm about to stop eating my pop-tart. I'll put it away. It's within distance. I'm going to eat it. CHRIS: Your high-fat content unfrosted pop-tart. STEPH: You know, surprise Sunday twist: it has icing on it. CHRIS: Steph, who even are you? STEPH: [laughs] CHRIS: There are a few canonical anchor facts that one knows about other people, and when one of those... STEPH: I like to keep everyone, including myself, on their toes. CHRIS: Or you've just secretly accepted that the icing adds another textural flavor adventure component. It's just better with icing. STEPH: All right, all right, all right. There's a complicated answer to this. And the complicated [chuckles] answer to this is that the more organic ingredients that I recognize when reading about pop-tarts are by a particular company, and they all have frosting on them. And the more generic pop-tarts that don't have frosting on them, I don't know how to pronounce a lot of those ingredients. So I'm like, no, but okay, I still eat them. But I prefer the ingredients I can pronounce. So I either go with the ingredients I can't pronounce or have a little bit of frosting on my pop-tart. And I'm going with the non-cancer route for today. CHRIS: For today, in this moment, and accepting the frosting. Okay, all right. Well, that is complicated. [laughs] It's tricky out there. Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey. STEPH: And I'm Steph Viccari. CHRIS: And together we're here to share a bit of what we've learned along the way. So, Steph, what's new in your world? STEPH: Hey, Chris. So the weather, I'm going to talk about the weather for a little bit. [chuckles] It's been almost non-stop rain for the past several days, which is fine. I'm sure it's great for plant life. But it's really hard on my dog Utah because then we can't go outside for our normal walks and playtime. Although he is my four-legged water baby because he absolutely loves water, and puddles, and playing in the rain. So he's very fine with going outside and playing for a long time. But then I have to essentially give him a full-on bath before I want to bring him back in. So not wanting to have to give him a bath each time, in the spirit of improvising, we started finding more indoor games to play. And I've started teaching him to play hide and seek. And he's not great at it mainly because he will only stay until I'm out of eyesight, and then he will come and find me. And so I have to be really, really fast at finding a hiding spot to like dash around a corner or hide behind the door. But I think he enjoys it because he will find me and then he seems very excited. And we go back, and we play again. And so I just have to work on teaching him to wait a bit longer so I can find better hiding spots. CHRIS: When you said that, at first, I was like, how did you teach him to hide? But I realize he's only playing the seek part of the game, and you're only playing the hide part of the game. STEPH: [laughs] CHRIS: I'm just so used to you exchange roles back and forth. First, you hide, then you seek, and then you switch it up. That would be a lot to get your dog to be like, now I'm going to secretly hide. STEPH: [laughs] I'd be very impressed. Yes, we have very distinct roles in this game. I am the one that always counts and hides. But he's a very good seeker. So that's been fun. We just got to work on getting a little better at it. But on a more tech-related note, one of the design directors at thoughtbot, Sameera Kapila, who also goes by Sam, was a guest on the podcast Things Worth Learning, which is hosted by Matt Stauffer. And Matt is also the host of The Five-Minute Geek Show and The Laravel Podcast. And in the show Things Worth Learning, Matt meets with individuals that are excited to share something that they're deeply passionate about; maybe it's tech, maybe it's not. And I've binged a couple of those episodes. And I really like how you can choose between the podcast format or the YouTube format. So then you can really watch the conversation unfold, which I know you and I a couple of times have thought it would be fun if people could see us because there are so many facial emotions and gestures that go along with conversations. So it was really delightful. And speaking of delightful, Sam shared her expertise about management and inclusion. And I definitely recommend listening to the episode because I can't share everything that Sam shared. But a couple of the topics that Sam mentioned that I really enjoyed and would love to chat about, so the first one is about helping someone, in this case, someone that you manage that comes to you with a concern. So there's often a presumption that just because someone comes to you with a concern or an issue that they've experienced at work, that they're the ones that will also want to work to address that concern, and that's often not true. It can be true; maybe that person wants to be involved. But they're often coming to you in the leadership or management role to say, "Hey, I've had this issue," and they really want help with that instead of walking away with homework for it. Because then that trains people to essentially be in this mindset of well, if I bring up this concern, then I'm going to be the one that has to address it, even if I'm the one that's most negatively impacted by this. And addressing this concern could be actively harmful to me. And she shared a really great real-world example from her own experience where her and another co-worker had noticed a concern about the hiring process. And her and that co-worker got together, and they talked about the concerns. They even rehearsed for the meeting because they were trained by the tech industry to say, "Hey, if you bring up a concern, you're going to be responsible for addressing and then resolving that concern." And so they had that meeting with the person in leadership. And they were pretty nervous about how it was going to go. And that person in leadership said to them, "Thank you both so much for sharing that. That must have been such a burden. And this is my responsibility to fix. And here are what my next steps are." And that was amazing because it allowed Sam and the other person to go back to client work. And they also received follow-up conversations about how that issue was being addressed. So there was even that feedback loop as to how things were going to change. And I have a personal example that...I really resonated with the example that Sam provided because I remember there are different teams that I've been a part of, where often I was one of the few women engineers on the team. And so we often have conversations about how do we get more women engineers into the company? And they're wonderful conversations. But there's a part of me that always felt resentful about, like, why am I here? Why am I the one fixing this? I understand I have some more insight and expertise, and experience in this area. But I was also frustrated by the fact that I was the one that was in that meeting often with other women, and it felt like our responsibility to fix this. And I used to feel bad about feeling resentful towards that. Because I was like, shouldn't I want to help other people? And I do. But Sam's example really helped remind me and clarify that yes, just because there's a concern doesn't necessarily mean you should be the one to address it. And it really takes everybody involved, or it takes leadership to step up and address that concern. CHRIS: Oh, that's really interesting the way Sam is framing that and describing the situation of not having any problem that you bring in be now your work to solve. Like, oh, I found the issue, and now we've got to go do this. But the idea that you can bring something to light and then be able to walk away from it. And the particular thing that you were saying that if your interaction is always that when you reference something when you bring in a concern that then your manager works with you to figure out how you can solve it, then you get this mental block of like, well, do I even want to say anything? Because I don't want to try and deal with big, amorphous unclear issues. So maybe I just won't even say anything. And so this as a way to make sure that there's room for all of the conversation is a really interesting framing that I hadn't really thought about, frankly, but it's very interesting. I haven't seen this interview either. So I'm definitely excited to give this a look because Sam is wonderful. And the topic that you're describing here sounds fantastic as well. STEPH: Yeah. There was an important moment for me where...one of my managers is Matt Sumner, who's been on the show. And when Matt was my manager, at one point, we were having a one on one, and we would often go for walks for our one on one. And I mentioned something about "I have this concern, or I have this problem, but I don't really know how to fix it. So I'm not sure I'm ready to talk about it." And Matt, in his delightful way, was like, "We can still talk about it. You don't have to have an answer or a solution." I'm like, "Yeah, but I feel like I should be able to fix it. Like, if you have a concern, or if you have something that you want to gripe about, then you should come to the table with solutions for it." And Matt was like, "No, you don't need to do that at all. We can totally gripe about stuff or talk about concerns and then either figure out the solutions together or go to other people for ideas." And that was really important to me because, like you'd mentioned, otherwise, it felt like this mental block where then it feels like you can't air out some of the things that you're worried about or have concerns about because then you think you're the only one responsible. And you may not be able to come up with the best solution. You may need other people to then help you strategize and come up with ideas. And I just love, love, love that part of Sam's discussion. And oh, there was one other part about the conversation. Well, there are lots of parts that were amazing. But another one in particular that blew my mind is about Comic Sans, the font, the font that everyone loves to hate. [chuckles] And I learned that it's one of the most legible fonts for kids. And it's one of the more accessible fonts for people with dyslexia. And it's actually recommended...I think there are still more academic studies that need to be done to really classify fonts that are best for people that have dyslexia. But Comic Sans is recommended by The British Dyslexia Association and the Dyslexia Association of Ireland. And there are some other really great posts that talk about the benefits of using a font like Comic Sans because the typeface has long ascenders and descenders and generous letter spacing and asymmetrical lowercase b and d to then help distinguish those letters. And I just thought that was so cool. This font that everybody wants to rip apart because it seems whimsical, unprofessional gets overused. There are lots of reasons, I suppose. [laughs] But there's a really big benefit to it, and it can help others. And I just found that very whimsical in itself. CHRIS: I love the idea that there are multiple levels of knowing about Comic Sans. First, you're just like, I don't even know the name, but it's that comic book-looking font. And then obviously, the next step is to be like Comic Sans? How could you ever use that? It's an atrocity. And then it's like, but actually, Comic Sans has some things going for it. And it is a really interesting consideration and something that you wouldn't necessarily think of. But then once you learn it, you're like, okay. Man, I wonder how many other things in the world have this interesting shape to them? Hmm. STEPH: Do you know the history behind Comic Sans? CHRIS: I do not. STEPH: I read about it fairly recently, but I'm probably going to botch some of the details. But I believe it was designed or created by Vincent Connare. And it was created for Microsoft. And Vincent was working on a project where I think there was a dog that was essentially going to have these bubbles that would then show you different parts of the application and walk you through the different features. And the dog had a very comic book feel to the character. And so then Vincent designed a font to go along with that comic book character, this dog and came up with Comic Sans. I don't think the dog actually launched with that particular font. But since the font was still developed, it was released as part of the available fonts. And there we go, there is the birth of Comic Sans. And then it just received so much love and ire all throughout history. [chuckles] CHRIS: There's something that you said there that I want to loop back on when you were talking about chatting with Matt Sumner and saying, "Here's this thing, but I don't know how to solve it. So I don't even want to bring it up." I really liked the framing that you gave and the fact that Matt was like, "No, no, we can still talk about it. We can at least explore this thing, have a conversation." I think that's really wonderful. There's a very similar thing that I experience a lot when doing code review, particularly when I'm in more of a leadership role within a team, which is I often want to highlight something that feels a little bit off to me in the code, but I may not have a specific solution. Like, I may see a variable name, or I may see a controller action that feels like it's the wrong shape or something. And I'll often name it but explicitly say, "I actually don't have a better idea here. So feel free to continue on with this, but I want to name it. So in case that sparks something in you, if you were also feeling some incongruousness, maybe it's worth you spending another minute to think about it, but I want to make sure my comment isn't blocking or otherwise making you feel uncomfortable." If I just come to you and I'm like, "This feels wrong," and that's all I say, that to me is unacceptable code review. Because now I want all of my code review feedback to be very actionable, it's either here's the thing that I feel strongly I think we should definitely change this. If you disagree, let's have a conversation. But yeah, this one definitely needs to change. Here's the thing that, like, I don't know, maybe we could break this into two lines and split it up. But if you don't like that, that's fine. Do whatever. And so then it's I've given the person my thoughts but given them clarity and a free rein to do whatever they want with that information. And then there are ones where I'm like, I don't even know what I think we should do here, but I think something. But if you don't have any ideas...like, I don't have any ideas specifically. If you don't have any ideas, it's fine. We'll continue on with this and maybe revisit it down the road. But I want to make sure each of those different tiers is actionable for the other person, and I'm not just giving them homework or something to be sad about because that would be bad code review. STEPH: I'm just imagining a PR comment that says, "I don't know what we should do here. But I don't think this is it," [laughs] and that just creating sadness. That's so interesting to me because I have flip-flopped with that opinion in regards to there are times that I very much resonate and do what you just said where I will point out to someone where I'm like, "I'm not sure why, but I just have concerns about this. And I don't know if you also ran into anything that was weird about this and would like to talk about it. I don't have any really great ideas, so I think this is good for now. And we should keep moving forward, so we're not blocked on it," but just wanted to, as you mentioned, highlight it in case it sparks something for the other person or for someone else that's reviewing the code. And then there are other times where I'll look at something, and I'm like, "Yeah, it's not great. There's something that feels brittle or potentially maybe hard to maintain or things like that. But I don't have a better idea." And I don't comment on it because I'm like, I don't want to distract that person or block them. And I do think it's good enough, and I don't have anything to add to the conversation, so I just leave it out. So it's interesting to me where is that line of when I feel like it's important enough to comment to then potentially spark some conversation versus just letting it go so then I don't add any distraction to their work? CHRIS: I think it's when the spidey-sense gets past 47%. It's a very specific number. I do the same thing where there's something, and I'm like, you know what? I can't even clearly express what about this makes me feel something off, and so I won't even comment on it, and I agree. And then there are things that trip past some magical line in the sand. And I'm like, you know what? I think I'm going to say something here, but I don't even have a recommendation. And then there's a whole spectrum of the nature of code review and, again, 47% being the specific number. STEPH: There's actually a thoughtbot blog post that correlates nicely to that concept of spidey sense. It's written by Mike Burns, and it's titled How to Skim a Pull Request. But essentially, grabbing from one of the lines here is where Mike presents an unexplained, incomplete, and arbitrarily grouped list of keywords that will cause us thoughtboters to read your code with more care and suspicion. [laughs] That feels perfectly aligned with that idea of spidey sense, spidey-sense 101. I'll be sure to include a link in the show notes. Or, you know, 40%. CHRIS: I think it was 47%. It's a very precise number. [chuckles] STEPH: Very precise nonsensical number. Got it. [laughs] CHRIS: If I'm making up fake statistics, I'm not going to have them round to an even 10. [laughter] STEPH: Makes it seem more legit somehow. CHRIS: Exactly. STEPH: But that's really the novelties that I wanted to chat about. Mid-roll Ad And now a quick break to hear from today's sponsor, Scout APM. Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more. Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform. See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed. STEPH: What's new in your world? CHRIS: I have some follow up on a recent topic that we talked about. So we had a kerfuffle which I described where we had a branch that got merged and the rebase some stuff got out of hand. And so we introduced some process, the protected branch configuration within GitHub that required the branches to be up-to-date before they can be merged and CI to be passing. And everybody was happy. It was like, this is great. Turns out it was never turned on. That's actually the day I was like, man; this is really straightforward. There's been no annoyance here. And then I got to the point where it was like; this seems weird because we just merged a lot of things in rapid succession. I went and checked, and it turns out what I thought was the name of the branch protection rule in GitHub's UI is, in fact, a regular expression pattern. It might not be a full regular expression but like a wildcard pattern for the branch name to match to, and so it's specific. I created this rule, and in small, gray text underneath, it said, "This applies to zero branches." I missed that the first time but then the second time going back, I was like, oh, I actually wanted it to apply to more than zero branches. So I went back in and changed that. It's a great example of very subtle UI that just slipped past me. STEPH: I was going to say in your defense, the very subtle gray font to say, "This applies to zero," feels tricky. CHRIS: That...also, going through the work of creating this thing and if that results in zero branches that would match, maybe that's the thing to emphasize on creation. I would love that. Because in my case, I was trying very specifically to target an existing branch. There is the ability to say, "Oh, any bugfix-* named branch," if you're using branch naming strategies like that, you can use this for that sort of thing. So it may be that currently, there are no branches with that name. But in my case, I was just like, please, main, anytime anything is happening on main, that is what we want to do. I just needed to put the word main there. But anyway, once I actually turned it on, insufferable, absolutely not, cannot survive in this world. We have a relatively small team. There are three of us, and not everyone is even full-time, and my time is pulled in a lot of different directions. So I'm actually not pushing as much code as I might otherwise. Even with that, nope, absolutely not. Our CI is like; I don't know, five-ish minutes per run. Turns out, especially Monday mornings, we have a volley of things that will have been reviewed and trickled in through Friday afternoon. And then there's a bunch of work we want to land Monday morning. And then, just at any point, it turns out, yes, this was untenable. So we have turned it off. I would like to revisit this down the road and introduce the MergeQueue functionality, so the idea of being able to say, "Yeah, you just name when you want something to go in, and then the system will manage the annoying finicky work there." But for now, I had to give up on my dream of everything running on CI, on a feature branch, before it gets merged. STEPH: Ooph, that phrase, "I had to give up on my dream," that breaks my heart for you. [laughs] CHRIS: I may be going a little bit fanciful with my language but, like, a little. STEPH: [laughs] CHRIS: I liked this thing. I want to exist in that world. But it is not feasible given the current state of the world. And that will only get worse over time, is my expectation. So I get to revisit this when I have the time to more thoroughly figure a thing out. But for now, I don't know, merge whatever; it will be fun. STEPH: There's a small part of me that feels a little reassured that it was a terrible time, although I hate that it was a terrible time. But I have felt that pain on so many other projects where I am constantly waiting, and I'm constantly checking to be like, can I merge? Can I merge? Can I merge? And then I can merge, but then someone beats me to it. And I'm like, oh, then I got to restart. And I got to wait, and I'm constantly checking. So that feels like it helps validate my experience. [chuckles] I am excited for that MergeQueue. I would be super excited to try that out and hear about how it goes just because that seems more like the dream where you can just say, hey, I want this PR to go whenever it can go. Just take care of it. I want it to be rebased, whatever the flow is, and have it be merged, so I don't ever have to check on it again. CHRIS: But once we configured this, there was a new thing that appeared in the GitHub UI, which was auto-merge. And so that was a button where I could say like, "Hey, merge this whenever CI passes," which was a nice upgrade, but it didn't have the additional logic of and rebase as necessary. Or the more subtle logic of like, you don't actually want to rebase where you have five different branches that are all trying to merge, and they keep rebasing. You want to have the idea of a queue, and so you get in line. And you rebase when it's your turn, and then you run the CI. And you try and be as smart as possible about that. If anyone at GitHub is listening, I would love if you all threw this into your platform, and then you could ping Slack if anything went wrong. But otherwise, there are, like I said, existing tools. At some point, I will probably, I don't know, over a long weekend or something like that, sit down with a large cup of coffee and explore these. But today is not that day. STEPH: I'm excited to hear about that day. CHRIS: So that is a tale of woe and sadness. But luckily, I get to balance it out with a tale of happiness and good outcomes. So that's good. The happiness and good outcome story does start with trouble, as they always do. So we had a bug that occurred in the application where something was supposed to have happened. And then there was an email that needed to go out to tell the user that this thing had happened. And the bug popped up within AppSignal and said something was nil that shouldn't have been nil. Particularly, we're using a gem called Time For a Boolean, which is by Caleb Hearth. And he's a former thoughtboter and maintains this wonderful gem that instead of having a Boolean for like, is this thing approved, or is it paid? Or is it processed? You use a timestamp. And then this gem gives you nice Boolean-like methods on top of that timestamp. Because it turns out, very often just having the Boolean of like, this was paid, it turns out you really want to know when it was paid. That would be a really useful piece of information. And so, while you're still in Postgres land, it's nice to be able to reach for this and have the affordances of the Boolean-like interface but also have the timestamp where available. So anyway, the email was trying to process but that timestamp...let's pretend that it was paid as the one that matters here so paid at was nil, which was very concerning. Because this was the email that's like, hey, that thing was processed. Or let's say it was processed, actually, because that's closer to what it was. Hey, this thing was processed, and here's an email notification to tell you that. But the process timestamp was nil. I was like, oh no. Oh no. And so when I saw this pop up, I was like, this is very bad. Everything is very bad. Oh goodness. Turns out what had happened was...because I very quickly chased after this, looked in the background job queue, looked in Sidekiq's UI, and the job was gone. So it had been processed. I was like, wait a minute, how? How did this fix itself? Like, that's not the kind of bug that resolves itself, except, in this case, it was. This was an interaction that I'd run into many times before. Sidekiq was immediately processing the job. But the job was being enqueued from within the context of a database transaction. And the database transaction had not been committed yet. But Sidekiq was already off to the races trying to process. So the record that was being worked on, the database record, had local changes within the context of that transaction, but that hadn't been committed. Sidekiq then reads that record from the database, but it's now out of sync because that tiny bit of Sidekiq is apparently very fast off to the races immediately. And so there's just this tiny little bit of time that can occur. And this is also a fun one where this isn't going to happen every time. It's only going to happen sometimes. Like, if the queue had a couple of other things in it, Sidekiq probably would have not gotten to this until the database transaction had fully closed. So the failure mode here is super annoying. But the solution is pretty easy. You just have to make sure that you enqueue outside of the database transaction. But I'm going to be honest, that's difficult to always do right. STEPH: That's a gnarly bug or something to investigate that I don't think I have run into before. Could you talk a little bit more about enqueueing the job outside the database transaction? CHRIS: Sure. And I think I've talked about this on a previous episode a while back because I have run into this one a few times. But I think it is sufficiently rare; like, you need almost a perfect storm because the database transaction is going to close very quickly. Sidekiq needs to be all that much more speedy in picking up the job in order for this to happen. But basically, the idea is within some processing logic that we have in our system; we find a record, we do some work. And then we need to update that record to assign this timestamp or whatever it is. And then we also want to inform the user, so we're going to enqueue a job to send the email notification. But for all of the database work, we are wrapping it in a transaction because we want it to either succeed or fail atomically. So there are three different records that we need to update. We want all of them to be updated or none of them to be updated. So, therefore, we wrap it in a transaction. And the way we had written, this was to also enqueue the job from within the transaction. That wasn't something we were actively intentionally doing because those are different systems. It doesn't really mean anything. But we were still within the block of ApplicationRecord.transaction do. We're now inside of that block. We're doing all of the record updates. And then the last piece of work that we want to think about is enqueueing the job to send the email. The problem is if we're still within that database transaction if it's yet to be committed, then when Sidekiq picks up that job to run it, it will see the prior state of the world. And it's only if the Sidekiq job waits a little bit that then the database transaction will have been committed. The record is now updated and available to be read by Sidekiq in the correct updated state. And so there's this tiny little bit of inconsistency that can happen. It's basically because Sidekiq is going out to Redis, which is a distinct system. It doesn't have any knowledge of the database transaction at play. That's why I sometimes consider using a Postgres-backed background job system because then actually the job can be as part of the database transaction. STEPH: Cool. That's helpful. That makes a lot of sense the way you explained the whole you're actually enqueueing the job from inside that transaction. I'm curious, that prompts another question. In the case where you mentioned you're using a transaction because you want to make sure that if something fails to update so, everything gets updated together, in the event that something does fail to update because you were previously enqueueing that job from the transaction, does that mean that the update could have failed but that email would still have gone out? CHRIS: That does not. And the reason for that is because we're within dry-monad world. And so dry-monad will implicitly capture the ActiveRecord rollback, which I think is an exception that gets raised or somehow...But basically, if that database transaction fails for any reason and ends up getting rolled back, then dry-monads will not continue processing through the rest of the sequential operation. And so, therefore, even if we move the enqueuing of the email outside of the database transaction, the sequential nature of that processing and the dry-monad stuff that we have in play will handle that. And I think that would more generally be true because I think Rails raises an exception on rollback. Not certain there. But I know in our case, we're fine on that. And we have actually explicitly checked7 for that sort of thing. STEPH: So I meant a slightly different question because that makes sense to me everything that you just said where if it's outside of the transaction, then that sequential order won't fire because of that ActiveRecord migration error. But when you have the enqueuing inside of the transaction because then that's going to be inside of the sequential order, maybe before the rollback error gets raised. Does that make sense? CHRIS: Yes. I think what you're asking is basically like, do we make sure to not send the job if the rest of the stuff didn't succeed? STEPH: I'm just wondering from a transaction perspective, actually. If you have a transaction wrapped block and then you have in there, like, update this record, send email, end block, let's say update...well, I guess it's going raise because you've got probably like an update bank. Okay, so then yeah, you won't get to the next line. Got it. Got it. Got it. I just had to walk myself through that because I forgot that you probably...I have to visualize [laughs] as to what that code probably looks like. All right, that answered my question. CHRIS: Okay. So back up to the top level then, this is the problem that we have. And looking through the codebase, we actually have it in a bunch of different places. So the solution in any one of those cases is to just take the line of code where we're saying enqueue UserMailer.deliver_later take that line of code, move it outside of the database transaction, and make sure it only happens if the database transaction succeeds. That's very easy to do in one case. But my concern was this is a very easy failure mode to end up in. And this is a very easy incorrect version of the code to write. As far as I can tell, we never want to write the code where this is happening inside of the transaction because it has this failure mode. But how do we enforce that? That was the thing that came to mind. So I immediately did a quick look of like, is there a RuboCop thing I can do here or something? And I actually found something even more specific, which was so exciting to find. It's a gem called Isolator. And its job is to detect non-atomic interactions within database transactions. And so it's fantastic. I was like, wait, really? Is this going to do the thing? And so I just installed the gem, configured it where I wanted, and then ran the test suite. And it showed me every place throughout the app right now where we were doing this pattern of behavior like enqueueing work from within a database transaction, which was great. STEPH: Ooh, that's really nifty. I kind of want to install that and just run it on my current client's codebase and see what I find. CHRIS: This feels like something like strong migrations where it's like, yeah, this is great. I kind of want to have this as part of my core toolset now. This one feels even perhaps slightly more so because sometimes I look at strong migrations, and I'm like, no, no, no, strong migrations, I get why you would say that, but for reasons, this is actually fine. And they have configurations within it to say, like, no, this is okay. Isolator feels like it's always telling me something I want to know. So this, very quickly, I'm like, I think this might be part of my toolset moving forward on every single app forever. And actually, there's another gem that I used. It's made by the same team. So this is from the folks over at Evil Martians, which is another Rails consultancy out there in the world. And the Isolator gem is one thing that they've produced. And then I think the same author of it who is an Evil Martian's employee created the aftercommiteverywhere gem. So aftercommit is one of Rails' ActiveRecord callbacks. But in this case, it allows you to use it everywhere, as the name implies. And so rather than actually having to take that line of code out of the database transaction block, which is naturally where we would write it because that's how we think about the code and how we want to express it, you can just use this aftercommit method, wrap the call in that, so it's after_commit, and then a block. So either braces or do..end. That enqueueing of the email now just gets wrapped in that. And so what that does is it says, "Defer this until after the transaction commits. If the transaction does not commit, if we roll it back, then don't run it." And what was nice is the actual code change when I finally submitted all of this was add the gem to the gem file. And then everywhere that we're doing the wrong thing, which running the test suite told me, I just went in, and I wrapped that line in after_commit and a block. And it was such a nice, clean...like, I didn't have to move the code around or actually shift the lines, which was my first attempt at this. I was able to just annotate each of those lines and say, "You're special, you're special, you're special," And then I'm done. And again, the first gem told me every case where I needed to do that. It's like, well, this is a wonderful little outcome here. STEPH: That's really nice, yeah, how you can make the changes and then, like you said, re-run the test or re-run that gem, and it lets you know what else still needs to be updated. I'm intrigued where you mentioned you didn't have to move any lines, though. Maybe I just need to look at the gem and see it, but I'm still envisioning that you have your transaction do block. And then you're doing some things; you're updating records, and then you have your end. And then after that, it's when you want to enqueue the email. And with this after_commit, you actually added that method call inside of the transaction but then wrapped the call to Sidekiq to send the email inside of that block. CHRIS: Correct. Yeah. So it's basically like saying, "Here's almost an anonymous function." If you think about a Ruby block in that nomenclature, you're saying, like, here's some work to do when and if the transaction succeeds. And so it meant that I was able to keep the code in the way that we as humans would talk about it but deal with the murky details, and edge cases of database transactions, and Sidekiq, and whatnot. Sort of just handle it by saying like...it almost feels like an annotation or a decoration or something like that. But it was this, in my mind, almost like a perfect melding of I don't want to think about this. Oh, cool. Okay, here's a quick, easy way to deal with it but to not have to fundamentally change how I write the code. STEPH: Interesting. So I like all the things you're saying. I'll be honest, I'm not totally sold, and I'm trying to think of why. I think the benefits...one, as you mentioned, it's something you don't have to think about or at least signals to others that hey, maybe you should think about this to the extent that you use after_commit. And so that way, you don't have these asynchronous events taking place inside the transaction. So I like that visibility and communication to the rest of the team. Putting it inside of the transaction feels interesting. I don't know why; I feel a little weird about this. [laughs] I'm bringing my true self. CHRIS: That's fair. So if we're being honest, I solved this first by finding the Isolator gem. Well, I solved it first by just doing it manually. I went through the app, and I found all the places. And I was like, you know what? I'm worried that the next person authoring code like this, it's so easy to fall into this trap. Like, this is such a subtle little thing that our brains are not thinking about. And so I had first fixed it, and so I had a diff that involved moving lots of lines of code, every instance of this moved from being in the database transaction out of it. And that was fine. I was fine with that as a solution. But it was a little bit noisy because I was moving a bunch of lines. So then I brought in the Isolator gem. I actually reset that, and I went back to before I had made the fix, ran the test just to make sure Isolator was actually finding every instance. They did; that was great. So I was like, all right, cool. This is better because now I have this thing that will tell anyone when this happens. So I'm very happy about that. Because frankly, this is some hard-earned knowledge that I had to read Sidekiq and remember how database transactions work and convince myself of what was going on here and finally come to what I believe the solution is. And now Isolator is just like, cool, that's encapsulated. And it gives a very nice failure message in the test suite. So it's like, excellent. I really like this. But still looking at it, the diff, the amount of code that I had to change, it's like, well, naturally, this is how we want to write this code, but for reasons, we can't. And it's appeasing the computer more than it's appeasing the reader or the author of the code. And so then I happen to be reading through the Isolator gem's README, and they mention the aftercommiteverywhere gem. And I was like, oh, that's interesting. So one more time, I reset. And then I really tried fixing it with after_commit. And the look of the diff there felt nice to me because the lines got a little more on them, but they didn't move. And so it's like, this is how we naturally would have authored it, and now it works correctly. And I liked that. But I understand your hesitation because you're like, but the thing is, it's wrong. And so you've made the wrong not wrong anymore, but you didn't...and so I get your hesitation. I still like the fancy version. STEPH: Yeah, I think you just helped me figure out my grumpiness with it or why I'm not totally sold on it. And it was in regards to adding a dependency to avoid a noisy diff is the oversimplified version that I was processing or the reason that I was a bit grumpy about adding this other gem for that. But then you also just brought a lot of other really good reasons. One thing that you said that I do really like is adding tools that help us author code in a more natural style, the way that we want to highlight this process, and how this application does work, and how this business logic flows. So given in that light, that makes me feel better about it. But yeah, I think that was my initial grumpiness. I was like, it'll be a noisy diff. It's okay. CHRIS: I think I definitely share your hesitation, or you're like, hmm, that's an interesting reason to bring more code into the application. But at the same time, I think the counterpoint that comes to mind for me is we're using Ruby because of its expressiveness; at least, that's why I'm using Ruby. I really want the code that I write to be as close as possible to the thing that I would say to another human about like, oh okay, when a user signs up for the application, we need to create a record in our system, and then we need to send them an email. And then we need to do this other thing. And so, the closer that our code is to those words that I would use to describe to another human, the happier I am. And I will put in some pretty significant effort to hold that line as long as the code can also be correct. And so, the Isolator gem here does a great job of enforcing that correctness. And then after_commit allows me to still maintain that expressiveness and not have to think about the murky details as much or not have to reshape my code to match the murky realities of different persistence engines. But I do agree. I think it's a good thing to look at and ask, like, is it worth it? Are you sure? And in this case, I will say, "Yeah, I think so," but with that amount of certainty in my voice, [chuckles] which is not a ton. STEPH: I think this is going back to my days of working with dependency bot PRs where every time there was an upgrade for a gem, I always ask, what do you do here? [chuckles] Do we need to upgrade you? Can we just remove you from the codebase? So I'm fairly...I don't know, resistant is a strong word. I'm skeptical of when we're adding stuff in, and I just want to question the value that it's adding. But I want to circle back to something that you said, and that is hard-earned knowledge. And that part I understand so much where when you have gone through a fair amount of work to uncover an issue, and then you want to make sure that others don't have to go through that. This is a really nice way to highlight; hey, there's something that's tricky about computers and software here, and we need to watch out for that. And I want to help you lookout for that. Versus this is just inherit information where this needs to happen outside or after that transaction. And so that makes a really nice entry point where someone can look to say, "Why did we add this gem?" And then there's a commit message that goes with it that explains this is why we use this after_commit gem because we're specifically looking to avoid this type of bug. And I love that. CHRIS: Yeah, I think more lines of git commit message than diff on this one. So yeah, I wrote a short novel describing all of the features, describing the different pieces that are coming together. And then it's actually a +28 -6 diff. So it's a very small code change. But yeah, lots of story captured there. STEPH: And if you had just moved the lines, you could still have that commit message. But it's not likely that someone's going to look up that git commit change or that message that went along with it because they're not going to know to blame that one. But if they look at that particular edition of after_commit, they're more likely to find that historical context. So long story short, I think you have walked me through my initial grumpiness and provided some really good ways to avoid that really tricky failure mode for other developers. CHRIS: Well, thank you. I'm getting Steph's seal of approval starting from grumpy places. [laughs] I feel good. All right. STEPH: I'll have some special Stephanie's approval stickers designed and printed for you. CHRIS: I hope you're not joking because I very much want a yellow heart that says, "Steph-approved." STEPH: [laughs] CHRIS: And I can put it on PRs, and I can put it on the wall. [laughs] STEPH: Well, now I have to find a sticker designer and make a...well, it's just a yellow heart. I can probably handle this. I'm going to use Comic Sans. That will be the approved part. [laughs] Yellow hearts and Comic Sans for everybody. CHRIS: Well, with that absolutely fantastic call back to earlier parts of the episode, shall we wrap up? STEPH: Let's wrap up. CHRIS: The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes, as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Byeeeeeeee! Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.

    312: Spooky Stories

    Play Episode Listen Later Oct 12, 2021 38:50

    Chris evaluates the pros and cons between using Sidekiq or Active Job with Sidekiq. He sees exceptions everywhere. Steph talks about an SSL error that she encountered recently. It's officially spooky season, y'all! sidekiq-symbols (https://github.com/aprescott/sidekiq-symbols) Transcript: CHRIS: Additional radiation just makes Spider-Man more powerful. STEPH: [laughs] Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Steph Viccari. CHRIS: And I'm Chris Toomey. STEPH: And together, we're here to share a bit of what we've learned along the way. Hey, Chris, what's new in your world? CHRIS: Fall is in the air. It's one of those, like, came out of nowhere. I knew it was coming. I knew it was going to happen. But now it's time for pumpkin beer and pumpkin spice lattes, and exclusively watching the movie Hocus Pocus for the next month or so or some variation of those themes. But unrelated to that, I did a thing that I do once, let's call it every year or so, where I had to make the evaluation between Sidekiq or Active Job with Sidekiq, as the actual implementation as the background job engine that is running. And I just keep running through this same cycle. To highlight it, Active Job is the background job system within Rails. It is a nice abstraction that allows you to connect to any of a number of them, so I think Delayed Job is one. Sidekiq is one. Resque is probably another. I'm sure there's a bunch of others. But historically, I've almost always used Sidekiq. Every project I've worked on has used Sidekiq. But the question is do you use Active Job with the adapter set to Sidekiq and then you're sort of living in both worlds, or do you lean in entirely and you use Sidekiq? And so that would mean that your jobs are defined to include Sidekiq::Worker because that's the actual thing that provides the magic as opposed to inheriting from Application Job. And then do you accept all of the trade-offs therein? And every time I go back and forth. And I'm like, well, but I want this feature, but I don't want that feature. But I want these things. So I've made a decision, but I want to talk ever so briefly through the decision points that were part of it. Have you done this back and forth? Are you familiar with the annoying choice that exists here? STEPH: It's been a while since I've had the opportunity to make that choice. I'm usually joining projects where that decision has already been made. So I can't think of a recent time that I've thought through it. And my current project is using that combination of where we are using Active Job and Sidekiq. CHRIS: So I think there's even a middle ground there where that was the configuration that I'd set up on the project that I'm working on. But you can exist in both worlds. And you can selectively opt for certain background jobs to be fully Sidekiq. And if you do that, then instead of saying, "Performlater," You say, "Performasync." And there are a couple of other configurations. It gives you access to the full Sidekiq API. And you can do things like hey, Sidekiq, here's the maximum number of retries or a handful of other things. But then you have to trade away a bunch of the niceties that Active Job gives. So as an example, one thing that Active Job provides that's really nice is the use of GlobalID. So GlobalID is a feature that they added to Rails a while back. And it's a way to uniquely identify a given record within your system such that when you say performlater, you can say, InvitationMailer.performlater and then pass it a user record so like an instance of a user model. And what will happen in the background is that gets serialized, but instead of serializing the whole user object because we don't actually want that, it will do the GlobalID magic. And so it'll turn into, I think it's GID:// so almost like a URL. But then it'll be, I think, your application name/model name down the road. And the Perform method actually gets invoked via the background system. Then you will just get handed that user record back, but it's not the same instance of the user record. It sort of freezes and thaws it. It's really nice. It's a wonderful little feature. Sidekiq wants nothing to do with that. STEPH: I'm so glad that you highlighted that feature because that was on my mind; I think this week where I was reviewing...somebody had made the comment where they were concerned about passing a record to a job and saying how that wouldn't play nicely with Sidekiq. And in the back of my mind, I'm like, yeah, that's right. But then I was also I'm pretty sure this got addressed, though. And I couldn't recall specifically if it was a Sidekiq enhancement or if it was a Rails enhancement. So you just cleared something up for me that I had not had time to confirm myself. So thanks. CHRIS: Well, to be clear, this works if you are using Active Job with Sidekiq as the adapter, but not if you are using a true Sidekiq worker. So if you opt-out of the Active Job flow, then you have to say, "Perform_async," and if you pass it a record, that's not going to work out particularly nicely. The other similar thing is that Sidekiq does not allow the use of keyword args, which, I'm going, to be honest, I really like keyword arguments, especially for background jobs or shuttling data through your system. And there's almost a lazy evaluation. I want some nicety to make sure that when I am putting something into a background job that I'm actually using the correct call signature, essentially passing the correct data in the correct shape. Am I passing a record, or am I passing the ID? Am I passing a list of options or a single option? Those sort of trade-offs that are really easy to subtly get wrong. I came around on this one because I realized although Active Job does support keyword arguments, the way it does that is it just has a JSON serialization format for them. So a keyword argument turns into a positional array with an associated hash that allows for the lookup or whatever. Basically, again, they handle the details. You get to use keyword args, which is great, with the exception that when you're actually calling performlater, that method performlater is a method missing type magic method. So it does not actually check the keyword arguments at that point. You're basically just passing an options hash as opposed to true keyword arguments that would error because they don't match up. And so when I figured that out, I was like, oh, never mind. This doesn't actually do the thing that I care about. It's a little bit nicer in terms of the signature of the method when you're defining your background job itself, but it doesn't actually do any logical checking. It doesn't give me any safety or robustness within my system. So I don't care about that. I did find a project called sidekiq-symbols, which does some things under the hood to how Sidekiq serializes and deserializes jobs, which I think gives largely the same behavior as Active Job. So I can now define my Sidekiq jobs with keyword arguments. Things will work. I can't use GlobalID. That's still out. But that's fine. I can do a little helper method that basically does the same thing as GlobalID or at least close approximation. But sidekiq-symbols lets me have keyword arg-like signatures in my methods; basically, it is. But again, it doesn't actually do any check-in when I'm enqueueing a job, and I am sad about that. STEPH: Yeah, that's another interesting distinction. And I'm unsurprisingly with you that I would favor having keyword args and having that additional safety in place. Okay, so I've been keeping track. And so far, it sounds like we have two points because I'm doing a little scorecard here between Active Job and Sidekiq. And we have two points in favor of Active Job because they offer a GlobalID, which then allows us to pass in a record, and then it takes care of the serialization for us. And then also, keyword args, which I agree with you that's a really nice feature to have in place as well. So I'm curious, so it sounded like you're leaning towards Active Job, but I don't want to spoil the ending. CHRIS: Yes, I could see why that's what you would be taking away from the conversation thus far. So again, just to reiterate, Active Job and Sidekiq with this sidekiq-symbols extension they both support keyword args, kind of. They support defining your job with keyword args and then enqueueing a job passing something that looks like keyword args. But it ends up...nobody's actually checking anything, so it's mostly like a syntactic nicety as opposed to any sort of correctness, which is still nicer, but it's not the thing that I actually want. Either way, nobody supports it, so it is not available to me. Therefore, it is not a consideration point. The GlobalID thing is nice, but it is really, again, it's a nicety more than anything. I have gone, and I'm leaning in the direction of full Sidekiq and Sidekiq everywhere as opposed to Active Job in most cases, but then Sidekiq when we need it. And that's because Sidekiq just has a lot more power and a lot more functionality. So, in particular, Sidekiq has a feature which allows you to say...it's a block that you put at the top of your Sidekiq job that says retries exhausted or something. I think Sidekiq retries exhausted is the actual full name of that at that point, which is really unfortunate in my mind, but anyway, I'll deal. At that point, you know that Sidekiq has exhausted all of the retries, and you can treat it as failed. I'm going, to be honest, I went on a quest to find a way to say, hey, I'm going to put some work into the background. It's really important for me to know if this work succeeds or if it fails. It's very easy to know if it succeeds because that just happens in-line in the method. But we can have an exception raised at basically any point; Sidekiq does a great job of catching those, of retrying, of having fundamental mechanisms there. But this is the best that I can get for this job failed. And so Active Job, as far as I can tell, does not have anything for this in order to say, yep, we are done. We are not going to keep working on this. This work has failed. It is dead. Dead is; actually, I think the more correct term for where we're at because failed is a temporary state, and then you retry after a failure. Whereas dead is, this has gone through all of its retries, and it will never be run again. Therefore, we should treat this as not having run. And in my case, the thing that I want to do is inform the user that this operation that we were trying to do on their behalf has not succeeded, will not succeed. And please reach out or otherwise deal with the fact that we were unable to do the thing that they asked us to do. That feels like a really important thing for me to be able to do, to be able to communicate back to my users. This is one of those situations where I'm looking at the available options, and I'm like, I feel like I can't be the only one who wants to know when something goes wrong. This feels like a thing that's important. But this is the best example that I've found, the Sidekiq retries exhausted block. And unfortunately, when I'm using it, it gets yielded the Sidekiq JSON blob deserialized, so it's like Ruby hash. But it's still like this blob of data. It's not the same data that gets passed into perform. And so, as a result, when I want to look up the record that was associated with it, I have to do this nested dig into the available hash of data. And it just feels like this is not a well-paved path. This is not something that is a deeply thought about or recommended use case. But again, I don't feel like I'm doing something weird here. Am I doing something weird, Steph, wanting to tell my users when I was unable to do the thing they asked me to do? [chuckles] STEPH: That feels like a very rhetorical question. [laughs] CHRIS: It does. I apologize. I'm leading the witness. But in your sincere heart of hearts, what do you think? STEPH: No, that certainly doesn't sound weird. I'm actually thinking back to some of the jobs that cause me stress in regards to knowing when they failed and then having that communication of knowing that we've exhausted all the retries. And, of course, knowing when those retries are exhausted is incredibly helpful. I am intrigued, though,, because you're highlighting that Active Job doesn't have the same option around setting the retry. And I'm trying to recall exactly how it's set. But I feel like I have set the retry count for Active Job. And maybe, as you mentioned before, that's because it's an abstraction, or I'm not sure if Active Job actually has that native support. So I feel a little confused there where I think my default instinct would have been Active Job does have that retry capability. But it sounds like you've discovered otherwise. CHRIS: I'm not actually sure what Active Jobs core retry logic or option looks like. So fundamentally, as far as I understand it, Active Job is an abstraction. And under the hood, you're always connecting an adapter. So it's either going to be Sidekiq, or Resque, or Delayed Job, or other. And each of those systems, whichever system you have as the adapter, is the one that's actually going to be managing retries. And so I know Sidekiq happens to have as a default 25 retries. And that spans, I think it's a two-week exponential back off. And Sidekiq has some very robust logic that they have implemented as the way retries exist within Sidekiq. I'm not sure what that would look like if you're trying to express it abstractly because it is slightly different. I know there was some good work that was done on Sidekiq to allow the Sidekiq options that's a method at the top level of the job, even if it's an Active Job job to express the retries. So that may be what you've seen, or there may be truly an abstraction that exists within Active Job, and then each adapter needs to know how to handle retries. But frankly, the what can Sidekiq do that Active Job can't? There's a whole bunch of stuff around limiting when you would retry limiting, enqueuing a job if there already exists one, when and how do those records get locked. There's a whole bunch of stuff. Sidekiq has a lot of power under the hood. And so if we want to be leaning into that, that's why I'm leaning towards let's just be Sidekiq all the time. Let's become Sidekiq experts. Let's accept that as a deep architectural decision within the app as opposed to just relying on the abstraction. Because fundamentally, if we're just using Active Job, we're not going to have access to the full power of Sidekiq or whatever the underlying system is, so sort of that decision that I'm making, but I don't know specifically around the retries. STEPH: Okay, thanks. That's really helpful. It's been a while since I've had to make this decision. I'm really enjoying you sharing your adventure because I'm trying to think what's the risk? If you don't use Active Job, what are the trade-offs? And you'd mentioned some of them around the GlobalID and keyword args, which are some niceties. But overall, if you don't go with the abstraction, if you lean into Sidekiq, the risk is then you want to migrate to a different enqueuing service. And something that we talk about is mitigating that risk, so then you can swap it out. That's also something I have never done or encountered where we've had to make that change. And it feels like a very low risk in my mind. CHRIS: Sidekiq feels like the thing you would migrate to, not a thing you would migrate from. It feels like it is the most powerful. And if anything, I expect at some point we'll be upgrading to Sidekiq pro or enterprise or whatever the higher versions that you pay for, but you get more features there. So in that sense, that is the calculation. That's the risk trade-off in my mind is that we're leaning into this technology and coupling ourselves more closely to it. But I don't see that as one that will reassess in the same way that people talk about Active Record and it being an ORM. And it's like, oh, we're abstracting the database underneath, and I'm like, no, I'm not. I'm always using Postgres. Please do not take Postgres. I'm not going to switch over to MySQL next week. That's totally fine if you start on MySQL. It's unlikely you're going to port over to Postgres. We may port to an entirely…like it's a Cassandra column store with a Kafka queue, I don't know, something weird down the road. But it's not going to be swapping out Postgres for MySQL or vice versa. Like you said, that's probably not a change that's going to happen. But that I think is the consideration. The other consideration I have in my mind is Active Job is the abstraction that exists within Rails. And so I can treat it as the lowest common denominator, and folks joining the project, it's nice to have that familiarity. So perform_later is the method on the Active Job jobs, and it has a certain shape to it. People may be familiar with that. Mailers will automatically use Active Job just implicitly under the hood. And so there's a familiarity, a discoverability. It's just kind of up the middle choice. And so if I can stick with that, I think there's a nicety there. But in this case, I think I'm choosing I would like the power and consistency on the Sidekiq side, and so I'm leaning into that. STEPH: Yeah, that makes a lot of sense to me. And I liked the other example you provided around things that were not likely to swap out and Postgres, MySQL, your database being one of them. And in favor of an example that I do have for something that...I do enjoy wrapping. It's not something that I adhere to strictly, but I do enjoy it when I have the space to make this choice. So I do enjoy wrapping HTTPClients, not just because then I can swap it out for a different HTTPClient, which frankly, that's also rare that I do that. Once I choose an HTTPClient, I'm probably pretty happy, and I don't need to swap it out. But I really like being able to extend to the API specifically if they don't handle error responses in a way that I would like to or if they raise, and then I want to change the API to have a more thoughtful interface and where I don't have to rescue those errors. But instead, I can interact with this object that then represents an error state. So that was just one example that came to mind for things that I do enjoy having an abstraction around and not just so I can swap it out because that feels like a very low risk, but more frankly, so I can extend the API. CHRIS: I definitely share the I almost always wrap APIs, or I try and hide whatever the implementation detail whether it be HTTPParty, or Faraday or whatever it is that I'm using and trying to hide that deeply within the system. And then I have whatever API client that we define. And that's what we're interacting with. It's interesting that you bring up errors and exceptions there because that's the one other thing that has caused me this...what I'm describing now seems perhaps like, oh, here's just a list of pros and cons, a simple decision was made, and there we are. This represents some real soul searching on my part, if we will. And one of the last things that I ran into that was just so frustrating is that Sidekiq is explicitly built around the idea of exceptions; Sidekiq retries if there is an exception raised in the job, otherwise, it treats it as success, and that's it. That is the entirety of it. That is the story. But if you raise an exception in a job, then you can't test that job because now it's raising an exception. You can't test retries or this retry exhausted block that I'm trying to lean into. I'm like, I want to put that in a feature spec and say, oh, this job goes in the background, but it's in a failure state, and therefore, the user sees the failure message. Sorry, I can't do that because the only way to actually fail a job is via an exception. And I've actually gone to some links in this application to try to introduce more structured data flow. I've talked a bunch about the command objects and the dry-monads and all those things. And I've really loved them where I've gotten to use them. But then I run into one of these edge cases where Sidekiq is like, no, no, no, you can't do that. And so now I have parts of my system that very purposefully return data as opposed to raising an exception. And I just have to turn around and directly raise that failure as an exception, and it just feels less expressive. I actually just ran into the identical thing with Pundit. They have a little bit better control over it; I can choose whether or not I want the raising version or not. But I see exceptions everywhere, and I want a little more discrete data flow. [chuckles] That is my dream. So anyway, I chose Sidekiq is the summary here. And slowly, we're going to migrate entirely to Sidekiq. And I'm going to be totally fine with it. And I'm done griping now. STEPH: This is your own little October Halloween movie, that I see exceptions everywhere. CHRIS: They're so spooky. STEPH: [laughs] That's cool about Pundit. I'm not sure I knew that, that you get to essentially turn on or off that exception flow behavior. On one hand, I'm like, that's nice. You get the option. On the other hand, I'm like, well, let's just not do it. Let's just never raise on people. But at least they give people options; that seems really cool. CHRIS: They do give the option. I think you can choose different strategies there. And also, if we're being honest, I'm newer to Pundit. And I used a different thing, which was to get the Policy Object and ask it a question. I wanted to ask, is this enabled or not? Can a user do this or not? That should not raise an exception. I'm just asking a question. We're just being real chill about this. I just want to know some information. Let's flow some data through our system. We don't need exceptions for that. STEPH: Why are you yelling at me? I just have a question. [laughs] CHRIS: Yeah. I figured out how to be easy on that front. Sidekiq apparently has no be easy mode, but that's fine. You know what? We're going to make it work, and it's going to be fine. But it is interesting deciding which of these facets of the system that I'm building do I really care about? Which are the ones where I'm like, whatever, just pick something, and we'll move forward, it's not a big deal? Versus, we're actually going to be doing a lot of work in the background. This is the thing that I care about deeply. I want to know about failure and success. I want to really understand that and have a robust answer to what our architecture looks like there. Similarly, Pundit for authorization. I believe that authorization will be a critical aspect of our system. It's typically a pretty important thing. But for us, I think we're going to have different types of users who can log in and see different subsets of data and having a consistent and concrete way that we have chosen to implement that we are able to test, that we're able to verify. I think that's another core competency within the app. But you only get to have so many of those. You can only be really good at a couple of things. And so I'm in that place where I'm like, which are our top five when I say are the things that I care a lot about? And then which are the things where I'm like, I don't know, whatever, just run with it? STEPH: Just a little bit ago, I came so close to singing because you said the I want to know phrase again. And that, I'm realizing, [laughs] is a trigger for me and a song where I want to sing. I held it back this time. CHRIS: It's smart. You got to learn anytime you sing on mic that is part of the permanent record. STEPH: Edward Loveall at thoughtbot, since I sang in a recent episode, did the delightful thing where then he grabbed that clip of where you talk a little bit, and then I sing and then encouraged everyone to go listen to it. And in which I responded, like, I would highly recommend that you save your ears and don't listen to it. But yes, singing on the mic is a thing. I do it from time to time. I can't hold it back. CHRIS: We all do. But since it doesn't seem that you're going to sing in this moment, I think I can probably wrap up my Odyssey of choosing between Sidekiq and Active Job. I hope those details were useful to anyone other than me. It was an adventure, so I figured I'd share it. But yeah, that about wraps it up on my side. Mid-roll Ad And now a quick break to hear from today's sponsor, Scout APM. Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more. Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform. See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed. STEPH: So, I would love to talk about an SSL error that I encountered recently. So one of the important processes in our application is sending data to another system. And while sending data to that other system, we started seeing the following error that the read "Certificate verify failed." And then in parens, it states, "Unable to get local issuer certificate." So upon seeing that error, I initially thought, okay, something is wrong with their SSL certificate or their SSL configuration. And that's not something that I have control over and can fix. So we should reach out and let them know to take a look at their SSL config. But it turns out that their team already knew about the issue. They had recently updated or renewed their SSL cert, and they saw our messages were no longer being processed, and they were reaching out to us for help. So at that point, I'm still pretty sure that it's related to something on their end, and it's not something that I can really fix on our end. But we can help them troubleshoot. Maybe there's a workaround that we can add to still get messages processing while they're looking into their SSL config. It seemed like they still just needed help. So it was something that was still worth diving into. So going back to the first error, I want to talk a little bit about it because I realized that I understand SSL just enough, just the surface to get by as a developer. But then, every time that I run into a specific error with it, then I really have to refresh my understanding as to what could be wrong, so then I can troubleshoot more effectively. So for anyone that could use a refresher on that certificate verification process, when your browser or your server is connecting to a site that uses SSL, then your browser server, whichever one you're using, is going to download that site certificate and verify a couple of things. So it's going to check does the certificate contain the domain name of the website? So essentially, you gave us a certificate. Is this your certificate? Does it match the site that we're connecting to? Is this cert issued by a trusted certificate authority? So did someone that we trust give you this certificate? And is the cert still valid, or has it expired? So that part is pretty straightforward. The second part, "Unable to get local issuer certificate," so that's the part I was less certain about. And I took this to mean that they had passed two of those three checks that their cert included the site's name, and it had not expired. But for some reason, we aren't able to determine if their cert was issued by someone that we should trust. So following that journey, my next question was, so what are they giving us? So this is a tool that I don't get to use very often, but I reached for OpenSSL and, specifically, the s_client command, which connects to a specified domain and prints all certificates in the certificate chain. You may already know this, but the certificate chain is basically a fancy way of saying, show me all the certificates necessary to prove your site certificate was authorized by a trusted certificate authority. CHRIS: I did not know that. STEPH: Okay, I honestly didn't either. [laughs] CHRIS: I liked that you thought I would, though. So thank you, but no. [chuckles] STEPH: Yeah, it's one of those areas of SSL where I know just enough. But that was something that was new to me. I thought there was a site certificate, and I didn't realize that there is this chain of certificates that has to be honored. So going back and looking through that output of the certificate chain, that's what highlighted to me that their server was giving us their certificate and saying, hey, you should trust our site certificate. It's legit because it was authorized by, let's say, XYZ certificate. And so if it were a proper certificate chain, then they would give us that XYZ cert. And essentially, we can use this chain of certificates to get back to a trusted authority that then everybody knows that we can trust. However, they weren't actually giving us a reference certificate; they were giving us something else. So essentially, they were saying, "Hey, look at our certificate and look at this very trustworthy reference that we have." But they're actually failing to give us that reference. So to bring it all home, we can download that intermediate certificate that they reference; that is something that is publicly accessible. That's why we're able to then verify each certificate that's provided in that chain. We could go and download that intermediate certificate from that certificate authority. We could combine that with their site-specific certificate, include that in our request to their system, and then complete the certificate chain. And boom, we're back in business. But it was quite a journey. CHRIS: That is quite the journey. And yeah, I definitely knew very little of that, although everything you're saying makes sense. And I have a bunch of cubbyholes in my brain for SSL knowledge. And the words you said all fit into the spaces that I have in my brain, but I didn't know a bunch of those pieces. So thank you for sharing that. SSL and cryptography, more generally or password hashing or things like that, occupy this special place in my brain where I'm both really interested in them. And I will occasionally research them. If I see a blog article, I'll be like, oh yeah, I want to read more about this password hashing. And what's a Salt? And what's a Pepper? And what are we doing there? And what is BCrypt versus SCrypt? What are all these things? This is cool. And almost the arms race on the two sides of how do we demonstrate trust in a secure manner on the internet? But at the same time, I am not allowed to do anything with this information. I outsource this as much as humanly possible because it's one of those things that you just should not do yourself and SSL perhaps even more so. So I have configured aspects of my password hashing. But I 100% just lean on the fact that Let's Encrypt exists in the world. And prior to that, it was a little more work. But frankly, earlier on in my career, I wasn't dealing with the SSL parts of things. But I'm so grateful to Let's Encrypt as a project that exists. And now, on almost every platform that I work with, there's just a checkbox for please do the SSL work for me, make it good, make it work, and then I will be happy. And I'm so glad that that organization exists and really pushed the envelope also. I forget what it was, but it was only like three years ago where SSL was not actually nearly as common as it is now. And now it is pervasive and everywhere. And all of the sites have it, and so that is a wonderful thing. But I don't actually know much. I know that I should have it. I must have it. I should force it. That's true. So I push that out… STEPH: Hello. CHRIS: Are you trying to get me to sing? [chuckles] STEPH: [laughs] No, but I did want to know if you get the reference, the Salt-N-Pepa. CHRIS: Push It Real Good the song? Yeah, okay. STEPH: Yeah, you got it. [chuckles] CHRIS: I will just say the lyrics. I shall not sing the lyrics. I would say that, though, that yes, yes, they do that. STEPH: Thank you for acknowledging my very terrible reference. Circling back just a little bit too in regards to...I'm with you; this is a world that is not one that I am very deeply technical in and something that I learned a fair amount while troubleshooting this particular SSL error. And it was very interesting. But there's also that concern where it's like, that was interesting. And we worked around the issue, but this also feels very fragile. So we still haven't fixed it on their end where they are sending the wrong certificate. So then that's why we had to do more investigative work, and then download the certificate that they meant to send us, and then send back a complete certificate chain so that we don't have this error anymore. But should they change anything about their certificate, should they renew anything like that, then suddenly, we're going to break again. And then, the next developer is going to have to go through the same journey. And this wasn't a light journey. This was a good half-day journey to figure out what was going on and to spend the time, and then to also get that fix out to production. So it's a meaningful task that I don't want anyone else to have to go through. But we are relying on someone else updating their configuration. So, on one hand, we're in a good spot until they are able to update. But on the other hand, I wrote a heck of a commit message for the next person just describing like, friend, just grab some coffee if we're going to chat. It's a very small code change, but you need to know the scoop. So should you need to replicate this because they've changed something, or if this happens…because we work with a number of systems that we send data to. So if someone else should run into a similar issue, they will understand some of the troubleshooting techniques that I used and be able to look up that chain and find out if there's a missing cert or something else they need to provide. So it feels like a win, but I'm also nervous for future selves, future developers. So there's another approach that I haven't mentioned yet, but it was often a top recommendation for when dealing with SSL errors. And specifically, it was turning off SSL verification. And I saw that, and I was like, well, that won't work. I'm definitely sending sensitive, important data. And I need to verify that who I'm sending this to is really the person that I want to send this data to. So that was not an option for me. But it made me very nervous how often that was an approach that people would recommend and be like, oh, it's okay, just turn off SSL. You'll be fine. Like, don't worry about it. CHRIS: I feel like this so perfectly fits into the...some of our work is finding the information and connecting the pieces together and making it work. But some of it is that heuristic sense, that voice in the back of your head that is like, wait, I'm sorry, what? You want me to just turn off the security perimeter and hope that the velociraptors won't come in? That doesn't seem like it's going to end well. I get that that's an easy option that we have available to us right now and will solve the immediate problem but then let's play this out. There are four or five Jurassic Park movies now that tell the story of that. So let's be careful. STEPH: It always ends super well, though, right? Like, it's totally fine. [laughs] CHRIS: [laughs] Exclusively. Although it's funny that you mentioned OpenSSL no verify because just this past week, I used that very same configuration. I think it was okay in my case; I'm pretty sure. But it is interesting because when I saw it, I was like, oh no, can't do that. Certainly not that. Don't turn off the security feature. That's the wrong way to deal with the issue. But in the particular case that I'm working with, I'm using Redis, Heroku Redis, in particular, in a Heroku configuration. And the nature of how Heroku configures the Redis instances and the connectivity to our app into our dyno...I forget why. I read an article. They wrote it; Heroku wrote it. I trust them; they're good. I've outsourced my trust to people that I do trust. The trust chain actually maps really well to the certificate trust chain. I trust that Heroku has taken security deeply seriously. And for some reason, their configuration of Redis requires that I turn on OpenSSL no verify mode. So I'm using this now both in Sidekiq, and then we're using our Redis instance for our Rails cache as well. So in both cases, I said, "It's fine. Don't worry about it." I used the Don't worry about it configuration. And I didn't love it but I think it's okay. And partly, I'm trying to say this into the internet radio right now just in case anyone's listening who's like, no, no, no, you can't do that. That's bad. So I'm willing to be deeply wrong on the internet in favor of someone telling me and then I get to get out in front of it. But I think it's fine. Pretty sure it's fine. It should be fine. STEPH: I love love love that you gave a very visual example of velociraptors, and then you're like, oh, but I turned it off. [laughs] So I'm going to start sending you a velociraptor gif each day. CHRIS: I hope you do. I hope the internet holds you accountable to that. STEPH: [laughs] CHRIS: And I really look forward to [laughs] moving forward because that's a great way to start the day. Well, it doesn't need to start the day, but I look forward to them. STEPH: [laughs] I am really intrigued because I'm with you. Like you said, there are certain entities that are in our trust chain where it's like, hey, you are running this for us, and so I do have faith and trust in you that you wouldn't steer me wrong and provide a bad recommendation. Someone on Stack Overflow telling me to turn off SSL verify uh; that's not my trust chain. Heroku or someone else telling me I'm going to take it a little more seriously. And so I'm also interested in hearing from...what'd you say? You're speaking into the internet phone. [laughs] What'd you say? CHRIS: I think I said internet radio. But yeah, in a way. I mean, we're recording over Skype right now. So in a manner of speaking, we're on the internet phone to make our internet radio show. STEPH: [laughs] Oh goodness, the internet radio. I'm also intrigued to hear if other people are like, oh, no, no, no. Yeah, that sounds like an interesting scenario. Because I would think you'd still want your connection to...you said it's for Redis. So you still want that connection to be verified. But then if Redis itself can't have a specific...yeah, we're testing the boundaries of my SSL knowledge here as to how the heck you would even establish that SSL connection or the verification process. CHRIS: Me too. And it also exists in an interesting space where Heroku is rather clear in their documentation about this. And it was a surprising claim when I saw it. And so, I don't expect them to be flippant about a thing that is important. Like, if they're like, "No, no, no, it is okay. You can turn off the security thing, don't worry." I trust that they're not just like, oh, we didn't think about it too much. But we figured why not? It's not a big deal. I'm sure that they have thought about it deeply because it is an important thing. And so in a weird way, my trust of them and the severity of what this thing represents, I'm like, oh yeah, I super trust that because you're not going to get a major thing wrong. You might get a minor, small, subtle thing wrong. But this is a pretty major configuration change. As I say it, I'm now getting more worried. I'm now like, I feel fine about this. This doesn't seem like a problem at all. But then I keep saying stuff, and I'm like, oh no. That's why I love having a podcast; I find out things about myself as I talk into a microphone to you. STEPH: We come here to share our deep, dark developer secrets. Chris: Spooky developer therapy. STEPH: But just to clarify, even though you've turned off the SSL verify, you're still connecting over SSL. CHRIS: Yes, I believe that's the case. And if I'm remembering, I think the nature of how this works is they're using a self-signed certificate because of shared infrastructure or something, something that made sense when I read it. But it was the idea that they are doing a self-signed certificate. Therefore, to what you were talking about earlier, there isn't the certificate authority in the chain of those because it's self-signed. And so, they are not a trusted certificate authority. Therefore, that certificate that they have generated would not be trusted. But it does still allow for the SSL handshake and then communication to happen over SSL. It's just that fundamental question of trust. I'm saying, in this case, for reasons, it's okay. Trust me that I trust them. We're good. Which, again, I don't feel great about, but I think yes, it is still SSL, but it is a self-signed certificate. So we have to make this configuration change. STEPH: Yeah, all of that makes sense. And it certainly sounds like you have been very thoughtful about that change and put in some investigative work. So on that note, I have a very unrelated bad joke for you. CHRIS: I'm very excited. STEPH: All right, here we go. All right, so what do you call an alligator wearing a vest? CHRIS: I don't know. What do you call an alligator wearing a vest? STEPH: An investigator. [laughter] On that note, shall we wrap up? CHRIS: Oh, let's wrap up. We should also include a link in the show notes to the episode where you told the joke about the elephant hiding in the trees because that's one of my favorite jokes. You slayed me with that one. [laughs] But on that note, yes, let us wrap up. The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes,,as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Byeeeeeeeeee!!! Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.

    311: Marketing Matters

    Play Episode Listen Later Oct 5, 2021 37:37

    Longtime listener and friend of the show, Gio Lodi, released a book y'all should check out and Chris and Steph ruminate on a listener question about tension around marketing in open-source. Say No To More Process, Say Yes To Trust by German Velasco (https://thoughtbot.com/blog/say-no-to-more-process-say-yes-to-trust) Test-Driven Development in Swift with SwiftUI and Combine by Gio Lodi (https://tddinswift.com/) Transcript: CHRIS: Our golden roads. STEPH: All right. I am also golden. CHRIS: [vocalization] STEPH: Oh, I haven't listened to that episode where I just broke out in song in the middle. Oh, you're about to add the [vocalization] [chuckles]. CHRIS: I don't know why, though. Oh, golden roads, Golden Arches. STEPH: Golden Arches, yeah. CHRIS: Man, I did not know that my brain was doing that, but my brain definitely connected those without telling me about it. STEPH: [laughs] CHRIS: It's weird. People talk often about the theory that phones are listening, and then you get targeted ads based on what you said. But I'm almost certain it's actually the algorithms have figured out how to do the same intuitive leaps that your brain does. And so you'll smell something and not make the nine steps in between, but your brain will start singing a song from your childhood. And you're like, what is going on? Oh, right, because when I was watching Jurassic Park that one time, we were eating this type of chicken, and therefore when I smell paprika, Jurassic Park theme song. I got it, of course. STEPH: [laughs] CHRIS: And I think that's actually what's happening with the phones. That's my guess is that you went to a site, and the phones are like, cool, I got it, adjacent to that is this other thing, totally. Because I don't think the phones are listening. Occasionally, I think the phones are listening, but mostly, I don't think the phones are listening. STEPH: I definitely think the phones are listening. CHRIS: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey. STEPH: And I'm Steph Viccari. CHRIS: And together, we're here to share a bit of what we've learned along the way. So, Steph, what's new in your world? STEPH: Hey. So we have a bit of exciting news where we received an email from Gio Lodi, who is a listener of The Bike Shed. And Gio sent an email sharing with us some really exciting news that they have published a book on Test-Driven Development in Swift. And they acknowledge us in the acknowledgments of the book. Specifically, the acknowledgment says, "I also want to thank Chris Toomey and Steph Viccari, who keep sharing ideas on testing week after week on The Bike Shed Podcast." And that's just incredible. I'm so blown away, and I feel officially very famous. CHRIS: This is how you know you're famous when you're in the acknowledgments of a book. But yeah, Gio is a longtime listener and friend of the show. He's written in many times and given us great tips, and pointers, and questions, and things. And I've so appreciated Gio's voice in the community. And it's so wonderful, frankly, to hear that he has gotten value out of the show and us talking about testing. Because I always feel like I'm just regurgitating things that I've heard other people saying about testing and maybe one or two hard-learned truths that I've found. But it's really wonderful. And thank you so much, Gio. And best of luck for anyone out there who is doing Swift development and cares about testing or test-driven development, which I really think everybody should. Go check out that book. STEPH: I must admit my Swift skills are incredibly rusty, really non-existent at this point. It's been so long since I've been in that world. But I went ahead and purchased a copy just because I think it's really cool. And I suspect there are a lot of testing conversations that, regardless of the specific code examples, still translate. At least, that's the goal that you and I have when we're having these testing conversations. Even if they're not specific to a language, we can still talk about testing paradigms and strategies. So I purchased a copy. I'm really looking forward to reading it. And just to change things up a bit, we're going to start off with a listener question today. So this listener question comes from someone very close to the show. It comes from Thom Obarski. Hi, Thom. And Thom wrote in, "So I heard on a recent podcast I was editing some tension around marketing and open source. Specifically, a little perturbed at ReactJS that not only were people still dependent on a handful of big companies for their frameworks, but they also seem to be implying that the cachet of Facebook and having developer mindshare was not allowing smaller but potentially better solutions to shine through. In your opinion, how much does marketing play in the success of an open-source project framework rather than actually being the best tool for the job?" So a really thoughtful question. Thanks, Thom. Chris, I'm going to kick it over to you. What are your thoughts about this question? CHRIS: Yeah, this is a super interesting one. And thank you so much, Thom, although I'm not sure that you're listening at this point. But we'll send you a note that we are replying to your question. And when I saw this one come through, it was interesting. I really love the kernel of the discussion here, but it is, again, very difficult to tease apart the bits. I think that the way the question was framed is like, oh, there's this bad thing that it's this big company that has this big name, and they're getting by on that. But really, there are these other great frameworks that exist, and they should get more of the mindshare. And honestly, I'm not sure. I think marketing is a critically important aspect of the work that we do both in open source and, frankly, everywhere. And I'm going to clarify what I mean by that because I think it can take different shapes. But in terms of open-source, Facebook has poured a ton of energy and effort and, frankly, work into React as a framework. And they're also battle testing it on facebook.com, a giant website that gets tons of traffic, that sees various use cases, that has all permissions in there. They're really putting it through the wringer in that way. And so there is a ton of value just in terms of this large organization working on and using this framework in the same way that GitHub and using Rails is a thing that is deeply valuable to us as a community. So I think having a large organization associated with something can actually be deeply valuable in terms of what it produces as an outcome for us as consumers of that open-source framework. I think the other idea of sort of the meritocracy of the better framework should win out is, I don't know, it's like a Field of Dreams. Like, if you build it, they will come. It turns out I don't believe that that's actually true. And I think selling is a critical part of everything. And so if I think back to DHH's original video from so many years ago of like, I'm going to make a blog in 15 minutes; look at how much I'm not doing. That was a fantastic sales pitch for this new framework. And he was able to gain a ton of attention by virtue of making this really great sales pitch that sold on the merits of it. But that was marketing. He did the work of marketing there. And I actually think about it in terms of a pull request. So I'm in a small organization. We're in a private repo. There's still marketing. There's still sales to be done there. I have to communicate to someone else the changes that I'm making, why it's valuable to the system, why they should support this change, this code coming into the codebase. And so I think that sort of communication is as critical to the whole conversation. And so the same thing happens at the level of open source. I would love for the best framework to always win, but we also need large communities with Stack Overflow answers and community-supported plugins and things like that. And so it's a really difficult thing to treat marketing as just other, this different, separate thing when, in fact, I think they're all intertwined. And marketing is critically important, and having a giant organization behind something can actually have negative aspects. But I think overall; it really is useful in a lot of cases. Those are some initial thoughts. What do you think, Steph? STEPH: Yeah, those are some great initial thoughts. I really agree with what you said. And I also like how you brought in the comparison of pull requests and how sales is still part of our job as developers, maybe not in the more traditional sense but in the way that we are marketing and communicating with the team. And circling back to what you were saying earlier about a bit how this is phrased, I think I typically agree that there's nothing nefarious that's afoot in regards to just because a larger company is sponsoring an open-source project or they are the ones responsible for it, I don't think there's anything necessarily bad about that. And I agree with the other points that you made where it is helpful that these teams have essentially cultivated a framework or a project that is working for their team, that is helping their company, and then they have decided to open source it. And then, they have the time and energy that they can continue to invest in that project. And it is battle-tested because they are using it for their own projects as well. So it seems pretty natural that a lot of us then would gravitate towards these larger, more heavily supported projects and frameworks. Because then that's going to make our job easier and also give us more trust that we can turn to them when we do need help or have issues. Or, like you mentioned, when we need to look up documentation, we know that that's going to be there versus some of the other smaller projects. They may also be wonderful projects. But if they are someone that's doing this in their spare time just on the weekends and yet I'm looking for something that I need to be incredibly reliable, then it probably makes sense for me to go with something that is supported by a team that's getting essentially paid to work on that project, at least that they're backed by a larger company. Versus if I'm going with a smaller project where someone is doing some wonderful work, but realistically, they're also doing it more on the weekends or in their spare time. So boiling it down, it's similar to what you just said where marketing plays a very big part in open source, and the projects and frameworks that we adopt, and the things that we use. And I don't think that's necessarily a bad thing. CHRIS: Yeah. I think, if anything, it's possibly a double-edged sword. Part of the question was around does React get to benefit just by the cachet of Facebook? But Facebook, as a larger organization sometimes that's a positive thing. Sometimes there's ire that is directed at Facebook as an organization. And as a similar example, my experience with Google and Microsoft as large organizations, particularly backing open-source efforts, has almost sort of swapped over time, where originally, Microsoft there was almost nothing of Microsoft's open-source efforts that I was using. And I saw them as this very different shape of a company that I probably wouldn't be that interested in. And then they have deeply invested in things like GitHub, and VS Code, and TypeScript, and tons of projects that suddenly I'm like, oh, actually, a lot of what I use in the world is coming from Microsoft. That's really interesting. And at the same time, Google has kind of gone in the opposite direction for me. And I've seen some of their movements switch from like, oh Google the underdog to now they're such a large company. And so the idea that the cachet, as the question phrase, of a company is just this uniformly positive thing and that it's perhaps an unfair benefit I don't see that as actually true. But actually, as a more pointed example of this, I recently chose Svelte over React, and that was a conscious choice. And I went back and forth on it a few times, if we're being honest, because Svelte is a much smaller community. It does not have the large organizational backing that React or other frameworks do. And there was a certain marketing effort that was necessary to raise it into my visibility and then for me to be convinced that there is enough there, that there is a team that will maintain it, and that there are reasons to choose that and continue with it. And I've been very happy with it as a choice. But I was very conscious in that choice that I'm choosing something that doesn't have that large organizational backing. Because there's a nicety there of like, I trust that Facebook will probably keep investing in React because it is the fundamental technology of the front end of their platform. So yeah, it's not going to go anywhere. But I made the choice of going with Svelte. So it's an example of where the large organization didn't win out in my particular case. So I think marketing is a part of the work, a part of the conversation. It's part of communication. And so I am less negative on it, I think, than the question perhaps was framed, but as always, it depends. STEPH: Yeah, I'm trying to think of a scenario where I would be concerned about the fact that I'm using open source that's backed by a specific large company or corporation. And the main scenario I can think of is what happens when you conflict or if you have values that conflict with a company that is sponsoring that project? So if you are using an open-source project, but then the main community or the company that then works on that project does something that you really disagree with, then what do you do? How do you feel about that situation? Do you continue to use that open-source project? Do you try to use a different open-source project? And I had that conversation frankly with myself recently, thinking through what to do in that situation and how to view it. And I realize this may not be how everybody views it, and it's not appropriate for all situations. But I do typically look at open-source projects as more than who they are backed by, but the community that's actively working on that project and who it benefits. So even if there is one particular group that is doing something that I don't agree with, that doesn't necessarily mean that wholesale I no longer want to be a part of this community. It just means that I still want to be a part, but I still want to share my concerns that I think a part of our community is going in a direction that I don't agree with or I don't think is a good direction. That's, I guess, how I reason with myself; even if an open-source project is backed by someone that I don't agree with, either one, you can walk away. That seems very complicated, depending on your dependencies. Or two, you find ways to then push back on those values if you feel that the community is headed in a direction that you don't agree with. And that all depends on how comfortable you are and how much power you feel like you have in that situation to express your opinion. So it's a complicated space. CHRIS: Yeah, that is a super subtle edge case of all of this. And I think I aligned with what you said of trying to view an open-source project as more generally the community that's behind it as opposed to even if there's a strong, singular organization behind it. But that said, that's definitely a part of it. And again, it's a double-edged sword. It's not just, oh, giant company; this is great. That giant company now has to consider this. And I think in the case of Facebook and React, that is a wonderful hiring channel for them. Now all the people that use React anywhere are like, "Oh man, I could go work at Facebook on React? That's exciting." That's a thing that's a marketing tool from a hiring perspective for them. But it cuts both ways because suddenly, if the mindshare moves in a different direction, or if Facebook as an organization does something complicated, then React as a community can start to shift away. Maybe you don't move the current project off of it, but perhaps you don't start the next one with it. And so, there are trade-offs and considerations in all directions. And again, it depends. STEPH: Yeah. I think overall, the thing that doesn't depend is marketing matters. It is a real part of the ecosystem, and it will influence our decisions. And so, just circling back to Thom's question, I think it does play a vital role in the choices that we make. CHRIS: Way to stick the landing. STEPH: Thanks. Mid-roll Ad And now a quick break to hear from today's sponsor, Scout APM. Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more. Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform. See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed. STEPH: Changing topics just a bit, what's new in your world? CHRIS: Well, we had what I would call a mini perfect storm this week. We broke the build but in a pretty solid way. And it was a little bit difficult to get it back under control. And it has pushed me ever so slightly forward in my desire to have a fully optimized CI and deploy pipeline. Mostly, I mean that in terms of ratcheting. I'm not actually going to do anything beyond a very small set of configurations. But to describe the context, we use pull requests because that's the way that we communicate. We do code reviews, all that fun stuff. And so there was a particular branch that had a good amount of changes, and then something got merged. And this other pull request was approved. And that person then clicked the rebase and merge button, which I have configured the repository, so that merge commits are not allowed because I'm not interested in that malarkey in our history. But merge commits or rebase and merge. I like that that makes sense. In this particular case, we ran into the very small, subtle edge case of if you click the rebase and merge button, GitHub is now producing a new commit that did not exist before, a new version of the code. So they're taking your changes, and they are rebasing them onto the current main branch. And then they're attempting to merge that in. And A, that was allowed. B, the CI configuration did not require that to be in a passing state. And so basically, in doing that rebase and merge, it produced an artifact in the build that made it fail. And then attempting to unwind that was very complicated. So basically, the rebase produced...there were duplicate changes within a given file. So Git didn't see it as a conflict because the change was made in two different parts of the file, but those were conflicting changes. So Git was like, this seems like it's fine. I can merge this, no problem. But it turns out from a functional perspective; it did not work. The build failed. And so now our main branch was failing and then trying to unwind that it just was surprisingly difficult to unwind that. And it really highlighted the importance of keeping the main branch green, keeping the build always passing. And so, I configured a few things in response to this. There is a branch protection rule that you can enable. And let me actually pull up the specific configuration that I set up. So I now have enabled require status checks to pass before merging, which, if we're being honest, I thought that was the default. It turns out it was not the default. So we are now requiring status checks to pass before merging. I'm fully aware of the awkward, painful like, oh no, the build is failing but also, we have a bug. We need to deploy this. We must get something merged in. So hopefully, if and when that situation presents itself, I will turn this off or somehow otherwise work around it. But for now, I would prefer to have this as a yeah; this is definitely a configuration we want. So require status checks to pass before merging and then require branches to be up to date before merging. So the button that does the rebase and merge, I don't want that to actually do a rebase on GitHub. I want the branch to already be up to date. Basically, I only ever want fast-forward merges on our main branch. So all code should be ahead of main, and we are simply updating what main points at. We are not creating new code. That code has run on CI, that version of the code specifically. We are fully rebased and up to date on top of main, and that's how we're going. STEPH: All of that is super interesting. I have a question about the workflow. I want to make sure I'm understanding it correctly. So let's say that I have issued a PR, and then someone else has merged into the main branch. So now my PR is behind me, and I don't have that latest commit. With the new configuration, can I still use the rebase and merge, or will I need to rebase locally and then push up my branch before I can merge into main but at least using the GitHub UI? CHRIS: I believe that you would be forced to rebase locally, force push, and then CI would rebuild, and that's what it is. So I think that's what require branches to be up to date before merging means. So that's my hope. That is the intention here. I do realize that's complicated. So this requirement, which I like, because again, I really want the idea that no, no, no, we, the developers, are in charge of that final state. That final state should always run as part of a build of CI on our pull request/branch before going into main. So no code should be new. There should be no new commits that have never been tested before going into main. That's my strong belief. I want that world. I realize that's...I don't know. Maybe I'm getting pedantic, or I'm a micromanager of the Git history or whatever. I'm fine with any of those insults that people want to lob at me. That's fine. But that's what I feel. That said, this is a nuisance. I'm fully aware of that. And so imagine the situation where we got a couple of different things that have been in flight. People have been working on different...say there are three pull requests that are all coming to completion at the same time. Then you start to go to merge something, and you realize, oh no, somebody else just merged. So you rebase, and then you wait for CI to build. And just as the CI is completing, somebody else merges something, and you're like, ah, come on. And so then you have to one more time rebase, push, wait for the build to be green. So I get that that is not an ideal situation. Right now, our team is three developers. So there are a few enough of us that I feel like this is okay. We can manage this via human intervention and just deal with the occasional weight. But in the back of my mind, of course, I want to find a better solution to this. So what I've been exploring…there's a handful of different utilities that I'm looking at, but they are basically merged queues as an idea. So there are three that I'm looking at, or maybe just two, but there's mergify.io, which is a hosted solution that does this sort of thing. And then Shopify has a merge queue implementation that they're running. So the idea with this is when you as a developer are ready to merge something, you add a label to it. And when you add that label, there's some GitHub Action or otherwise some workflow in the background that sees that this has happened and now adds it to a merge queue. So it knows all of the different things that might want to be merged. And this is especially important as the team grows so that you don't get that contention. You can just say, "Yes, I would like my changes to go out into production." And so, when you label it, it then goes into this merge queue. And the background system is now going to take care of any necessary rebases. It's going to sequence them, so it's not just constantly churning all of the branches. It's waiting because it knows the order that they're ideally going to go out in. If CI fails for any of them because rebasing suddenly, you're in an inconsistent state; if your build fails, then it will kick you out of the merge queue. It will let you know. So it will send you a notification in some manner and say, "Hey, hey, hey, you got to come look at this again. You've been kicked out of the merge queue. You're not going to production." But ideally, it adds that layer of automation to, frankly, this nuisance of having to keep things up to date and always wanting code to be run on CI and on a pull request before it gets into main. Then the ideal version is when it does actually merge your code, it pings you in Slack or something like that to say, "Hey, your changes just went out to production." Because the other thing I'm hoping for is a continuous deployment. STEPH: The idea of a merge queue sounds really interesting. I've never worked with a process like that. And one of the benefits I can see is if I know I'm ready for something to go like if I'm waiting on a green build and I'm like, hey, as soon as this is green, I'd really like for it to get merged. Then currently, I'm checking in on it, so I will restart the build. And then, every so often, I'm going back to say, "Okay, are you green? Are you green? Can I emerge?" But if I have a merge queue, I can say, "Hey, merge queue, when this is green, please go and merge it for me." If I'm understanding the behavior correctly, that sounds really nifty. CHRIS: I think that's a distinct but useful aspect of this is the idea that when you as a developer decide this PR is ready to go, you don't need to wait for either the current build or any subsequent builds. If there are rebases that need to happen, you basically say, "I think this code's good to go. We've gotten the necessary approvals. We've got the buy-in and the teams into this code." So cool, I now market as good. And you can walk away from it, and you will be notified either if it fails to get merged or if it successfully gets merged and deployed. So yes, that dream of like, you don't have to sit there watching the pot boil anymore. STEPH: Yeah, that sounds nice. I do have to ask you a question. And this is related to one of the blog posts that you and I love deeply and reference fairly frequently. And it's the one that's written by German Velasco about Say No to More Process, and Say Yes to Trust. And I'm wondering, based on the pain that you felt from this new commit, going into main and breaking the main build, how do you feel about that balance of we spent time investigating this issue, and it may or may not happen again, and we're also looking into these new processes to avoid this from happening? I'm curious what your thought process is there because it seems like it's a fair amount of work to invest in the new process, but maybe that's justified based on the pain that you felt from having to fix the build previously. CHRIS: Oh, I love the question. I love the subtle pushback here. I love this frame of mind. I really love that blog post. German writes incredible blog posts. And this is one that I just keep coming back to. In this particular case, when this situation occurred, we had a very brief...well, it wasn't even that brief because actually unwinding the situation was surprisingly painful, and we had some changes that we really wanted to get out, but now the build was broken. And so that churn and slowdown of our build pipeline and of our ability to actually get changes out to production was enough pain that we're like, okay, cool. And then the other thing is we actually all were in agreement that this is the way we want things to work anyway, that idea that things should be rebased and tested on CI as part of a pull request. And then we're essentially only doing fast-forward merges on the main branch, or we're fast forward merging main into this new change. That's the workflow that we wanted. So this configuration was really just adding a little bit of software control to the thing that we wanted. So it was an existing process in our minds. This is the thing we were trying to do. It's just kind of hard to keep up with, frankly. But it turns out GitHub can manage it for us and enforce the process that we wanted. So it wasn't a new process per se. It was new automation to help us hold ourselves to the process that we had chosen. And again, it's minimally painful for the team given the size that we're at now, but I am looking out to the future. And to be clear, this is one of the many things that fall on the list of; man, I would love to have some time to do this, but this is obviously not a priority right now. So I'm not allowed to do this. This is explicitly on the not allowed to touch list, but someday. I'm very excited about this because this does fundamentally introduce some additional work in the pipeline, and I don't want that. Like you said, is this process worth it for the very small set of times that it's going to have a bad outcome? But in my mind, the better version, that down the road version where we have a merge queue, is actually a better version overall, even with just a tiny team of three developers that are maybe never even conflicting in our merges, except for this one standout time that happens once every three months or whatever. This is still nicer. I want to just be able to label a pull request and walk away and have it do the thing that we have decided as a team that we want. So that's the dream. STEPH: Oh, I love that phrasing, to label a pull request and be able to walk away. Going back to our marketing, that really sells that merge queue to me. [laughs] Mid-roll Ad And now we're going to take a quick break to tell you about today's sponsor, Orbit. Orbit is mission control for community builders. Orbit offers data analytics, reporting, and insights across all the places your community exists in a single location. Orbit's origins are in the open-source and developer relations communities. And that continues today with an active open-source culture in an accessible and documented API. With thousands of communities currently relying on Orbit, they are rapidly growing their engineering team. The company is entirely remote-first with team members around the world. You can work from home, from an Orbit outpost in San Francisco or Paris, or find yourself a coworking spot in your city. The tech stack of the main orbit app is Ruby on Rails with JavaScript on the front end. If you're looking for your next role with an empathetic product-driven team that prides itself on work-life balance, professional development, and giving back to the larger community, then consider checking out the Orbit careers page for more information. Bonus points if working in a Ruby codebase with a Ruby-oriented team gives you a lot of joy. Find out more at orbit.love/weloveruby. CHRIS: To be clear, and this is to borrow on some of Charity Majors' comments around continuous deployment and whatnot, is a developer should stay very close to the code if they are merging it. Because if we're doing continuous deployment, that's going to go out to production. If anything's going to happen, I want that individual to be aware. So ideally, there's another set of optimizations that I need to make on top of this. So we've got the merge queue, and that'll be great. Really excited about that. But if we're going to lean into this, I want to optimize our CI pipeline and our deployment pipeline as much as possible such that even in the worst case where there's three different builds that are fighting for contention and trying to get out, the longest any developer might go between labeling a pull request and saying, "This is good to go," and it getting out to production, again, even if they're contending with other PRs, is say 10, 15 minutes, something like that. I want Slack to notify them and them to then re-engage and keep an eye on things, see if any errors pop up, anything like that that they might need to respond to. Because they're the one that's got the context on the code at that point, and that context is decaying. The minute you've just merged a pull request and you're walking away from that code, the next day, you're like, what did I work on? I don't remember that at all. That code doesn't exist anymore in my brain. And so,,, staying close to that context is incredibly important. So there's a handful of optimizations that I've looked at in terms of the CircleCI build. I've talked about my not rebuilding when it actually gets fast-forward merged because we've already done that build on the pull request. I'm being somewhat pointed in saying this has to build on a pull request. So if it did just build on a pull request, let's not rebuild it on main because it's identically the same commit. CircleCI, I'm looking at you. Give me a config button for that, please. I would really love that config button. But there are a couple of other things that I've looked at. There's RSpec::Retry from NoRedInk, which will allow for some retry semantics. Because it will be really frustrating if your build breaks and you fall out of the merge queue. So let's try a little bit of retry logic on there, particularly around feature specs, because that's where this might happen. There's Knapsack Pro which is a really interesting thing that I've looked at, which does parallelization of your RSpec test suite. But it does it in a different way than say Circle does. It actually runs a build queue, and each test gets sent over, and they have build agents on their side. And it's an interesting approach. I'm intrigued. I think it could use some nice speed-ups. There's esbuild on the Heroku side so that our assets build so much more quickly. There are lots of things. I want to make it very fast. But again, this is on the not allowed to do it list. [laughs] STEPH: I love how most of the world has a to-do list, and you have this not-allowed to-do list that you're adding items to. And I'm really curious what all is on the not allowed to touch lists or not allowed to-do list. [laughs] CHRIS: I think this might be inherent to being a developer is like when I see a problem, I want to fix it. I want to optimize it. I want to tweak it. I want to make it so that that never happens again. But plenty of things...coming back to German's post of Say No to More Process, some things shouldn't be fixed, or the cost of fixing is so much higher than the cost of just letting it happen again and dealing with it manually at that moment. And so I think my inherent nature as a developer there's a voice in my head that is like, fix everything that's broken. And I'm like, sorry. Sorry, brain, I do not have that kind of time. And so I have to be really choosy about where the time goes. And this extends to the team as well. We need to be intentional around what we're building. Actually, there's a feeling that I've been feeling more acutely than ever, but it's the idea of this trade-off or optimization between speed and getting features out into the world and laying the right fundamentals. We're still very early on in this project, and I want to make sure we're thinking about things intentionally. I've been on so many projects where it's many years after it started and when I ask someone, "Hey, why do your background jobs work that way? That's a little weird." And they're like, "Yeah, that was just a thing that happened, and then it never changed. And then, we copied it and duplicated, and that pattern just got reinforced deeply within the app. And at this point, it would cost too much to change." I've seen that thing play out so many times at so many different organizations that I'm overwhelmed with that knowledge in the back of my head. And I'm like, okay, I got to get it just right. But I can't take the time that is necessary to get it, quote, unquote, "Just right." I do not have that kind of time. I got to ship some features. And this tension is sort of the name of the game. It's the thing I've been doing for my entire career. But now, given the role that I have with a very early-stage startup, I've never felt it more acutely. I've never had to be equally as concerned with both sides of that. Both matter all the more now than they ever have before, and so I'm kind of existing in that space. STEPH: I really like that phrasing of that space because that deeply resonates with me as well. And that not allowed to-do list I have a similar list. For me, it's just called a wishlist. And so it's a wishlist that I will revisit every so often, but honestly, most things on there don't get done. And then I'll clear it out every so often when I feel it's not likely that I'm going to get to it. And then I'll just start fresh. So I also have a similar this is what I would like to do if I had the time. And I agree that there's this inclination to automate as well. As soon as we have to do something that felt painful once, then we feel like, oh, we should automate it. And that's a conversation that I often have with myself is at what point is the cost of automation worthwhile versus should we just do this manually until we get to that point? So I love those nuanced conversations around when is the right time to invest further in this, and what is the impact? And what is the cost of it? And what are the trade-offs? And making that decision isn't always clear. And so I think that's why I really enjoy these conversations because it's not a clear rubric as to like, this is when you invest, and this is when you don't. But I do feel like being a consultant has helped me hone those skills because I am jumping around to different teams, and I'm recognizing they didn't do this thing. Maybe they didn't address this or invest in it, and it's working for them. There are some oddities. Like you said, maybe I'll ask, "Why is this? It seems a little funky. What's the history?" And they'll be like, "Yeah, it was built in a hurry, but it works. And so there hasn't been any churn. We don't have any issues with it, so we have just left it." And that has helped reinforce the idea that just because something could be improved doesn't mean it's worthwhile to improve it. Circling back to your original quest where you are looking to improve the process for merging and ensuring that CI stays green, I do like that you highlighted the fact that we do need to just be able to override settings. So that's something that has happened recently this week for me and my client work where we have had PRs that didn't have a green build because we have some flaky tests that we are actively working on. But we recognize that they're flaky, and we don't want that to block us. I'm still shipping work. So I really appreciate the consideration where we want to optimize so that everyone has an easy merging experience. We know things are green. It's trustworthy. But then we also have the ability to still say, "No, I am confident that I know what I'm doing here, and I want to merge it anyways, but thank you for the warning." CHRIS: And the constant pendulum swing of over-correcting in various directions I've experienced that. And as you said, in the back of my mind, I'm like, oh, I know that this setting I'm going to need a way to turn this setting off. So I want to make sure that, most importantly, I'm not the only one on the team who can turn that off because the day that I am away on vacation and the build is broken, and we have a critical bug that we need to fix, somebody else needs to be able to do that. So that's sort of the story in my head. At the same time, though, I've worked on so many teams where they're like, oh yeah, the build has been broken for seven weeks. We have a ticket in the backlog to fix that. And it's like, no, the build has to not be broken for that long. And so I agree with what you were saying of consulting has so usefully helped me hone where I fall on these various spectrums. But I do worry that I'm just constantly over-correcting in one direction or the other. I'm never actually at an optimum. I am just constantly whatever the most recent thing was, which is really impacting my thinking on this. And I try to not do that, but it's hard. STEPH: Oh yeah. I'm totally biased towards my most recent experiences, and whatever has caused me the most pain or success recently. I'm definitely skewed in that direction. CHRIS: Yeah, I definitely have the recency bias, and I try to have a holistic view of all of the things I've seen. There's actually a particular one that I don't want to pat myself on the back for because it's not a good thing. But currently, our test suite, when it runs, there's just a bunch of noise. There's a bunch of other stuff that gets printed out, like a bunch of it. And I'm reminded of a tweet from Kevin Newton, a friend of the show, and I just pulled it up here. "Oh, the lengths I will go to avoid warnings in my terminal, especially in the middle of my green dots. Don't touch my dots." It's a beautiful beauty. He actually has a handful about the green dots. And I feel this feel. When I run my test suite, I just want a sea of green dots. That's all I want to see. But right now, our test suite is just noise. It's so much noise. And I am very proud of...I feel like this is a growth moment for me where I've been like, you know what? That is not the thing to fix today. We can deal with some noise amongst the green dots for now. Someday, I'm just going to lose it, and I'm going to fix it, and it's going to come back to green dots. [chuckles] STEPH: That sounds like such a wonderful children's book or Dr. Seuss. Oh, the importance of green dots or, oh, the places green dots will take you. CHRIS: Don't touch my dots. [laughter] STEPH: Okay. Maybe a slightly aggressive Dr. Seuss, but I still really like it. CHRIS: A little more, yeah. STEPH: On that note of our love of green dots, shall we wrap up? CHRIS: Let's wrap up. The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes, as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Byeeeeeee!!! Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.

    310: Schedule Shut Down, Complete

    Play Episode Listen Later Sep 28, 2021 39:16

    Chris talks feature flags featuring Flipper (Say that 3x fast!), and Steph talks reducing stress by a) having a work shutdown ritual and b) the fact that thoughtbot is experimenting with half-day Fridays. (Fri-yay?) Flipper (https://featureflags.io/2016/04/08/flipper-a-feature-flipper-feature-toggle-library/) Drastically Reduce Stress with a Work Shutdown Ritual (https://www.calnewport.com/blog/2009/06/08/drastically-reduce-stress-with-a-work-shutdown-ritual/) Iceland's Journey to a Short Working Week (https://autonomy.work/wp-content/uploads/2021/06/ICELAND_4DW.pdf) Burnout: The Secret to Unlocking the Stress Cycle (https://www.burnoutbook.net/) Transcript: STEPH: Hey, do you know that we could have an in-person recording at the end of October? CHRIS: I do. Yes, I'm planning. That is in the back of my head. I guess I hadn't said that to you yet. But I'm glad that we have separately had the same conversation, and we've got to figure that out, although I don't know how to do noise cancellation and whatnot in the room. [laughs] How do we...we'll have to figure it out. Like, put a blanket in between us but so that we can see across it, but it absorbs sound in the middle. It's weird. I don't know how to do stuff. Just thinking out loud here. STEPH: We'll just be in the same place but still different rooms. So it'll feel no different. [laughter] Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Steph Viccari. CHRIS: And I'm Chris Toomey. STEPH: And together, we're here to share a bit of what we've learned along the way. Hey, Chris, what's new in your world? CHRIS: Feature flags. Feature flags are an old favorite, but they have become new again in the application that I'm working on. We had a new feature that we were building out. But we assumed correctly that it would be nice to be able to break it apart into smaller pieces and sort of deliver it incrementally but not necessarily want to expose that to our end users. And so, we opted with that ticket to bring along the feature flag system. So we've introduced Flipper, in particular, which is a wonderful gem; it does the job. We're using the ActiveRecord adapter. All that kind of makes sense, happy about that. And so now we have feature flags. But it was one of those mindset shifts where the minute we got feature flags, I was like, yes, okay, everything behind a feature flag. And we've been leaning into that more and more, and it really is so nice and so freeing, and so absolutely loving it so far. STEPH: I'm intrigued. You said, "Everything behind a feature flag." Like, is it really everything or? Yeah, tell me more. CHRIS: Not everything. But at this point, we're still very early on in this application, so there are fundamental facets of the platform, different areas of what users can do. And so the actual stuff that works and is wired up is pretty minimal, but we want to have a little more surface area built out in the app for demo purposes, for conversations that are happening, et cetera. And so, we built out a bunch of new pages to represent functionality. And so there are sidebar links, and then the actual page itself, and routing, and all of the things that are associated with that, and so all of those have come in. I think there are five new top-level nav sections of the platform that are all introduced behind a feature flag right now. And then there's some new functionality within existing pages that we've put behind feature flags. So it's not truly every line of code, but it's basically the entry point to all new major features we're putting behind a feature flag. STEPH: Okay, cool. I'm curious. How are you finding that in terms of does it feel manageable? Do you feel like anybody can go into the UI and then turn on feature flags for demos and feel confident that they know what they're turning on and off? CHRIS: We haven't gotten to that self-serve place. At this point, the dev team is managing the feature flags. So on production, we have an internal group configured within Flipper. So we can say, "Ship this feature for all internal users so that we can do testing." So there is a handful of us that all have accounts on production. And then on staging, we have a couple of representative users that we've been just turning everything on for so that we know via staging we can act as that user and then see the application with all of the bells and whistles. Down the road, I think we're going to get more intentional with it, particularly the idea of a demo account. That's something that we want to lean into. And for that user, we'll probably be turning on certain subsets of the feature flags. I think we'll get a little more granular in how we think about that. For now, we're not as detailed in it, but I think that is something that we want to expand as we move forward. STEPH: Nice. Yeah, I was curious because feature flags came up in our recent retro with the client team because we've gotten to a point where our feature flags feel complex enough that it's becoming challenging and not just from the complexity of the feature flags but also from the UI perspective. Where it feels challenging for users to understand how to turn a feature on, exactly what that impacts, and making sure that then they're not changing developer-focused feature flags, so those are the feature flags that we're using to ship a change but then not turn it on until we're ready. It is user-facing, but it's something that should be managed more by developers as to when we turn it on or off. So I was curious to hear that's going for you because that's something that we are looking into. And funnily enough, you asked me recently, "Why aren't y'all using Flipper?" And I didn't have a great answer for you. And that question came up again where we looked at each other, and we're like, okay, we know there was a really good reason we didn't use Flipper when we first had this discussion. But none of us can remember, or at least the people in that conversation couldn't remember. So now we're asking ourselves the question of we've made it this far. Is it time to bring in Flipper or another service? Because we're getting to the point that we're starting to build too much of our own feature flag system. CHRIS: So did you uncover an answer, or are you all just agreeing that the question makes sense? STEPH: Agreeing that the question makes sense. [laughs] CHRIS: That's the first step on a long journey to switching from internal tooling to somebody else managing that for you. STEPH: Yeah, because none of us could remember exactly. But it was funny because I was like, am I just forgetting something here when you asked me that? So I felt validated that others were like, "Oh yeah, I remember that conversation. But I too can't recall why we didn't want to use Flipper in the moment or a similar service." CHRIS: I'll definitely be interested to hear if you do end up trying to migrate off to another system or find a different approach there or if you do stick with the current configuration that you have. Because those projects they're the sort of sneaky ones that it's like, oh, we've been actually relying on this for a while. It's a core part of our infrastructure, and how we do the work, and the process, and how we deploy. That's a lot. And so, to switch that out in-flight becomes really difficult. It's one of those things where the longer it goes on, the harder it is to make that change. But at some point, you sometimes make the decision to make it. So I will be very interested to hear if you do make that decision and then, if so, what that changeover process looks like. STEPH: Yeah, totally. I'll be sure to keep you up to date as we make any progress or decisions around feature flags. CHRIS: But yeah, your questions around management and communication of it that is a thing that's in the back of my mind. We're still early enough in our usage of it, and just broadly, how we're working, we haven't really felt that pain yet, but I expect it's coming very soon. And in particular, we have functionality now that is merged and is part of the codebase but isn't fully deployed or fully released rather. That's probably the correct word. We have not fully released this functionality, and we don't have a system right now for tracking that. So I'm thinking right now we're using Trello for product management. I'm thinking we want another column that is not entirely done but is tracking the feature flags that are currently in flight and just use that as a place to gather communication. Do we feel like this is ready? Let's dial this up to 50%, or let's enable it for this beta group or whatever it is to sort of be able to communicate that. And then ideally, also as a way to track these are the ones that are active right now. You know what? We feel like this one's ready. So do the code change so that we no longer use the feature flag, and then we can actually turn it off. Currently, I feel like I can defer that for a little while, but it is something that's in the back of my mind. And then, of course, I nerd sniped myself, and I was like, all right, how do I grep the codebase for all the feature flags that we're using? Okay. There are a couple of different patterns as to how we're using…You know what? I think I actually need an AST-based parser here, and I need to use the Visitor...You know what? Never mind. Stop it. Stop it. [laughs] It was one of those where I was like...I was doing this not during actual work hours. It was just a question in my mind, and then I started to poke at it. I was like, oh, this could be fun. And then I was like, no, no, no, stop it. You need to go read a book or something. Calm down. STEPH: As part of the optimization around our feature flag system that we've created, we've added a few enhancements, which I think is also one of the reasons we're starting to question how far we want to go in this direction. One of them is we want a very easy way to track what's turned on and what's turned off for an environment. So we have a task that will easily check, or it prints out a really nice list of these are all your flags, and this is the state that they're in. And by using the system that we have, we have one file that represents...well, you mentioned migration because we're migrating from the old system to this new one. So it's still a little bit in that space of where we haven't fully moved over. So now, moving over to a third thing like Flipper will be even more interesting because of that. But the current system, we have a file that lists all the feature flags and a really nice description that goes with it, which I know is supported by Flipper and other services as well. But having that one file does make it nice where you can just scan through there and see what's in use. I really think it's the UI and the challenges that the users are facing and understanding what a feature flag does, and which ones they should turn off, and which ones they shouldn't touch that that's the point where we started questioning okay, we need to improve the UI. But to improve the UI, do we really want to fully embrace our current system and make those improvements, or is now that time that we should consider moving to something else? Because Flipper already has a really nice UI. I think there is a free tier and a paid tier with Flipper, and the paid tier has a UI that ships. CHRIS: There's definitely a distinct thing, Flipper Cloud, which is their hosted enterprise-y solution, and that's the paid offering. But Flipper just the core gem there's also Flipper web, I want to say is what it is, or Flipper UI. And I think it's an engine that you mount within your Rails app and that displays a UI so that you can manage things, add groups and teams. So we're definitely using that. I've got my eye on Flipper Cloud, but I have some fundamental questions around I like to keep my data in the system, and so this is an external other thing. And what's the synchronization? I haven't really even looked into it like that. But I love that Flipper exists within our application. One of the niceties that Flipper Cloud does have is an audit history, which I think is interesting just to understand over time who changed what for what reasons? It's got the ability to roll back and maintain versions and whatnot. So there are some things in it that definitely look very interesting to me. But for now, the open-source, free version of Flipper plus Flipper UI has been plenty for us. STEPH: That's cool. I didn't know about the audit feature. CHRIS: Yeah. It definitely feels like one of those niceties to have for a more enterprise offering. So I could see myself talking me into it at some point but not quite yet. On that note though, so feature flags we introduced a week and a half, something like that, ago, and we've been leaning into them more and more. But as part of that, or in the back of my mind, I've wanted to go to continuous deployment. So we had our first official retro this week. The project is growing up. We're becoming a lot of things. We used retro to talk about continuous deployment, all of these things that feel very real. Just to highlight it, retro is super important. And the fact that we haven't had one until now is mainly because up till now, it's been primarily myself and another developer. So we've been having essentially one-on-ones but not a more formal retro that involves others. At this point, we now have myself and two other developers that are working on the project, as well as someone who's stepped into the role of product manager. So we now have communication collaboration. How are we doing the work? How are we shipping features and communicating about bugs and all of that? So now felt like the right time to start having that more formal process. So now, every two weeks, we're going to have a retro, and hopefully, through that, retro will do the magic that retro can do at its best which is help us get better at all the things that we're doing. But yeah, one of the core things in this particular one was talking about moving to continuous deployment. And so I am super excited to get there because I think, much like test-driven development, it's one of those situations where continuous deployment puts a lot of pressure on the development process. Everything that is being merged needs to be ready to go out into production. And honestly, I love that as a constraint because that will change how you build things. It means that you need to be a little more cautious. You can put something behind a feature flag to protect it. You decouple the idea of merging and deploying from releasing. And I like that distinction. I think that's a really meaningful distinction because it makes you think about what's the entry point to this feature within the codebase? And it's, I think, actually really nice to have fewer and more intentional entry points into various bits of functionality such that if you actually want to shut it off in production, you can do that. That's more straightforward. I think it encourages an intentional coupling, maybe not a perfect decoupling but an intentional coupling within the system. So I'm very excited to explore it. I think feature flags are going to be critical for it, and I think also observability, and monitoring, and logging, and all those things. We need to get really good at them so that if anything does go wrong when we just merge and deploy, we want to know if anything goes wrong as quickly as possible. But overall, I'm super excited about all of the other niceties that fall out of it. STEPH: [singing] I wanna know what's turned on, and I want you to show me. Is that the song you're singing to Flipper? [laughs] CHRIS: [laughs] STEPH: Sorry, friends. I just had to go there. CHRIS: That was just in your head. You had that, and you needed to get it out. I appreciate it. [laughter] Again, I got Flipper UI, so that's not the question I'm asking. I think that's the question you have in your heart. STEPH: [laughs] Mid-roll Ad And now we're going to take a quick break to tell you about today's sponsor, Orbit. Orbit is mission control for community builders. Orbit offers data analytics, reporting, and insights across all the places your community exists in a single location. Orbit's origins are in the open-source and developer relations communities. And that continues today with an active open-source culture in an accessible and documented API. With thousands of communities currently relying on Orbit, they are rapidly growing their engineering team. The company is entirely remote-first with team members around the world. You can work from home, from an Orbit outpost in San Francisco or Paris, or find yourself a coworking spot in your city. The tech stack of the main orbit app is Ruby on Rails with JavaScript on the front end. If you're looking for your next role with an empathetic product-driven team that prides itself on work-life balance, professional development, and giving back to the larger community, then consider checking out the Orbit careers page for more information. Bonus points if working in a Ruby codebase with a Ruby-oriented team gives you a lot of joy. Find out more at orbit.love/weloveruby. STEPH: That's funny about the CI deployment adding pressure to the development process because you're absolutely right. But I see it as such a positive and improvement that I don't really think about the pressure that it's adding. And I just think, yes, this is awesome, and I want this to happen and if there are steps that we have to take in that direction. It dawned on me that what you said is very true, but I've just never really thought about it from that perspective about the pressure. Because I think the thing that does add more pressure for me is figuring out what can I deploy, or do I need to cherry-pick commits? What does that look like? And going through that whole cycle and stress is more stressful to me than figuring out how do we get to continuous deployments and making sure that everything is in a safe space to be deployed? CHRIS: That's the dream. I'm going to see if I can live it. I'll let you know how it goes. But yeah, that's a bit of what's up in my world. What else is going on in your world other than some lovely singing? STEPH: Oh, there's always lots of singing. It's been an interesting week. It's been a mix of some hiring work. Specifically, we are helping our client team build their development team. So we have been helping them implement a hiring process. And then also going through technical interviews and then going through different stages of that interview process. And that's been really nice. I haven't done that specifically for a client team where I helped them build a hiring pipeline from scratch and then also conduct those interviews. And one thing that stood out to me is that rotations are really important to me and specifically that we don't ask for volunteers. So as we were having candidates come through and then they were ready to schedule an interview, then we are reaching out to the rest of the development team and saying, "Hey, we have this person. They're going to be scheduled at this time. Who's available? Who's interested? I'm looking for volunteers." And that puts pressure on people, especially someone that may be more empathetic to feel the need to volunteer. So then you can end up having more people volunteer than others. So we've established a rotation to make sure that doesn't happen, and people are assigned as it becomes their next turn to conduct an interview. So that's been a lot of fun to refine that process and essentially make it easier. So the rest of the development team doesn't have to think about the hiring. But it still has an easy way of just saying, "Hey," and tapping someone to say, "Hey, it's your turn to run an interview." The other thing I've been working out is figuring out how to measure an experiment. So we at thoughtbot are running an experiment where we're looking to address some of the concerns around sustainability and people feeling burned out. And so we have introduced half-day Fridays, more specifically 3.5 Fridays, as our half-day Fridays just to help everybody be certain about what a half-day looks like. And then also, you can choose your half-day. Everybody works different schedules. We're across different time zones, so just to make sure it's really clear for folks and that they understand that they don't need to work more than those hours, and then they should have that additional downtime. And that's been amazing. This is the second Friday of the experiment, and we're doing this for nine Fridays straight. And one of the questions that came up was, well, how do we know we did a good thing? How do we know that we helped people in terms of sustainability or addressing some of the feelings that they're having around burnout? And so I've collaborated with a couple of other thoughtboters to think through of a way to measure it. It turns out helping someone measure their wellness is incredibly complex. And so we went for a fairly simple approach where we're using an anonymous survey with a number of questions. And those questions aren't really meant to stand up to scientific scrutiny but more to figure out how the team is feeling at the time that they fill out the survey and then also to understand how the reduced weekly hours have impacted their schedule. And are people working extra hours to then accommodate the fact that we now have these half Fridays? So do you feel pressured that because you can't work a full day on Friday that you are now working an extra hour or two Monday through Thursday to accommodate that time off? So that survey just went out today. And one of the really interesting parts (I just haven't had to create content for a survey in a while.) was making sure that I'm not introducing leading questions or phrasing things in a very positive or negative light since that is a bias that then people will pick up on. So instead of saying, "I find it easy to focus at work," and then having like a multiple choice of true, always, never, that kind of thing, instead rephrasing the question to be, "Are you able to focus during work hours?" And then you have a scale there. Or instead of asking someone how much energy they have, maybe it's something like, "Do you experience fatigue during the day?" Or instead of asking someone, "Are you stressed at work?" because that can have a more negative connotation. It may lead someone to feel more negatively as they are assessing that question. Then you can say, "How do you feel when you're at work?" And then you can provide those answers of I'm stressed, slightly stressed, neutral, slightly relaxed, and relaxed. So it generated some interesting conversations around the importance of how we phrase questions and how we collect feedback. And I really enjoyed that process, and I'm really looking forward to seeing what folks have to say. And we're going to have three surveys total. So we have one that's early on in the experiment since we're only two Fridays in. We'll have one middle experiment survey go out, and then we'll have one at the end once we're done. And then hopefully, everybody's responses will then help us understand how the experiment went and then make a decision going forward. I'll be honest; I'm really hoping that this becomes a trend and something that we stick with. It is a professional goal of mine to slowly reduce the hours that I work each week or quickly; it doesn't have to be slowly. But I really like the four-day workweek. It's something that I haven't done, but I've been reading about it a fair amount lately. I feel like I've been seeing more studies conducted recently becoming published, and it's just very interesting to me. I had some similar concerns of how am I still going to be productive? My to-do list hasn't changed, but my hours are changing. So how am I still going to get everything done? And does it make sense for me to still get paid the same amount of money if I'm only working four out of the five days? And I had lots of questions around that, and the studies have been very enlightening and very positive in the outcome of a reduced workweek, not just for the individuals but for the companies as well. CHRIS: It's such an interesting space and exploration. The way that you're framing the survey sounds really great. It sounds like you're trying to be really intentional around the questions that you're asking and not being leading and whatnot. That said, it is one of the historically hard problems trying to quantify this and trying to actually boil it down. And there are so many different axes even that you're measuring on. Is it just increased employee happiness? Is it retention that you're talking about? Is it overall revenue? There are so many different things, and it's very tricky. I'm super interested to hear the results when you get those. So you're doing what sounds like more of a qualitative study like, how are you feeling? As opposed to a more quantitative sort of thing, is that right? STEPH: Yes, it's more in the realm of how are you feeling? And are you working extra hours, or are you truly taking the time off? CHRIS: Yeah, I think it's really hard to take something like this and try and get it into the quantitative space, even though like, oh yeah, if we could have a number, if it used to be two and now it's four, fantastic. We've doubled whatever that measure is. I don't know what the unit would be on this arbitrary number I made up. But again, that's the hard thing and probably not feasible at all. And so it makes sense the approach that you're taking. But it's super difficult. So I'm very interested to hear how that goes. More generally, the four-day workweek thing is such a nice idea. We should do that more. I'm trying to think how long I did that. So during the period that I was working freelance, I think there were probably at least five months where I did just a true four-day workweek. Fridays were my own. It was fantastic. Granted, I recorded the podcast with you. But that day was mine to shape as I wanted. And I found it was a really nice decompression period having that for a number of weeks in a row. And just getting to take care of personal stuff that I hadn't been and just having that extra little bit of space and time. And it really was wonderful. Now I'm working full five days a week, and my Fridays aren't even investment days, so I don't know what I'm doing over here. But I agree. I really like that idea, and I think it's a wonderful thing. And it's, I don't know, sort of the promise of this whole capitalism adventure we're supposed to go on, increasing productivity. And wasn't this the promise the whole time, everybody, so I am intrigued to see it being explored more, to see it being discussed. And what you're talking about of it's not just good for the employees, but it's also great for the companies. You're getting people that are more engaged on the days that they're working, which feels very true to me. Like, on a great day, I can do some amazing work. On a terrible day, I can do mediocre to bad work. It is totally possible for me to do something that is actively detrimental. Like, I introduce a bug that is going to impact a bunch of customers. And the remediation of that is going to take many more hours. That is totally a realistic thing. I think we often think of productivity in terms of are you at zero or some amount more than zero? But there is definitely another side of that. And so the cost of being not at your best is extremely high in my mind. And so anything we can do to improve that. STEPH: There's a recent study from a non-profit company called Autonomy that published some research called Going Public: Iceland's Journey to a Shorter Working Week. It's very interesting. And a number of people in my social circle have shared it. And that's one of the reasons that I came across it. And they commented in there that one of the reasons...I hope I'm getting this right, but we'll link to it in case I've gotten it a bit wrong. But one of the reasons that Iceland was interested or open to this idea of moving workers to a shorter workweek is because they were struggling with productivity and where people were working a lot of hours, but it still felt like their productivity was dropping. So then Autonomy ran this study to help figure out are there ways to improve productivity? Will shortening a workweek actually lead to higher productivity? And there was a statement in there that I really liked where it talks about the more hours that we work; we're actually lowering our per hour productivity which rings so true for me. Because I am one of those individuals where I'm very stubborn, and so if I'm stuck on something, I will put so many hours into trying to figure it out. But at some point, I have to just walk away, and if I do, I will solve it that much faster. But if I just try to use hours as my way to chip away at a problem, then that's not going to solve it. And my ability to solve that problem takes exponentially more time than if I had just walked away and then come back to the problem fresh and engaged. And some of the case studies I admired the way that they tackled the problem. They would essentially pay the company. So the company could reduce the hours for certain employees so then they could run the experiment. So if they reduced employees to say 32 hours but the company didn't actually want to stop working at 32 hours and they wanted to keep going, so then they brought in other people to work the remaining eight hours. Then as part of that study, they would pay the company to help them stay at their current level of productivity or current level of hours. This way, they could conduct the study. And I thought that was a really neat idea. I do have lots of questions still around the approach itself because it is how do you reduce your to-do list, essentially? So just because you dropped to a four-day workweek. So essentially, you have to just say less stuff gets done. Or, as these case studies promise, they're saying you're actually going to be more productive. So you will still continue to get a lot of your work done. I'm curious about that. I'd like to track my own productivity and see if I feel similarly. And then also, who is this for? Is this for everybody? Does everybody get to move to a four-day workweek? Is this for certain companies? Is it for certain jobs? Ideally, this is for everybody because there are so many health benefits to this, but I'm just intrigued as to who this is for, who it impacts, how can we make it available for everyone? And is the dream real that I can work four days a week and still feel as productive, if not more productive, and healthier, and happier as I do when working five days a week? Mid-roll Ad And now a quick break to hear from today's sponsor, Scout APM. Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more. Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform. See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed. CHRIS: I remember there was an extended period where working remote was this unique benefit that some organizations had. They had adopted that mode. They were async, and remote, and all of these wonderful things. And it became this really interesting selling point for those companies. Now the pandemic obviously pushed public opinion and everything on that in a pretty significant way such that it's a much more common thing. And so, as a result, I think it's less of a differentiator now. It used to be a way to help with recruiting. I wonder if there are organizations that are willing to take this, try it out, see that they are still close to as productive. But if it means that hiring is twice as easy, that is absolutely...especially if it is able to double your ability to hire, that is incredibly valuable or retention similarly. If you can increase retention or if you can make it easier to hire, the value of that is so, so high. And it's interesting in my mind because there's sort of a gold rush on that. That's only true for as long as a four-day workweek is a unique benefit of working at the organization. If this is actually the direction that everything's going and eventually everyone's going to settle to that, then if you wait too long to get there, then you're going to miss all the benefits. You're going to miss that particular benefit of it. And so I do wonder, would it be advantageous to organizations...I'm thinking about this now. Maybe this is the thing I have to do. But would it be advantageous to be that organization as early on as possible and try to get ahead of the curve and use that to hire more easily, retain more easily? Now that I say it all out loud, I'm sold. All right. I got to do this. STEPH: Yeah, I think that's a great comparison of where people are going to start to look for those types of benefits. And so, if you are one of the early adopters and you have the four-day workweek or a reduced workweek in general, then people will gravitate towards that benefit. And it's something that people can use to really help with hiring and retention. And yeah, I love it. You are CTO. So you have influence within your company that you could push for the four-day workweek if you think that's what you want to do. And I would be really intrigued to hear how that goes and how you feel if you...well, you've done it before where you've worked four days a week. So applying that to your current situation, how does that feel? CHRIS: Now you're actually holding me accountable to the things that I randomly said in passing. But it's interesting. So we're so early stage, and there's so much small work to do. There's all…oh, got to set up a website. We've got to do this. We've got to build that integration. There's just kind of scrambling to be done. And so there's a certain version in my mind that maybe we're in a period of time where additional hours are actually useful. There's a cost to them. Let's be clear about that. And so how long that will remain true, I'm not sure. I could see a point perhaps down the road where we achieve a little bit closer to steady-state maybe, who knows? It depends on how fast growth is and et cetera, a lot of other things. So I'm not sure that I would actually lead with this experiment myself, given where the organization is at right now. But I could see an organization that's at a little bit more of a steady-state, that's growing more incrementally, that is trying to think really hard about things like hiring and retention. If those were bigger questions in my mind, then I think I would be considering this more pointedly. But for now, I'm like, I kind of just got to do a bunch of stuff. And so my brain is telling me a different story, but it is interesting. I want to interrogate that and be like, brain, why is that the story you have there, huh? Huh? STEPH: I really appreciate what you're saying, though, because that makes sense to me. I understand when you are in that earlier stage, there's enough to do that that feels correct. Versus that added benefit of having a reduced workweek does benefit or could benefit larger companies who are looking to hire more heavily, or they're also concerned about retention or just helping their people address feelings of burnout. So I really appreciate that perspective because that also rings true. So along this whole conversation around wellness and how we can help people work more sustainable hours, there's a particular book that I've read that I've been really excited to share and chat with you about. It's called Burnout: The Secret to Unlocking the Stress Cycle. It's written by two sisters, Emily and Amelia Nagoski. And they really talk through the impact that stress has on us and then ways to work through that. And specifically, they talk about completing the stress cycle. And I found this incredibly useful for me because I have had weeks where I have just worked hard Monday through Friday. I've gotten to the end of my day Friday, and I'm like, great, I'm done. I've made it. I can just relax. And I walk away from work, and I can't relax. And I'm just like, I feel sick. I feel not good. Like, I thought I would walk away from work, and I would just suddenly feel this halo of relaxation, and everything would be wonderful. But instead, I just feel a bit ill, and I've never understood that until I was reading their book about completing the stress cycle. Have you ever had moments like that? CHRIS: It has definitely happened to me at various points, yes. STEPH: That makes me feel better because I haven't really chatted about this with someone. So until I read this book and I was like, oh, maybe this is a thing, and it's not just me, and this is something that people are experiencing. So to speak more about completing the stress cycle, they really highlight that stress and feelings, capital F feelings, can cause physiological symptoms. And so it's not just something that we are mentally processing, but we are physically processing the stress that we feel. And there's a really big difference between stressors and stress. So a stressor could be something like an unmeetable deadline. It could be family. It could be money concerns. It could be your morning commute, anything that increases your stress level. And during that, there's a very physical process that happens to your body anytime there's a perceived threat. And it's really helpful to us because it's frankly what triggers our fight, flight, or freeze response. And our bodies receive a rush of adrenaline and cortisol, which essentially, if we're using that flight response, that's going to help us run. And a number of the processes in our system will essentially go into a state of hibernation because everything in our body is very focused on helping us run or do the thing that we think is going to save our life in that moment. The problem is our body doesn't know the difference between what's more of a mental threat versus what is a truly physical threat. So this is the difference between your stress and your stressors. So in more of a physical threat, if there's a lion that you are running from, that is the stressor, but then the stress is everything that you still feel after you have run from that lion. So you encounter a lion, you run. You make it back to your group of people where you are safe, and you celebrate, and you dance, and you hug. And that is completing the stress cycle because you are essentially processing all of that stress. And you are telling your body in a body-focused language that I am safe now, and everything is fine. So you can move back, and anything that was in a hibernation state, all of that dump of adrenaline and cortisol can be worked out of your system, and everything can go back to a normal state. Most of us aren't encountering lions, but we do encounter jerks in meetings or really stressful commutes. And whenever we have survived that meeting, or we've gotten through our commute to the other side, we don't have that moment of celebration where we really let our body know that hey, we've made it through that moment of stress, and we are away from that stressor, and we can actually process everything. So if you're interested in this, the book's really great. It talks about ways that you can process that stress and how important it is to do so. Otherwise, it will literally build up in your system, and it can make you sick. And it will manifest in ways that will let us know that we haven't dealt with that stress. And one of the top methods that they recommend is exercise and movement. That's a really great way to let your body know that you are no longer in an unsafe state, and your body can start to relax. There's also a lot of other great ways. Art is a really big one. It could be hugging someone. It could be calling someone that you love. There are a number of ways that you can process it. But I hadn't recognized how important it is that once you have removed yourself from a stressor, that doesn't necessarily just mean you're done, and you can relax. You actually have to go through that physical process, and then you can relax. So I started incorporating that more into my day that when I'm done with work, I always find something to do, and it's typically to go for a walk, or it's go for a run. And I have found that now I really haven't felt that ill-feeling where I'm trying to relax, but I just feel sick. Saying that out loud, I feel like I'm a mess on Fridays. [chuckles] CHRIS: I feel like you're human. It was interesting when you asked the question at the beginning. You were like, "Is this a thing that other people experience?" And my answer was certainly, yes; I have experienced this. I think there's something about me that I think is useful where I don't think I'm special at all on any axis whatsoever. And so whenever there's something that's going on, I'm like, I assume that this is just normal human behavior, which is useful because most of the time it is. And this is the sort of thing where if I'm having a negative experience, I will look to the external world to be like, I'm sure other people have experienced this, and let me pull that in. And I've found that really useful for myself to just be like, I'm not special. There's nothing particularly special about me. So let me go look from the entirety of the internet where people have almost certainly talked about this. And I've not read the book that you're describing here, but it does sound like it does a great job of describing this. There is a blog post that I found that has stayed in the back of my mind and informed a little bit of my day-to-day approach to this sort of thing which is a blog post by Cal Newport, who I think at this point we've mentioned him a handful of times on the show. But the title of the post is Drastically Reduce Stress with a Work Shutdown Ritual. And it's this very interesting little post where he talks about at the end of your day; you want to close the book on it. I think this is especially pointed now that many of us are working from home. For me, this is a new thing. And so, I've been very intentional with trying to put walks at the beginning and end of my day. But in this particular blog post, he describes a routine that he does where he tidies things up and makes his list for the next day. And then he has a particular phrase that he says, which is "schedule shut down, complete." And it's a sort of nonsense phrase. It doesn't even quite make sense grammatically, but it's his phrase that he internalized, and somehow this became his almost mantra for the end of the day. And now when he does it, that's like his all right, okay, turned off the brain, and now I can walk away. I know that I've said the phrase, and I only say the phrase when I have properly set things up. And so it's this weird structure that he's built in his mind. But it totally works to quiet those voices that are like, yeah, but what about…Do we think about…Do we complete…And he's got now this magic phrase that he can say. And so I've really loved that. For myself, I haven't gotten quite to that level, but I've definitely built the here's how I wind down at the end of the day. Here's what I do with lists and what I do so that I can ideally walk away comfortably. Again, this is one of those situations where I sound like I know what I'm doing or have my act together. This is aspirational me. Day-to-day me is a hot mess like everybody else. [laughs] And this is just what I...when I do this, I feel better. Most of the time, I don't do this because I forget it, or because I'm busy, or because I'm stressed, [chuckles], and so I don't do the thing that reduces stress, you know, human stuff. But I really enjoyed that post. STEPH: I haven't heard that one. I like a lot of Cal Newport's work, but I haven't read that particular blog post. Yeah, I think the idea of completing the stress cycle has helped me tremendously because by giving it a name like completing the stress cycle has been really helpful for me because working out is important to me. It's something that I enjoy, but it's also one of those things that's easy to get bumped. It is part of my wellness routine. And so, if I'm really busy, then I will bump it from the list. And then it's something that then doesn't get addressed. But recognizing that this is also important to my productivity, not to just this general idea of wellness, has really helped me recenter how important this is and to make sure that I recognize hey, it's been a stressful day. I need to get up and move. That is a very important part of my day. It is not just part of an exercise routine, but this is something that I need to do to close out my day to then make sure I have a great day tomorrow. So bringing it back, it's been a week that's been filled with a lot of discussions around burnout and then ways that we can measure it and then also address it. And I've really enjoyed reading this book. So I'll be sure to drop a link in the show notes. On that note, shall we wrap up? CHRIS: Schedule shut down, complete. The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes, as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Byeeeeeeeeeee!!! Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.

    309: Naming the Change

    Play Episode Listen Later Sep 21, 2021 35:28

    Steph talks about a new GitHub feature and Twitter account (@RubyCards (https://twitter.com/RubyCards)) she's really excited about and Chris talks about his new job as a CTO of a startup and shifting away from writing code regularly. GitHub (https://docs.github.com/en/codespaces/developing-in-codespaces/web-based-editor) RubyCards (https://twitter.com/RubyCards) Resilient Management (https://resilient-management.com/) The Manager's Path (https://www.amazon.com/Managers-Path-Leaders-Navigating-Growth/dp/1491973897) Transcript: CHRIS: Oh God, my computer is so stupid slow. I need a new computer. STEPH: Come on, little computer, you can do it. You know you could just buy a new one. You don't have to wait for the fancy-schmancy M1. CHRIS: I want to wait for the fancy. I want it so bad. STEPH: [laughs] CHRIS: Do you know how long I've had this computer? And if I can hold out one more month, I want the fancy stuff. I've waited this long. Why would I give in now when I'm right on the cusp of victory? STEPH: One more month. I'm going to send you...as a kid, did you ever make those construction… CHRIS: Oh yeah. STEPH: They look like chain links bow construction paper. So we would make those for a countdown to special days. I'm going to send you one that's all crumpled and folded in the mail. It would be delightful. And you'll be able to snip off a little chain each day as your countdown to your new fancy-schmancy. [laughs] CHRIS: I love it. Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey. STEPH: And I'm Steph Viccari. CHRIS: And together, we're here to share a bit of what we've learned along the way. So, Steph, what's new in your world? STEPH: Hey. Well, I just got back from vacation. So getting back to work is what's new in my world. And vacation is nice. I miss it already. But it's also nice to be back, and see everybody, and see what they've been up to. CHRIS: I've heard wonderful things about vacation. STEPH: Yeah. Have you had one recently? I know you've been quite busy. CHRIS: I have. I think it's hard to tell, especially because everything just kind of blends together these days. But I think I took off a few days recently. I haven't had an extended vacation since much earlier on in the summer, I think. And so I think I'm due for one of those sometime in the not too distant future. But it's one of those things where you got to plan it. And you got to think ahead, and I haven't been doing that of late really with anything. So kind of living for the moment, but that's not how you take a vacation. So I got to rethink some strategies here. [chuckles] STEPH: Yeah, I've been trying to schedule more vacation time just further out. Because then if I don't want to take it, like if I decide that I don't want the staycation or I don't need the day off, then I can just change my mind, and that's pretty easy to do. But I'm like you; if I don't plan it, then I don't feel like I have the energy to plan a vacation, and then it just doesn't happen. So I know that's one thing that I've been doing. I've also been mentoring or coaching others, just checking in with them to say, "Hey, when's your next vacation? Have you scheduled any days off? Do you want to schedule a day off next month?" And saying that to other people has also been a very helpful reminder to me to do so. CHRIS: Oh, I like that a lot as a recurring one-on-one question of, so what can you tell me about vacation? What do you got in the works there? Because that's the most important thing, [chuckles] which it kind of is. It's the way that we keep doing the work that we do. STEPH: And I think so many people just haven't been taking a vacation. I mean, in 2020, we were all locked in and going through a pandemic, so then a lot of people weren't taking those breaks. And so part of it is just reminding people that even if you can't go somewhere, still please take some downtime and just know that you can step away from work and should step away from work. But for us, we did go somewhere. So we went out to Seattle, which I've never...I've been out to the West Coast, but it's more like I've been out to L.A., Santa Monica. But this time, we went to the Northwest region. We went to Seattle, and we explored and did a lot of hiking and camping around the Northern Cascades and then Mount Rainier. And both of those are amazing. And I've never flown with camping gear, but that went really well. It worked out nice. We had an Airbnb every so often just for showers and having a roof over your head. That's really nice. But for most of the trip, we did a lot of camping and hiking. CHRIS: That sounds like an awesome trip. STEPH: Yeah, it was really cool. I'd love to go back to the Olympic National Park because there are just so many national parks that are around Seattle and in Washington that we couldn't begin to do it all. But Olympic National Park is still on my list. And I'm really grateful to have also seen the Northern Cascades and Mount Rainier. But switching gears a bit, I have something that I'm really excited to share with you because I don't think you've seen it yet. I'm excited to find out if you have. But it's a new GitHub feature that came out, I think about a month ago, but there doesn't seem to have been much fanfare from GitHub about announcing this new feature. And I happened to find out through Twitter because someone else found it, and then they were really excited. And so now I think it's really gaining some more traction. But it still seems like one of those sneaky feature releases, but it's really cool. So GitHub has added the ability to open up a web-based editor that allows you to view the source code for a repo, view it in syntax, highlighting, make a code change, and commit the change. And it's free for everybody. And there's a couple of ways to get there, but I'll pause there. Have you seen this yet? Have you interacted with it? CHRIS: I think I've seen it and poked around ever so gently with it. I want to say this is GitHub Codespaces. Is that the name of this feature? STEPH: Yep. That's it? CHRIS: Yes. I poked around with it just a tiny bit, and I'm very excited about it. But it's very much in the like, huh, okay, cool; I'll look at that someday down the road and figure out what I want to do with it. But have you actually dug into it particularly deeply? STEPH: I used it to make a change for a personal project, just because I wanted to see the whole flow. So I went to a personal project, and there are two ways that you can open it up for anyone that hasn't seen this yet. So you can either press the period button that's on your keyboard, and that will open it up, or you can just alter the URL. So instead of github.com, replace that .com with .dev, and then that will also open up the browser. And so I made a change to a personal project, and it worked really well, and it commits the change to main. And it was nice. It was easy. In my case, I was just making a change to make a change. I think I actually went to an older project where I was still using the underscore target to force users that when they clicked on a link that it opened a new tab, and I was like, perfect. This is a good thing to just change. And I could do it from my iPad. I didn't have to be at my computer. And it was really nifty. I was very impressed with it. And they also mentioned that it's very easy to integrate your own VS Code settings and environment. I'm not a heavy VS Code user, so I haven't tried that. But I've heard really positive things about how easy it is to sync your settings between your local VS Code and then GitHub's editor. But overall, it was really easy to use. CHRIS: That's super cool. My very limited understanding of it is like GitHub has had the ability to edit files and things like that for a while. But it was very much like a simple web editor where it's a big text box that happens to contain the code. And they've added some stuff for like browsing with syntax highlighting and even some context-aware show usage and things like that. But as far as I understand it, this is like a whole VS Code instance in the cloud that is running it. And then I think what you're saying about you can have your VS Code settings in there, but even your project settings and the ability to run the tests, I'm not sure where the edges of it are. But my understanding with Codespaces it's like this is how your team can develop. Everyone gets one of these Codespaces. You're developing in the cloud. But it does VS Code remote sync type stuff. I'm very intrigued to see where it goes and that idea of...obviously, I like Vim. That's the thing that's probably known and true about me. So I will probably be one of the later adopters of this. But the idea of being able to bottle up the development environment for your projects and have those settings, and the ability to run the test and all of that packaged up as part of the repository, and then allow people to run with that, especially in the cloud, and be able to carry that with them as they move around, that's really intriguing. And the idea of having this very easy on-ramp, especially for open-source projects and things like that. If you want people to be able to contribute easily but with the linting, and the configuration, and the settings, and all the stuff, well, now you can have that packaged up. And that is very interesting to me. So I'm super intrigued to see where it goes. Again, I will probably be one of the later adopters of this platform for reasons. But I am super interested, and I continue to like...the work with VS Code is so interesting in the way it keeps expanding out and the language server stuff and now the Codespaces stuff. And it's super interesting developments across the board. STEPH: Yeah, I'm with you. I don't actually see this replacing my current development that I do day-to-day, but it's more generally nice to have access. So if I needed to make a change and I don't have my laptop or if it's just something small and I don't want to have to go through…I guess essentially, if I don't have my laptop, but I wanted to make a change, then I could do this realistically from something that doesn't have my full local dev setup. I don't know if you have the ability to run tests. I didn't explore that far as to whether you can actually have access to run those types of commands or processes. I did see some additional notes while reading through GitHub's documentation about this new editor. And they included some notes that talk about how the editor runs entirely in your browser's sandbox. So it doesn't actually clone the repo, but instead, it loads your code by invoking the services API directly from the browser. So then your work is saved in the browser's local storage until you commit it, and then you can persist your changes by then committing it back to the repo. And because there's no associated compute, you won't be able to build and run your code or use the integrated terminal. Ah, I think that actually answers the question about running tests. So only a subset of extensions can run in the web will appear in the extensions panel and can be installed. So this does impose certain limitations for particular programming languages and full functionality, things that we may need like running tests. CHRIS: Interesting. That now puts it back more on the uncanny valley for me where it's like, oh, it's just VS Code, except it can't do a bunch of the stuff. So yeah, I'll probably be hanging out in Vim for a while. But again, I'm super interested to see where they can push this and what the browser platform allows, and then how they're able to leverage that and so on and so forth. STEPH: There is one flow that I was testing out because I was reading someone else mentioned that not only can you use this for looking at source code and then changing that source code but also for a pull request. And so I went to a pull request and changed the URL to dev. And I do have the ability to make changes, but I'm not quite sure if I could commit my changes and if that would go to the branch or how that would work. It wasn't obvious to me how I could save my changes. But it was obvious to me that I could make changes. [laughs] So that part feels weird to me, and I will have to test that out. But I'm going to wait until I have my own PR before I start fooling around [laughs] so I don't ruin somebody else's PR. CHRIS: Ideally, the worst case is you just push commit to a branch, and commits are reversible. You can throw them away. You can reset, and you can do all sorts of stuff. But I agree with you that maybe I'll do this on my home turf first before I start messing around with somebody's PR. STEPH: That way, someone doesn't reach out to me and say, "Steph, what is this commit that I have on my PR?" And I'm like, "Oh, I'm just testing." [laughs] But that's something that I was excited to talk about and share with you. What's new in your world? CHRIS: Well, what's new in my world? I think we've talked about this a little bit, but to give a little bit of context on what's new in my world, I joined a startup. I am now engineer number one. I'm also CTO, a very fancy title, but again, I'm the team of one, so count it as you will. But we do have some consultants working with us. So there is a small team that I am managing, and very quickly, I found myself shifting away from the code or having to balance that trade-off of maker versus manager time. Like, how much of the time am I actually coding and shipping features versus managing and communicating, and trying to figure out the work to be done and triaging the backlog? And all of those sorts of things. I've also just been coding less, and I think that's a trend that will almost certainly continue, and I'm intrigued by that. And that's a thing that I want to poke at just a little bit. And then I've also noticed that my work has become much more reactive than it used to be, where there are lots of things in Slack. And there's stuff that I'm kind of the only person that can do certain things because I have certain access levels and yadda yadda. And I want to make sure other folks aren't blocked. So I'm trying to be as responsive as possible in those moments. But I'm also struggling with that that trade-off between reactive versus proactive. My ideal version I think of the work is gather all of the information, all of the different permutations, and what are all the features we want? And then I think about them holistically, and then I respond once solidly as opposed to little one-off interactions and things like that. So there are just a lot of subtle differences. And I think there are trends that will continue. And so I'm trying to just take a step back, observe them from a distance and say, "How do I feel about these?" But probably most interesting to me is the moving away from code. Have you noticed that at all in your work? Or is that something you've thought about, something you'd be interested in, opposed to? How do you feel about that space in the coding world? STEPH: That is a wonderful question. It's one that I have wrestled with for a while because I really love my current position. I love being a team lead because I feel like there's this wonderful balance between where I get to code a lot of the time, but then I also get to learn how to be a manager, and help those around me, and provide some coaching or mentoring or just help people find the resources that they need essentially. And I really like that balance. That feels like the right balance to me, where I still get to grow in both areas. But then, as you'd mentioned, it still feels like one tries to take over the other with time. Like you find that more responsibilities are growing as CTO of the company. And so you feel more responsible to do more of the managerial task or unblocking others and taking on that role, and then that reduces your time for coding. And I often find myself in that space where I think it's just how I'm wired. I'm very interested and empathetic towards how people are doing and how they're feeling. So I'm always looking for ways to support others and to help unblock them and make sure that they're having a very positive experience with our project. And so then that may mean I'm coding less because then I'm more focused on that. But then, it's still also a very valid part of my job to code. So finding the right balance between those is frankly hard. To answer your other question, I don't think I want to give that up. I've considered for myself if I'm going to head towards more of a manager path, and I'm going to reserve the right to change my mind. But currently, I still like maintaining most of my individual contributor status with a dash of management sprinkled in there and then some responsibilities for making sure that the team is doing well and that people are enjoying their work. Along that line, as I've been having conversations with others around, tell me more about your job as a manager, and what does that look like? What responsibilities do you have? How much coding do you still get to do? There have been a couple of books that have been recommended to me that really help someone define are you interested in management? Is that a place that you see yourself going? This is really an honest look at what it means to be a manager. The fact that a lot of your fulfilling work isn't necessarily work that you get to produce, but it's actually helping someone else produce that work and then getting to see them succeed. That is your new fulfillment or a big part of it. So you are losing that closeness of being a maker,, but instead, you are empowering someone else to be the maker, and then that becomes your win. And that becomes an indication of your success. Versus as an individual contributor, it's really easy to see our wins in a different light: how many tickets have we addressed? How many PRs have we reviewed? That type of work. So there is an interesting dichotomy there, and I can't remember the books off the top of my head, but I will find them and I'll add a link to them in the show notes. CHRIS: Yeah, definitely interested to see the book recommendations. And generally, yeah, everything you're saying makes sense to me. I think I'm somewhat on the adventure right now. I very much intentionally chose this, and I want to lean into it and explore this facet of the work and doing more of the management and leading a team. But I have to accept that that comes with letting go of some of the individual contributor parts. And I was coding a bit over the weekend. I was just rediscovering the flow of that. And I was like, oh yeah, I really like this. Huh, that's interesting. What am I going to do with that? But I think, again, it's an exploration. And there are facets of both sides that I really like. And I've spent a lot of time deeper in the individual contributor side. And I've explored the manager side somewhat but not quite as much. And so this is very much about that I want to push on those edges and try and find what feels true to me. So the moving away from code and then moving more into management, I think I like that overall. Although I know there's the small amount in the back of my head that I'm like, I know there's a cost there. That is a trade-off. And so do I find more time in my evenings and weekends to do personal coding projects and things like that just to have that enjoyable work for myself? The maker versus manager stuff is interesting, though, where my day is now split up into smaller pieces. And even if I'm not coding, there's still writing up docs, or there are things that still require structured blocks of time. And my day is now just sprinkled with other things. And so trying to find that heads down of I want to just do the work right now, and I want to think hard about something is just fundamentally harder to do with more meetings and things speckled throughout the day. So that's one that I think I just don't like overall. But it's sort of a trade-off inherent to the situation. So I think there's also a version of trying to be intentional about that and saying, you know what? I need some heads-down time. And so Tuesday and Thursday afternoons those are going to be mine. I'm going to wall those off on my calendar and try and protect that time so that whatever necessary heads-down work that I need to do this week fits into those blocks of time and then fit the rest of things around that. But I think I have to make that intentional choice to do that. Mid-roll Ad And now we're going to take a quick break to tell you about today's sponsor, Orbit. Orbit is mission control for community builders. Orbit offers data analytics, reporting, and insights across all the places your community exists in a single location. Orbit's origins are in the open-source and developer relations communities. And that continues today with an active open-source culture in an accessible and documented API. With thousands of communities currently relying on Orbit, they are rapidly growing their engineering team. The company is entirely remote-first with team members around the world. You can work from home, from an Orbit outpost in San Francisco or Paris, or find yourself a coworking spot in your city. The tech stack of the main orbit app is Ruby on Rails with JavaScript on the front end. If you're looking for your next role with an empathetic product-driven team that prides itself on work-life balance, professional development, and giving back to the larger community, then consider checking out the Orbit careers page for more information. Bonus points if working in a Ruby codebase with a Ruby-oriented team gives you a lot of joy. Find out more at orbit.love/weloveruby. STEPH: Your mention of having more meetings really resonates with me. And it also made me think of a recent episode of a new TV show I just started watching. Have you seen the TV show called Schmigadoon!? CHRIS: I have indeed. STEPH: Okay. We need to have a whole conversation about Schmigadoon! in an upcoming episode. I'm very excited about this show. It's delightful. [laughs] There's a particular line that Keegan-Michael Key says that I just love so much where he says that he became a surgeon because he wanted to help people without talking to people. And I was like, oh, that's a developer. [laughs] I'm the same way. And I really enjoyed that. Although I do like talking to people but still, it just made me think about when you're talking about more meetings and then increasing the amount of talking that needs to be done as you progress into more of a management role. Also, circling back, I really like what you said earlier about you're noticing the changes that are happening. You're letting those changes happen, and then you're reflecting on how you feel about it. I really like that approach. Do you think that's working well for you? Does it feel too loose because then you don't feel in control enough of those changes? Or do you actually feel like that's a really good way to explore a new role and then find out if you like those changes? CHRIS: Now that you are restating it back to me, I'm like, oh yeah, I guess that is a good way to do things. But to clarify, I'm not doing nothing with it. I am trying to proactively, where I can, structure my days and do things like that or recognize that right now, I'm probably not the right person to be moving code along. And so I'm saying okay, that is true. And I'm actively choosing to not pick up the bigger pieces of work or to pair with someone else so that they can then run with it but not having me being the person that owns it. So it's not completely letting it happen, but it is almost like meditation to invoke that idea of I'm observing that I'm having these thoughts, and I'm just going to let them go. And it's more about the thinking and the response to it. So I'm trying to name the thing and be like, oh, this is interesting that this is happening. And I'm noticing an immediate visceral reaction to it where it's like, you're taking away my coding? And I'm like, well, hey, it's not them, it's you; you chose to do this. But let's just spend a minute there. That's okay. How do we feel about this? And so it's trying to not have it be a purely reactive response to it but have it be a more intentional, more thoughtful, and more observing, and then giving it a little bit of time to ruminate and then see a little bit more what I think. And also, some of it is purposefully pushing myself out of my comfort zone. I think I'm happy, and I do a reasonable job when I'm the person moving the code along. But I also have really enjoyed being at the edge of an engineering team and working with sales or working with other groups and facilitating the work that's happening. And so, if I explore that a little bit more, what's that going to look like for me? So this period of my career, I'm very intentionally trying to do stuff that I'm like, well, this is a little bit different for me, or this is stretching a little bit, but that is the goal. And I hope good things will come out of it across the board. But it may be that I find like, you know what? Actually, I really miss coding, and I need to find a way to restructure that. And I have seen examples of individuals who are even in CEO positions that are like, no, no, no, I still make some time to code. Like Amir, the founder of Todoist talks regularly about the fact that he is a CEO who still codes. And that organization has a very particular approach to work. And they're very much about async remote, et cetera. So having these blocks of times and being intentional about how they work. So it's not surprising that he's been able to do that and a purposeful thing that he's structured. I don't think that will make sense for me immediately. But I could see a version down the road where I'm like, this is who I am. I need to get this thing back. But for now, I'm purposefully letting it happen and seeing how I feel from there. Also, as I'm saying all of this, it sounds like I'm totally on top of this and really thinking it through. I'm like, no, no, no, this is in the moment. I'm noticing some stuff and being like, oh, okay, well, that's interesting. And some of it I intentionally chose. Again, intentionally chose to get out of my comfort zone. So I think I'm just actively out of my comfort zone right now and saying things about it. And then I think I'm telling the story of how I want to respond to it moving forward but not necessarily perfectly achieving that goal immediately. STEPH: I think that's a nice representation of essentially how you and I have processed things. We've highlighted before that you and I...it's funny, I just made the joke about not talking to people, but it's how I actually process stuff. And the best is when I'm talking out loud to somebody else. And so it totally makes sense that as you were noticing this and reflecting on it, that then this is another way that you are then processing those changes and reflecting on it and thinking through is this a good change? Is it something that I'm going to enjoy? Or am I really going to miss my street coding creds? I need to get back to the editor. CHRIS: I just need that precious flow state that comes from drinking some Mountain Dew and coding for hours. STEPH: Do you drink Mountain Dew? CHRIS: No, I gave it up years ago. STEPH: [laughs] CHRIS: I don't drink soda broadly. But if I'm going to drink soda, it's going to be Mountain Dew because if we're going to do it, let's do this thing. I'm pretty sure that stuff is like thermonuclear, but that's fine. STEPH: [laughs] That's funny. I know we've had this conversation before also around Pop-Tarts where you're like, hey, if I'm going to have a Pop-Tart, I'm going to have the sugariest (Is that a word - sugariest?) Pop-Tart possible. CHRIS: To be clear, that means it has icing on it because some people in the world, namely you, would prefer the ones without icing. Although we recently learned that the ones without icing have a higher fat and calorie content, so I don't know. The world's murky. I wish it were all just clear, and we could just work with it. But it turns out even Pop-Tarts icing versus not is not a simple question. STEPH: It's a very simple question. You just need to be on the right side, which is the non-frosted side. [laughs] I can simplify this for you because fat is delicious. Fat trumps sugar; that's my stance. That's my hot take. CHRIS: I'm saying both, a little from column A, a little from column B. You got yourself a stew. STEPH: [laughs] You got a fat sugar stew. CHRIS: Yeah. That was in Arrested Development. All right, we're veering way off course now. [laughter] To bring it back, what you were highlighting of I'm definitely someone who thinks through stuff by talking out loud, and so it's been wonderful. I've learned so much about myself while talking to you on this podcast. I'll say something, and I'll be like, wait, I actually believe that thing I just said. This is fantastic. Now I can move forward with the knowledge that I've just gained for myself by talking about it on a podcast. So highly recommended: everybody should get a podcast. STEPH: Plus one. I also have a very real, maybe silly, follow-up question for you as we are, like you just said, exploring the things that we believe or not. My question for you is part of the transition to management and moving away from coding. Isere some fear in the back of your mind where you're like, if I stopped coding, I'm going to lose this skill? CHRIS: Honestly, no. And I feel kind of bad saying that because I feel like I should say, "Yeah, I feel like it'll fade away and whatnot." But I think I have an aptitude and an interest towards this work. And if I were to ignore it for two years, then frankly, I also know myself. And I'm still going to keep an eye on everything for a while. So I think I'll be aware of what's going on and maybe just haven't spent as much time with it. But I think if I need to two years from now, I'm like, all right, I got to rebuild my coding muscle. I'll skip a couple of JavaScript frameworks, which will be nice, and I'll be on to the 15th iteration that's new now. But I hope that I could revisit that not trivially, not with no effort. It's the wonderful nature of coding. It's one of the things that I love about it so much is that there are blog posts and YouTube tutorials. And it's so individually discoverable that I'm not really worried about that aspect. My concern, if anything, isn't so much that I'm going to lose my skills or not be able to code anymore; it's that I really enjoy coding. It's a practice that I find very enjoyable. A workweek is enjoyable when it contains big blocks of me putting on my headphones, listening to music, and digging into a problem, and then coding and producing a solution. And those tiny little feedback loops of test-driven development or running something and then going to the browser and clicking around like that, there's a directness there that has always really worked well for me. And so the more I'm abstracted away from that sort of thing, and the more of my work is I'm helping a team, and I'm directing strategy, or whatever it is, that just feels so indirect. And so I'm very interested to find out how I respond to that sort of thing. I've definitely enjoyed it in the past, and so that's why I'm intentionally leaning into it. But I know that I'm giving up a part of the work that I really love, and giving up is too strong of a word as well. I'm going to find what shape makes sense moving forward. And I expect I'll still be pairing with the other developers on the team and helping to define architecture and things like that. So it's not like it's 100% gone. But for now, I think the world where most of my week was spent coding is no longer the case. And so just naming that and being intentional about it. And yeah, that's the game. STEPH: Cool. Yeah, that makes a lot of sense. I was mainly interested in that question because that is a question that I've asked myself from time to time that I think I do have that worry that if I step away from coding for too long, then it won't be easy to jump back into. And I've talked myself out of that many times because I don't think it's true for all the reasons that you just said. But it is something that I have considered as like, well, if I take this leap of faith into this other direction, how easy is it for me to get back if I decide to change my mind and go back to being more of an individual contributor? And one other thing that weighs on me as I'm splitting my time between two areas that I really want to grow…So I'm constantly trying to grow as a developer. I'm also trying to grow as a manager, and I don't want to do a bad job at either. I want to do a great job at both, and that's frankly not always possible. And at times, I have to make trade-offs with myself around okay, I'm going to focus a little heavier this day or this week on being a really great manager or focus a little bit more on being a developer and to pick and choose those topics. And then that sometimes means doing like B+ work in one area, and that's really hard for me. I'm an A-work person. So even downgrading to a B+ level of effort is challenging. But I have found that that's a really great space to be because then I'm doing well in both areas, not perfect, but doing well enough. And often, that's really what counts is that we're doing well enough and still pursuing growth in the areas that are important to us. CHRIS: Yeah, I think that intentional switching back and forth between them is the space that I'm in. I expect my work will remain very technical, and I hope that that's true. And I think to a certain extent; I get to shape it and determine that. And so how much of it is strategy and planning and things like that? Versus how much of it is helping the team with architecture and defining processes as to how we code, and what are our standards, and what are our languages and frameworks and all of that? I expect I'm still going to be involved in the latter. And again, I think to a certain extent; I get to choose that. So I am actually interested to see the shape that both naturally the organization needs out of the role that I'm in. But also, what sort of back pressure I can apply and be like, but this is how I want it to be. Is there room for that, or is there not? And it's all an experiment, and we're going to find out. But personally, for me, I'm going to keep reading Twitter and blog posts every day, and I'm probably going to code on the weekends and things. So the idea of my coding muscle atrophying, I don't know, that one doesn't feel true. But we'll see what I have to say a year from now or after what that looks like. But I expect...this has been true of me for so long, even when I had an entirely different career that I was just reading blogs and other things all the time because this is a thing that deeply interests me. So we will see. STEPH: Yeah, I'm excited to hear how it goes. And I think there's something to be said for the fact that you are also a CTO that's very close to the work that's being done. So being someone that is very involved in the technical decisions and the code that's being written but then also taking on more of the management responsibilities. And that feels more of a shift where you still have a lot of your coding skills. And you are writing code day-to-day at least based on what you're saying, but then you are also acquiring a lot of these management skills to go along with it. Versus if someone were going into management and maybe they're at a really large company and then they are very far away from the development team. And they're focused on higher-level themes and discussions, at least that's my guess. But I'm very excited to hear more about your updates and how this experiment is going and to find out who is the true Chris? CHRIS: Who's the true Chris? That feels complicated. I feel like I contain multitudes. But yeah, you know what? I'm excited to find out as well. Let's see what's going on there. But yeah, so that's a grand summary of the things that are going on in my head. And I expect these are topics that will be continuing to evolve for me. So I think we'll probably have more conversations like this in the future but also some tech stuff. Because like I said, I don't know, I can't stop. Mid-roll Ad And now a quick break to hear from today's sponsor, Scout APM. Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more. Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform. See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed. STEPH: Yeah, that's actually the perfect segue as we were talking earlier about just ways that we're looking to grow as developers. And I saw something that I really enjoyed, and it's published by another thoughtboter. Their name is Matheus Richard. And Matheus runs a Twitter account that's called @RubyCards. And I don't recall the exact cadence, but every so often, Matheus will share a new snippet of either Ruby or Rails code and then will often present the information as a question. So I'll give you an example, but the highlight is that it teaches you something, either about Ruby or Rails. Maybe you already knew it, maybe you didn't. But it's a really nice exercise to think through okay, I'm reading this code. What do I think it's going to return? And then respond to this poll and then see how other people did as well. Because once the poll closes, then Matheus shares the actual answer for the question. So one example that I saw recently highlights Ruby's endless method definition, which was introduced in Ruby 3. So that would be something like def, and then let's say the method name is message. And then you have closing, but empty parenthes equals a string of "Hello, World." And so then the question is if you call that method message, what would that return? And then the poll often has options around; it would return "Hello World," or it's going to return a syntax error. It's going to return nil. And then it highlights, well, because of Ruby's endless method definition, this would return "Hello, World." And then I also saw a new method that I hadn't used before that's defined in Ruby's Hash class that's called store. And so you can use it calling it on a Hash. So if you have your hash equals and then curly brackets, let's say foo is equal to an integer of zero, then you can call hash.store and then pass in two arguments. The first argument's going to be the key. The second argument is the value. And then, that would essentially be the same syntax that we use for assigning a value to a hash. But I just hadn't actually seen the method store before. So there are fun snippets of Ruby or Rails code. A little bit of a brain teaser helps you think through how that code works, what it's going to execute, what it's going to return. And I really enjoy it. I'll be sure to include a link to it in the show notes so other people can check it out. CHRIS: Oh, that sounds fun. I hadn't seen that, but I will definitely be following. That's the word on Twitter, right? You have subscribing, subscribe and follow, smash that like button, all of the things. I will do all of the things that we do here on the internet. But I do like that model of the question and answer, and it's slightly more engaging than just sharing the information. So yeah, super interested to see that. STEPH: Yeah, I like the format of here's some code, and then we're going to ask you what does it return? So that way, you get a moment to think it through. Because if I read something and it just shows me the answer, my brain just doesn't absorb it. And I'm like, okay, that makes sense, and my brain quickly moves on. But if I actually have to think about it and then respond with my answer, then it'll likely stick with me a lot longer. At least we'll find out; that's the dream. On that note, shall we wrap up? CHRIS: Let's wrap up. The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes,; maybe as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Byeeeeeeeeeee! Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.

    308: That's Picante

    Play Episode Listen Later Sep 14, 2021 48:05

    You know what really grinds Chris' gears? (Spoiler Alert: It's Single-Page Applications.) Steph needs some consulting help. So much to do, so little time. Sarah Drasner tweet about shared element transitions (https://twitter.com/sarah_edo/status/1431282994581413893) Article about Page Transitions API (https://developer.chrome.com/blog/shared-element-transitions-for-spas/) Svelte Crossfade layout demo (https://svelte.dev/repl/a7af336f906c4caab3936972754e4d6f?version=3.23.2) Svelte Crossfade tutorial page (https://svelte.dev/tutorial/deferred-transitions) (Note - click "Show Me" on the bottom left) Transcript: CHRIS: I have restarted my recording, and we are now recording. And we are off on the golden roads. Isn't software fun? STEPH: Podcast battle. Here we go! Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Steph Viccari. CHRIS: And I'm Chris Toomey. STEPH: And together, we're here to share a bit of what we've learned along the way. Hey, Chris, happy Friday. How's your week been? CHRIS: Happy Friday to you as well. My week's been good with the exception of right before we started this recording, I had one of those experiences. You know the thing where software is bad and software is just terrible overall? I had one of those. And very briefly to describe it, I started recording, but I could hear some feedback in my headphones. So I was like, oh no, is that feedback going to show up on the final recording? Which I really hope it doesn't. Spoiler alert - listener, if I sound off, sorry about that. But so I stopped recording and then I went to go listen to the file, and I have our audio software configured to record directly to the desktop. And it does that normally quite well. But for some reason, the file wasn't there. But I remember this recently because I ran into it another time. For some reason, this is Finder failing me. So the thing that shows me the files in a graphical format, at least on my operating system. Although I think it also messes up in the terminal maybe. That feels like it shouldn't be true, but maybe it is. Anyway, I had to kill all Finder from the terminal to aggressively restart that process. And then suddenly, Finder was like, oh yeah, there's totally files there, absolutely. They were there the whole time. Why do you even ask? And I know that state management is a hard problem, I am aware. I have felt this pain. I have been the person who has introduced some bugs related to it, but that's not where I want to experience it. Finder is one of those applications that I want to just implicitly trust, never question whether or not it's just sneakily telling me that there are files that are not there or vice versa. So anyway, software. STEPH: I'm worried for your OS. I feel like there's a theme lately [chuckles] in the struggles of your computer. CHRIS: On a related note, I had to turn off transparency in my terminal because it was making my computer get very hot. [chuckles] STEPH: Oh no, you're not a hacker any more. CHRIS: I'm not. [chuckles] I just have a weird screen that's just dark. And jellybeans is my color scheme, so there's that going on. That's in Vim specifically. Pure is my prompt. That's a lovely little prompt. But lots of Day-Glo colors on just a black background, not the cool hacker transparency. I have lost some street cred. STEPH: What is your prompt? What did you say it is? CHRIS: Pure. STEPH: Pure, I don't know that one. CHRIS: It is by Sindre Sorhus; I think is his name. That's his Twitter handle, GitHub name. He is a prolific open-source creator in the Node world, particularly. But he created this...I think it's a Bash and a Zsh prompt. It might be for others as well. It's got a bunch of features. It's pretty fast. It's minimal. It got me to stop messing around with my prompt, which was mostly what I was going for. And it has a nice benefit that occasionally now I'll be pairing with someone, and I'll be like, "Your prompt looks like my prompt. Everything is familiar. This is great." STEPH: Well, if you get back in the waters of messing around with your prompts again, I'm using Starship. And I hadn't heard of Pure before, but I really like Starship. That's been my new favorite. CHRIS: Wow. STEPH: Wow. CHRIS: I mean, on the one hand… STEPH: You're welcome. [laughs] CHRIS: On the one hand, thank you. On the other hand, again, let me lead in with the goal was to stop messing around with my prompt. So you're like, oh, cool. Here's another prompt for you, though. [chuckles] STEPH: [laughs] But my goal is to nerd snipe you into trying more things because it's fun. CHRIS: I don't know if you know this, but I am impervious to nerd sniping. STEPH: [laughs] CHRIS: So try as you might, I shall remain steady in my course of action. STEPH: Are we playing two truths and a lie? Is that what we're doing today? [laughs] CHRIS: Nah, just one lie. It's easier. Everybody wins one lie. STEPH: [laughs] CHRIS: But anyway, in other news, we're going to do a segment called this really grinds my gears. That's today's segment, which is much like when I do a good idea, terrible idea. But this is one that I'm sure I've talked about before. But there's been some stuff that I saw moving around on the internet as one does, and it got these ideas back into my head. And it's around the phrase single-page application. I am not a fan of that phrase or SPA as the initialism. Thank you, Edward Loveall, for teaching me the difference between an initialism and an acronym. I really hope I'm getting it right, by the way, [laughs] SPA as people call them these days. I feel weird because of how much I care about this thing, how much I care about this idea, and how much whenever I hear this acronym, I get a little bit unhappy. And so there's a part of it that's I really do think our words shape our thinking. And I think single-page application has some deeply problematic ideas. Most notably, I think one of the most important things about building web applications is the URL. And those are different pages, at least in my head. I don't know of a different way to think about this. But if you are not emphasizing the URL and the fact that the URL is a way to address different pages or resources within your application, then you are throwing away one of the greatest advancements that humankind has made, in my mind. I care a lot about URLs; it turns out. And it's not inherent to an SPA that you will not be thinking about URLs. But again, in that idea that our words shape our thinking, by calling it an SPA, by leaning into that idea, I think you are starting down a path that leads to bad outcomes. I'm going to pause there because I'm getting kind of ranty. I got more to say on the topic. But what do you think? STEPH: Yeah, these are hot takes. I'm into it. I'm pretty sure that I know why URLs are so important to you and more of your feelings around why they're important. But would you dive in a bit deeper as to why you really cherish URLs, and why they're so important, and why they're one of the greatest advancements of humanity? CHRIS: [laughs] It sounds lofty when you say it back to me, but yeah. It's interesting that as you put into a question, it is a little bit hard to name. So there are certain aspects that are somewhat obvious. I love the idea that I can bookmark or share a given resource or representation of a resource very simply. Like the URL, it's this known thing. We can put hyperlinks in a document. It's this shared way to communicate, frankly, very complex things. And when I think of a URL, it's not just the domain and the path, but it's also any query parameters. So if you imagine faceted search on a website, you can be like, oh, filter down to these and only ones that are more than $10, and only ones that have a future start date and all those kinds of nuance. If you serialize that into the URL as part of the query param, then that even more nuanced view of this resource is shareable is bookmarkable is revisitable. I end up making Alfred Workflows that take advantage of the fact that, like, oh, I can look at this URL scheme, and I can see where different parts are interpolated. And so I can navigate directly to any given thing so fast. And that's deeply valuable, and it just falls naturally out of the idea that we have URLs. And so to not deeply embrace that, to not really wrap your arms around it and give that idea a big hug feels weird to me. STEPH: Yeah, I agree. I remember we've had this conversation in the past, and it really frustrates me when I can't share specific resources with folks because I don't know how to link to it. So then I can send you a link to the application itself to the top URL. But then I have to tell you how to find the information that I thought was really helpful. And that feels like a step backward. CHRIS: Yeah. That ability to say, "Follow this link, and then it will be obvious," versus "Go to this page, click on this thing, click on the dropdown, click on this other thing." Like, that's just a fundamentally different experience. So one of the things that I saw that got me thinking about this was I saw folks referring to single-page applications but then contrasting them with MPAs, which are multiple-page applications. STEPH: So the normal application? [laughs] CHRIS: And I was like, whoa, whoa, everybody. You mean like a website or a web app? As much as I was angry at the first initialism, this second one's really getting me going. But it really does speak to what are we doing? What are we trying to build? And as with anything, you could treat this as a binary as just like there are two options. There are either websites which, yeah, those have got a bunch of URLs, and that's all the stuff. And then there are web apps, and they're different. And it's a bundle of JavaScript that comes down, boots up on the client, and then it's an app thing. And who cares about URLs? I think very few people would actually fall in that camp. So I don't really believe that there is a dichotomy here. I think, as always, it's a continuum; it's a spectrum. But leaning into the nomenclature of single-page application, I think pushes you more towards that latter end of the spectrum. I think there are other things that fall out of it. Like, I believe deeply in having the server know more, have more of the logic, own more of the logic, own more authorization and routing, and all of those things because really great stuff falls out of that. And that one has more of a trade-off, I'd say. But I won't name any names, but there is a multiple billion-dollar company whose website I had to interact with recently. And you land on their page on their marketing site. And then, if you click log in, it navigates you to the application, so a separate domain or a separate subdomain, the application subdomain, and the login page there. And the login page renders, and then I go to fill in my username and password. Like, my mouse makes it all the way to click on the little box or whatever I'm doing if I'm using keyboard things. But I have enough time to actually start to interact with this page. And then suddenly, it rips away, and it actually just renders the authenticated application because it turns out I was already logged in. But behind the scenes, they're doing some JWT dance around that they're checking; oh no, no, you're already logged in, so never mind. We don't need to show you the login page, but I was already on the login page. And my feeling is this sort of brittle UI; this sort of inconsistency erodes my trust in that application, particularly when I'm on the login page. That is a page that matters. I don't believe that they're doing anything fundamentally insecure. But I do have the question in my head now. I'm like, wait, what's going on there, everybody? Is it fine? Was that okay? Or if you see something that you shouldn't see and then suddenly it's ripped away from you, if you see half of a layout that's rendered on a page and then suddenly you see, no, no, no, you actually don't have access to that page, that experience erodes my trust. And so, I would rather wait for the server to fully resolve, determine what's going to happen, and then we get a response that is holistically consistent. You either have access, or you don't, that sort of thing. Give me a loading indicator; give me those sorts of things. I'm fine with that. But don't render half of a layout and then redirect me back away. STEPH: I feel like that's one of the problems with knowing too much because most people are not going to pick up on a lot of the things that you're noticing and caring deeply about where they would just see like, oh, I was logged in and be like, huh, okay, that was a little weird, but I'm in and just continue on. Versus other folks who work very closely to this who may recognize and say, "That was weird." And the fact that you asked me to log in, but then I was already logged in, did you actually log me in correctly? What's happening? And then it makes you nervous. CHRIS: Maybe. Probably. But I wonder…the way you just said that sounds like another dichotomy. And I would say it's probably more of a continuum of an average not terribly tech-savvy user would still have a feeling of huh, that was weird. And that's enough. That's a little tickle in the back of your brain. It's like, huh, that was weird. And if that happens enough times or if you've seen someone who uses an application and uses it consistently, if that application is reasonably fast and somewhat intuitive and consistent, then they can move through it very quickly and very confidently. But if you have an app that half loads and then swaps you to another page and other things like that, it's very hard to move confidently through an application like that. I do think you're right in saying that I am over-indexed on this, and I probably care more than the average person, but I do care a lot. I do think one of the reasons that I think this happens is mobile applications came along, and they showed us a different experience that can happen and also desktop apps for some amount of time this was true. But I think iOS apps, in particular really great ones, have super high fidelity interactions. And so you're like, you're looking at a list view, and then you click on the cell for that list view. And there's this animated transition where the title floats up to the top and grows just a little bit. And the icon that was in the corner moves up to the corner, and it gets a little bigger. And it's this animated transition to the detailed view for that item. And then if you go back, it sort of deanimates back down. And that very consistent experience is kind of lovely when you get it right, but it's really, really hard. And people, I think, have tried to bring that to the web, but it's been such a struggle. And it necessitates client-side routing and some other things, or it's probably easiest to do if you have those sorts of technologies at play, but it's been a struggle. I can't think of an application that I think really pulls that off. And I think the trade-offs have been very costly. On the one positive note, there was a tweet that I saw by Sarah Drasner that was talking about smooth and simple page transitions with the shared element transition API. So this is a new API that I think is hoping to bring some of this functionality to the web platform natively so that web applications can provide that higher fidelity experience. Exactly how it'll work whether or not it requires embracing more of the single-page application, client-side routing, et cetera, I'm not sure on that. But it is a glimmer of hope because I think this is one of the things that drives folks in this direction. And if we have a better answer to it, then maybe we can start to rethink the conversation. STEPH: So I think you just said shared element transitions. I don't know what that is. Can you talk more about that? CHRIS: I can try, or I can make a guess. So my understanding is that would be that sort of experience where you have a version of a certain piece of content on the page. And then, as you transition to a new page, that piece of content is still represented on the new page, but perhaps the font size is larger, or it's expanded, or the box around it has grown or something like that. And so on mobile, you'll often see that animate change. On the web, you'll often see the one page is just completely replaced with the other. And so it's a way to have continuity between, say, a detailed view, and then when you click on an item in it, that item sort of grows to become the new page. And now you're on the detail page from the list page prior. There's actually a functionality in Svelte natively for this, which is really fancy; it's called crossfade. And so it allows you to say, "This item in the component hierarchy in the first state of the application is the same as this item in the second state of the application." And then, Svelte will take care of transitioning any of the properties that are necessary between those two. So if you have a small circle that is green, and then in the next state of the application, it's a blue rectangle, it will interpolate between those two colors. It will interpolate the shape and grow and expand it. It will float it to its new location. There is a really great version of it in the Svelte tutorial showing a to-do list. And so it's got a list on the left, which is undone things, and a list on the right that is done things. And when you click on something to complete it, it will animate it, sort of fly across to the other list. And if you click on it to uncomplete, it will animate it and fly back. And what's great is within Svelte because they have this crossfade as a native idea; all you need to say is like, "It was on this list, now it's on this list." And as long as it's identifiable, Svelte handles that crossfade and all the animations. So it's that kind of high-fidelity experience that I think we want. And that leads us to somewhat more complex applications, and I totally get that. I want those experiences as well. But I want to ask some questions, and I want to do away with the phrasing single-page application entirely. I don't want to say that anymore. I want to say URLs are one honking good idea. Let's have more of those. And also, just to name it, Inertia is a framework that allows me to build using some of the newer technologies but not have to give up on URLs, give up on server-side logic as the primary thing. So I will continue to shout my deep affection for Inertia in this moment once again. STEPH: Cool. Thanks. That was really helpful. That does sound really neat. So in the ideal world, we have URLs. We also have high fidelity and cool interactions and transitions on our pages. We don't have to give it a fancy name like single-page application or then multi-page application. I do wonder, with our grumpiness or our complaint about the URLs, is that fair to call it grumpy? CHRIS: It's fair to call it grumpy, although you don't need to loop yourself in with me. I'm the grump today. STEPH: [laughs] CHRIS: You're welcome to come along for the ride if you'd like. And I'm trying to find a positive way to talk about it. But yeah, it's my grumpytude. STEPH: Well, I do feel similarly where I really value URLs, and I value the ability to bookmark and share, like you said earlier. And I do wonder if there is a way to still have that even if we don't have the URL. So one of the things that I do is I'll inspect the source code. And if I can find an ID that's for a particular header or section on the page, then I will link someone to a section of that page by then adding the ID into the URL, and that works. It's not always great because then I have to rely on that being there. But it's a fix, it's a workaround. So I wonder if we could still have something like that, that as people are building content that can't be bookmarked or the URL doesn't change explicitly, or reference that content, to add more thoughtful bookmark links, essentially, or add an ID and then add a user-facing link that says, "Hey, if you want to link someone to this content, here you go." And under the hood, it's just an ID. But most people aren't going to know how to do that, so then you're helping people be able to reference content because we're used to URLs, so just thinking outside the box. I wonder if there are ways that we can still bookmark this content, share it with people. But it's okay if the URL isn't the only way that we can bookmark or reference that content. CHRIS: It's interesting that you bring that up, so the anchor being the thing after the hash symbol in the URL. I actually use that a ton as well. I think I built a Chrome extension a while back to try what you're saying of I'll inspect the DOM. I did that enough times that I was like, what if the DOM were to just tell me if there were an ID here and I could click on a thing? Some people's blogs...I think the thoughtbot blog has this at this point. All headers are clickable. So they are hyperlinks that append that anchor to the URL. So I wouldn't want to take that and use that functionality as our way to get back to URLs that are addressing resources because that's a way to then navigate even further, which I absolutely love, to a portion of the page. So thinking of Wikipedia, you're on an article, but it's a nice, long article. So you go down to the section, which is a third of the way down the page. And it's, again, a very big page, so you can link directly to that. And when someone opens that in their browser, the browsers know how to do this because it's part of the web platform, and it's wonderful. So we've got domains, we've got paths, we've got anchors, we've got query params. I want to use them all. I want to embrace them. I want that to be top of mind. I want to really think about it and care about that as part of the interface to the application, even though most users like you said, are not thinking about the shape of a URL. But that addressability of content is a thing that even if people aren't thinking of it as a primary concern, I think they know it when they...it's one of those like, yeah, no, that app's great because I can bookmark anything, and I can get to anything, and I can share stuff with people. And I do like the idea of making the ID-driven anchor deep links into a page more accessible to people because you and I would go into the DOM and slice it out. Your average web user may not be doing that, or that's much impossible to do on mobile, so yes, but only more so in my mind. [laughs] I don't want to take anchors and make them the way we do this. I want to just have all the URL stuff, please. Mid-roll Ad Now we're going to take a quick break to tell you about today's sponsor, Orbit. Orbit is mission control for community builders. Orbit offers data analytics, reporting, and insights across all the places your community exists in a single location. Orbit's origins are in the open-source and developer relations communities. And that continues today with an active open-source culture in an accessible and documented API. With thousands of communities currently relying on Orbit, they are rapidly growing their engineering team. The company is entirely remote-first with team members around the world. You can work from home, from an Orbit outpost in San Francisco or Paris, or find yourself a coworking spot in your city. The tech stack of the main orbit app is Ruby on Rails with JavaScript on the front end. If you're looking for your next role with an empathetic product-driven team that prides itself on work-life balance, professional development, and giving back to the larger community, then consider checking out the Orbit careers page for more information. Bonus points if working in a Ruby codebase with a Ruby-oriented team gives you a lot of joy. Find out more at orbit.love/weloveruby. STEPH: I have a confession from earlier when you were talking about the examples for those transitions. And you were describing where you take an action, and then the page does a certain motion to let you know that new content is coming onto the page and the old content is fading away. And I was like, oh, like a page reload? We're just reimplementing a page reload? [laughs] That's what we have? CHRIS: You have a fancy, though. STEPH: Fancy, okay. [laughs] But that felt a little sassy. And then you provided the other really great example with the to-do list. So what are some good examples of a SPA? Do you have any in mind? I think there are some use cases where...so Google Maps, that's the one that comes to mind for me where URLs feel less important. Are there other applications that fit that mold in your mind? CHRIS: Well, so again, it's sort of getting at the nomenclature, and how much does the acronym actually inform what we're thinking about? But taking Google Maps as an example, or Trello is a pretty canonical one in my mind, most people say those are single-page applications. And they are probably in terms of what the tech actually is, but there are other pages in those apps. There's a settings page, and there's a search page, and there's this and that. And there's like the board list in Trello. And so when we think about Trello, there is the board view where you're seeing the lists, and you can move cards, and you can drag and drop and do all the fancy stuff. That is a very rich client-side application that happens to be one page of the Trello web app and that one being higher fidelity, that one being more stateful. Stateful is probably the thing that I would care about more than anything. And so for that page, I would be fine with the portion of the JavaScript that comes down to the client being a larger payload, being more complex, and probably having some client-side state management for that. But fundamentally, I would not want to implement those as a true client-side application, as a true SPA. And I think client-side routing is really the definition point for me on this. So with Trello, I would probably build that as an Inertia-type application. But that one page, the board page, I'd be like, yeah, sorry, this is not going to be the normal Inertia thing. I'm going to have to be hitting JSON endpoints that are specifically built for this page. I'm going to have a Redux store that's local. I'm going to lean into all of that complex state management and do that within the client-side app but not use client-side routing for actual page-level transitions, the same being true for Google Maps. The page where you're looking at the map, and you can do all sorts of stuff, that's a big application. But it is one page within the broader website, if you will. And so, I still wouldn't want client-side routing if I can avoid it because I think that is where I run into the most problems. And that thing I was talking about where I was on the login page for a second, and then I wasn't; I do not like that thing. So if I can avoid that thing, which I have now found a way to avoid it, and I don't feel like I'm trading off on that, I feel like it's just a better experience but still reserving the right to this part of the application is so complex. This is our Wiziwig drag and drop graphical editor thing, cool. That's going to have Redux. That's going to have client-side state management, all that stuff. But at no point does single-page application feel like the right way to describe the thing that we're building because I still want to think about it as holistically part of the full web app. Like the Trello board view is part of the Trello web app. And I want it all to feel the same and move around the same. STEPH: Yeah, that makes sense. And it's funny, as you were mentioning this, I pulled up Google Maps because I definitely only interact with that heavy JavaScript portion, same for Trello. And I wasn't even thinking about the fact that there are settings. By the way, Google Maps does a lot. I don't use hardly any of this. But you make a great point. There's a lot here that still doesn't need such heavy JavaScript interaction and doesn't really fit that mold of where it needs to be a single-page app or even needs to have that amount of interactivity. And frankly, you may want URLs to be able to go specifically to these pages. CHRIS: That actually is an interesting, perhaps counterpoint to what I'm saying. So if you do have that complex part of one of your applications and you still want URL addressability, maybe you need client-side routing, and so that becomes a really difficult thing to answer in my mind. And I don't necessarily have a great answer for that. I'm also preemptively preparing myself for anyone on the internet that's listening to this and loves the idea of single-page applications and feels like I'm just building a straw man here, and none of what I'm saying is actually real and whatnot. And although I try to...I think we generally try and stay in the positive space of like what's good on the internet. This is a rare case where I'm like, these are things that are not great. And so I think in this particular case, leaning into things that I don't like is the way to properly capture this. And giant JavaScript bundles where the entirety of the application logic comes down in 15-megabyte download, even if you're on 3G on a train; I don't like that. I don't like if we have flashes of a layout that they can get ripped away b; it'secause it turns out we actually aren't authorized to view that page, that sort of thing. So there are certain experiences from an end client perspective that I really don't like, and that's mostly what I take issue with. Oh, also, I care deeply about URLs, and if you don't use the URL, then I'm going to be sad. Those are my things. Hopefully, that list is perhaps a better summary of it than like...I don't want it to seem like I'm just coming after SPA as a phrase or a way of thinking because that's not as real of a conversation. But those particular things that I just highlighted don't feel great. And so I would rather build applications that don't have those going on. And so if there's a way to do that that still fits any other mold or is called whatever, but largely what I see called an SPA often has those sorts of edge cases. And I do not like those edge cases. STEPH: Yeah, I like how you're breaking it down where it's less of this whole thing like I can't get on board with any of it. You are focusing on the things that you do have concerns with. So there can be just more interesting, productive conversations around those concerns versus someone feels like they have to defend their view of the world. I have found that I think I'm a bit unique in this area where when people have a really differing opinion than mine, that gets me really excited because then I want to know. Because if I believe very strongly in something and I just think this is the way and then someone very strongly says like, "No, that's not," I'm like, "Oh yeah. Okay, we should talk because I'm interested in why you would have such a different opinion than mine." And so, I typically find those conversations really interesting. As long as everybody's coming forward to be productive and kind, then I really enjoy those conversations. CHRIS: That is, I think, an interesting frame that you have there. But I think I'm similar, and hopefully, my reframing there puts it in the way that can be a productive conversation starter as opposed to a person griping on a podcast. But with that said, that's probably enough of me griping on a podcast. [chuckles] So what's up in your world, Steph? STEPH: Oh, there are a couple of things going on. So I am in that pre-vacation chaotic zone where I'm just trying to get everything done. And I heard someone refer to it recently as going into a superman or superwoman mode where you're just trying to do all the things before you go, which is totally unreasonable. So that has been interesting. And the name of the game this week has been delegate, delegate, delegate, and it seems to be going fairly well. [chuckles] So I'm very excited for the downtime that I'm about to have. And some other news, some personal news, Utah, my dog, turns one. I'm very excited. I'm pretty sure we'll have a dog birthday party and everything. It's going to be a thing. I'll share pictures on Twitter, I promise. CHRIS: So he's basically out of the puppy phase then. STEPH: Yeah, the definition for being a puppy seems to be if you're a year or younger, so he will not be an adult. Teenager? I don't know. [laughs] CHRIS: What about according to your lived experience? STEPH: He has calmed down a good bit. CHRIS: Okay, that's good. STEPH: He has gotten so much better. Back when we first got him, I swear I couldn't get 15 minutes of focus where he just needed all the attention. Or it was either constant playtime, or I had to put him in his kennel since we're using that. That was the only way I was really ever getting maker's time. And now he will just lounge on the couch for like an hour or two at a time. It's glorious. And so he has definitely calmed down, and he is maturing, becoming such a big boy. CHRIS: Well, that is wonderful. Astute listeners, if you go back to previous episodes over the past year, you can certainly find little bits of Utah sprinkled throughout, subtle sounds in the background. STEPH: He is definitely an important part of the show. And in some other news, I have a question for you. I'm in need of some consulting help, and I would love to run something by you and get your thoughts. So specifically, the project that I'm working on, we are always in a state where there's too much to do. And even though we have a fairly large team, I want to say there's probably somewhere between 7 and 10 of us. And so, even though we have a fairly...for thoughtbot, that's a large team to have on one project. So even though there's a fair number of us, there's always too much to do. Everything always feels like it's urgent. I can't remember if I've told you this or not, but in fact, we had so many tickets marked as high priority that we had to introduce another status to then indicate they're really, really high, and that is called Picante. [chuckles] CHRIS: Well, the first part of that is complicated; the actual word that you chose, though, fantastic. STEPH: I think that was CTO Joe Ferris. I think he's the one that came up with Picante. So that's a thing that we have, and that really represents like, the app is down. So something major is happening. That's like a PagerDuty alert when we get to that status where people can't access a page or access the application. So there's always a lot to juggle, and it feels a lot like priority whiplash in terms that you are working on something that is important, but then you suddenly get dragged away to something else. And then you have to build context on it and get that done. And then you go back to the thing that you're working on. And that's a really draining experience to constantly be in that mode where you're having to pivot from one type of work to the other. And so my question to you (And I'll be happy to fill in some details and answer questions.) is how do you calm things down? When you're in that state where everything feels so urgent and busy, and there's too much to do, how do you start to chip away at calming things down where then you feel like you're in a good state of making progress versus you feel like you're just always putting out fires or adding a band-aid to something? Yeah, that's where I'm at. What thoughts might you have, or what questions do you have? CHRIS: Cool. I'm glad you brought an easy question that I can just very quickly answer, and we'll just run with that. It is frankly...what you're describing is a nuanced outcome of any number of possible inputs. And frankly, some of them may just be like; this is just the nature of the thing. Like, we could talk about adding more people to the project, but the mythical man-month and that idea that you can't just throw additional humans at the work and suddenly have that makes sense because now you have to coordinate between those humans. And there's that wonderful image of two people; there's one line of communication. Three people, suddenly there are a lot more lines of communication. Four people, wow. The exponential increase as you add new people to a network graph, that whole idea. And so I think one of the first questions I would ask is, and again, this is probably not either/or. But if you would try and categorize it, is it just a question of there's just a ton of work to do and we're just not getting it done as quickly as we would want? Or is it that things are broken, that we're having to fix things, that there are constant tweaks and updates, that the system doesn't support the types of changes that we want, so any little thing that we want to do actually takes longer? Is it the system resisting, or is it just that there's too much to do? If you were to try and put it into one camp or the other. STEPH: It is both, my friend. It is both of those camps. [chuckles] CHRIS: Cool. That makes it way easier. STEPH: Totally. [laughs] To add some more context to that, it is both where the system is resistant to change. So we are trying to make improvements as we go but then also being respectful of the fact if it is something that we need to move quickly on, it doesn't feel great where you never really get to go back and address the system in a way that feels like it's going to help you later. But then, frankly, it's one of those tools that we can use. So if we are in the state where there's too much to do, and the system is resisting us, we can continue to punt on that, and we can address things as we go. But then, at some point, as we keep having work that has slowed down because we haven't addressed the underlying issues, then we can start to have that conversation around okay; we've done this twice now. This is the third time that this is going to take a lot longer than it should because we haven't really fixed this. Now we should talk about slowing things down so we can address this underlying issue first and then, from now on, pay the tax upfront. So from now on, it's going to be easier, but then we pay that tax now. So it is a helpful tool. It's something that we can essentially defer that tax to a later point. But then we just have to have those conversations later on when things are painful. Or it often leads to scope creep is another way that that creeps up. So we take on a ticket that we think, okay, this is fairly straightforward; I don't think there's too much here. But then we're suddenly getting into the codebase, and we realize, oh, this is a lot more work. And suddenly, a ticket will become an epic, and you really have one ticket that's spiraled or grown into five or six tickets. And then suddenly, you have a person that's really leading like a mini project in terms of the scope of the work that they are doing. So then that manifests in some interesting ways where then you have the person that feels a bit like a silo because they are the ones that are making all these big changes and working on this mini-project. And then there's the other one where there's a lot to do. There are a lot of customers, and there's a lot of customization for these customers. So then there are folks that are working really hard to keep the customers happy to give them what they need. And that's where we have too much to do. And we're prioritizing aggressively and trying to make sure that we're always working on the top priority. So like you said, it's super easy stuff. CHRIS: Yeah. To say it sincerely and realistically, you're just playing the game on hard mode right now. I don't think there is any singular or even multiple easy answers to this. I think one question I would have particularly as you started to talk about that, there are multiple customers each with individualized needs, so that's one of many surface areas that I might look t say, "Can we sort of choke things off there?" So I've often been in organizations where there is this constant cycle of the sales team is going out. They're demoing against an InVision mock. They're selling things that don't exist. They're making promises that are ungrounded and, frankly, technically infeasible or incredibly complicated, but it's part of the deal. They just sold it, and now we have to implement it as a team. I've been on teams where that was just a continuing theme. And so the engineering team was just like, "We can never catch up because the goalpost just keeps moving." And so to whatever degree that might be true in this case, if there are ten different customers and each of them right now feels like they have an open line to make feature requests or other things like that, I would try to have the conversation of like, we've got to cut that off right now because we're struggling. We're not making the forward progress that we need to, and so we need to buy ourselves some time. And so that's one area that I would look at. Another would be scope, anywhere that you can, go into an aggressive scope cutting mode. And so things like, well, we could build our own modal dialogue for this, but we could also use alert just like the JavaScript alert API. And what are all of the versions of that where we can say, "This is not going to be as nice, and as refined, and as fitting with the brand and feel and polish of the website. But ways that we can make an application that will be robust, that will work well on all of the devices that our users might be using but saves us a bunch of development time"? That's definitely something that I would look to. What you described about refactoring is interesting. So I agree with we're not in a position where we can just gently refactor as we find any little mess. We have to be somewhat ruthless in our prioritization there. But like you said, when you get to that third time that a thing is working way harder, then take the time to do it. But really, like just every facet of the work, you just have to be a little better. If you're an individual developer and you're feeling stuck, raise your hand all the earlier because that being stuck, we don't have spare cycles right now. We need everybody to be working at maximum efficiency. And so if you've hit a wall, then raise your hand and grab somebody else, get a pair, rubber duck, whatever it is that will help you get unstuck. Because we're in a position where we need everybody moving as fast as they can. But also to say all of those aren't free. Every one of those where you're just like, yeah, do it the best you can. Dial it up to 11 on every front. That's going to drain the team, and so we have to also be mindful of that. This can't be forever. And so maybe it is bringing some new people onto the team or trying to restructure things so that we can have smaller communication channels. So it's only four people working together on this portion of the application, and therefore their communication lines are a bit simpler. That's one way that we can maybe save a little bit. But yeah, none of these are free. And so, we also need to be mindful that we can't just try harder forever. [laughs] That's a way to burn out the team. But what you're describing is like the perfect storm of every facet of this is difficult, and there's no singular answer. There's the theory of constraints (I think I'm saying that right.) where it's like, what's the part of our process that is introducing the most slowdowns? And so you go, and you tackle that. So if you imagine a website and the app is slow is the report that you're getting, and you're like, okay, what does that mean? And you instrument it, and you log some stuff out. And you're like, all right, turns out we have tons of N+1s. So frankly, everything else doesn't matter. I don't care if we've got a 3 megabyte JavaScript bundle right now; the 45 N+1s on the dashboard that's the thing that we need to tackle. So you start, and you focus on that. And now you've removed that constraint. And suddenly, the three megabyte JavaScript bundle is the new thing that is the most complicated. So you're like, okay, cool, let's look into tree shaking or whatever it is, but you move from one focus to another. And so that's another thing that could come to play here is like, which part of this is introducing the most pain? Is it feature churn? Is it unrealistic sales expectations? Is it developers getting stuck? And find the first of those and tackle it. But yeah, this is hard. STEPH: Yeah, it is. That's all really helpful, though. And then, I can share some of the things that we are experimenting with right now and then provide an update on how it's going. And one of the things that we're trying; I think it's similar to the theory of constraints. I'm not familiar with that, but based on the way you described it, I think they're related. One of the things that we are trying is breaking the group into smaller teams because there are between 7 and 10 of us. And so, trying to jump from one issue to the next you may have to really level up on different portions of the application to be able to make an impact. And there are areas that we really need infrastructure improvements and then essentially paving the way for other people to be able to move more quickly. We do have to prioritize some of that work as well. So if we break up into smaller teams, it addresses a couple of areas, or at least that's the goal is to address a couple of areas. One is we avoid having silos so that people aren't a bottleneck, or they're the only ones that are really running this mini-project and the only one that has context. Because then when that person realizes the scope has grown, bringing somebody on to help feels painful because then you're in an urgent state, but now you have to spend time leveling someone else up just so that they can help you, and that's tough. So the goal is that by having smaller teams, we will reduce that from happening because at least everything that feels like a small project...and by feels like a small project, I mean if we have more than one ticket that's associated with the same theme, that's going to start hinting at maybe this is more than just one ticket itself, and it might actually belong to an epic. Or there's a theme here, and maybe we should have two people working on this. And breaking people into groups, then we can focus on some people are focused more on the day-to-day activity. Some people are focused on another important portion of the codebase as we have what may be extracted. I'm going to say this, but we're going to move on, maybe extracted into its own service. [laughs] I know that's a hot one for us, so I'm just going to say it. CHRIS: I told you I can't be nerd sniped. This is fine. Let's continue on. [laughs] STEPH: [laughs] And then a small group can also focus on some of those infrastructure improvements that I was alluding to. So smaller teams is something that we are trying. We are also doing a really great job. I've been really happy and just proud of the team where folks are constantly reaching out to each other to say, "Hey, I'm done with my ticket. Who can I help?" So instead of immediately going to the backlog and grabbing the next thing. Because we recognize that because of this structure where some people are some silos, they have their own little mini backlog, which we are working to remove that to make sure everything is properly prioritized instead of getting assigned to one particular person. But we are reaching out to each other to say, "Hey, what can I do to help? What do you need to get done with your work before I go pick something else up?" The other two things that come to mind is who's setting the deadlines? I think you touched on this one as well. It's just understanding why is it urgent? Does it need to be urgent? What is the deadline? Is this something that internally we are driving? Is this something that was communicated without talking to the rest of the team? Is this just a really demanding customer? Are they setting unrealistic expectations? But having more communication around what is the sense of urgency? What happens if we miss this deadline? What happens if we don't get to this for a week, a month? What does that look like? And then also, my favorite are retros because then we can vote on what feels like the highest priority in terms of pain points or run these types of experiments like the smaller teams. So those are the current strategies that we have. And I'm very interested to see how they turn out because it is a tough way. Like you said, it's challenge mode, and it is going to burn people out. And it does make people feel fatigued when they have to jump from one priority to the next. So I'm very interested. It's a very interesting problem to me too. It just feels like something that I imagine a lot of teams may be facing. So I'm really excited if anybody else is facing a similar issue or has gone through a similar challenge mode; I'd love to hear how your team tackled it. CHRIS: Yeah, I'm super interested to hear the outcome of those experiments. As a slightly pointed question there, is there any semi-formal version of tracking the experiments? And is it just retro to retro that you're using for feedback on that? I've often been on teams where we have retro. We come up with it, and we're like, oh, this is a pain point. All right, let's try this. And then two weeks later, we're like, oh, did anyone actually do that? And then we just forget. And it's one of those things that I've tried to come up with better ways to actually manage, make slightly more explicit the experiments, and then have a timeline, have an almost scientific process of what's the hypothesis? What's the procedure? What are the results? Write up an executive summary. How'd it go? STEPH: We are currently using retro, but I like that idea of having something that's a bit more concrete. So we have action items. And typically, going through retro, I tend to revisit the action items first as a way to kick off retro. So then that highlights what did we do? What did we not do? What do we not want to do anymore? What needs to roll over to the current iteration? And I think that could be just a way that we chat about this. We try something new, and we see how it's going each week in retro. But I do like the idea of stating upfront this is what we're looking to achieve because I think that's not captured in the retro action item. We have the thing that we're doing, but we haven't captured this is what we hope to achieve by taking this experiment on. Mid-roll Ad And now a quick break to hear from today's sponsor, Scout APM. Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more. Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform. See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed. STEPH: As for the other thing that you mentioned, I do have an idea for that because a former client that I worked with where we had experiments or things that we wanted to do, we were using Trello. And so we would often take those action items…or it was even more of a theme. It wasn't something that could be one-and-done. It was more of a daily reminder of, hey; we are trying this new thing. And so, we want to remind you each day to embrace this experiment and this practice. And so we would turn it into a Trello ticket, and then we would just leave it at the top of the board. So then, each day, as we were walking the board, it was a nice reminder to be like, hey, this is an ongoing experiment. Don't forget to do this. CHRIS: I do like the idea of bringing it into a stand-up potentially as like that's just a recurring point that we all have. So we can sort of revisit it, keep it top of mind, and discard it at some point if it's not useful. And if we're saying we're doing a thing, then let's do the thing and see how it goes. So yeah, very interested to hear the outcomes of the experiment and also the meta experiment framework that you're going to build here. Very interested to hear more about that. And just to say it again, this sounds like your perfect storm is not quite right because it doesn't sound like there's a ton of organizational dysfunction here. It sounds like this is just like, nah, it's hard. The code's not in perfect shape, but no code is. And there's just a lot of work to be done. And there are priorities because frankly, sometimes in the world, there are priorities, and you're sort of at the intersection of that. And I've been in plenty of teams where it was hard because of humans. In fact, that's often the reason of we're sort of making up problems, or we're poorly communicating or things like that. But it sounds like you're in the like, nope, this is just hard. And so, in a way, it sounds like you're thinking about it like, I don't know, it's kind of the challenge that I signed up for. Like, if we can win this, then there's going to be some good learnings that come out of that, and we're going to be all the better. And so, I wish you all the best of luck on that and would love to hear more about it in the future. STEPH: Thank you. And yeah, it has been such an interesting project with so many different challenges. And as you've mentioned, that is one area that is going really well where the people are wonderful. Everybody is doing their best and working hard. So that is not one of the competing challenges. And it is one of those; it's hard. There are a lot of external factors that are influencing the priority of our work. And then also, some external areas that we don't have control over that are forcing some of those deadlines where customers need something and not because they're being fussy, but they are themselves reacting to external deadlines that they don't have control over. So it is one of those where the people are great, and the challenges are just real, and we're working through them together. But it's also hard. But it's helpful chatting through all the different challenges with you. So I appreciate all of your thoughts on the matter. And I'll report some updates once I have some more information. On that note, shall we wrap up? CHRIS: Let's wrap up. STEPH: The show notes for this episode can be found at bikeshed.fm. CHRIS: This show is produced and edited by Mandy Moore. STEPH: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or a review in iTunes as it helps other people find the show. CHRIS: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed on Twitter. And I'm @christoomey. STEPH: And I'm @SViccari. CHRIS: Or you can email us at hosts@bikeshed.fm. STEPH: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Byeeeeeeee! Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.

    307: Walking Contradictions

    Play Episode Listen Later Sep 7, 2021 36:56

    On this episode, Chris talks about testing external services and dissects a tweet on refinements for Result. Steph talks about thoughbot's recent improvement to their feature flag system. Links: refinements For Result (https://twitter.com/alassek/status/1430683412264857600) Faking External Services in Tests with Adapters by German Velasco (https://thoughtbot.com/blog/faking-external-services-in-tests-with-adapters) Testing Interaction with 3rd-party APIs (https://thoughtbot.com/upcase/videos/testing-interaction-with-3rd-party-apis) Transcript: CHRIS: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey. STEPH: And I'm Steph Viccari. CHRIS: And together, we're here to share a bit of what we've learned along the way. So, Steph, what's new with you? STEPH: Hey, Chris. Well, today is Summit Day at thoughtbot, and it's the day where all the bots gather, and we hang out, and we chat, and we play games. And it's a lot of fun. We're actually taking more of a respite this year just because life has been taxing. And so we decided to give people more of the day off. So we still had some fun events, but most of it is everybody gets a chill day. Do something that brings you joy is the theme of the day. But we had Lightning Talks, which is my favorite thing that we do on Summit Day because I realize that I just work with the coolest people, and they have such interesting things to talk about. And we had such a variety of topics. So one of them, Alex Chen taught us acronyms in K-pop. And Sam Kapila, our resident foodie, taught us about a variety of spices. And one of my favorite talks was by Akshith Yellapragada, and it's the top 10 best limo entrances by The Bachelor, and it was phenomenal. And I really want to share some stuff that I learned with you. CHRIS: The Bachelor like the TV show? STEPH: Yeah, like the TV show. Are you familiar with it? Have you seen it before? CHRIS: I am familiar with it. I know it exists. I know that there's a spinoff, The Bachelorette. And I believe we have now exhausted my information on the matter. STEPH: [laughs] That's fair. For anyone that hasn't seen the show, the show revolves around a single person. For the bachelor, it's a single bachelor who dates a number of people over several weeks, and then they narrow down the people. There are elimination rounds, and the whole goal is for them to find their true love. So each week, someone is eliminated, and I think the show ends with a marriage proposal. So it's a wild show. It's something. [chuckles] And in Akshith's talk, I learned some really fun terminology. The first one is the Crown, and this is actually an important building block because we're going to get to the rest of the terminology that uses this word, so we got to start here. So the first one is the Crown, and this is the person that everyone's competing for. So they're the star of the show. They're the one that everybody is hoping to fall in love with or will fall in love with them so they get a marriage proposal. So then the other stuff that I've learned is all about the entrance because again, we're talking about the top 10 best entrances. And one of them is the sidecar entrance. So this is where the player, because yes, this is totally a game, has someone assist them in meeting the crown. So it could be like a family member, maybe it's like your grandma. And then there's TOT, T-O-T, which is short for Trick Or Treat. And this person exits the limo wearing a costume. So it's someone wearing a shark costume. There was someone wearing a sloth costume where they really dedicated to the role, and they climbed a tree and hung from a branch. I don't know for how long but for long enough to really vibe with the role. And then there's the Kringle, and this person brings a prop or a present to the Crown. And there's the Grandy, and this player arrives in something other than a limo. So the example that Akshith provided is someone arrived in a motorized cupcake. CHRIS: Was the cupcake edible? STEPH: I don't think so, fair question. [laughs] CHRIS: So really just like a go-kart that looked like a cupcake, not really a motorized cupcake, if I'm going to meet pedantic about the thing, [chuckles] which I think is my job. STEPH: Yes, it is a motorized non-edible cupcake, but that seems like something a next player should do. They should really up the game, and they should bring an edible motorized cupcake. CHRIS: Yeah, because you get the visual novelty, but then you layer on top of it that it's actually something that you can now eat, and it's a double win. STEPH: Ooh, and then you're a Grandy, and you're a Kringle because you arrived in something other than a limo, and it's a present. CHRIS: I love how you have so deeply internalized this now that you're like, ooh, okay. I can remix here. I'm going to bring together the pieces. Yeah, all right. Yeah, this all makes sense. STEPH: Yeah, it was a lot of fun. Those are most of my notes for today. I have some tech stuff too, but this felt like the most important thing to start the show with. CHRIS: We use the phrase tech talk and nonsense to describe the show often, but I think nonsense and tech talk is the correct orientation. STEPH: [chuckles] CHRIS: Correct in terms of importance and chronological order, and whatnot. But yeah. STEPH: I love that we start with a bit of nonsense. So I do have some tech stuff. But first, before I share any of that, what's going on in your world? CHRIS: I'm sure there's plenty of nonsense in my world, but at the top of my list is some tech stuff. So someone on Twitter, Adam Lassek, reached out and he suggested related to the conversation and the back and forth that I've been having with myself around some of the data structures within the app that I'm building…So I've talked about the dry-monads result object, and there's this success and failure. And I wanted to introduce this new method called bimap, but I wanted to do it in a reasonable way. So I wrapped, and then I wrapped, and I wrapped things. As an aside, former colleague and friend of the show, Joel Oliveira, sent a wonderful tweet which was a reference to the SNL video where they make a taco and put it inside of a pizza and put it inside of a bag. And that was his joke about it, which I really liked. That was an excellent reference. But in this case, Adam Lassek reached out and suggested if I'm that squeamish about monkey patching, which I am, have I considered refinements? And so he sent an image of a code sample, which is so kind of him to send that much detail over, but it was interesting because I know of refinements in Ruby. I know of that as an alternative to monkey patching, a more refined way, but a safer way, a more controlled way to alter code, but I've not actually used them. STEPH: I'm not familiar with refinements. What is that? CHRIS: Refinements are a way...so similar to monkey patching, where you say like, I'm going to reopen this class or this module and define a new method or redefine a method or do something like that, a refinement is a way to do that in a scoped manner. So I'll be honest, I'm not super familiar with them. I think I came into Ruby at a time where the community was moving away from monkey patching. And the dogmatic swing of the pendulum was like, that's a bad thing to do. And so even the refinements were introduced, as far as I understand it, to be a more controlled way to do it. So it's not just like, hey, cool. This module is redefined now in your app in a magical way that's really hard to figure out and hard for folks to debug refinements. You have to explicitly opt into within a certain lexical scope. I'll be honest; I know that at the headline level. I don't actually know the ramifications or where and when you can use them and how you can. But I know that that was the idea is refinements are a way to do monkey patching but in a more controlled, more understandable manner, and so the code sample that Adam shared does that. And it's very interesting. As I'm looking at it, I'm like, okay, that's cool because I think it'll be a little bit safer. But at the end of the day, my concern wasn't safety in this case because I was introducing a method that would be new, that would be additive to the API of this module that I'm working with, and so that I think of as a relatively safe operation. My hesitation was more around how does someone figure it out if they're working with this? And particularly, the name of the method that I was introducing was bimap so, B-I-M-A-P. And if someone sees that in our codebase and is like, "Bimap, where is this coming from?" Well, this is one of those dry-monad result objects. And they go to the code, and they try and look it up in the docs, and they're just not going to find anything. And I can imagine losing a lot of time to try and chase that down. There are ways to figure it out. There's the method in Ruby, which is a wonderful trick for chasing things down. Or if you grep the codebase, you'd find it. But I think I'm possibly over-indexed on worrying about that lost time, that moment. But I've lost that time so many times in my life where I'm like, I can't grep for this. I can't Google for this. And so I have so strongly moved in the direction of being like, everything should be grepable, everything should be googleable. Those are the two of the things that I believe about software. I think I believe a bunch of stuff. STEPH: I think we have a full episode that talks about what we believe in software. CHRIS: I believe we do. STEPH: Cool. Thanks. Yeah, I have not heard of refinements. That sounds really interesting. I really like that bit about everything should be grepable, and everything should be googleable, googling everything. I kind of agree with that one. We live in a world where we're always doing bespoke things so that one feels a little bit harder that we're always going to be able to Google it. But then that encourages people to constantly publish the bespoke work that they're doing so then others can benefit from that work. But the grepable, I absolutely agree with that one. It's so frustrating where I see a method, but I cannot find its definition. And then having the ways to figure out where that method is defined to then find its definition is crucial. CHRIS: Yeah, it's interesting. I definitely feel that way very strongly. And it's in such stark contrast to Rails. Rails is like, hey, don't worry. There's going to be a lot of methods. You don't need to worry about where they come from, or why they exist, or what they are, or what they do. Well, probably what they do. But all of the magic inflections on database tables,, and suddenly you have methods named after every column. That's both very magical and hard to grep for or impossible to grep for, but it also leaks the entire structure of your database into your application in a way that I've always felt a little bit complicated about. And so explicitness, grepability, those are things that I care about. There's another one, delegates in Rails, that I sometimes pause around using especially when it's like delegates 19 methods to user prefix user. And so you end up with methods that are like username. And that's a delegation to the user object to get the name method off of it, but it creates the method user_name. And you're never going to be able to grep for that. And it saves like a little bit of code, definitely, but it saves this very obvious, very knowable code. So this one I actually shy away from using delegates in most cases, and I'll just write out the methods manually because sometimes I like to hear the clackety of my keyboard. There's a reason I have a clackety keyboard. STEPH: You want to get your money's worth. You want to clackety as much as possible. Yeah, I'm also not a fan of delegates. This may be a lie, but I don't know that I've actually ever used it. I've worked with it, but I can't think of a time that I've implemented delegates. Maybe that's a lie, but I'm going to say it anyways because that feels true, at least in the last couple of years. CHRIS: I feel like that could be true for the last couple of years. I would be surprised if you have never even added to a delegates line. Because that's the thing, you can just keep shoveling stuff into them as well. So I would put money on you having used it at some point and then just forgotten about it. But who knows, maybe not. STEPH: This is where we play two truths and a lie and that one's my lie. [laughs] Yeah, that's also fair about adding to it because if that's already defined and it's easier to add to it, I don't know. Who knows what past Stephanie has done, probably some wild stuff. CHRIS: It's unknowable at this point. It's lost to the sands of time. But looping back to the core thing of this refinement and the module, I think I'm leaning in the direction of doing that and unwinding my wrapping and wrapping layer thing. Because obviously, as I talked about...I think it was the previous episode or maybe two episodes ago. There was conceptual complexity to the additional wrapping layer. Even as I was fully in the context of working on that, I was still getting myself confused in either triple wrapping or then unwrapping too much or whatever. And these are the concerns with this type of code. So moving away from that feels better, having just a single layer of context wrapping around a given value. And then the other thing it's actually just a lot less code, and it's less prone to error, I think. That's my hope. I have to look into exactly how refinements get used, but I noticed in a couple of places that sometimes we were wrapping with this local value object that gave us the bimap method, and sometimes we were forgetting to. And so, I could see that being a very subtle, easy way to introduce failures into the app that would be hard to catch just by looking at it. So I think having a more global refinement...although I think that's sort of a contradiction, a global refinement because I think refinements are meant to be local. But anyway, I'm going to look into it because it's a much more concise code sample than what I have. Yeah, I'm going to poke at that a little bit. But it was an interesting exploration of some different things. And then it forced me to consider why am I so resistant to monkey patching at this point, especially in this particular case where I think it's okay-ish? STEPH: That's a good question. Do you have any insights? I am also resistant to monkey patching. I feel that pain and also that timidness of diving into that space. But I'm curious, have you figured out any other reasons that you really prefer to avoid it? CHRIS: I think this one falls into that sort of...what's the word? Like tribal knowledge of we've been burned by it in the past and therefore we build almost a...religious is too strong of a word but that sort of cultural belief. This is a thing that we do not do because of the bad things that we've experienced in the past. And there are a lot of things that fall into that experiential negative space. So with monkey patching, things that I know we can run into is if I introduced this bimap method, but I introduce it subtly differently than the library will eventually, then they could eventually introduce it themselves. And suddenly, I have this fork of my code expects it to work this way, but you've now implemented it that way. I no longer can upgrade. This is a critical piece of infrastructure in my app. I've just painted myself into a corner by doing this. Whereas if I do this wrapping layer, that's my code. I own that. It's not going to be a problem in that same way. There's also the subtlety, the grepability that sort of thing is a concern in my mind. Like, is this our code? Is this their code? Is this an engine? Being able to find code within a codebase, I think, is a critical thing. And so that's a part of the hesitation. I also know longer ago prototypes...I want to say Prototype JS was the name of the project, but it was one that was just like, yeah, JavaScript doesn't have enough stuff in the standard library. So we're just going to override everything and add all of these wonderful methods sort of in the way that Active Support does, which is an interesting comparison. But the JavaScript community definitely moved away from Prototype. And now JavaScript is a language or the standard runtime that's available in most JavaScript engines. It has a lot of the methods, but there are conflicts, and stuff gets weird, and it's all complicated. But again, as I thought of it, Active Support is a complete contradiction to everything I'm saying. Active Support just adds whatever to anything, 2.days.ago. Why does the number 2 have a days method? Because it's great, that's why. But I'm just a walking contradiction, I guess. STEPH: Everything you said really resonates with me. And I'm just trying to reason with myself like yes, Active Support uses a lot of this, a lot of metaprogramming, and adds everything it wants to. So why does that feel okay? And I wonder if it comes down to one is more almost like an agreed standard. It's built by a team, and it's maintained by a team, and then it's used by a large number of people, and then you get that feedback. Or maybe it's not even just a team, but it's a larger community versus if it's internal to your software team, maybe that doesn't feel like a big enough group or if it just needs...Rails is also documented. So maybe that's part of it, too, is if you are going to dive into that space, it's easy to discover, and it's well-documented as if you are building an open-source project that other people are going to use. Like, you designed for the intent of people to use this pattern that you've introduced, then perhaps that's when it starts to feel okay. , But the experiences I have had is where people basically will add some dynamic programming or monkey patch an existing feature. And then that's very hard to find and has surprising results, or it gets outdated. So I guess it comes down to who are you designing for? Are you designing for more of an open-source community, or you're at least designing for the people behind you that are going to be using this? Or is this a one-off adventure that you have chosen for yourself and future developers to discover? [chuckles] CHRIS: Yeah, I think that's a good summary, although I'm open to the fact that I exist in a state of contradiction. I'm also fine with that, to be clear. [chuckles] But I think what you said is true, and I think there is subtlety and nuance and reasons that it's okay in one context and less okay in others. And that idea of just like, I don't know, this is one of those things that I got in my head that I've done the thinking a long time ago to decide this is a thing I don't do. So now, in order to override that, I would have to do so much thinking. I would have to be like, all right, well, my brain tells me, no, but I'm going to go reread everything about monkey patching right now to convince myself that it's okay or to fully get the context and the subtlety and the nuance. And so sometimes we have to rely on that heuristic knowledge of monkey patching, nope, don't do that. That's not a thing, but other stuff is fine. And well, Active Support is fine because it's Rails. But it is interesting to observe contradictions and be like, huh, look at me go. All right. Well, moving on. STEPH: It's our lizard brain that's saying, "Hey, there's danger here." [laughs] CHRIS: Exactly. STEPH: I rather like living in a world of contradictions, or at least I find it that I'm drawn to them. And maybe that's also one of the things that I really like about consulting is because then I join all these different teams, and I hear all these different opinions. So as I'm forming these opinions around something like tests are great, I really like tests, and then someone's like, "I really hate tests." I'm like, "Cool. Let's talk. I want to understand why you don't like this thing that I think is wonderful because then I'm really interested." So I find that I'm often really drawn to contradictions as I like hearing opinions that are very different than mine and finding out why people have a different opinion than mine. CHRIS: Yeah, the world is full of contradictions. So it's, I think, at least a useful way to exist in the world, to be open to them and to enjoy exploring them. But yeah, I'll update in future weeks if I do end up going the refinements route. I'll let you know if anything interesting falls out of that. And now we're going to take a quick break to tell you about today's sponsor, Orbit. Orbit is mission control for community builders. Orbit offers data analytics, reporting, and insights across all the places your community exists in a single location. Orbit's origins are in the open-source and developer relations communities. And that continues today with an active open source culture in an accessible and documented API. With thousands of communities currently relying on Orbit, they are rapidly growing their engineering team. The company is entirely remote-first with team members around the world. You can work from home, from an Orbit outpost in San Francisco or Paris, or find yourself a coworking spot in your city The tech stack of the main orbit app is Ruby on Rails with JavaScript on the front end. If you're looking for your next role with an empathetic product-driven team that prides itself on work-life balance, professional development, and giving back to the larger community, then consider checking out the Orbit careers page for more information. Bonus points if working in a Ruby codebase with a Ruby-oriented team gives you a lot of joy. Find out more at orbit.love/weloveruby. STEPH: So we made a recent improvement to our feature flag system, which I'm really excited about, that we have found a way to improve that workflow because it felt really great that we're...well, okay, I should say that with a caveat. It felt really great that we're using feature flags to ensure that the main branch is always in a deployable state. But it did not feel great around how tedious it was becoming to add all of the feature flags specifically because each time we're adding a feature flag, we're having to add a migration. So we're having to run a migration, add the feature flag column, and then we can interact with that feature flag. And that part's okay. It was more removing that feature flag once we're done with it, that that part was starting to feel tedious because then that's becoming a two-deploy process. So one change is to remove the code that's relying on that feature flag. And then the second deploy was to actually drop that column because we wanted it to be safe to make sure that the code wasn't trying to reference a database column that didn't exist anymore, which is what happened at one point at first when we weren't doing the two-deploy process. So the improvement that Chris White came up with is where we're now using a Postgres JSONB column. And it's here that we actually have a feature flag YAML file. And we can have the name of the feature flag. We have a description of the purpose of the feature flag. And we have an enabled property on there, so then we can turn it on and off. The benefit of this is now we don't have to do that two-deploy process. And we also don't have to run a migration for when we're adding a new feature flag. So we can add it to the feature flag file, we can load it in, and then we can set that property to say, "Yes, this is enabled," or "No, it's not." And that has just simplified our feature flag process. One tricky bit that I believe the team ran into is around enabling this with Active Admin because Active Admin was just relying on those database columns to then turn something on or off. But then we've added some methods that work well with Active Admin that then say, "Read from here when you're checking to see if something is enabled," or "Look at this list to see which feature flags can be turned on and off." So it's been a really nice improvement, and everybody on the team seems to be in favor of the ways that we've improved this. So it's been really nice. So I wanted to come back and bring an update on how we've simplified our feature flag system. CHRIS: That definitely sounds like a nice improvement, the ability to just more regularly iterate around that or taking away the pain, any pain associated with using feature flags. Because they are such a nice thing to have, but there's that overhead. Then you start to have that voice in your head that's like, do I really need a feature flag for this? Could I just sneak this one in? And we always regret that. I had a similar thing this week where I wrote some code. I didn't quite write as many tests as I should have. And it was wildly broken, just like all of the connection points through everything were broken. But then it pushed me in an interesting direction where I was like, well, what I'm going to do is write an integrated test. It was basically an event coming in from a webhook that then enqueued a job, which did a thing, which then spit out an email. But it was broken at like three layers, and I was very embarrassed, if we're being honest. But, I don't know, I was just having a low energy afternoon, and I did not write the test, which I know I'm supposed to do. So similarly, any pain that we can take out of these things that we're supposed to do, any way that we can pave the happy path, I'm all about those. I'm intrigued because I think we've talked about this before, but it sounds like you guys have a very home-grown feature flag system. Is that true? STEPH: We do. CHRIS: Is there something about it that makes it unique to your situation, or was it just like that's what happened? Someone early on was like, "We need feature flags. I can just do the simplest thing that works," and then that's where you're at now or? STEPH: You're asking a very good question. And I'm trying to recall what led us to the state that we're in because I feel like we had this same discussion several episodes back when we were introducing the home-grown feature flag system. And I was like, there are reasons, but I didn't really dive into those reasons because it felt very custom to the application. But now I've forgotten what those reasons were. So I think you ask a great question where it'd be worth revisiting to confirm that yes, there's a reason for this home-grown version versus using something like Flipper. CHRIS: I'm glad I'm at least consistent over time in the questions that I ask and the heuristics that I have. This does feel like one of those things. It's not quite like crypto where I'd be like, we can never write our own crypto. But a feature flag system, I would be really intrigued if there are things that they are just workflows or functionality that you really need that are not supported by any of the existing solutions that are out there. I think audit trails is an interesting one. I think Flipper has a hosted product at this point that does that, but the local version wouldn't necessarily. So maybe that's a thing that you want to get. Again, I'd just be really interested. It sounds like the current state of the world that you have is enabled or disabled; just broadly, that's it. Those are the two states for any given flag. Is that true? STEPH: It is. There's nothing complex with the flags in that nature. And then we use naming to indicate if something is more for beta, so if it's a change that we're making to the codebase, but it's a feature flag that we plan on removing, versus maybe it's a feature flag for enterprise customers. CHRIS: Oh, interesting. I wouldn't think of using a feature flag in that context where it's going to be like a persistent, long-lived; this is conditional logic around some state or some property of the viewer. I think of feature flags as a way to gate code conditionally based on a point in time. And the reason I asked about the enabled-disabled basically like the Boolean state for your flags is when I've worked with feature flags in the past, I've liked having the ability to say, for this user or these users, or this group of users, which we've named this is our beta list…and it's the ten people that just really love the product and are happy to bump into some rough edges. And so we'll put things on for them first or even like percentages, so roll it out to 10% and then 50% and so on. And I think the larger an application and user base gets, the more that sort of thing starts to feel right. STEPH: Yeah, we certainly have some complexity around where each customer can really specify which features that they want. And then the features also differ a bit for each customer. So we are in a world where we're pretty customized or configurable for different customers. And whether that's something that we could simplify, that would certainly be a good question or something to pursue. But part of this also feels like our decision may have been based around what the system was already doing, and we're looking for ways to make slow improvements versus trying to redesign the whole thing. Because initially, the way we were customizing all of these different features for customers was in a YAML file. And that part was painful because then, anytime we wanted to make a change, it required a deploy. So the introduction of feature flags is really to get away from having to deploy to then make a small change like that. But now that we're in the space that we can easily configure that change and do that on the fly and not have to issue a deploy, I think we're now in a good space to reassess. And the team may have some really good answers. Perhaps I'm just not recalling as to why we've chosen the more home-grown feature flags. But yeah, I'll visit that topic and report back. Because I've been coasting along on our new system and enjoying it, but you're asking some really good questions. CHRIS: I mean, as an aside, if you're coasting along and really enjoying it, then maybe you don't need to ask any questions. It's still interesting. I would be intrigued to know. But if it's not causing you any pain, then you probably shouldn't change it. Because frankly, changing out the feature flag system is going to be non-trivial, I'm pretty sure. You could feature flag the feature flag system, and then you can transition from one to the other. You need a third feature flag system for that. But anyway, I digress. [chuckles] STEPH: You referenced crypto earlier. So I think I like the feature flag, the feature flag system. We should have some crypto flags in there somewhere. I think that's a thing too. But I think the main goal if I'm looking into changing it would be, circling back to what we were talking about earlier, is discoverability, so having a home-grown feature flag system. How easy is it for…if nobody was around on the team and there was someone new working with it, how easy would it be for them to turn something on or off? And if that's easy, then that's great. Then I think we've got a great home-grown system. If that's challenging, then I definitely think it's worth reassessing. And now a quick break to hear from today's sponsor, Scout APM. Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more. Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform. See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed. CHRIS: One of the things that's been interesting working lately in the app that I'm building is thinking about testing. We have a number of interactions with third-party services. Frankly, a lot of the app is that at this point. We have a handful of different external data providers systems that we're interacting with, webhooks and flows and things like that. And so we had to make that decision that you always have to make in these sorts of situations which is, how are we going to test this? And there's a wonderful blog post on the thoughtbot blog called Faking External Services in Tests with Adapters. It's by the one and only German Velasco. And it is a beautiful summary of the different approaches that you can take, but it really dials into one, which is the adapter pattern. There's also a weekly iteration episode on Upcase with Joël Quenneville, which discusses a little bit more of an exploration of the different options. There are sort of a handful of different options that we can consider your whereas the blog post by German talks specifically about the adapters approach. But to talk about them briefly, there's one where you can go all the way outside your app, spin up a fake service. Typically, we would do this with Capybara Discoball, which is a wonderfully named project. But it allows you to spin up a little Sinatra app type thing such that your web application is still making quote, unquote "real HTTP requests." This external service is going to catch that and respond with whatever canned data or structured responses that you want. But you still have the ability in that to, say, tell it to create data beforehand or be in a certain state or respond with certain data or have any stateful persistence. So if you create a record in that external system, and then later you query for it, that system can do that. But it has the complexities of now, your test suite is running different systems. And do you have thread-safety or all that kind of stuff? So that's a particularly complex end of the spectrum. At the lowest end would be stubbing and mocking. You just take whatever external clients you have, and you're mocking the API calls in them. That's the lowest end. And that's the one, especially for feature specs, those I try and avoid. Then there's a middle ground of like WebMock or VCR, those sort of things where you're saying whenever you see an HTTP request that looks like this, respond in this way. You record the cassettes, all that kind of stuff. And then there's the one that we've settled on, which is the adapters. So the client that we've introduced in our local codebase to interact with any of these third-party systems internally has a class attribute, a cattr_accessor in the Rails parlance, I believe. And that allows us to switch out the backend. And so we have a real HTTP backend, and that's the one that actually runs in production and a test in-memory backend. And that in-memory backend can implement whatever logic. We're ending up with one of them almost recreating this external service, sort of re-coding some of their inconsistencies or oddities but also features and whatnot. But it feels like it has struck just the right balance, and it allows our feature specs to be very rich, very real. We start up the world, and we say, "Hey, external service be in this state." And then I'm going to go visit the page. I'm going to see the data. But we are almost making real HTTP requests. It's very close. It's always an interesting choice to make here. I'm very happy with the one that we've made, but it's still not perfect. There are always going to be trade-offs between the different options here. But it's always interesting revisiting this and being like, which one am I going to choose today? STEPH: I feel like my natural progression when testing external services; I always start with WebMock, and then I progress to using adapters. And then from there, I go to actually replacing the HTTP service that is receiving and then returning a response, like you mentioned to Capybara Discoball earlier. So I can certainly see what you like about the adapter pattern. You mentioned that you're coding some of the inconsistencies. That feels very real. I'm curious if you have an example of how you've had to manage that recently. CHRIS: A specific example would be the external API responds with certain error codes or error structures. So it's an error. It has a status of a number and then a reason, or sometimes instead of a key that is reason; it's the message. So it's like, oh, okay, I see that in this endpoint, you respond with reason, and then this endpoint you respond with message. So now, do I encode that into my fake? I guess I do. So my adapter now implements things like that. There are cases where it's inconsistency where I'm like, well, this is the way they behave. So I would like our test suite to exist in the context of that because then our app is getting exercise in a real way. But in some cases, it's like little bits of logic validation that an external system might do if that's an important part of the flow. The app that we're building has a lot of forms and a lot of data validation and things like that. And so, we want to make sure that we have robust handling around that robust messaging to the user so that it's very clear what they need to do and how they need to respond to things. And so putting in little bits of that like, oh, that's how you format a phone number, okay, cool. Our fake will also format phone numbers in that way, things like that. STEPH: Every time the topic of testing external services comes up, I really, really want VCR to be the answer. I really like the idea of being able to validate that...because you'd mentioned that we're programming the expected return from this other service. And it's very easy to get out of sync with those actual responses. And then we don't really have a great way to stay up to date other than we wait for production or staging environment to fail. And then we realize something has changed, and we have to go and update either our mock or our adapter. And maybe that doesn't happen often if you're working with an external service that is very good about broadcasting when they have a breaking change. But if you're working with a less stable endpoint, then I always want VCR to really work. But it's just one of those areas where I'm like, yes, that's the thing that I want. I want this idea where I can rerun my tests in a way that they actually hit that service and record the response. But then I have felt pain [chuckles] from working with VCR and how it's configured, and how people have used it. It's one of those where I don't blame the library. I like the library. But the way people have implemented it and test I have felt a lot of pain from that. CHRIS: Yeah, I definitely agree with that. It feels like it's nice if you can push the mocking all the way out to that layer. Because like right now, our codebase has code in it that is subtly changing the behavior for a test, and I don't like that. It's only the swapping out of the adapter, so it's a very minimal thing. And we try and push all logic away from that such that the test adapter is as similar as possible to the real production situation. But it's enough difference that I agree I would like if VCR would just like, I catch the HTTP requests, and I respond with the same thing and sometimes we can pass through. I do think one of the fundamental limitations, or at least very hard to get right things, would be sequential requests. So I post to this endpoint in the external service, which creates some data. And then later, when I make a GET request to their endpoint, I should get back that data that I just created. That's, I guess, doable because you can have sequential requests, have cassettes that are first this request, then that request, then that request. And it knows that, like scope them to a given spec. But that feels extra difficult. And it does, again to your comment, the maintainers of that project do a wonderful job, but it's a really hard target to hit. STEPH: Well, and one of the other hard requirements with using a tool like VCR is then that external service really needs that sandbox staging environment that you can use. So that way you can create this data, you can rerun your test. So they're actually going to hit this real environment. They're going to create this data and that not have any harmful effects. And then you can record fetching that data. So it requires a lot of pieces to fall into place for it to work well. But then I was just thinking as you're talking about adapters, I'm like, yeah, I love the adapter pattern. I've really enjoyed that one for testing as well. But then I immediately start to think, oh, well, what happens when it gets out of sync, and how do we know that it got out of sync? And I don't have a great answer to that. CHRIS: Production blows up, obviously. STEPH: Production blows up, and then we go update our adapter. That's very calm. [laughs] CHRIS: It would be great if CI could more proactively catch that or...yeah, I agree. I would love if VCR would work because that facet of it is so attractive. But [chuckles] I've never gotten to walk exclusively the happy path with VCR. So here we are. This is a classic case of here's four options as to how we can think about this hard and important thing that we do in our codebases, and they all have trade-offs much like everything else in software. STEPH: I'm going to add this to my developer bucket list to live in a world where I can easily validate if an external API has changed or not and then also have tests that know when something has broken before production does. CHRIS: Ooph, dare to dream. I like it. STEPH: I'm a dreamer. CHRIS: I want to live in that world. Well, with that wonderful dream to take us out, should we wrap up? STEPH: Let's wrap up. The show notes for this episode can be found at bikeshed.fm. CHRIS: This show is produced and edited by Mandy Moore. STEPH: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or a review in iTunes as it helps other people find the show. CHRIS: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed on Twitter. And I'm @christoomey. STEPH: And I'm @SViccari. CHRIS: Or you can email us at hosts@bikeshed.fm. STEPH: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Byeeeeeeeee. Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.

    306: If You Want To Go Far, Go Together

    Play Episode Listen Later Aug 31, 2021 45:14

    In this episode, Steph and Chris talk about things they've changed their minds about over the course of their careers as software developers. Steph talks about as it turns out, arm chair rests are good, feature flags and comments are also good, she's changed her mind about how teams structure the work that each person is doing at once, and believes strongly in representation in the field. Chris is not a fan up upgrading his operating system and when he first started out, he gravitated towards learning dynamic languages, and since then, much prefers functional languages, static typing or more broadly, static analysis. He also no longer believes in the 10x engineer, and also very much believes that URLs matter on the internet. So basically, don't call them single-page applications; call them client-side applications instead! Arq (https://www.arqbackup.com/) Karabiner-Elements (https://karabiner-elements.pqrs.org/) Kent C. Dodd's Epic React Course (https://epicreact.dev/) The Art of Code Comments by Sarah Drasner (https://www.youtube.com/watch?v=yhF7OmuIILc) Gary Bernhardt: Functional Core, Imperative Shell (https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell) Transcript: CHRIS: I still have dreams that I missed an entire semester of math class, and now it's time for the final. I don't know that I'm ever going to grow out of that. STEPH: That's wild. CHRIS: You don't experience that? It's a mixture of I'm in elementary school, but it's a college final. Like, the physical school that I'm in is my elementary school, but it's a calculus college course that I missed. And now it's time for the final, and I won't graduate college as a result. But it's also high school at the same time. Just every part of education sort of melded together into this nightmare scenario. Do you not experience that? I thought this was normal. STEPH: [chuckles] Not in a very long time, not since I was in college. But I'm imagining this very cute, young Chris showing up with a backpack to the calculus final like, "Oh no." [laughs] CHRIS: Yeah, pretty much, yeah. I really thought I would grow out of it at some point. But it shows...I think it manifests when I have anxiety about something else in the world, and then I have a math terror dream. STEPH: That's your stress sign. That's your terror dream. CHRIS: Apparently. STEPH: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Steph Viccari. CHRIS: And I'm Chris Toomey. STEPH: And together, we're here to share a bit of what we've learned along the way. Hey, Chris, how's your week going? CHRIS: Oh, it's going fine. Yeah, I'll go with fine. I had to upgrade my operating system. Enough things had stopped working or seemed to be pestering me about it regularly, which normally I'm going to ignore that for as long as I can. That's sort of where I'm at in the world these days. Like, I don't want to upgrade because I don't know what's going to break and whatnot, but then things had broken already. Text messages were no longer showing up on my computer. And it turns out that the primary way that I interact with text messages is by replying to them through my computer. I don't want to type on my phone, that's not a thing. I'm already grumpy enough about text messages, to begin with, that I will regularly respond switching to email, and then I'll go off from there. But yeah, they stopped working, it stopped connecting. And then I got this really weird message from Apple when I tried to sign in. And I was like, I feel like I should at least try to upgrade to the new operating system, which I think has been out for a long time, and I've just been ignoring it. But then I had the added problem of I didn't have enough space on my computer to install it, which I tried once before. So I downloaded the installer, but the installer downloader doesn't check whether or not you have enough space to do the install. So it's just like, hey, so you know how you didn't have enough space? Well, we took up the remainder of it, and now you can't do anything about it. And the installer is hidden somewhere in the computer. So at one point, it just went away, and then suddenly had a lot of space on my computer. But finally, I decided to bite the bullet. I found a bunch of caches on my computer. So there was a cache for my backup utility, which is called Arq, A-R-Q, which was a lot of space. It was like 20 gigs or something like that. So it was like, sorry, you have no more cache. I'm pretty sure my computer's going to light on fire the next time it tries to do a backup because it has no cache to rely on, and it's got to try a lot harder, pull a lot more data down. I don't know what it does, but whatever. It's going to do that. And then, I found the more general application caches on the computer. Spotify had like six gigs of cache. Well, what are you doing? Aren't you streaming from the internet? Stop it. That's not okay. That is not acceptable. Yarn had three gigs. I was like, what is everybody doing? And I busted all of these. I threw away everything, and my computer seems to be doing fine after the fact. So, were the caches even doing anything? I ask. Anyway, so I upgraded, and then some stuff didn't work. And so then I had to find the versions to make stuff work. The particular one that stood out was Karabiner-Elements, which I used to make my mechanical keyboard do the right things for the function keys. That stopped working. And I tried to upgrade it to the newer version because I figured okay; they probably hopefully released a new version, but it failed in the upgrade process. And it turns out the secret was I had to upgrade to an intermediate version. I was on 12.3, and I needed to go to 13.4. But in between, I had to go to 12.10. And if I went to 12.10, then the upgrade to 13...everything about it was everything that I hate about upgrading software. It's like, I just know it's working right now, and I feel like if I even just look at it wrong, this whole tower of software is going to fall over. The worst thing, the thing that I have not been able to fix, is now I use iTerm as my terminal, my terminal emulator as it were. And I typically run with transparency mode on which some people look at and say, "Wow, that's a choice." And I say, "I kind of like it. I don't know; it makes me feel like a hacker or something." I don't know, whatever. [chuckles] Let me live my life. But for some reason, switching to Big Sur, the version of OS X that I'm on now, iTerm doesn't have transparency anymore. And I just haven't been bothered to fix it yet. But, man, I got rambly. I clearly have some feelings about upgrading software. STEPH: You have so many feelings. The fact that you kept going...People can't see me, but I'm just dying because of that whole story. [laughs] CHRIS: I kind of felt like I had to get through it. I had to exorcise the demons, tell my tale, and then be done with it, which I think I'm at now. STEPH: When I start laughing that hard, [laughs] I try to hide from the camera view because I want you to keep going for people to listen. CHRIS: But what's fun is you bob and weave. You'll hide for a minute, and then you'll come back and be like, okay, I'm composed, never mind. And then you'll just fade off to the side again. So yeah, but I powered through. [laughs] STEPH: Oh, all right, there is so much there. [laughs] Upgrading is the worst. I agree with that. That was actually something I ran into earlier this week. Well, it was a mix of where upgrading presented a problem and then upgrading something else resolved that problem. And so that was an adventure where I shared a tweet. I can link to it in the show notes as well. But Ruby was just taking up 100%, a full core, just all the time, and I couldn't figure out why. I wasn't doing anything with Ruby. We weren't talking at the moment, but it was just turning up one of those 100% CPU or higher. And so then I did some searching. And I did find the resolution, which was to upgrade the Listen gem because there was something in the Listen gem that didn't fully support Big Sur. Is that the name of the thing that I am on? CHRIS: That's the new one, yeah. I know because I've just upgraded to it. I have thoughts on the matter. [chuckles] STEPH: Cool. [chuckles] Yeah, when I upgraded to Big Sur. But then someone had kindly marched in to fix it, then upgrading resolved that problem. And Ruby is back to a peaceful level as to the amount of process, the amount of CPU that it should be taking up. Transparency mode, I'm thumbs up on it. I like how you called that out, how that's a choice. And I'm with you on that choice, although I didn't realize that's broken. I guess I just hadn't...I guess I don't care deeply enough that I've tried to restore my transparency, but you're telling me to hold on. CHRIS: We're going to get realer now in this moment. So I have a very old version of iTerm because it has a different way of going fullscreen than the default operating system level fullscreen. I really hate that it animates to fullscreen, and it doesn't quite fill the full screen. Like, it still had a border around it or something. So I have a very old version of iTerm that I've been running with forever, and I refuse to upgrade in any way as a result of I want to cling to this old version of things working. But as a result, I think I finally hit the end of the road on that. This is like years running now too. I remember I kept it in a Dropbox folder so that each time I upgrade or get a new computer, I'm like, okay, good. I still have my old special version [chuckles] of iTerm. But I think that time is over and I got to find...I feel like there are new terminal emulators out there. It's like Alacritty and other stuff that people talk about. So maybe it's time for me to try and find something new as long as I can get that transparency because I want to feel like an uber lead hacksaw. STEPH: You have such a brand of new-new that I'm now discovering that you are also a software hoarder, so you have both in your personality. [chuckles] CHRIS: There was a period early on in my software career that was like, oh, I got to find all this stuff. I got to figure things out and configure it. And then I was like, wow, that's taking up a lot of my time, I should stop it. And I think since then, I haven't upgraded anything. If you go look at my .files, I don't know the last time I pushed to them, but it's been a while. I'm still doing things, of course, but not as much. I know the cost of it, and I know the cost of maintenance. And really, this is an allegory for software overall. This isn't just about our local development environments, but entropy exists in software. Software does not exist at rest, and it will decay over time. And so the idea of we've worked with so many clients where they're like, yeah, we're on Ruby 1.8, and it's Rails 0.9. So okay, all right, well, we're going to have to deal with that, it turns out. We can't just keep ignoring that. So really, it's the same story played out but in my local hoarder cavern. STEPH: There was a part of the saga, the story that you shared with the installer and that you don't have enough space, and it took up the rest of the space, and you can't do anything. I'm very nervous; what happened to your stuff, your space? How did that resolve? [chuckles] CHRIS: I finally bit the bullet. And so I have a bunch of...I've tried a bunch of the different pieces of software that will visually analyze your disk space. So they crawl the whole directory starting from the very root of your computer, and it will be like, all right, applications has this much, and the library directory in your home directory has this much. Here are all of the different places that stuff might be hiding on your computer. And then you can visualize and be like, okay, that's where the most of it is. Node modules, as an aside, we did not choose an efficient way to approach how to put code on my computer because Node modules take up a lot of space on my computer, but they're so spread out. Multiple times I've seen people share a version of rm -rf, and then it's some subshell that does find every Node modules directory underneath a code folder. So you can find every single Node module and just blow them away. That will regain you some space. But that was not the solution this time. I've tried lots of piecemeal solutions over time. But eventually, the thing that got me there was just busting all of those caches. So I cleared the backup utility, Arq's cache. I cleared a bunch of them, Spotify Yarn, et cetera. And that cleared enough space for the installer to actually run. And then, once that was done, the installer program itself was no longer around, so I reclaimed that space. But it was this weird chicken and egg thing where I had to have enough space to complete the installation such that the installer could go away. And now...actually, let me see what my hard drive looks like now. So somehow, according to the Macintosh hard drive info, I have 50 gigabytes of available space, which is really frustrating because there were a number of weeks where we went into a Bike Shed recording, and I was like, I have one gigabyte. I'm not safe right now because this audio is going to be more than that. And so I don't know how now I'm sitting at 50. I guess all those caches that I cleared and the installer being gone probably puts me in a good spot. But anyway, I'm living in an upgraded, wonderful world. As an aside, Big Sur is ridiculously rounded and colorful and almost cartoonish. They're really leaning into the iOS vibes. And I'm not sure it's my personal aesthetic, but that's fine. I spend most of my time in the terminal anyway. But I think that's enough of me ranting about upgrading my operating system, which apparently I had a lot to say about. But what else is up in your world, Steph? STEPH: I do appreciate the ranting, though. You're not often grumpy, and when you are, it's quite humorous. [laughs] I really enjoy the grumpiness. And it's often a painful process. So I appreciate all of that story. Something that I really need to share with you and get off my chest is a couple; I don't know, x number of episodes back, you and I were talking about computer chairs. And I bragged about the fact that I have a computer chair that has no armrest, and I love it. I love my chairs like this, and it's wonderful. And I just think it's the best way to live. And it turns out that that's bad because I happened to go see a massage therapist who's also very well-skilled in physical therapy and other areas. And they were talking to me about my desk setup. And I mentioned the fact that I get these typical headaches, and I have my chair, but there's no armrest. And they're like, "Oh, that would do it." I was like, "Why? I like my setup. What's wrong with it?" And they're like, "Well, if you don't have armrests, then your back is having to compensate and to hold up your arms and your shoulders all day. So while you're typing, you're using more muscles to then hold that. And then they eventually tighten and contract, and then that can cause headaches." So in case, I have led anyone astray into having no armrest, they are apparently very important to not having headaches or having your back overworked to the point that you have headaches, which I'm a bit sad about. But on that front, I have ordered a new chair, and we'll see how it goes. I will have to assimilate into the world of chairs with armrests. CHRIS: We welcome you with open armrests. [laughs] Sorry, I saw it, and then I went with it. Anyway, I'm realizing now I actually don't use the armrests on my chair per se. I actually end up putting my arms on the desk, which is probably not ideal either. I have a little wrist pad so that my wrists are brought up and so that I don't have the upward breaking of the wrist thing going on. I think that matters a lot. And then my arms are supported by the desk, but it is just right on the desk, and I wonder if that's worse. But I've never...I don't know, getting the armrests just right and then also having the wrist pad. But I can't adjust my desk is probably the main problem. If I could bring my desk down a little bit, and if it were a thinner top, then I'd have more flexibility. The chair that I have is wonderful and has flexibility. The arms can go up and forward into the side and lumbar and this and that. And so I'm able to make the chair work to the desk. But I do wish I had more of an adjustable...ideally, like a stand-sit desk. But I haven't made that jump just yet. STEPH: When you're ready to make that jump, I'm going to share with you where I bought my desk because I'm really happy with it. And it's also not nearly as expensive as most of the other desks that will go up and down. CHRIS: Presumably, we can include it in the show notes as well so that we share it with everyone. STEPH: Definitely, yeah. CHRIS: Otherwise, that's just kind of mean. [laughs] You and I have a weird back channel that we talk about on the show, but they're not actually put in the show notes. STEPH: We're not mean. We wouldn't do that. I love my desk. And it was from someone else. They're the ones that shared it with me, so I'm happy to pass it along because it has served me well. And yeah, I'm also not sure about how this is going to work with the chair and the armrest because I'm just worried they're going to be too wide, and they're not going to actually offer support. I have doubts. I have lots of doubts, but I'm willing to investigate. And we'll see how this goes because I would like for the headaches to stop. CHRIS: Good luck on that front. That definitely seems like an indication of worth putting in some effort there. STEPH: Agreed. I also have some other exciting news. Stephen Hanson at thoughtbot has organized a number of other thoughtboters to get together who are interested in really diving into leveling up, learning React, and specifically focusing on purchasing the Kent C. Dodd's Epic React course. And it's for anyone that is comfortable writing code, whether you know React really well or if you're new to it. Everyone's welcome to join. So we just kicked that off today where we're going to go through the course together and then meet every Friday. I think the cadence is probably three hours, three and a half hours every Friday, that then we're going to commit to working through the course together. And I have to admit, I always nerd out a bit over how does someone build a course? Like, I'm really excited about the content as well, but I just want to know how did someone go about producing this content and then sharing it with everyone? And then what's their outline? How do they help people that are getting stuck because they can't be there in the same room? How do they record their videos? So I'm really excited to see all the ways that Kent has crafted this workshop. And so far, there's so much content, but I'll have more to report as we really start to dive in. But I'm excited to revisit React because I haven't been in React land for at least a year and a half; it's been a while. And so it's one of those areas that I know some bits, but a lot has also changed. And I would like to just revisit that world. So I'm really excited to dive into the course. And so far, I really like the structure that Kent has taken with the curriculum where we're focusing first on what exactly is happening and all the effort that goes into if you wanted to actually write HTML and then layer on JavaScript on top of that. But then here's how React makes that easier for you. Here is how JSX makes it even easier on top of the React API. I really liked that. Here's some pain; feel a little bit of pain, let's get a little bit better. And then let's get even better on top of that. And that has been a really nice reminder and progression into the course. CHRIS: I'm definitely a fan of the way you're describing it like, feel some pain, and then let's get better. But then, like, what's the hook? With any educational content, this is the sort of structure where there can be full education. But this is the thing that I feel very deeply about conference talks is my goal isn't to teach you everything if I'm giving a conference talk; it is just to get your attention just to say, "Here's the thing, here's why you might care." And starting from the problem, starting from the pain is always such a good way to do that. Because you know how this stuff is hard? What if I had an option that was easier? And then building from that totally makes sense. I want to say that course, Kent's course was built in conjunction with the egghead team, egghead.io. And it's a distinctly branded course. But it was built on top of the framework in the platform that's there and all of that, and then some of the editing support. I don't know this for certain, but I think there was some teamwork there. And I love just pushing forward the envelope of how we do educational content in the world of development because it is such an interesting world that has, frankly, such a need for ongoing development. The world is changing out from underneath us every two days. And therefore, having great educational content is so important. So yeah, definitely interested to hear how your experience goes both with the course and then also diving deeper into React. Well, switching gears just a little bit, I had a topic that I wanted to dig into with you today. And so to give some context, the topic, the thing that we're going to be talking about today is what have we changed our mind about? So you and I have both done a little bit of thinking and tried to come up with some answers to this. The background, this was actually inspired by a tweet that I saw between Shawn Wang, aka "Swyx" on the internet, and Charity Majors, a recent guest here on this podcast. And Charity is someone who is known for having strong opinions. But Shawn asked the question of what are some opinions that you've changed your mind about? And Charity actually had a wonderful list, which we'll link to her tweet thread where she shared some of her both technical and then also more personal ones, but really talking about the sort of evolution of thinking and the way someone's thoughts can change over time. And I thought it was just such an interesting thing because, for most points in time, we experience someone's sort of snapshot of where are you at now? What do you believe to be true? But I think there's such an interesting story and sort of the arc there of what did you believe to be true that you don't anymore? What have you softened your beliefs on? What have you strengthened your beliefs on? So yeah, with that as the context, what have you changed your mind about, Steph? STEPH: Yeah, this one really got me thinking, and I feel a little stumped on it. I have a few that I'm excited to share. But I'm very excited to hear your list to see if that also helps me reflect more on some of the things that I have changed my mind about. And I have found that there's only a couple maybe that I feel like I've really solidly changed my mind about. The others, I've either dialed up the strictness, or I've dialed it down. So the ones where I've really changed my mind about are feature flags and comments. Those are two of them. Well, there's a third one, but I'll get to that in a moment. So starting with the first one, feature flags I was more in the camp where I very much appreciate feature flags, but I use them sparingly because then there is a tedious nature of introducing them and then having to clean them up, and then having to maintain two states of code. But now I've really seen the value of feature flags and how we can make sure that we have calm releases and ensuring that main is always in a deployable state. So feature flags is one for me. I'm very invested in having more of a robust feature flag system because I see the benefit to that. The other one was comments. I used to be very rigid about comments are bad. We should never have comments in our code. They are just waiting to go out of date, and they're not going to be helpful. But I have since dialed down that strictness where I have certainly seen moments where comments do feel very helpful, and I can see how people use them. I still want to avoid them for the most part, but I am less strict now in regards to people who really find value in comments. I'm more open to that discussion. I want to understand what it is they find helpful about that comment, and if it is something that we can't capture with code or a test, where does that live? CHRIS: Those are both interesting. Feature flags, for me, I think I actually was more strongly opposed in the beginning. Earlier on in my career, I saw them as added complexity, as noise. I often would encounter them left behind in a codebase. And so, I had this negative association with them. And I didn't see the value; I hadn't yet felt that pain. And over time, I've definitely shifted to where you're at where I'm like, I love feature flags. This is a critical tool in our toolset of how we actually…like you said, calm deploys, being able to always deploy main, making sure that we don't have long-running feature branches. There are so many benefits that come out of it that I'm now very strongly in favor of them. But it's interesting; I think I would say that I started in a more strongly opposed place. So that wasn't on my list, but it's an interesting one that you've brought up and probably one that I've moved more on. Code comments, I think, actually started in my career being like, obviously, you comment your code. It's the thing that I read about and stuff. And slowly, over time, I think I've just dialed in on I don't think we should be doing that. There are, of course, going to be exceptions. And actually, one of the things that I discovered about myself as I was trying to go through this exercise is there are very few things that I believe are black and white. If anything, that maybe is one of the things that I've leaned into over time. It's like, nothing is binary. Nothing is black and white. Everything is on a continuum or shades of gray. There are things that I believe a little more seriously. But there's almost nothing that I can be like, nope, absolutely I will not equivocate on this beyond how we interact with other humans and being reasonable, kind people. And in terms of software practices, not really. Comments, though, are one that I still am pretty strongly not going to lean into. So it's interesting that you're like, eh, I've kind of opened up to that one. STEPH: There's a particular talk, The Art of Code Comments by Sarah Drasner, and that's the one that really shifted some of my opinions around comments, and then how we talk about them, and what benefits they can play. But I will admit, if I see a PR that has code comments, I still immediately have a negative reaction to that. And I want to have a conversation around why that comment was added and if we can remove it, and how we can remove it. But even with that negative perspective, I still find that I'm more open to that discussion versus before, where I would have been like, no, that's just unequivocally bad. CHRIS: I do like that you always bring up that talk whenever we talk about comments. This is a great talk. And in the background, I just looked up Sarah's Twitter profile because every time you bring it up, then I mention that she has a still from the movie Labyrinth in her Twitter background, but she actually changed it. And so now that's not true anymore. It's now something from The Force Awakens. Well, it's actually a joke, but I'm still going to suggest that you watch the movie Labyrinth at some point. That's the thing that I feel actually kind of weird about. It's a weird movie. STEPH: I'm going to take your suggestion, but not watch it. But thank you. [laughs] To share my truth today. CHRIS: That's fair, that's fair. STEPH: What are some of the things on your list? CHRIS: Okay, I have a couple, some more on the technical. Let's lean into one of the technical ones. Early on, I started with dynamic languages. I think I started with Python primarily and a little bit of JavaScript. I eventually found my way to Ruby and felt very at home there. And then, I started to explore functional languages. And I started to lean into them really hard and felt that immutability and functional programming and true pure functional programming was the thing. It was the answer, and I just needed to figure out how to do it. And so I would say that is the belief that I have since changed my mind on and decided, you know what? Actually, it feels like a bit of a force fit. I have tried. And maybe for others, it is actually a really fantastic way to build software. But having worked with a number of other people in more functional contexts, I find that it is a bit of a force fit. It's a bit rough. And in particular, of late, I've been working with Svelte as opposed to React, and React does sort of lean into the functional paradigm, especially with Hooks and all those sorts of things. And it's a little bit rough because it turns out UIs are these deeply mutable things. We're changing values or typing things in. There are actions that are changing the state over time, and having a system that just more directly models that feels very natural. I still love functional programming for the more core of an application. So again, I reference this talk often, but Gary Bernhardt's Functional Core, Imperative Shell. Gary has really formed some of my thinkings on this. And now I've started to find the examples in the work that I'm doing of like, oh, okay, I see that pattern actually applied here. But much as I would love to use them, the functional languages I find just aren't quite landing for me. And additionally, the mutability, particularly in the front end right at the edge of the UI, is not quite as good of a fit. STEPH: So I think that resonates with me although I do still get very excited about following more patterns that represent more immutable state just because I felt so much pain and found bugs from the fact that we have mutated state in surprising ways. I'm honestly not quite sure how I feel about it. I'm going to have to think on that one. That's a very interesting one that you've changed your mind on. CHRIS: Yeah, similarly, my feelings are lukewarm, whereas before, they were stronger. I was like, oh, okay, I think I found something here. And then, in attempting to use it across a wide variety of applications, it just didn't quite feel right. I felt like I was swimming upstream sort of thing. Actually, there is an interesting counterpoint. One thing that I have leaned into and definitely changed my mind on and embraced is static typing or, broadly, static analysis. But I think static typing being the most pointed version of that. Early on, like I said, I got my start in very dynamic languages in Ruby, and Python, and JavaScript. And so that dynamic duck typing runtime can be anything. We just make our systems respond to the messages, and all of that sounded great. But it turns out I really love having a compiler that can tell me some truths about my program before it ever reaches runtime. And the idea that a typo can make it to production feels absurd at this point. And actually, as I'm working in Ruby, I'm like, man, I really got to go look at that whole Ruby typing thing we got going on. I don't know what the state of it is. I've looked at it in the past, and I need to revisit it soon. But like TypeScript, I've definitely embraced that very strongly. And I would not work without TypeScript in a JavaScript project at this point. I've loved the work that I've done in Elm, although that also sort of blends into the functional stuff where it's like, it was a little bit noisy, though, I'll say that. But the type system and the fact that the compiler can give you so much rich information about your program, I would not trade that at this point. And I don't see myself going back on that front, which is an interesting place for me to be on of actually, I'm not that into the functional programming as the core way that I build my applications. But I do like static typing. And I feel like functional programming and static typing actually go together incredibly well. And functional programming and, more imperative, whatever it is that I'm doing with my day-to-day life these days is a more interesting fit. But it is interesting to me to observe that sort of combination of opinions where I really like static typing, and having a compiler, and something that can tell me about my program before I get to runtime. But also saying that I don't quite want the functional programming thing, or at least not as the entire way that I modeled my application because I found it a bit difficult to work with. Because I think static typing or compilers and functional programming go really well together. But I think generally, what I'm finding is a more middle ground dynamic optimization of a bunch of different things. And the answer is like, well, it depends which I guess if you've listened to the show before, you'll have heard those words said, so I guess it makes sense. STEPH: Yeah. All of that makes sense to me. And I can see why you might have a favor for types or why that feels more valuable initially because that is giving us so much feedback right off the bat versus following a more functional paradigm is something that could feel like more of a force fit and doesn't provide that same immediate feedback. But it has a longer-term or a longer cycle of that reward system. So I can see why you might favor one over the other or why I myself would favor one over the other. CHRIS: How do you feel about types? STEPH: I'm a big fan, although I say that, but I work in Ruby. [laughs] I don't have them. But when I have worked with types, I very much enjoyed it because it makes me think more about the design of my code in a way that I don't as much with Ruby. And working with types has heavy influence than when I am working in Ruby and thinking about the design of my code. So I think working with types is a wonderful thing that, frankly, all of us should do as developers at some point because it is so influential. So I'm for types, but I'm not using types in my day-to-day. Another thing that I have changed my mind about is how we structure the work that each person is doing. So I used to be more in the camp of everybody can work on their own very complicated piece of codebase, their own complicated feature. We can have a bunch of complicated things in the sprint, and everything will just be great; it'll be fine. And we'll get a bunch of work done, and we'll ship it. And then we're an even more productive team. And I very much disagree with that now where I have found where everybody is working in their own silo on a complicated feature has slowed down the progress of then being able to ship that feature. Because we often want to collaborate with someone, we need to collaborate with someone. Then the PR review process is tough if I really have no idea what you're working on, and I don't have a context that then when I look at your code, not only am I evaluating at the code level, but then I'm also trying to understand the feature and gain all of that context. And that's a heavy cost for me to have to pay to then pick all of that up and then for you to have to reintroduce me to what's happening. Or I might make the bigger mistake, and I may look at your code and just evaluate it from the code perspective but not really understand the feature, the value that's being delivered. And that doesn't feel useful. And I have a recent example where that happened where someone was working on a very complicated feature that I didn't have any insight into. So then, when I was looking at the PR, it was easier for me to just look at the code and get feedback on that. But then it was probably a day or two later. It wasn't until then that I finally started asking, what are we building? Like, what purpose is this serving? And that opened up a much larger discussion where we realized what was being built didn't actually really deliver what we needed to deliver. So I no longer agree with the idea that everybody should be working on their own complicated features independently, and there should be some collaboration. And, you know, it's the buddy system; we all need a buddy. CHRIS: Well, I like that one. I feel like I've shared similar ideas where it made sense. It was just the efficient thing to do, to split the work up and have everybody very independent. I also feel like earlier on in my career; I was more scared of Git conflicts and things like that or people interacting with the same parts of the code. And so in my mind, it made sense to really strongly separate like, oh, you shouldn't even be touching the controller for this. I'll handle the views, and you handle the controller; it'll be separate. And I care less about that now. And I think what you're saying of like, it's actually better if we have some shared context, and we understand what we're working on, and it's more of a collaborative process. Yeah, I like that one. I think I followed a similar arc, and I'm at a similar place now as well. Interestingly, to go into another one of mine that I think you'll probably be most surprised by on my list is I think I used to believe in 10x engineers. I used to believe in the idea of that one developer just off in the corner fueled entirely by Mountain Dew that would just produce the perfect code. They would just solve it. Over the weekend, they would write the entire billing system, and it would be great. And I think it was predicated on the idea that the coding is the hard part, which I no longer believe. I think coding at its core is communication. It's taking this thing that we want to be true in the world and then communicating it to a computer but also ideally communicating it to our teammates, and to future versions of ourselves, such that we can revisit that code, we can maintain it over time, other people can add to or augment it. And so the idea of this loner that can just do incredible volumes of work and have that be a good outcome that just doesn't make sense to me anymore. I've worked with incredibly talented developers, to be clear, folks that I was sort of in awe of. I've worked with people who have, I think, just truly photographic memories. They seem to remember every single bug that they've ever had and exactly where they can look it up. Or from the top of their head, they can just intuitively know, oh, this bug means this. Go look at this line of code. I'm like, how did you do that? How did you do that magic trick? And they're incredibly capable developers. But at the end of the day, the folks that I see being most impactful on a team are the folks that are able to communicate and collaborate most effectively and make the whole team more effective. STEPH: Maybe it's the Mountain Dew; maybe that's actually the secret sauce here. That's what I'm missing from my life to take me into that status. CHRIS: I'm now imagining Mountain Dew but in a more viscous form, like a barbecue sauce, but it's Mountain Dew flavored. That's the secret sauce because it's a very…anyway, moving on. [laughs] STEPH: It's a terrible product. We should make it and sell it. [laughter] CHRIS: Career pivot, we now sell Mountain Dew sauce. STEPH: [laughs] CHRIS: But yeah, I do not believe in 10x engineers anymore. If anything, I believe that that is a huge warning sign if you have anyone that's behaving in something close to that space. STEPH: Yeah, I'm super interested in that you've shared because I don't think...We've talked about 10xers, but we haven't talked about the fact that you used to think that they were more of a thing and that they existed. And now it's all I'm sorry, but it's all crap. [chuckles] That's super interesting to me. Do you remember what changed your mind? Do you remember that pivotal moment of where you were like, oh, maybe this is all bullshit? CHRIS: I think it was just an amalgamation of experience over time. I've encountered people who fit the archetype. But if anything, I would say they're deeply problematic in teams. They're that individual who refuses to collaborate, who just goes off and heads down, writes a bunch of code, but then it doesn't integrate with the other pieces, or no one else knows how to use it, or they won't let anyone contribute to it. And yeah, I've seen that just be very, very problematic. So the folks that most fit, I think the imagined version of this, actually end up, in my experience, leading things astray. And the folks that are actually most productive and really cause teams to improve in a drastic way behave very differently. They're much more collaborative; they're much more engaged with the team. It's less about their individual contributions and it's more about building a system together, collaborating, communicating, engaging external stakeholders, et cetera, et cetera. It's all that stuff that matters. And so, it's very much in contrast to what the 10x engineer ethos is about. But there's no one day where suddenly this idea that I had in my head crumbled when I saw that behind the pile of Mountain Dew cans, there was nothing there. [laughs] STEPH: It's all a mirage. [laughs] I do like what you just said around that there are very impressive people out there. And those impressive people often focus less on their individual contributions and more at a higher level around communication. And then they are the powerhouses that then is helping facilitate everybody else be their best and have high levels of individual contribution. Those are the ones that...I'm still not going to endorse a 10xer, but they are the ones who, to me, embody the idea of someone that is incredibly efficient and really good at their job. CHRIS: There's an adage that comes to mind here that "If you want to go fast, go alone. If you want to go far, go together." And that does ring true to me. I think an individual can have their individual productivity be higher if they're working entirely on their own, if they understand every line of code because they wrote every single line of code if they know where every feature of the platform is integrated because they wrote the whole thing. But they're going to be fundamentally limited. And in order to do bigger, more complex things, fundamentally, we have to work as a team. And then the way you have to interact just fundamentally changes. So I think it started from that, like, one person on their own I think can be individually more effective. But the minute you start to have a team, that one person acting on their own is actually dragging the team down because other people can't then work in that space, and that's a problem. STEPH: I really like that adage that you just shared where, "If you want to go fast, go alone. If you want to go far, go together." And that touches on something else that I have really changed my mind about, and that's representation. And this is more specific to me. So when I joined engineering and became a web developer, and I joined a team, and I was the only female engineer on that team, my initial feelings were I am the only female engineer, and that is fine. We're all just a group of engineers. We're here to solve problems together. It really doesn't matter if there's anyone here on this team that's like me. It's fine if there's no one that I can see myself in that's in leadership because we're all just people, is what I was coming down to. And I've completely changed my mind and realized that that's not true. And I've experienced this where I've worked on other engineering teams with female engineers, and it's fucking awesome, and it does make a difference. And then when I can see someone that I can see myself in, in a leadership position, that is also inspiring. So that is something that I went in where I think it was more of I was trying to shield myself from the idea that I am different from everybody else in this room, and that could be a problem. And instead, I just tried to neutralize it by saying it's not. But I think representation is incredibly important. People are not just people. We all have very important social and racial, and cultural identities. And it's very important that we get to feel that we can express all of those identities and see people that represent those identities in spaces where we would like to go. That's a big one that I've changed my mind on. CHRIS: Yeah, I certainly agree that representation certainly matters, and being able to bring your full authentic self to work and seeing others around you that reflect that. And frankly, having teams that are made up of people that represent the users of the software that we're building feels so critically important. And it's very interesting to hear about the arc that you've had on that where initially, you tried to downplay it, but then you found a little more truth in it. And so yeah, thank you for sharing. STEPH: You're welcome. It feels good to say that, too, because that's something that I've admitted and realized on my own, that that is something that has changed and shifted. But it's nice to be able to share that here with you as we're going through the things that we've changed our mind about. What else is on your list? CHRIS: Well, to round us off with one more very technical version because, of course, that's where I'm going to take us after a much deeper and more nuanced topic that you led us on, single-page applications. Broadly, I'm opposed to the name; that's a side conversation. But, man, URLs matter on the internet. So don't call them single-page applications, but client-side applications or whatever. Broadly, the idea of a bundle of JavaScript, and so you send down an empty HTML document, and then you reference a bundle of JavaScript, which that thing boots up and it then makes a bunch of API requests to the backend, and then it starts to fill in the page. I was convinced for a while that this is a reasonable and perhaps even necessary way to build software. We need APIs for our mobile apps anyway. So if we're doing that, then let's have that be the consistent way that we are accessing information. This is going to be fine; it's not a problem. And then eventually, we found some problems. So then we got GraphQL, and we tried to solve it that way. But overall…and I have spent a lot of time trying to make this thing work, trying to find a version of this that I'm happy with that I find the end outcome of the software to be as pleasant to work with from an end-user perspective as a server-driven application, and I can't find it. And so, to be clear, I'm still doing client-rendered applications these days. But Inertia.js is the framework that I've leaned into that helps me bridge that gap. And the idea that the server owns routing, that the server owns statefulness, things like that, not having to think about client-side routing, not having to think about client-side state management, being able to use traditional auth mechanisms built into cookies, all of these familiar things that we've had. Leveraging the fact that the server is the more privileged in terms of the information it has access to, the more secure, the more powerful environment, all of these things feel right to me. And the nature of the application that I can build just feels more robust, more consistent, easier to evolve. There were a lot of promises that I heard when we started building applications in these ways. And I just haven't seen an example or have not worked on an example, at least of an application that is built as a client-side bundle that boots up and does some stuff and had a good experience with that. So Inertia, as an aside, is my answer to this. And I continue to be extremely happy with that as a solution, as really a middle-ground solution. Because going all the way back to true HTML server-side rendering is limiting in other ways that I didn't like. But I find that Inertia really strikes an ideal balance in the middle there. STEPH: I feel like I completely agree with everything you're saying. But I also feel like I have a developer secret to share where I really haven't worked on single-page applications, and I am okay with that. [laughs] CHRIS: It's fine, skip it. Just go straight to Inertia. It's better. STEPH: Cool, cool, cool. I am working on leveling up React, and then the plan is to go to Svelte and Inertia. So I'll just completely...I'll skip that. I'll skip that part of my career. CHRIS: I actually want to back up just a little bit as I'm saying this because I really try to avoid being in a more negative space. And I think this space, this architecture for building applications, is complex, and there are things that will warrant it. So things like Google Maps, it makes sense to have a lot of Dynamic JavaScript and to be doing complex things on the client-side. Trello is another example of an application that that as a server-rendered thing, doesn't really make sense. And frankly, using a tool like Inertia wouldn't quite work there. That said, that is, in my mind, truly a single page within the broader application. So the Trello board page is a very, very complex stateful application, and I think modeling it as such makes sense. Google Maps, similar. But there's still the profile page, and the login page, and all of these other things. I think routing is probably where it breaks down for me. I think client-side routing is the thing that I feel the most pain on. Because at the end of the day, the server still needs to know the answer. And if we do client-side routing, we end up with this duplication of logic across the client and the server-side. We end up with disagreements from time to time. We end up with the weird flashes of half-rendered layout, and then we go to the login page because we get an API response that is different. And so, I think that is probably the kernel of the thing that I struggle with. And, of course, it is possible to build great things using any of these technologies. But I think my summary is I've really tried on that front, and I've just not been able to make the fidelity of application that I want using…primarily; I'd say it's client-side routing is the thing that I struggle with the most. STEPH: Yeah, it sounds like you're saying there are very valid use cases for using a single-page app or following that structure. But we haven't really gotten there in terms of our web development expertise, where we've made that easier to maintain and easier to implement. And there's still enough pain points around it that even though it seems like a very valid idea and approach, it still feels painful enough that you actively avoid it until it feels like something that you have to then invest in at that point to then really deliver the user experience that you want to provide. CHRIS: Yeah, I think that's an accurate summary. And I think adding on to that, I'm noticing it becoming more and more of the standard approach; this is the way we build applications, and I don't agree with that. That is probably the thing that is the kernel of what I don't believe in. I think actually server rendering is a great way to start, and then you can slowly augment or move more things into complex client-side behavior. But starting with this as the mode that we're building our applications just feels like a less stable foundation than I would want. So it's perhaps an architecture that you want to evolve to at some point as the complexity necessitates it, but I definitely wouldn't be starting there. Similar to service-oriented architecture, not going to start there. Client-side routing, I'm not going to start there. STEPH: Ooph. I feel like I've been holding my breath this episode. I feel like this was a very interesting topic that has been challenging to reflect on what we believe and what we've changed our mind about. CHRIS: I think it's perhaps more nuanced than a lot of our episodes where often we're saying this is what we did, and this is how we felt in the moment. And that can be very experiential and true. But this, yeah, we had to draw the line in the sand and say what do we believe? I similarly definitely feel more tension in this episode than other ones. But hopefully, it was useful. Hopefully, folks found some value in the things, and hearing our story, also, the idea that we have singular formed opinions. Hopefully, this episode has broken that idea in anyone's head. And we're all on a journey. STEPH: I really like how this has prompted me to reflect on the things that I used to hold dear and really cherish or follow strictly to then reflect on what are things that I used to believe versus what I believe now? Because that transition often happens so seamlessly for me that I don't really stop to think about it to be like, oh, something just happened that is really changing how I approach things, how I build, how I work with teams. And I really like this reflection point to be like, oh, what did I used to believe, and what's different today? I'd like to keep this practice going and just try to track the things...I'll have to make a list of all the things I believe. That seems like an easy list. [laughs] CHRIS: Just the easiest list to write. STEPH: The easiest list to write. And then I'll just check in with it every so often, scratch stuff out, or update it with the things that have changed my mind about. This is the good idea, terrible idea where you go, "Stephanie, that's a terrible idea." [laughs] CHRIS: I don't know, write it down on a list, and then look at it in six months and see if it sounds like a good idea, and then we'll be able to close the loop on the whole thing. But with that, should we wrap up? STEPH: Let's wrap up. I've got a list to write. CHRIS: The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review on iTunes, as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us @bikeshedor reach me on Twitter @SViccari. CHRIS: And I'm @christoomey. STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Byeeeeeeee! Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.

    305: Burnout & Bugs

    Play Episode Listen Later Aug 17, 2021 50:02

    This week Chris talks about Bifunctor optics and introduces an app he's been liking recently called CleanShot X, which is a replacement for the built-in screenshot utilities on OSX. Steph talks about her experience using New Relic Browser Stats to troubleshoot a slow page and burnout. Who's feeling it? (Raise your hand.) How do we identify it? What do we do about it? Svelte Is Beloved! - Stack Overflow Survey (https://twitter.com/sveltesociety/status/1422372693827985409?s=21) Bifunctors (https://stackoverflow.com/questions/41073862/what-are-bifunctors/41075765#41075765) CleanShot X (https://cleanshot.com/) Next.js Image (https://nextjs.org/docs/api-reference/next/image) Transcript: CHRIS: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. And we're off the rails already, everybody. It's going to be a good one. Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey. STEPH: And I'm Steph Viccari. CHRIS: And together, we're here to share a bit of what we've learned along the way. So, Steph, how's your week going? STEPH: Hey, Chris, it's going really well. We talked recently that I have a new laptop. So I have been migrating the things that I'm accustomed to over to my new laptop, but I also love that clean, fresh start. So as part of that fresh start, I was like, what if I use Safari? What if I just switch? I'm a Chrome user, for the record. I'm pretty sure you know that, but just to share that. I was like, well, what if I just switched and I try out Safari for a while? So that was the thing. CHRIS: So I heard the words try and the phrase that was the thing, but I'm going to probe a little deeper. How'd that go? Was it good, great, not so great? STEPH: Honestly, it was fine. I did enjoy being in a new environment to see how Safari handles bookmarks and then also the inspector. So it was novel to be in a different browser where I really don't spend much time in a different browser other than when I need to test this specific UI bug or things like that. But the reason that I ended up migrating back to Chrome was frankly for Chrome profiles because I really like that I can have this clear separation now between my work life and my personal life, and then it also keeps me signed in. So my personal email versus my thoughtbot one versus before the Chrome profiles, which I'm not sure how recent of an addition that is where Chrome introduced that feature. But before, I just always had to be signed into both, and it was just all together in one spot. But now I really like that I can separate. And it's more intentional where I'm like, oh, I'm going into work mode, so I just want that profile versus I do need to hop over to my personal side for a while. So that was the thing that brought me back. CHRIS: Interesting. I don't take advantage of that at all. I know of the feature, but it's never really called to me. And if anything, I do the opposite. So specifically, this doesn't work in the browser, but on my phone, I use the iOS Gmail client, and I use the unified inbox. So I just have everything come together. And I subscribe to the idea of, I don't know, it's all work and stuff. And hopefully, people aren't sending me a lot on the weekends, and I will defer and snooze and all of that. But that holistic view pulls me in. And so it's interesting that you're just on the other side of that. It totally makes sense. I actually think I'm wrong here. I think I'm doing the wrong, bad thing. But it's interesting just the way we're on the two sides of that. STEPH: I can see the merits for your approach where it all goes to one place. So you have one place to go and triage, and I think that makes total sense. I haven't triaged my personal life well enough that I want it to come into my work life. And that's the one that needs the more immediate response typically. So I want to prioritize all of my work emails and focus on that and then have my personal ones more like, okay, I've got some time, and I want to check on this. But I don't want to blend those together. Because frankly, I need to do some more triage on the personal side if I'm just going to bring it all into one space. CHRIS: Interesting. Yeah, I would almost view it from the other point of view of I want to protect my personal space, and this is obviously not what I do based on what I just said but protect my personal time so that when it's evenings or weekends or whatever, that I'm not seeing work emails in there. I do my best to snooze them and get them out of the way. But if they are coming in, maybe there's something I need to respond to or, I don't know, maybe it's FOMO in a certain way, FOMO but professional FOMO. I don't really know. It's interesting that that's the feature that brought you back. But overall, how was your experience using Safari? I have heard loosely that now most of the browsers are evergreen; even Edge has really caught up and is now implementing features in a similar way. And so Chrome, Firefox, and Edge are very similar. And my understanding is Safari is the one that actually lags behind or even holds back web standards and implementations and things like that. So, did you find any rough edges of that sort, or was it otherwise just fine, and it was mostly the profile stuff that made you switch? STEPH: It was honestly just fine. I also may have not used it long enough to run into any of those rough edges. But overall, it was just fine. It worked. I just got to that point where I've run into this situation before where I'm signed into my personal email, and then I'm signed into my work email. And then I'm going to Google Hangouts, and Google Hangouts gets confused, and it's like, which person are you? And then I have that moment of where I have to sign out of one, or sometimes it just gets complicated. And what I found with profiles is that that's just never an issue. I don't have to worry about it anymore. So yeah, overall, Safari was fine. I wouldn't mind going back to using it. I just really like the profile feature. This was one of those moments where it helped me notice how much I really liked that feature because I had just opted into it a while back. But this was that moment where I was like, oh yeah, I really miss that. So I'm going to go back to it. CHRIS: The thing you said a minute ago about which person am I? [chuckles] There's a deep philosophical underpinning there, but I've definitely struggled with that and trying to trick the browser into it. So Trello is the one that I'm struggling with that right now. I am one human in the world, I assure you. But GitHub gets this; GitHub plays the game correctly where I'm one human, but I have multiple internet identities. I am the work person. I am the open-source person. And I'm able to route notifications and things to the different inboxes based on the organization that they're part of, et cetera. And I really liked that, that GitHub seems to understand that I am a human that is multifaceted, whereas Trello does not. And so I use Trello in a professional context a lot, but it's my personal...like, I would have to create a distinct account on Trello. And I'm like, Trello, that's not true; I'm still one person. Just understand this Trello organization is a separate facet of my existence. Got on my soapbox on that part. The other thing I want to say is I do feel bad about the fact that I'm just on Chrome. Because increasingly, Chrome has got so much of the market share, and it's becoming the new deeply dominant thing. And so I want to be the agent of change or like, no, we should use different browsers, and we should support them and make sure that we're testing against them and all of that. And then I'm just on Chrome all the time, and I feel bad about it. But it's one of those like; I have so much muscle memory and built-up knowledge around how to use Chrome. And I've just used it for so long now that the switching cost would be pretty high, I assume. I actually haven't even really tried, but I feel bad about it. I'm now saying two things which are I feel bad about it, and I've never even really tried. So I don't feel great in this moment, but these are my truths. STEPH: [laughs] Well, I can plus-one your truths. Those resonate with me. Well, there's always stuff that I am trying that's new all the time. So I feel like I need some constant in my life until I'm ready for other things to be the constant in my life. And then I can muck around with which browser I'm using and change other things. And you have to be in that moment. You have to be ready for it. So going back to a thing that you said a minute ago about separating your work life and your personal life, I very much like that framing, and that's a nice segue, frankly. And it's something that I've been thinking about where you and I often start with technical topics. But I have a very people-centric topic that I'd love to chat with you about today, and it is emphasis on burnout. And who's feeling it? How do we identify it? What do we do about it? And that's been very much on my mind because I have noticed a lot of people around me, including myself; I just feel like we are more inclined to experience burnout right now or are going through it actively. And it feels even more important to have those conversations with each other and with ourselves to talk about what does it look like when we're burned out? How do we recognize when we're there? Because often, when we are burned out, it's not something that happens gradually, or at least it's not something that we notice happening gradually. It's like, okay, I'm fine. And then suddenly, okay, I'm burned out. And I'm at a place where then I can't really focus. I feel overwhelmed. I'm drained. For anyone that is less familiar with burnout, one, hooray, and then two, burnout is a state of emotional, physical, and mental exhaustion that can be caused by excessive and prolonged stress. So then that's what leads to us feeling very overwhelmed, emotionally drained, unable to meet constant demands, or those are the things that are causing our burnout. So I have been doing what I typically do when I'm thinking about a particular topic, and then I'm looking to gather knowledge and information is I try to go pretty wide where I start looking for podcasts, books, just people that are having similar conversations and trying to synthesize a lot of the information that they're sharing. And I have found some really good stuff. The question is now, what does one do once one has that content, and then how do you bring it back and help apply that content to yourself and then people that are around you? So I have some thoughts there, but before I go further, I'm curious, what's your experience with burnout? CHRIS: I think for me, I've been somewhat lucky in that I don't think I've ever really got into an acute period of burnout, but I've definitely had periods where I just felt weighed down. And there are ebbs and flows of life, and of work, all of those things. There is something that I've been thinking about recently, which is the inherent nature of the work that we do where consistently we're working on something where we don't quite know how to do it, and we're struggling, and we're struggling. And finally, we figure out how to do the thing, how to trick the computer into doing what we want. And then the minute we do that, in trying to encode, ideally, we're automating that away. And we take that solved problem, and we just ship it off. And then, we pick up the next unsolved problem from the list. This isn't entirely true, but it feels like sometimes unspecificity in sort of I'm just working on things that are underdefined, underspecified, and I'm trying to solve little puzzles constantly. And, I don't know, I was feeling that recently of the nature of the work was burning me out. And I think earlier on in my career; I definitely experienced this in a certain way. And then, in the middle of my career, there was this perfect inflection point of my skills and the level of tasks that I was going for. But then, the further I got into my career, the more I tend to take the weird underspecified stuff and anything that's relatively clear I'm giving to other folks on the team. I'm like, "Oh, here's this well-defined piece of work here. Can you go implement this admin page?" Whereas I am doing the investigate integrating with third-party platform XYZ that uses a SOAP API that isn't documented. I'm like, okay, cool. Let me roll up my sleeves and figure out what that means. And I noticed in my work that that was starting to weigh on me, and I was able to shake that off and shift around some of the tasks that I was doing. But that was a particular form where the work itself was weighing on me. And I took a step back, and I was like, why do we do the things that we do as developers? Because there's something just fundamental like, you have to enjoy that nature of challenge and constantly escalating challenge to a certain degree, I think, to really like this work, but it can be a lot sometimes. So I feel like maybe that's a slight digression from the topic, but it was a thing that I was feeling in this space. And that's a little bit of my story. STEPH: Well, the beautiful thing about that is it highlights everybody experiences burnout differently. So that could really be how someone is experiencing burnout where they're taking on all these very complicated, different tasks, and they're feeling just worn down by that and that they're not able to meet demand. And they get to that point where maybe they lose their interest in tech and coding because they have pressed too hard in one direction. And so then they need to take a step back. As for me, I've been thinking back over the last couple of months because there was once or twice where you and I had, I think a conversation here on The Bike Shed where I shared that things were okay, but I didn't feel like my normal self. I was losing some of my interest and energy for technology and coding. And I'm very fortunate; I love what I do. So the fact that I wasn't feeling that interest was a really big sign to me that something's different; something feels off. And it does vary depending on the client that I'm working with. And I think feeling that burnout then was a mix of some of those client pressures that I was feeling and that I was working perhaps too many hours as I was very interested in that client's success. And then the other stuff was more personal because we only have, to borrow from the spoon theory, we only have so many spoons to give. And so if you have a lot going on in your personal life as well, that's going to detract from the energy that you also have to give to work. Are you familiar with the spoon theory? CHRIS: I am not. STEPH: I recently heard about it, and I can't stop using it now because I really like it. But it essentially...and there's a really great article that we can link to so others can read about it because I'm not going to remember exactly who came up with this theory. But the idea is that each spoon represents a unit of energy. And let's say if you start each day with only ten units of energy and you use spoons to represent that, as someone needs energy from you, maybe it's work, maybe it's a personal commitment, maybe you're dealing with a chronic illness, then you are giving a spoon away to each of those. So at some point, you're going to run out of spoons. And you want to also be mindful of who you're giving these spoons to because you are giving that energy away. CHRIS: I definitely liked the idea of we start each day with a certain amount of energy, and different things can pull from that pool and whatnot. I'm intrigued by spoons as the unit. It just feels like a weird...I got this little bag of spoons that I walk around with, [chuckles], and I give them out throughout the day. I guess it could be anything in there, you know, objects. But, I don't know, spoons are interesting to me. STEPH: I think it's because this person who came up with the idea was literally having a conversation with their friend in a cafe. And so that was just something that was in front of them. And they're like, oh, I can use spoons to represent. Well, we'll have to double-check the article to make sure, but I think that's why spoons became the representation. So circling back to once you're in burnout, what do you do with it? And that is one of my questions right now. And that's what I'm trying to synthesize a lot of information around. Because once you're in that state, I don't know of a lot of great ways to help other than take time off because, at that point, you're in a crisis state. And you need to step away, and you need to find out how you can recover from having entered this state of crisis. So that feels really important to identify ways that once someone is in that state, that then we can help them. And that feels good. We can advise someone to take PTO. I still don't feel great about it in terms that then, as a manager myself, I don't really know of other helpful ways to then help someone through that period. So then I really started thinking about the fact that once someone is in that burnout stage, frankly, it's too late. We have let someone get to that point that now they are in that crisis instead of addressing it early on. So that is the other thing that's on my mind is one, how do we help people that are already in that crisis state? But then two, how do we start identifying that someone is starting to go in that direction? And then how do we help them tell us? How do we then triage those situations? How do we prevent them from getting to that burnout state? And that's where I've also found some really good content. And specifically, there is a podcast that I've started listening to called The Burnout Show. They essentially share their experience with burnout, and what they did about it, how they recovered from it, and then how they continue to fight it because a lot of people then still go back to the workforce. So then, once you do find a way to recover, then how do you go back to work? And there have been some really great episodes. And I'll be sure to include a link for it in the show notes. There's one particular episode with Grant Gurewitz, who is a guest on the show. And he speaks specifically to the strategy of Three Good Pockets. And this speaks to the idea that there are many things that we can't control in our day. It could be work, family, other commitments, but we can strive for Three Good Pockets of time where we focus on something that's just for us. This is time that's reserved for you and any activity that you find restorative or joyful. And each pocket can vary in size. So perhaps that first pocket is spent just reading a few pages from a book that you're enjoying, and then the next pocket of time is spent outside or calling a friend. And Grant also has a great suggestion around if you're worried that you'll get sidetracked and not actually step away, which I felt called out for that one because that one's definitely me. I will have good intentions, but then I won't actually take the break that I set for myself. So Grant recommends creating a list of restorative activities so that way when it is time for that break when your calendar is reminding you, then you have a list of these activities to choose from. So it makes it easier to say, okay, then I can do this for a couple of minutes, and I can truly step away from work and step away from my screen. But especially now, when so many of us when we're sharing our workspace with our restorative space, for everybody who is still working from home or working remotely, then creating those daily breaks are incredibly important to our wellbeing. And so, it has me thinking about what restorative activities can I add to my day? How can I encourage other people to add more restorative activities to their day? So I really appreciated that advice. And I have noticed that the idea of burnout, but not so much burnout specifically, I've been thinking of it as recovery and balance is a theme for me. And it is something that I am purposely choosing as a theme right now where I want to research and understand more of how we handle these situations and continue to make progress not just for myself but also for my team. CHRIS: I think finding that right cadence and structure and way to reinvest in yourself and ideally gain more spoons if that is at all possible or at least defend the spoons that you have, those all feel very meaningful. I do have a question. I'm interested in your thoughts on this. I feel like we hear about burnout a lot in our industry. I get the sense maybe that it is a more common thing. Like, I hear so many developers talking about how their dream is just to give up tech and go get a cabin and just farm in the woods or something like that. And I wonder, is it a more pervasive thing in our industry? So that's one question. Another is just an observation that we actually do work in a wonderfully...it's an amazing industry where being a developer, there are so many jobs out there. And I don't want to discredit anyone's efforts if they're earlier on and struggling with that. But broadly speaking, it is a developer's market trying to go out there and get jobs and extremely well-compensated, as a general rule. But does that come with this inherent burnout? And if so, which I'm not sure is true, I wonder if maybe we're just more vocal and maybe we actually share more in public. We have more blogs and podcasts and things like that. And that's just a common thing for developers, and so we hear the stories more often, whereas maybe in other industries, it is actually very common, but people are suffering in silence. But also I do wonder, our industry is still so young. The work that we're doing is changing constantly, and that churn and that working in the unknown maybe there is an inherent nature. So that's a bunch of pontifications off the top of my head. And I have no idea what the answer to any of them is. But I am intrigued because it does feel like the shape of burnout as a concept in the developer world is perhaps a little overrepresented, or maybe it shows up more than I would expect. And, I don't know, is the work that hard? I don't know. But then I hear these stories constantly, and I definitely have felt it myself, so maybe. STEPH: Yeah, maybe. Yes, I do think the work is that hard for the record. It's challenging work. I enjoy it, but it is challenging work between figuring out the tech but then also everything else that comes with that. I don't have anything to back this up, but I suspect that a lot of other industries are also experiencing burnout. And I just happen to be more aware of it right now because I'm hearing it more from my friends and the people that I work with. And I suspect that's more directly related to we all just went through 2020, and probably a number of us were trying to forge ahead and get through that time. And so there may be a lot of us that are just now dealing with those consequences of where we just pushed ourselves through a very hard time. And now a lot of that is manifesting and surfacing around really identifying the damage that we may have done to ourselves by just prioritizing work and trying to put our head down and get the work done even though there was so much happening around us. And I suspect that may be a contributing factor is that now people are really starting to recognize, like, oh, I feel this way. And maybe there's time for me to address it. Or frankly, it may not even be that there's time, but your body is just like, okay, I'm done. I made it through the past year or however many months, and I'm going to start shutting down on you. I've given you all the warning signs, but now we're here. We're at a breaking point. So I don't know about the other industries, but I do know the reason that it's more on my mind is because I'm just hearing it more from people, and they're just expressing it. And so, it has become more of a focal point for me, and I've experienced it myself more recently. I'm sure I experienced this back early on in my career, but I took a strategy of well, I'm just a junior, and I just have to get through this. And I have to build experience. For the record, that is not a healthy mentality. I'm just being honest about where I was in my life. And so, I didn't really stop to think about it, but perhaps it is becoming more normalized where people are having more open, honest discussions about where they're at. And if other industries aren't talking about this, I would love for them to. So to round that out a bit, this is something that is just very interesting to me. It's very top of mind. So I suspect I will be sharing a lot more content in future episodes that are just around this. How do we recover? And then how do we balance? How do we work hard without burning out? CHRIS: Work hard, play hard; those are the two placards that you have. Well, I look forward to continued conversations on all of those topics because they are sort of that's the story that underpins all of the work that we do. So I'm very interested to chat more about that. STEPH: Thanks. So what's going on in your world? How's your week been? CHRIS: Oh, my week has been fine. My topics are going to be way more mundane and tech-focused. But let's see, a couple of things, so one is that Stack Overflow has their I think it's Annual Developer Survey. And this year, the results came out, and there was an interesting standout, which was that Svelte was the most beloved framework, which was very exciting to see. Granted, you always have to take these sorts of stats with a grain of salt. But Svelte was 71% loved and 23% dreaded, which they give it as a ratio of how many people really love this thing versus how many people really hate this thing. And so Svelte, 23% of people who have used it are like, I hate that, but 71% loved, so that's a 48% net approval rating. Versus React which was 69% loved, 31% hated or dreaded as the word would be, so that's a 38% net approval. And then Vue, interestingly, was 64% loved, 36% dreaded for a 28% net approval rating. So, yeah, Svelte was decidedly winning in that. But again, the big grain of salt there is looking at the usage stats. React has 40% usage. So of all the respondents, 40% of the people responding to the survey were like, yeah, I've done React professionally, which is a wildly high number for a JavaScript framework. Vue was at 19%, so roughly half of React's usage, which I'm actually impressed that Vue is that high. And Svelte came in at 3%, so it's definitely still in the early adopter strong fan phase. So it makes sense that they would have this outsized high rating. I'm actually surprised that Vue wasn't higher than React, given that. Because I feel like more people are cajoled into React versus Vue can be more of a choice. And I would have expected this to shape out a little bit differently, but yeah, that's the story. STEPH: That's really cool. I liked how you described that as in the very early adopters' strong fan base stage. CHRIS: But nonetheless, the people that are using Svelte do seem to really like it; that's coming through in these numbers. And that definitely is my experience. I love Svelte and would love to continue using it for as long as possible. But really, I want a lot of other people to start using it. I want to really grow the usage base so that there are more libraries, and frameworks, and blog posts, and just mindshare in that space because I really do believe there are some wonderful ideas in Svelte. And it's just so straightforward to implement things that I just want more people hanging out. So that's one quick thing. Another quick thing is, I've been using a utility lately or a program called CleanShot X, which is a replacement for the built-in screenshot utilities on OSX, and it is just fantastic. So I can capture a screenshot. I can capture a window. You can capture a GIF or a video. And then you can do little trims and annotations. And then it has this really nice feature where after you take a screenshot, it just hovers in the bottom corner of your screen and is easily accessible. So if you take a video, and then you want to upload it to a Trello card, it's just floating there waiting for you. You can actually dismiss it and push it down, but it's still peeking up from the bottom of your screen, and you can pull it back up, and you can have a couple of them. But it just really makes the whole workflow of grabbing screenshots or videos so easy. And I cared deeply about that because now that I have this tool, I'm all the more inclined to grab a screenshot or a video with just about every piece of work that I do. So it's going into pull requests; it's going into Trello cards. And it's so nice to have a utility that just really makes that as easy as possible. STEPH: I really liked how you mentioned that you can annotate because I often...I'm laughing as I'm thinking about this. When I am taking a video of something that I'm going to share with someone, I will use my mouse to indicate, oh, this is important. And so I circle around it and do silly things with my mouse to try to indicate but being able to annotate would be so much nicer. I know there is another tool that you're really excited about that I can't remember off the top of my head right now. Do you know the name of the tool I'm thinking of? CHRIS: Was it Loom? STEPH: Yes, Loom, because I also used that for a little while, and I've really enjoyed it. So I'm curious, how does Loom and CleanShot X stack up? Is one replacing the other, or are they complementary tools? CHRIS: Mostly complimentary. Loom is great because it hosts the videos, and you can also do audio capture, although I wonder if CleanShot has that as well. CleanShot also, I think, has a hosting thing. So I think there's a strong overlap in their functionality, but right now, I'm using both. And definitely for screenshots and things, CleanShot owns that end of it. And I think it's more likely that I could have CleanShot as the entire tool that I'm using. But I'm still using Loom for this is a walkthrough where I'm going to talk to you about a thing. I want to make it available at a URL that everyone can see rather than actually getting a GIF or MOV artifact file on my computer. So ever so slightly different, but I think of them, CleanShot X is probably the ideal one. But yeah, I'm still reaching for both. So the one other thing I did want to talk about is I have been expanding our use of the dry-monads within the project that I'm working on. And I've done some things. I did some stuff, Steph, and I think it's good. STEPH: Shtuff with Shteph. [chuckles] CHRIS: Shtuff with Shteph, yeah. I'm definitely pushing the envelope of how much we're leaning on these concepts within the app, and I continue to question it. I'm really intrigued to see what happens when other folks come into the project, and they're like, "Why can't I just get the value? It should be a string. Why isn't it a string? Why is it a string that I have to do a ceremony and a dance to get at?" And I'm like, "Well, because everything can fail, you know, like life." But what I have done here so dry-monads is the project that we're using, particularly their result type. So the result represents something that can either succeed or fail. And so we either have a success, which is this wrapper around the value that's successfully executed. So say we make an API call, we get back a response. If we get a 200 or maybe even a 300, then we get the data, and that's a success, or we get a failure and the error message. But fundamentally, we're modeling that in our system in a way that downstream from that, we have to basically determine if it was success or failure. So we're really encoding into the system; listen, pretty much everything can fail, so let's be careful with that. Let's be intentional and purposeful with it. But there is an interesting thing where these objects have fmap as a method on them. So fmap is a way to transform that wrapped value, but fmap works specifically on the success case. So if you make an API request, you get back the data. Everything's great. You can call fmap, and it will yield into a block that data. You can transform that data in some way, and then it will rewrap it up as a success object. So you can operate on this thing as if it has been successful. But in the case that it's a failure, it will just ignore that transformation because you don't want to transform the failure. It's going to be a totally different shape of data. So you want to separate those. We're getting into functors and monads here. So I'm going to handwave a bunch. But fundamentally, that's the thing that we're going for here. But we found ourselves really wanting to work with both sides. So we make this API request, and in the case that it succeeds, we actually want to transform and actually slice out a piece of data from the nested object that we get back. So that's one transformation that we want to apply on the success portion of the aisle. But then, we also want to transform the failure message. It turns out this backend is giving us very unfriendly error messages. So we want to take those and transform them into friendlier user-facing error messages. So it turns out we want to map both sides. And so I went to dry-monads, and I was like, what do you got? I want to know about this in the world. And it turns out they did not have anything. So I started looking into it, and it turns out this is a concept in the world of functors, specifically. Or, more specifically, I reached out to a former colleague, Sid Raval, a former thoughtboter as well. And he likes the functional programming stuff, so I knew he was the right person to ask about this. And he pointed me at bifunctors. So I found myself in a new space and category theory which I never thought I would explore a category theory in this way, but here we were. So a bifunctor basically is exactly what I was talking about where there are these two branches. In our case, it's either success or failure, but it allows you to operate on both sides, both branches. So the method or the function that gets applied there is bimap. So it's fmap which I don't know why it's f why that's typically what it's called. Success map would be a really great word in this context in my mind. So success map only deals with the success side, but bimap takes two different transformations, one for the successful outcome and one for the failure outcome. And it allows you to very directly talk about what you want to do with that. To be clear, dry-monads has a function called Either or Either, depending on how you want to pronounce it. And that takes two Lambda proc-type things because it's Ruby, and functions are kind of weird in Ruby. But it yields you either the successful value or the failure value, but then it doesn't rewrap them. So it's meant to be the terminal. You use that in a controller when you're either redirect or render or whatever it is you want to do. What I wanted was something for mapping, so staying in the success object or the failure object but yeah, bimaps. So I introduced my own extra wrapping layer. This is where things go off the rails, I think. We now have our own internal result objects. I thought about monkey patching for a while. I convinced myself monkey patching was a bad idea. Now that I've implemented as an extra layer of wrapping and I got the wrapping wrong like four times, or I kept recursively wrapping and re-wrapping, and there's a reason people aren't supposed to write these things themselves. But I think monkey patching may have been a better idea here, or maybe I should have never done any of this. We ended up with a stable working implementation and a nice test suite that covers it. But I introduced bimap and failmap as two different methods on our success object. And I did it by doubly wrapping the result objects. So we have our internal result, which wraps the dry-monad result. And I'm worried about that future situation where a junior developer comes on the team and is like, "I don't know what any of this is." STEPH: I love the weekly progression of I've done some things, and let's talk about it. And then seeing this glimpse into your argument with yourself as to yes, but we need it, and we want it, and it's not something that's defined. So let's go ahead and implement it. You ended on a high there where you talked about the fact that it is nice to work with. It does the thing that you'd like it to do, and it's well tested; I love that part. I'm deciding which thread to go with because there were a lot of interesting bits in everything that you shared. And I'm intrigued about the monkey patching as to why you think that could have been a better approach. Could you talk more about that one? CHRIS: Sure. So I ended up having to introduce the secondary object that then wraps the result. And so if you poke at that even a tiny bit, you start to see this like Russian doll nesting of it's our result wrapping a result, wrapping a value. And it's a burrito with three different tortillas wrapped around it. And if you want to add guacamole, you got to unwrap all three burritos. I'm sorry, this is a terrible monad joke here. [laughs] STEPH: For the record, if Taco Bell is not offering that, they should now, now that you've created that. [laughter] CHRIS: There is one, but there's usually cheese in between the layers. They're not just extra layers of tortillas, so that's what I've got here. It's way too much tortilla, and that's sad. You don't want that. And it's confusing. You're like, wait, does this one have two or three layers of tortilla? So when I was working on it and when I was implementing our additional wrapping layer, I tricked myself multiple times. And my test suite was telling me that things were working, but I was testing incorrectly. And I was like, oh man; this is very subtle. And even though I'm deeply immersed in the context here, I'm still struggling with this. So the question is, did I successfully encapsulate all of this? And now anyone downstream just gets to use it,, and everything will be fine. Am I the heroic programmer that made the perfect abstraction that no one's ever going to struggle against, or was that pain that I was feeling representative of the complexity of what I'm trying to do here, and maybe I got it wrong? And so then the monkey patching side is we've got this one layer of wrapping. What if we just monkey patch the result such that it's got these new methods? I'm not adding an additional layer. I don't need to deal with double mapping through multiple layers, and I just get to deal with the context that I have. So I did an initial spike of an implementation that way, but I talked myself out of it because #monkeypatchingisbad, but I don't know. I don't know where I'm ending here. I am happy with where we're at, but I am aware that I may be sad down the road. STEPH: I'm just dying over here [laughs] from everything you're saying. I have this image of you staring out the window thinking, am I the hero, or am I the villain? And figuring out who you are in this scenario with this abstraction that you've created. CHRIS: To be clear, it's raining, and I have a nice rocks glass of scotch in my hand. And I'm just wistfully looking out the window trying to determine what's true. That's pretty accurate, actually. That's pretty much what's going on here. STEPH: I think we're just going to need updates as it progresses along. CHRIS: I will say overall this paradigm...so failures can happen at all levels. These command objects, which are the core of where this is coming in in the application, really represent the workflows of the app in a wonderful, testable, straightforward way. So I love that part. And if I have that, it implies that I have to have this other stuff. I don't think I can get away from that. The other thing is I've always loved Gary Bernhardt's Functional Core, Imperative Shell, which is a conference talk that he gave a while back. I talked to Gary about it actually when he was on the show, and we can link to both that and the conference talk because they are fantastic. And I just love the way he thinks about software. But that was always a little bit abstract for me. Like, what does that actually look like, though, in say, a Rails architecture? And I didn't have a great answer. And now this thing that I'm doing is the closest I think to that where the innards of the system are almost functional even though it's Ruby. We're leaning into that. And so we have these command objects that take in some data, and then they operate on it, and they yield out these results. Did it go well, or did it not? We've got the railway-oriented stuff, which again I'll link to. I link to now every third episode, apparently, but here we are. And that just models the reality of these programs in a really great way. And then we've been trying to introduce some, not rules per se, but guidelines as to how we interact with these things. So inside of the core of the application, we're trying to be as functional as possible. We do transformations on these result objects, but that's it. And then it's only really in the controllers or the mailers that we are doing unwrap or deal with the actual nested value, but everything else is working on conceptual values or whatever it is…these result objects. And that's actually been really nice, and it's allowed us to have really nice error handling within the app. The logging is very straightforward. A lot of apps that I've worked on in the past, I've just silently thrown away many error cases or edge cases. And this is a really great way to sequence the work that needs to be done but never throw away data that you would want. And so far, I'm finding it to be really great. And I'm seeing very obvious ways to hook into it like, oh, this is where we need to find the user-facing error message versus this is where we figure out what we want to log. And so, in some ways, it's great, but I am still open to the idea that this was a terrible idea. I always remain open to that idea to be clear. [chuckles] STEPH: I love how that's the feedback that you're always open to it. You're always trying something new, and then you're constantly going back to revisit; was this a good idea or a bad idea? To go back just a little bit, I do absolutely love the priority and focus that you're giving to the failure state because I feel like that is an area that we, as developers we're very skittish of that failure state. And I realize I'm projecting here. So if you're listening, feel free to take that however you like; maybe it doesn't apply to you, maybe it does. But the failure state is like you said, it's life, it's important, and it's something that is going to happen. And it is something that we should make accommodations for. And I find that we're often very hand-wavy with a failure state. So I love, love how much you always prioritize the failure state and make that something that people can work with and understand. Versus then when something goes wrong, then that's when we have to start to understand the failure state. I recognize there's a balance there because you're not going to know the failure state until you encounter it, but there are ways that we can still optimize to have observability into that failure state for when we do encounter that failure. CHRIS: I've definitely seen that as an evolution in my own thinking, how much am I focused on how easily can I do the core thing, the happy path versus how robustly can I do all of the variations of what this app needs to do? What if the network's down? What do we do there? I do occasionally worry that I've overcorrected on that. And it's like, you know what? This thing that I'm worried about that I'm protecting against in the application is a 0.01% edge case. It's going to affect almost no users, and we're both putting time into trying to avoid it. But also, there's code complexity that comes from trying to handle all the different variants. And so there's definitely an optimization, and I feel like, at different points in my life, I've been undercorrected or overcorrected on that. But I think if I were to describe the arc of my career, it is desperately searching for that optimal path and trying to find exactly the right amount of error handling to apply, and then yeah, then I'll be happy, then it'll be great. But it is like when I look at DHH's classic 15-minute I'm making a blog, look how much I'm not doing, I'm like, sure, sure, sure. Show me that in three years, though. What does the blog look like? How easily can I add a new feature? What happens when there's a bug in production, and a user reports it? Can I chase it down? Can I figure it? Can I fix it? These are the questions that I care about now, almost to the exclusion of what's the first run experience like? I almost don't care about that at this point. Because I spend my time…six months and on that's where the hard work is. And so the first couple of months where you're figuring things out, that's not the hard work of this thing. And so, I'm very strongly focused on those later periods of time. But again, I'm open to the idea that maybe I am overcorrected there. STEPH: I think it does highlight more of a shift in our career. We're still building, but we have experienced the maintenance side as well, and we felt that pain. And so that has led to perhaps overcorrecting, or maybe it's the correct amount of correction. But I do like how you highlighted there is always a cost to each side and those are usually the questions that I'm asking myself when I'm thinking about the failure mode and how much I want to optimize for the failure mode is how much does it cost when this fails? Who's it going to impact? And how much does it cost for me to make this more observable or to address this failure state? And then I try to find the balance between those two. Because you're right, it's not free to address that failure state. And so I may not want to fully optimize to handle that if it's going to be a very small percentage of users that actually are impacted by this failure state, or it seems very rare this is going to happen. But then still finding ways to know that if it does fail, then I can say, "Okay, I'll come back, and now it's worth the investment to improve this." CHRIS: When you said earlier that this is really hard work that we do, I don't know that I believed you. What you just described sounds super easy. You just handle all the stuff, and you dynamically optimize for the needs at the point in time. And that seems easy. [laughs] STEPH: Super easy, yeah. [laughs] Way to bring it back. Well, speaking about observability and failure states, that does lead nicely into a bug that I was working on this past week where there was a particular page that was loading very slowly. And it was something that we'd heard from users that then they let us know that this page was either taking a very long time to load or, frankly, it was just crashing. And then they were never getting to that page. So I happened to be the one that then picked up that ticket. And I went to reproduce the issue, and sure enough, when I clicked on this particular link and then started counting, it took about 14 seconds for that page to load, which is a very long time. And then also sometimes it was just crashing. So the first place that I went was to our error tracking. So I went to New Relic to then look to see okay; maybe there's a slow query. There's something here that's creating this performance issue, but I couldn't find anything. And New Relic does a great job of breaking down all the different response times so I can see how long Postgres is taking, Redis, and Ruby. All of those looked very normal. I couldn't find anything that seemed alarming that was indicating that the page was struggling to load even though I could reproduce the problem. Because I was clicking on it several times thinking, okay, well, if I just do this a couple of times, New Relic's going to notice, and then I'll get to see something, a little breadcrumb that's going to lead me in the right direction. And while I was waiting for New Relic to surface something helpful to me, I mentioned to another developer the issue that I was triaging. And they said, "Yeah, that page has been getting progressively slower, and we don't know why." And I thought, ooh, okay, I'm intrigued even more now as this is something that has been escalating over time, and now we've hit this threshold that we're working on it. And I discovered that in New Relic, I can look specifically at Postgres, Redis, Ruby, all those different response times. But there's a browser monitoring tool that I had not used before. And it showed a lot of helpful information around first paint, First Contentful Paint, window load, all of those areas. So I started diving in and found session tracing, and it was there that then I saw New Relic was telling me, "Hey, you have a page that's taking about 14 to 15 seconds to load." And I thought, okay, I feel validated now that at least New Relic is recognizing this issue. I have seen this issue, but I still didn't know why it's occurring. So the next tool that I used that I don't know if I've used before or it's just been a very long time; it felt fresh in the moment, but it's the Chrome DevTools, the performance tool. And so you can open that up in your inspector, and then you can go to the page that you want to track the performance. And then you can essentially say, "Hey, go ahead and start profiling and reload this page." And it has so many stats when it finally does load. It has CPU flames charts, which essentially it visualizes a collection of all the stack traces. It has a film strip, so you can actually see the rendering progress of your website along different time points. So if you wanted to go back to a specific time, you can see what did the webpage look like at this point? And then if you go a little further, okay, how much was loaded at this point? So there's a lot of interesting and a little overwhelming information that's there. But the thing that did catch my attention is there's a chart. I don't actually know what this chart is called. It's not a pie chart because there's no center to it. So it looks like a donut chart, and it's broken down. And it shows you the loading times, scripting, rendering, painting, all of those different values. And the rendering time was taking 35 seconds. And I was like, ooh, okay, that is meaningful right there. So then further investigation, now that I knew what I was looking for, I wasn't looking for something more on the back end. I was looking for something more on the front end. And I didn't think it was necessarily JavaScript because we also have JavaScript on this page. So at least this was helping me get a little bit closer before then I went into the codebase to start seeing what's happening. So once I knew it was a rendering issue, I went to look specifically at that view, and we have a form on that page that was generating an empty HTML select option for every record that's in the system. So let's say that you're ordering from a restaurant. On this page, there was a form where it had a list of all the restaurants, and, in our particular case, we had about 17,000 restaurants. So there were 17,000 empty HTML selection options, which could have some significant impact on the DOM and page load time. And that was the piece that was really leading to the performance, is the fact that we were rendering that empty select option. So from there, it was then just triaging okay; we don't really need to render all of these restaurants. There are ways we can scope this down. And that way, we're only showing a little bit at a time versus creating all of these empty options. I should clarify they're empty because part of this form is you select from the first dropdown, and then it populates the other one, and it gives you more information. But the way that this form was implemented, it was actually trying to show all of them at once. But it didn't actually have the data yet, but it was doing like a restaurant.all type of count. And so then that's how we were getting that many empty options. So it was a very interesting journey. It was very helpful to learn that New Relic has this browser monitoring tool. And I really appreciated their performance tool. And circling back to Chrome, Safari may have something similar. But I found Chrome's performance tool very helpful because then it helped me realize that it was the rendering. And so then I could really focus on the markup and the view versus knowing it wasn't more in the database layer. CHRIS: I really love the description, almost like a mystery novel of these bugs when we encounter them. Because if you just get to the end and you're like, oh, I was rendering a select, and it had all of this, that loses so much of this story because again, the coding is not the hard part of the work that we do; it's the figuring out what needs to be done. And in this case, that journey that you went on to find the bug. I really like the point where you said, "And someone mentioned this page has just been getting progressively slower over time." I was like, ooh, that's interesting. Now we got a clue. Now we've got a lead, and we'll chase it down, and then finding the browser tools and all of that. And also, as an aside, browsers are just such an immensely impressive piece of technology, everything that they do. And then you add the DevTools on top of them and magical stuff going on there. But yeah, also probably don't render 17,000 empty selects. [laughs] That seems like it will get you in trouble pretty quickly. But also very easy to get to and especially if there is this incremental, slow creep over time where it's like, oh, that page seems like it's a little slower. It's a little slower still, and it just keeps creeping up over time. But yes, I appreciate you taking us on that journey with you. STEPH: Yeah, it was a fun discovery. And it made me realize that while we have alerting set up for some of our other queries, we don't have anything set up for the browser time. So that would be a good optimization on our side is to start alerting us before a page gets to the point that it's taking that long to load to notify us sooner. So we don't have to wait for a user to reach out to us, but we can triage sooner. CHRIS: I also do love the idea of extending the metrics that we hold ourselves accountable to all the way through to the user, and so the First Contentful Paint and all of that. The one that I really love recently that has captured an idea that I struggled to put words to is the Cumulative Layout Shift. Are you familiar with this piece? STEPH: Uh-uh. CHRIS: So there's like, how quickly does the page render? That's the thing that we want to know. But a lot of applications these days, particularly single-page apps, render pretty quickly, but they render what ends up being a skeleton or a shell of the page. And then behind the scenes, there are like ten different AJAX requests happening. And as the data comes in, suddenly, a part of the screen will render. And they'll render a list of items that they just got back from the back end, but they're still waiting for the information to populate the header. And so if you look at that page, it's constantly shifting as it's loading and just feels, I don't know, flimsy in my mind. But I didn't have a good word, or I didn't have a metric or a number to attach to that. And then I learned about Cumulative Layout Shift, and I was like, oh, that's the one. Now you've mapped the thing that I was feeling. And I like when that happens. STEPH: Is that the difference between the first paint and First Contentful paint? Is that similar? CHRIS: I think it's more than that because there are not just two discrete events in this. It can be multiple. And so it's like, how many different times did the thing that's rendered on the screen move around? And so if images are loading, but you didn't have a proper image height and width set, that's another way that this can happen. Then initially, the browser is not going to reserve any space for that because it's like, I don't know how big this is. And then, when the image shows up, it now knows the intrinsic height and width of the image. So suddenly, your page is going to jump from that. You can get ahead of that by putting the height and width on your image, and that's great to do. And frameworks like Next.js have done some really amazing work of making that a build time step as opposed to something you have to do manually. But then also, more generally, how do we handle this? React is doing some interesting work with Suspense, where you can aggregate together multiple different loading states into one collective thing. It's almost like promise.all, but for your page. I haven't followed that too closely, but I know that that's framework-level work that's happening over there. GraphQL does a really great job of allowing you to group queries together. So there's a solution on that side. But broadly, if you just render some HTML on the server and you send it to the front end, then you don't have this problem because you just have one ball of HTML. The browser is pretty good at rendering that in one pass versus if you have single-page applications that are making a handful of AJAX requests that will resolve in their own timelines and eventually paint to the screen. You get this different shape. And then the worst case of it in my mind is you render half the page. And then suddenly, one of the requests realizes the JWT has expired, and suddenly, you get thrashed over to the login page. Please don't give me that experience, developers, please. Please do something else that isn't that. That makes me sad in my heart. STEPH: Prioritize the failure state. That's what I'm hearing. CHRIS: Callbacks. STEPH: Well, on that wonderful circular reference, shall we wrap up? CHRIS: Wait, I thought circular references were bad...Never mind. Let's wrap up. The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review on iTunes,, as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us @bikeshed, or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey. STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Byeeeeeeeeee. Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.

    304: MEGA Crossover Episode (The Bike Shed x Rails with Jason x Remote Ruby x Ruby on Rails Podcast)

    Play Episode Listen Later Aug 11, 2021 34:38

    This is the sweeps week episode, the epic crossover episode, the mega episode! We have a very special episode as Chris, and Steph teamed up with the hosts of three other podcasts to bring you one giant, mega Ruby episode! In this episode, you'll hear from the hosts of Remote Ruby, Rails with Jason, and Brittany Martin, the host of the Ruby on Rails podcast. They cover the origins of their shows, their experiences as hosts, and why podcasting is so important in keeping the Ruby community thriving. Remote Ruby (https://remoteruby.transistor.fm/) Rails with Jason (https://www.codewithjason.com/rails-with-jason-podcast/) Ruby on Rails podcast (https://5by5.tv/rubyonrails) *Transcript: * STEPH: Hello and welcome to another episode of the Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. This week we have a very special episode as Chris, and I teamed up with the hosts of three other podcasts to bring you one giant, mega Ruby episode! In this episode, you'll hear from the hosts of Remote Ruby, Rails with Jason, and Brittany Martin, the host of the Ruby on Rails podcast. This episode was so much fun to record, and we have Brittany Martin to thank as she organized and moderated this special event. So without further ado, here is the mega Ruby episode. BRITTANY: Welcome, everyone. We have a whopping seven podcast hosts recording today. So, listeners, you are in for a treat. This is the sweeps week episode, the epic crossover episode, the mega episode. We're going to need our editor to insert some epic sound effects right here. Announcer: The mega episode. BRITTANY: So let's go ahead and introduce the crew today. I am Brittany Martin from the Ruby on Rails Podcast. CHRIS OLIVER: I'm Chris Oliver from Remote Ruby. JASON CHARNES: I am Jason Charnes, also from Remote Ruby. ANDREW: I am Andrew Mason, also from Remote Ruby. STEPH: And I'm Stephanie Viccari from The Bike Shed. CHRIS TOOMEY: I'm Chris Toomey from The Bike Shed. JASON SWETT: And I'm Jason Swett from Rails with Jason BRITTANY: Today, we're going to cover the origins of our shows, our experiences as hosts, and why podcasting is so important in keeping the Ruby community thriving. Now I know personally, I really enjoy the origin story behind Remote Ruby. So, Chris Oliver, could you kick us off with that? CHRIS OLIVER: Yeah, we can go back maybe to the first time that Jason and I met, which was Jason emailed me out of the blue and was like, "Hey, are you going to be at RailsConf?" And I wasn't planning on it, but it was over in Kansas City, like four hours away from me. I was like, "No, I'm not going, but I'll meet you." So we went and drove over there and met and have been friends ever since. And Jason had the idea of doing an online meetup. And I'll let him explain where that started and turned into the Remote Ruby Podcast. JASON CHARNES: I thought it would be a good idea. There weren't any online meetups. This was pre even the idea of shutting down the world for a pandemic. And maybe I was just too soon because I got Chris to speak at the first one, and we had 40, 50 people. I spoke at the next one, and there were 20. And by the third one, there were five of us. So it wasn't really a super sustainable thing for me to do. So Chris and I got together and said, "What if we tried podcasting?" Chris, you hadn't really done your own podcast at that point, had you? CHRIS OLIVER: No, I don't think so. And you and I were just having calls every week or whatever just to hang out and chat. And we were like, why don't we just record that and publish that as a podcast? And here we are. JASON CHARNES: Yeah. So we've been doing that. I think we started in 2018, so yeah, three years in June, and somehow people still keep listening to us talk but probably because we brought along our friend, Andrew. ANDREW: Wow. Okay. No, that's not true. But yes, I was a guest on Remote Ruby before I joined as a host. And not to get into the details, but I was on another podcast, and something went down, and I no longer was on that podcast anymore. And Chris and Jason were like, "Do you want to come hang out with us?" And I was like, [chuckles] "Absolutely." So I started doing that, and at the same time, I also started The Ruby Blend with Nate Hopkins and Ron Cooke. And so we were doing that for a while until that had to tragically shut down. But I'm still here with Jason and Chris. I guess I should also mention that Jason Swett gave me my start in podcasting a month or two after I started full-time as a Rails developer on a now archived show called The Ruby Testing Podcast. BRITTANY: Which is the perfect segue because Jason Swett was also my first opportunity to guest on a podcast. So I was already hosting, but I hadn't guested, which is kind of the opposite order. So, Jason, do you want to tell the origin of where Rails with Jason came from? JASON SWETT: Sure. I'd been involved with podcasting since around 2016. I somehow ended up on the Ruby Rogues Podcast and was on there for maybe a year or so. And then, somehow, I got the idea that I could start my own podcast. And as an experiment, I started a podcast that I called The Ruby Testing Podcast, which I figured was sufficiently narrow that I could get some traction. And to my surprise, guests actually said yes to coming on the show. And also, to my surprise, people actually listened to the podcast. That gave me some confidence. So maybe a year later, I broadened, and I changed from The Ruby Testing Podcast to just Rails with Jason. And I have been doing that for something like two years. BRITTANY: That's fantastic. I want to move to probably our most experienced podcast veteran, and that would be Chris Toomey. When I was learning how to code, I was listening to Giant Robots and then was excited for the transition that The Bike Shed took. Chris, I would love to hear the story of what it was like taking over a really popular podcast and really maintaining the drive behind it. CHRIS TOOMEY: So, as you mentioned, I had done a little bit of podcasting. It was about a six-month run where I was a co-host on Giant Robots, which was the original podcast of thoughtbot. And that was more in the business and sort of how do we build a software company? So at that point, I was running Upcase, which was the subscription learning platform that thoughtbot had. So I was talking about the inner details of the business, and the marketing tests, and A/B tests and things like that that I was doing. And every week, I was sharing my MRR rather transparently in that thoughtbot way that we do. I did that for, like I said, about six months and then took a while off. And in the background, thoughtbot had started up a new podcast called The Bike Shed, and that started October 31st of 2014. So The Bike Shed has been going for a long time now, and that was hosted by Derek Pryor and Sage Griffin. And they ran that for a number of years. I think it was about four years that the two of them worked collectively on that. But at some point, they both moved on from thoughtbot, and there was an opportunity for new hosts to step in. So I took over in August of 2018. So I've been doing this now for about three years. And so, for that first year, I took the opportunity to do a tour around thoughtbot and talk with many different individuals from the company and a handful of people external to thoughtbot. But I knew that there were so many great voices and ideas and points of view within thoughtbot that I really wanted to spend some time getting to know more of them personally and then sharing that as much as I could with the existing audience that The Bike Shed had. But secretly, all along, I was looking for a person to hang out with all the more so, and Steph was the person that was a perfect choice for that. And so, for the past two years, Steph and I have been chatting. And I will send it over to Steph to share a little bit of her point of view on that transition. But from my point of view, it's been fantastic. STEPH: I still remember exactly when we had the conversation. You were running The Bike Shed and doing an incredible job of just having weekly guests. And then you'd reached out to me and said, "Hey, would you be interested in doing an episode?" And I thought, "No, absolutely not. I can't podcast. I can't begin to do this." So you continued to convince me. And finally, you said something that resonated where you were like, "Well, we can just show up and record, and we don't have to publish. We can just see how it goes." I was like, that's a perfect safety net. I'm into that. So I showed up, and I think the first episode that you and I recorded ended up being titled What I Believe About Software. And it was a lot of fun. I realized I have a lot of things to say. And after that, I think it was another month or so. You continued interviewing more guests, but then you reached out to me and asked me if I wanted to be a co-host. And at that point, I was super jazzed about it, and it's been wonderful. It's been a roller coaster. I have learned a ton. BRITTANY: I'm kind of seeing a pattern here where over the last three years, it seems like Remote Ruby came into place, Bike Shed transitioned. That's when I took over as host of the 5by5 Ruby on Rails Podcast. We're going to call it the golden era of the Ruby Podcasts. But for me, I probably have the longest-running podcast. It was started back in 2009 on the 5by5 Network, but it's gone through many different hosts. And so, I took over roughly about three and a half years ago as the main host from Kyle Daigle. And then, just a couple of weeks ago, as I announced on my podcast, we took the podcast independent. We are now just The Ruby on Rails Podcast. And I'm starting to change the model where I'm bringing in more co-hosts. So that way, I can get those regular updates that I really appreciate on all these podcasts we have featured on the show today. I am curious. I want to talk about how we put together the episodes and plan out how everything's going to go down. I know for me, I'm currently a mix of interviews and co-host episodes. So I'd love to hear from Andrew. How do you plan out what Remote Ruby is going to be week to week? ANDREW: This is an easy question because we don't at all. We don't plan. We do have some guests that come on, and sometimes, they may get their Zoom link the day of; who's to say? But we really don't have a plan. We don't talk about what we're going to talk about beforehand. We all just kind of show up, and I think we have that kind of relationship and flow where it always just works. JASON CHARNES: And I think part of that came from actually how Chris and I started the show because we were trying to make it as low stress as possible because we knew if we put a lot of pressure on it, we would stop doing it. Our first episodes were YouTube live links that we just shared out. And then in our next episodes, we were like, oh, we should start using some software to do this. And then eventually, we got an editor, but that same core of let's just keep it fun for better or for worse, I think, also affects our planning. BRITTANY: I've been lucky in the sense that I have guests sit on all three of the episodes. And I do want to give a compliment to The Bike Shed because it is very well run and very well planned. So I want to kick it over to Steph as to how putting together a Bike Shed episode looks. STEPH: Oh, thank you. That's wonderful to hear, by the way. That's wonderful feedback. So we predominantly use Trello to organize our thoughts. So we will have...and as we're capturing community questions that are coming in, so we will capture those on the board. And then, we will have a ticket that represents a particular episode. Usually, on the day of, we'll share some thoughts about, hey, these are the broad topics I'm interested in. And there's usually some hot takes in there, which is fun because the other person doesn't know exactly what's coming, and we can have real honest conversations on the mic. And then, every so often, we'll grab a beer, and we'll go through that list. And we'll chat through what sparks joy. What do we want to talk about? What would we like to respond to? And that's pretty much how we organize everything that we discuss. Chris, is there anything I've left out that you want to add? CHRIS TOOMEY: I think that mostly covers it. We do occasionally have interviews just as a way to keep some variety and different things going on, but primarily it's the sort of what's new in your world? And I find that those episodes are the ones that I think are the most fun to record for Steph and I when it really feels like a sincere conversation. I've recently taken to a segment I call good idea, terrible idea where I'm like, "I'm actually considering this, Steph. What do you think?" And live on-air, I'm getting Steph's feedback, and generally, we're very aligned. But every once in a while, she's like, "That's a terrible idea. Don't do that." And I love those, and I love being able to share that because I think it's really easy to talk about, you know, here's a list of things that are true about software, but really, everything depends. And it's all the nuance. And so, being able to share some of our more pointed experiences and then share the conversation that we have over those is hopefully very valuable to the audience but definitely the thing that I enjoy the most. BRITTANY: So kicking it over to Jason Swett, I really enjoy the interviews that you do. I'm curious, how do you select guests? JASON SWETT: Well, thanks. Selecting guests is tough. I had Peter Cooper on the other day, and I was telling him that I feel like every guest that I get on the show is the last guest I'm ever going to be able to get on the show. But somehow, I keep finding more and more guests. Early on, it was relatively easy because I would just find book authors, or if somebody else does podcasting, then it's fairly obvious okay, you're the kind of person who does podcasts, so I'll invite you. But it's a little bit tough because I don't want to invite people who aren't into podcasting and would be really thrown, although sometimes that happens. But let's see, sometimes I send an email out to my email list, and I'm like, "Hey, I'm looking for guests for my show." Sometimes I just tweet that I'm looking for guests. And sometimes I get some really interesting guests from surprising places. But at least in the start, it was looking for those authors and podcasters and the people who are known in the Ruby community. BRITTANY: I know for me, I strive to have at least 50% of my interviews be with people who've never been on a podcast before. And so that usually involves the top of the episode they're dry heaving into a paper bag. And I'm explaining to them, don't worry, about halfway through the episode, you're not going to remember that you're recording anymore. It'll be fine. And you know what? It's always fine. And so, I do love hearing from a wide variety from the Ruby community just because it really proves just how big it is. So I'm curious, could you host the podcast that you are currently hosting now if you weren't actively working in Ruby? ANDREW: I could because Chris is the one that has all the clout. I could sit back and make dumb jokes and memes during it. And as long as Chris is there, I think we'll be good. JASON SWETT: Yeah, I think I could because a good majority of what we talk about on Rails with Jason actually has nothing to do with Rails, so that would probably actually work out. STEPH: I think yes is the answer. While a lot of our conversations do focus around Ruby and Rails, we often use a lot of other languages and tools, and those are a lot of fun to talk about. So I think I would just talk about whatever new tool or language that I'm using. So I think yes, it would just take a slightly different form but would still be at its core the same where we're still talking about our daily experiments and adventures in web development. BRITTANY: I agree with you, Steph. I will say that it seems like Chris Oliver and Chris Toomey have an endless well of things to talk about just based on what they do day-to-day. CHRIS TOOMEY: I try and go on adventures and then share as much as I can. But to resonate with what Steph was saying there, we try to make the show more generally about software, and it happens to be that it's grounded in Ruby on Rails because the vast majority of the work that we do is in that. And I just recently started a new project. I was given the choice of I could pick any technology I want, and it remains the technology that makes sense to me to be the foundation of an application that I want to maintain for years and years and years. So, on the one hand, I think I could definitely talk about software more generally. I think I'm doing that most of the time. But at the other end of the spectrum, but it's always going to be based on Ruby because I haven't found a thing elsewhere in the world that is better than that. CHRIS OLIVER: I completely agree with that. I probably have a little bit of a unique thing doing a screencast every week. A lot of those are based on I'm building some project, and I need to build some random feature like Stripe Checkout. And that's a good one to do a screencast on and implement in the project. And then, we can also talk about the decisions along the way on the podcast, which is kind of nice. BRITTANY: Yeah, it feels like every week, Chris Oliver is like, yeah, I've created a new open-source library, and I'm fabulous. [laughs] Let me listen to this. CHRIS OLIVER: Too many of them. I'm currently rewriting a lot of the Pay gem. And it's just one of those things where you make a bunch of decisions. And then, if you make an open-source project, people use it in all these different ways that you didn't intend yourself, and so you want to support that. But then you need to rearchitect things in it. It is a lot of learning as you go, which is always a lot of fun. So those I think are really good topics to talk about when you're building something like that. I'm always amazed by how does the Rails core team make these decisions on what should be in the framework and what shouldn't? And what do they want to maintain, and how do they keep it flexible but yet have some sort of rule with how they allow things to be implemented and whatever? It is a very hard job to have. So I get my little taste of that with some open source but not on their level. BRITTANY: I always thought that you had a good contrast to Jason Charnes because Jason works at Podia. And while you do get to work on a lot of really cool technologies, I feel like the stakes are much higher. So you can't just rip out StimulusReflex and put in something else just because it sounds cool that week. And I love how you talk through the pluses and minuses to making a big change within the Podia codebase. JASON CHARNES: Yeah. I haven't really thought about that contrast before, but it's helpful for me even just to talk it out with two other people once a week, and luckily, pretty cool about me just coming on and talking about hey, these are the steps we took to get here. Yeah, it's a cool dynamic. BRITTANY: Steph, have you ever had a client from thoughtbot say, "Hey, were you talking about me?" whenever you're talking about your current client? STEPH: That is one of my fears at times that it will happen [chuckles] although we stay very positive on the show. That's something that's very important to us. There's enough negativity in the world. So we really want to focus on our positive experiences through the week. But there have been times where I'm speaking about some of the challenges or things that we are running into that yes, the engineering team is listening to the podcast, and they're like, "Oh, I heard you talk about this feature that we're working on or this particular challenge." And that's really cool because they get that behind-the-scenes peek to see how Chris and I are chatting about that. But yet they know enough, and they know which project that I'm on that they recognize exactly the technology and the feature that I'm trying to describe. So that has certainly happened, and it can be a lot of fun when it does. BRITTANY: Andrew, how have things changed for you now that you're not working at CodeFund, which was very much like an open-source thing? People could see what you were actively working on. And now you're working for a company where it's closed source. And so, you might not be able to reveal as much as what you're working on at any given point. ANDREW: It's different, but I don't think it's been an issue per se. I'm not like, oh crap, I let that slip, and I didn't mean to. That's not really an issue. I really cherish the time I had at CodeFund. When I think back on my experiences, that was my favorite time just because I was able to do that thing that a lot of people really want to do. I was working as an open-source developer. We were spiking StimulusReflex; that's when we were building up StimulusReflex and trying to build up the community. I joined Ruby. We started the Ruby Blend, and things were going good before a dramatic turn. But in terms of the closed and open source, it hasn't been that big of a shift just because instead of talking about what I'm doing at work, like, I still talk about it, but I speak about it in more general terms. But I also then kind of freed up to talk a lot more about the dumb crap I do on the nights and weekends. BRITTANY: So the majority of our podcasts either have the word Ruby or Rails in it, but I think we've all agreed that a lot of the topics that we're talking about are not specific to that community. But in a lot of ways, I feel that having podcasts in our community is how we're going to keep our community thriving. So I'm curious if anyone has any thoughts around...is there a way to market our podcasts so that other developers will listen to it? I get really excited when I get listener feedback saying, "Hey, I used to do Rails maybe ten years ago, but I've been listening to your podcast, and I really enjoy such and such episode." How can we make our podcasts accessible to the general software community as opposed to just Ruby? CHRIS TOOMEY: One thing that stands out to me about Ruby and Rails is because it's full-stack, because of its foundations, it tends to be holistically about web development. And so, whereas I look at React projects or other JavaScript or different things that are going on, I see a more narrow focus in those frameworks. And with Ruby and Rails, what I love about it is that it's really about building software. It's about building products that are valuable, that deliver value to end-users. And so that being the core of it, that's the story that constantly brings me back to Ruby and Rails. And it's the story that I want to keep telling as much as possible. And it's the thing that keeps me engaged with this community. And so, I think podcasts are a great way to continue to literally tell those sorts of stories and really celebrate that aspect of Ruby and Rails and why it remains such a productive way to build software. CHRIS OLIVER: I think related to that, one of the things that we should talk about more is the draw of Rails was look at what you can do with one person or two people. And I feel like we went down the JavaScript route, and now you need two teams of people, and you end up building bigger stuff. And Hotwire has kind of been like, hey, here's a reminder of what you can do with a very small team. And I think that resonates a lot with a lot of people building startups and trying to build side projects and everything. And that's one that is Rails-related. But there's a ton of people building Hotwire stuff in Laravel too. And they're all very similar. So I think at a certain point, yeah, we're talking about maybe Rails specifically, but you can apply all those things to different frameworks and just different tools. STEPH: I'd like to add on and extend that because I wholeheartedly agree with what both Chris Toomey and Chris Oliver just said. And in addition, a lot of the conversations that we have on The Bike Shed are focused on Ruby and Rails, but then we will extract that particular concept to the point that it really doesn't matter which language that you're using or which framework that you're using. We're talking more about the high level. What's your process? What are you thinking as you're going through and implementing this? And based on more of our recent conversations, you'd think we're more of a Postgres podcast, how much we hype up Postgres, and the things that we can do at the database layer. So I think there are a lot of ways that we can start with a foundation of this is how we're doing it with Ruby and Rails, but then talk about it at a higher level where then it's really applicable for everybody. JASON CHARNES: If talking about one technology defined your podcast, we might as well be a Laravel podcast because we talk about that framework more than we do Rails sometimes. [chuckles] BRITTANY: So that begs the question: is there room for more Ruby and Rails podcasts outside of who's currently on this call? JASON SWETT: I think so. And I mentioned that Peter Cooper was on our podcast a little bit ago. That's something he and I actually talked about in that episode. And I shared the anecdote about how in the new America's founding, Ben Franklin's brother or something like that wanted to start a newspaper. And somebody told him what a dumb idea that was because America already had a newspaper. And people might say, oh, there are already however many Rails podcasts. There are a small handful. But I think there could be ten more Rails podcasts or even more than that potentially because I think people have an appetite for help, and camaraderie, and stuff like that. And I don't think we've nearly bottomed out in terms of satisfying people's appetite for that stuff. JASON CHARNES: Yeah, I agree with that because a lot of times, when I listen to podcasts, the more you get to know someone, that connection becomes what it's about for me. So, yeah, there's plenty of room. I mean, brand it as Ruby and tell me about your life as a developer I'll listen. CHRIS TOOMEY: I'll also throw it out there that the way you framed the question is like, is there room for it? But one of the wonderful things about podcasting as a medium is it is distributed. It's not centralized. You can start up a podcast any day. And I will say, as someone who inherited a popular podcast or a sufficiently popular podcast and just got to run with that, it has been such a wonderful way to get my voice out there and provide opportunities that I want that for everyone. I want everyone to have this ability to speak about the way they think about software and then find like-minded people and be able to build even many communities within the larger community of Ruby on Rails. So beyond the question of, Is there room?” which I definitely think there is, I so wholeheartedly support anyone pursuing this for their own reason. ANDREW: Yeah, I think to bring it all the way back, one thing that Chris, Jason, and I care a lot about is Ruby as a community. The community aspects of Ruby are very important to us. And we're actively trying to build that up and bring in new people and bringing people onto their first podcast. We say it all the time, like, hey, if you want to come on the show, let us know. We've had a few people even, you know, recognition in jobs from that. So to us, that is the payoff of doing the show. Maybe our show is the first time someone learns about Rails. And that to me is the possibility in the future. It's like, how can we market our shows that markets Ruby as well so that this meme of Ruby being dead finally goes away because it's not. I think it's growing. And I think the more and more we push as people who are public figures in this space that we want to bring more people on, that this is a space for everyone, I think that's just kind of the ethos that all of us have, and I think that's great. BRITTANY: So I'm curious, on a lighter note, has anyone had the funny experience of realizing that you're not just podcasting into the ether and that what you're saying and what you're doing matters? For me, I have definitely been at conferences where people will run up and hug me just because they heard my voice, and they are like, "I didn't know what you looked like, but I have your voice memorized," and it just blew my mind. And I was like, "Thank you so much for being such a loyal listener." And it just proves that people are out there listening. ANDREW: I tend to talk very openly about mental health. And I very often fail in public and talk about it. And I've had a lot of people message me and email me over the past three or four years and be like, "Hey, thank you for talking about this thing that's not actually about Ruby. It's not actually about coding, but it's just about being a developer." And those are the emails that make me feel the best. Like, someone who's out there like, "Yeah, I also feel like this. Thank you for speaking about it." JASON SWETT: I had a surreal experience. I went to India in 2019 through RubyConf India. And this guy wanted to take a selfie with me because apparently, he considered me famous. So that was cool and pretty surprising because I definitely didn't consider myself famous. STEPH: My favorite has been when we receive listener questions because it lets us know that people are listening and engaged in the conversation, and I essentially feel like they're part of the conversation. They will write in to us and share anecdotes, or they'll share answers to some of the questions that Chris and I will pose on the show. But every now and then, we will also get an email from someone that says, "Hey, just thanks for doing the show. I listen, and it's great," and that's all they share. And that, to me, is just the most wonderful thing that I could receive. BRITTANY: Some of my favorite episodes from all of your shows is when we get an inside peek into what people are doing, like Andrew moving. Jason Charnes, you putting together a conference was actually some of my favorite episodes of yours, which was really early on, which proves that I'm a Remote Ruby OG. But I loved hearing the inside track as to what organizing a conference is because I think we need to get more content out there about how difficult but how rewarding it is. JASON CHARNES: Yeah, I hadn't really thought about...that was around those times we hadn't done... It feels like it's been ages since we did Southeast Ruby, but Chris and I actually podcasted from the last Southeast Ruby we did. We just met in a room and recorded. But when I started that conference, I didn't have a lot to go on. So I'm more than glad to share because the reason I started is there were no Ruby conferences around me, plus I'm an open book. So for better or for worse, maybe that's good podcast material. JASON SWETT: Side note, it's one of the most enjoyable conferences I've ever been to. JASON CHARNES: Thank you. BRITTANY: I completely agree. I miss the regional conferences. JASON CHARNES: We lucked out because we were already planning on skipping 2020 because we were tired, and then COVID hit. I just sat on the couch one night and looked at Shannon (she helps me put on the conference), and I was like, "Wow, that would have been terrible. That would have come out of our own bank account, all that loss if we would have already booked somewhere." So phew, when it chills out, we'll try it again. BRITTANY: So let's talk about legacies. I know that some of us have taken over from popular podcasts. Some of us have grown podcasts from the very beginning. So I'm curious, do you ever put any thought into the legacy of your podcast, whether or not you're going to stay with it to the end? Would you eventually pass it off? Do you think about whether or not it's your responsibility to the community to make sure that it keeps going? JASON SWETT: I, for one, plan to have my consciousness uploaded to a supercomputer upon my death so that the Rails with Jason Podcast can continue on indefinitely. JASON CHARNES: Did you recently watch Upload the TV show? JASON SWETT: No, I've never heard of it. JASON CHARNES: Oh, man. That's a whole nother conversation. BRITTANY: Consider that homework, Jason. JASON CHARNES: It's an interesting question because we started ours out of nothing. I wonder, is one of us going to get tired and just quit? I'd like to think that if one of us did, it would keep going because there are plenty of cool people who could hang out and talk Ruby on it. But it's interesting, something that's casually crossed my mind, but I think we're good. I think we're still doing it unless Chris and Andrew have a surprise for me today. ANDREW: Surprise! [chuckles] I've thought about it a few times, specifically because I'm the youngest member of Remote Ruby. What if Jason and Chris just left, and they were like, "Oh, it's all yours now." Could I keep running it by myself? I think honestly, the answer is I would probably still do it just to have an excuse to talk to someone. I enjoy it. It's almost like a hobby at this point. I don't feel any obligation to create it. To me, it's really like an excuse to hang out with two friends, and other good stuff comes from that. But at the end of the day, I cherish that time just us hanging out a lot. CHRIS OLIVER: Yeah. I think that's why we sometimes joke about it being a weekly therapy session where we are just hanging out and chatting about stuff. It's nice to be able to talk about programming things at a high level with people you don't work with that have totally different perspectives and stuff. So yeah, if Jason and Andrew dropped off, I would still try to have conversations with random people I know and keep it going just because it's enjoyable. I would hope that we would be able to keep it going and have other people on there. BRITTANY: I'd love to hear from someone from The Bike Shed. STEPH: I have thought about it. I've thought about it partially from the perspective that Chris Toomey brought up earlier in regards to being on a podcast is an incredible platform. You get to share your opinions, and people listen to you. And they know you, and it's really wonderful marketing. So I have thought about it from the perspective of I want other people to have access to this really wonderful podcast that we put on each week. So part of me is very aware of that and thinking about how more people can have similar exposures. So a sort of a similar event occurred when Chris was moving on from thoughtbot and pursuing other interests. And at that moment, I just thought, oh my goodness, Chris brought me on as co-host, and now I'm here alone, and I don't know what I'm going to do. And I just panicked. I truly don't think I even considered other options. I was like, well, okay, it's over now. This was fun. And then it turned out where Chris was going to stay with the show. So things have just gone on swimmingly, and it's been wonderful. But similar to what someone was saying earlier around when you start listening to a podcast, and you really develop that relationship and you go back to that podcast because you really enjoy hearing from those people and their adventures, it's very similar for me where The Bike Shed is very much the conversations and chats with Chris. So I think if we were to move on, it would be whenever Chris and I decided to move on and give the reins over to somebody else. I don't know if Chris fully agrees, so this will be interesting to find out. [chuckles] CHRIS TOOMEY: I agree with that. Honestly, I'm honored to have continued on in the podcast after having moved on from thoughtbot because, in a very real way, the show is thoughtbot's channel to talk about things. I was at thoughtbot for seven years. I think I live and breathe that truth. And to me, that's what maybe has made sense for me to continue on. But I really do feel a responsibility to keep the show in good shape so that someday someone else gets to inherit this thing because I was so happy to get handed it. It was such a wonderful thing. And it has been such a joy to do for these past three years. But at some point, I do presume that we will move on. And at that point, I do hope that other people pick up the mantle. And thankfully, thoughtbot as an organization, there is a group of individuals that I'm sure there will be someone wonderful that gets to step in, but I'm in no hurry to do that. And, Steph, I hope you're not either. So we'll continue the conversations for now, but I definitely do want to keep this thing alive if for no other reason than I got handed it. I don't feel like I could let it drop on the floor. That doesn't feel right. BRITTANY: Well, I think on that warm, fuzzy feeling, we should wrap up. So let's go through everybody and just tell the listeners where they can listen to your podcasts and follow you. I am Brittany Martin, @BrittJMartin on Twitter. And you can listen to the Ruby on Rails Podcast at therubyonrailspodcast.com. JASON CHARNES: So I'm Jason. We are Remote Ruby. I am @jmcharnes on Twitter. And I'll let the others tell you where you can find them. ANDREW: You can find me everywhere @andrewmcodes. And if you email me, there's a really good chance you're never going to see a response because my email is a disaster. Please don't email me, but you can contact me anywhere else. CHRIS OLIVER: I'm Chris Oliver, and you can find me on Twitter @excid3 or at Go Rails, and of course, gorails.com. And you can find the Remote Ruby podcast at remoteruby.com. CHRIS TOOMEY: I am @christoomey on Twitter. The Bike Shed is @bikeshed on Twitter. We are at bikeshed.fm for a URL. I'm pretty sure www works, but I'm going to go check that real quick after because I want to make sure that's true. And yeah, that's me. And I'll send it over to Steph for her part. STEPH: I am on Twitter @SViccari, and I post programming stuff, usually pictures of cute goats, cute dogs, that kind of content if you're into that. JASON SWETT: For me, if you want to find my podcast, it's Rails with Jason. And if you search for Rails with Jason anywhere, you should be able to find it. And then my website, if you're interested in my blog and all that stuff, is codewithjason.com. BRITTANY: Fantastic. Thank you, everyone, for being on this mega episode today. It was a lot of fun. We are going to be having a podcast panel at RubyConf; we're excited to announce and some of us will be present. So stay tuned for details around that. And if you enjoyed this mega episode and want to see more mega episodes, please let us know on Twitter. All: Bye. CHRIS: The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review on iTunes, as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us @bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey. STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Bye. Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.

    303: Dear Mr. Grumpy Goose

    Play Episode Listen Later Aug 3, 2021 45:45

    Chris gives a DB sessions update and talks bifunctors & command objects. Steph shares the coolness of a gem she's been using called after_party, and excitedly gushes about her new laptop. (Chris is hoping to hold off on replacing his until the end of the year and then they can compare!) The two then answer a listener question on retrospectives and how they've seen productive ones run, while giving some of their own helpful opinions on dos and don'ts. They're talking to you, Grumpy Goose! dry-monads gem (https://github.com/dry-rb/dry-monads) attr_extras gem (https://github.com/barsoom/attr_extras) after_party gem (https://github.com/theSteveMitchell/after_party) What Went Well? - Bike Shed 123 (https://www.bikeshed.fm/132) What I Believe About Software - Bike Shed 172 (https://www.bikeshed.fm/172) Is Agile Over? - Bike Shed 299 (https://www.bikeshed.fm/299) Running a Retrospective - Upcase (https://thoughtbot.com/upcase/videos/running-a-retrospective) Transcript: STEPH: Cool. [laughter] CHRIS: Good. No, I like what you did there. STEPH: Yeah, I feel like we can get rambling on that one. CHRIS: It's been great. This is what the Bike Shed is at its best. It's the two of us just rambling and being like, well, what about this? And if it's this, then that, then these, and it depends. And it's complicated and it's nuanced. And what about the humans? That's the story of The Bike Shed right there. [laughs] STEPH: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Steph Viccari. CHRIS: And I'm CHRIS Toomey. STEPH: And together, we're here to share a bit of what we've learned along the way. Hey, Chris, how's your week? CHRIS: My week has been good. I have some updates actually on some topics from previous episodes. One of the things that I can update on is the discussion around the cookie versus the database store. So I had posed this as a thing that I was going to be doing in the app for a handful of reasons. Most notably, I wanted the ability to invalidate sessions from the server-side, wanted to have a little more control over that. And so that's a dream that the database-backed session store can do. Eventually, I have to make that actually work in the way that I want. But I was asking the question in that episode, which we can include a link to the specific episode, but I was asking the question of why don't we just do this all the time? The database-backed sessions seem better in all these ways. It's a lower overhead per request because you're just sending the session ID and the cookie instead of the whole payload of the session. You actually can have more data stored in it, a bunch of things that seemed really great. And then right after I introduced it, I figured out the thing. I figured out the secret. It's not a big issue, and we're going to stick with database session stores. But we have to be purposeful because it turns out they are essentially plain text in the database. And so if there's anything that you are putting into the session like say a social security number or an authentication token or other things which naturally I might have done if it was in a cookie that lives on the user's browser and never actually lives on the server, persists on the server, that seems fine to me. But now these things are getting stored in the database and that really changes the calculus, especially because if I'm not purposeful, they'll just stick around for forever. So social security is probably the most pointed example of this. If you happen to have a form in the app that accepts a social security number and you want that to persist through some number of other steps, not actually going to store the social security number in the database because that's a thing that I have actively chosen not to do. I need to send it off to some other system, but I do need to hold onto it for a few minutes. The session is a perfect place to put that unless the session gets stored in my database. STEPH: That's such a great point. I'm so glad you discovered that. And in our recent conversation, we were trying to think of the reasons why this isn't the default case. You may be headed in this direction, but this may also be timely, the fact that you're discovering this issue but also the fact that Rail 6.0 now has encrypted columns. Is that where you're headed with the fact that you can still keep session data in a database? CHRIS: That is a great question, and it is an intriguing option. But it's not the one that I'm going with here. I think broadly, my hope is to completely avoid ever persisting this data in the database, this truly sensitive user-specific PII or PCI or social security numbers or any of these other fancy acronyms that get collected together under the umbrella of I probably don't want that on my server. For those, I'm just opting to push them back into a cookie. So I'm using particularly a...In rails, it's fun because they have a fluent interface where you can just chain together things, so it's cookies.signed.encrypted.whatever, and then you go from there. But I'm using signed, encrypted cookie, which is essentially what the session store views; the cookie session store uses itself. So I'm basically reverting to the old session store behavior for specific values. So anything that is truly sensitive like that, I'm just saying, cool, that's actually just going to live in a cookie, and that will be it, but not leaning on the ability to encrypt the database sessions. There's just enough subtlety around that. There's so much volume of data if I do allow that sensitive data into the system that any failure, any exploit that happens, would be somewhat catastrophic. So, in my mind, this lowers the surface area and says, yeah, this data really never lives on the server. It comes with a request, and then it's gone after the fact. And that's the world I want to live in. STEPH: Yeah, that's super interesting. You're also raising questions for me that I hadn't considered when we originally had this conversation where there's necessity or that you're looking to store form data or sensitive data in that session as well. So that makes a lot of sense to me that for that type of behavior, we're going to separate that from the idea of authentication and the user session and still use encrypted cookies for those details. So it only stays with the user's browser, but then the actual authentication of a user that part could still live in the database. CHRIS: It is ending up being a weird Venn diagram of; this is data that I want to stick around but only sometimes and particular to the machine that the user is interacting with because the session is still associated with a cookie at the end of the day. So a user may have multiple sessions in the database-backed session version. It is somewhat interesting, and I'm going to see how it develops over time. But yeah, at a minimum, I have now found this edge case of like, ooh, okay, sensitive data, that's a thing, which is one of the reasons that I would reach for the session inherently. So it turns out, as always, it depends. Things are complicated. STEPH: It's a nice update. I like when we have closure to a question like that, especially so quickly. CHRIS: Love to provide that continuity. It's what I'm all about. But yeah, what's up in your world? STEPH: What's up in my world? I am excited that I have a new laptop. So I have been using a MacBook Pro for about the last...it's lasted me for a while. I think I've had it for a good four, four, and a half years, but that's on the fritz. The keyboard, in particular, the keys are popping off, and that's something that I could go get fixed. But I'm at the point that I need a new laptop. So I have a brand new shiny laptop. And I had the option to either go with a 16-inch MacBook Pro or to go with one of the new, fancy laptops that has the M1 chip. And I was torn for a little while because having the M1 chip sounds really cool and novel, and there's a lot of speed improvements that come with that. But I ended up going with just the 16-inch MacBook Pro; specifically, one, it's still very fast. It's very reliable. I can use this as my work machine and just know everything's going to work. That part feels really important to me. And then also the screen size is important. So any Mac laptop that is using the new M1 chip, I think they only go up to a 13-inch, right now, screen size. And I really want the 16-inch in case I am traveling, so I have that larger desktop. But I did do some research into the M1 just because I know about it. I know it's out there. I know it's hot. People are interested in it, but I didn't know a whole lot about it. So for anyone else that's like me and is curious about what the heck this M1 chip is, it's essentially Apple's foray into making their own processors. So traditionally, their machines have used Intel CPUs and third-party graphic processors, and other parts. And this introduction of the M1 chip really represents Apple's switch to having their own internal architecture rather than relying on those third-party parts. And it also means that all those features that were sourced from other parties like the CPU and its security are now being combined into a single chip, which has also led to some performance improvements. And while I was reading about the M1, there's a lot to go through, but the thing that stood out to me was this idea of Apple's Neural Engine. And I thought, well, that sounds super fancy. What is that? Are you familiar with Apple's Neural Engine? Have you read about that? CHRIS: I don't think I am. What all is that? STEPH: Yeah, good question. That was a question I was asking myself just recently. So essentially, their neural engine it's a microprocessor that specializes in the acceleration of machine learning algorithms. So it's really similar to how a GPU will focus on accelerating graphics rendering. And their neural engine or neural engines in general then focus on accelerating neural network operations. And the inclusion of a neural engine isn't something that's new because Apple introduced this into iPhones and iPads back in 2017 to support their features like Face ID and emoji, searching for photos with dog pictures. Siri speech recognition is also one that's using this engine and other machine learning tasks. But the sparkly stat that Apple is sharing with this new design is it's a 16-core design that can perform 11 trillion operations per second, which sounds very fancy, very fast. But it really got me thinking about how companies are working to improve, not just laptops but also our mobile devices to run machine learning software more efficiently, and then how that's just going to evolve and change all the different features that we use, and then how developers can integrate with this engine. I think currently, Apple hasn't shared much information about how this engine works, but I think they've exposed a few developer tools so people can still build features that will then use the power of this faster, improved neural engine. CHRIS: Oh, that's super interesting. I have still not really delved into machine learning or artificial intelligence, or any of that stuff in any real way. But it's one of those things like the number of mentions is ticking up. And at some point, I'm like; I probably have to pay attention to this, don't I? I'm still in the not paying attention to it camp. So if I'm understanding, though, you just described this wonderful feature, but you opted for the machine that does not have all the fancy stuff. You did not... STEPH: Exactly. [laughs] CHRIS: Okay, yeah. STEPH: Yes, it would have been nice. That would have been neat, but yeah, I needed a machine with a larger screen, all those good things. And that's still really fast, for the record. CHRIS: Oh yeah. I'm desperately hoping to make it to the end of this year. This is going to be a bit of a rumor mill here, but my understanding is the expectation is that Apple is going to release a 14-inch MacBook Pro with the M1 and the return of MagSafe, and the removal of the touch bar. And that sounds like my dream machine right there. I want that piece of hardware. I also seem to care a little bit less about the size of the laptop screen. I'm so often working at my desk with a large-format monitor that I'm connected to. And so, when I'm on the road, I want to optimize for portability when I'm traveling because I do it so rarely, and then I'm hopefully focusing on travel at that point. But we'll see if that remains true as the shape of my work changes and I start to not only work from home. And maybe I'll actually change my tune on that. But for now, that's my hope is to make it to that machine and then get one, and that it exists because right now, those are all rumors. STEPH: Well, I totally support this goal of yours. So that way, you can have that new-new, and then you can report back on what it's like, and then we can compare. Because I'll have the other version, the Intel CPU, and then you'll have the M1 chip, and we can see how our lives are different. CHRIS: You'll have the new, and I'll have the new-new, and that's how we'll categorize them. STEPH: [laughs] But yeah, I'm very much looking forward. Having a new laptop is always just such a fun feeling. It's just a clean space that I get to rebuild. It's like going through and prioritizing; what are the things that still spark joy? And then I get to only port over the stuff that I still really use all the time and want to keep. So I'm looking forward to getting it set up. CHRIS: I need to do that sometime soon. I'm like five years deep, at least on this machine. So I've been dragging along. Also, the hard drive is just completely full, and I regularly have to go through and delete things before we start recording because it turns out these audio recordings start as very large files. [chuckle] So it's almost a weekly thing where I'm just like, got to throw something out today. I don't know what. It's fine. I'm going to be fine. [laughter] I'm going to make it to the end of the year, and it's going to be great. STEPH: What else is going on in your world? CHRIS: Well, I wrote some fancy code, and I use fancy not necessarily as a good word. [chuckle] So I'm intrigued that the code could be described perhaps as clever or other words like that, which I think are very complicated words in the coding space. I tend to try and avoid this type of coding where I'm trying to introduce abstractions and clean things up, and remove duplication because I've been burned by that so many times in the past. But this time, I think maybe this time it'll work. So, in particular, there are two different areas of the application. There were two sets of refactorings, but they really went together. One is we have the idea of command objects within the application that we're working on. So there are a lot of cases where we need to save something to the database and then communicate something to an external API. And then presuming the results of that is a successful response from them, then unpack some data, make sure it's in the right shape, and then save something else to the database. And ideally, wrap that all in a transaction and keep everything together and then return some data at the end of it. So that whole sequential operation, I've been using dry-monads to model that. I've talked about this on a few previous episodes. I'm really enjoying it. The more I lean into it, the more I find that it is just a really great way to wrap up that very procedural code. But ideally, do it in almost a functional way so that we've got these sequential operations that feed into each other. There's the railway-oriented programming stuff, which is associated with this idea. But there is a lot of boilerplate to these objects. So the way we've defined them is they have a class method called run that takes whatever the arguments are, and then it needs to pass those arguments into the initialize and then call run on the instance. So in order to define one of these objects, what we had been doing was def self.run and then all the arguments. And then inside of the body of that, it's new, and then pass forward all the arguments .run, and then define initialize to capture all of those and set all the instance variables, and then define the run method, which actually does stuff. Also need to define an Adder reader for all of those instance variables, which is a thing that I enjoy doing. So that's the interface I want, or that's the way that I want this class to work. I know other folks in the Ruby world feel differently. But that's the shape of the thing that I want, but that's a lot. And there's also I regularly would find myself forgetting to duplicate something that we put into the class method run interface into the initialize method. And it was just like, this is all just wiring up and plumbing. There's also the binding of the dry-monads do notation for the run method as well as the inclusion of the results type within dry-monads. Type is a strong word, but that gives us the success or the failure objects that we can create. So ideally, all of these command objects either return a success object or return a failure object. It's one of the two. And that's one of the things that I really like about them. But yeah, so much plumbing. So we define a base command, and the base command has the self.run method, the class method, and that method is defined very abstractly. So it's just args * keyword args. So we're capturing all of the arguments and then forwarding them on to new. So that way, I don't have to think about that interface. It basically just says, "Give me anything, and I'll forward it onto new." And the new or initialize is in charge of actually defining things. It also includes the result type. It includes the macro annotation for the run method, which is how dry-monads does its magic, that actually I had to include inline within the self.run, just because of the sequence of definition and the metaprogramming that's going on there. As I said, that sentence terrifies me a little bit, but hopefully, no one ever needs to look at this magic base class [chuckles] and figure anything out. So that was one part of it. That cleaned a lot of things up, so that meant I didn't have to write a ton of the wiring up code. Then there was still the noise of actually defining all of the arguments to these classes. They often take a handful of arguments because that's their job is to grab a bunch of things and do some work with those things. So for that, I have brought Adder Extras, which is a gem that I've talked about probably in previous episodes, I think so. But this is the first time that I've really leaned into it and used it. And it gives some very high level what look like macros are just class methods. But the one that I'm using is Adder private initialize, and that you can then pass a variety of values too. And it will then say, okay, this method accepts a required keyword arg, a defaulted keyword arg, and a positional argument or something to that effect. But it's a very, very concise way to express that and then also get the private Adder readers, which again is the direction that I want to go with all of this. So that's a bunch of things that I have said. But all total, it cleaned up these command objects very nicely. And now, when you look at one of these command objects, all you see is the run method that does the work. And the plumbing and the wiring up behind the scenes should just happen. I am concerned about the day that someone forgets to inherit from the space command, and then it's like, why does nothing work? I thought command objects just worked in the system. But we're going to deal with that when we get there, which is hopefully a while down the road. STEPH: I like how you're pushing at the boundaries of our comfort zone. I say our comfort zone because I imagine we feel similar. CHRIS: It is. We definitely got a shared comfort zone. [laughter] STEPH: Yeah, we have a shared comfort zone with inheritance, but you're pushing at that boundary of that comfort with inheritance because it is something that can be so painful. But you've identified an area where inheritance feels useful. And then it also sounds like a very meaningful...you're introducing this pattern and then trying to make it easier for others to follow this pattern. So it's a very intentional design decision of where we want to group these behaviors together and then make it very easy for other developers to then pick up this pattern and run with it, and then also work with these classes. So I am intrigued to hear how it goes and how others feel about the pattern as well. I also wonder, this is one of those areas where it feels like this very intentional design decision. Is it something that you think in the base class would be worth highlighting? Like, hey, here are the things that we are using in this base class. This is the intention of this base class. I don't know if that's maybe a comment or if that's something that's documented in the README. I know; I see your eyebrows went up when I said comment. But it does feel like one of those areas where it's like, hey, we have introduced this new concept. We want you to follow along. Here are some helpful guidelines. CHRIS: Those were mostly joking eyebrow raises because I have thought of that. I haven't actually gone to that level. But in the back of my mind, there's this pattern that we have within this application. Ideally, we're going to lean into it more and more so that A, we have a clear way that we do things within the app but also make that as understandable and discoverable as possible. I'm not sure if a comment in the class is the right thing or...so I'm deferring what I want to do on that for now because right now, it's myself and one other developer. We sort of developed this in tandem. So we were working together on it. We would pair in a bunch of the features. And what we have now is the crystallization of what we found useful. And we're both very comfortable with it. So there isn't the need to explain it. I'm almost thinking about it as just-in-time educational content around this piece of our application. I don't actually trust that I would do a good job describing it in the abstract because I know it. Like, to me, this thing makes sense right now. But I've been on the other side of stuff where someone was like, "Hey, this totally makes sense." And I'm like, "I don't know any of the words you just said," and so I felt that pain being on the other side. You could say I'm just being lazy, but I do think this is a purposeful delaying of that where I want to wait until I actually have someone to teach this to. And at that moment, I want to see what that conversation looks like. And I'll try and explain it to the best of my ability, but I'm sure they're going to ask questions, and I'll be like, "Oh, wow. Yeah. I hadn't even thought of that. But now that you ask the question, totally let me explain this part that I was going to gloss over and forget to mention." And so, ideally, that is what will happen down the road. And then from that, hopefully, some artifact becomes clear, whether it's a documentation page in the repo or a comment in the class if it's simple enough or maybe even it's a recording of a pairing session. And that's the artifact that we keep around that explains this piece of the application. So I definitely think a version of that makes sense, but I am not doing it yet. STEPH: It's funny; you're saying so many good things that I agree with. I love the just-in-time education; that part is fun. And yeah, there's a part of me that definitely still leans into the idea because we've talked about this in the past too, where we write down, in the moment, the things. Having that context when we're implementing it is really important and helpful. So even if it's not this grand explanation…which I really like what you said around having someone to explain it to or have that conversation with so that way you're documenting the useful bits, that part I like very much, but capturing the intent as soon as the change was introduced. So even if it is a very high level like, hey, we are using dry-monads and Adder Extras, even if it's just links to those things, that's something that I think I would still favor just to go ahead and start surfacing this is a pattern. This is a choice. And then, as you continue to work with the pattern, if you change your mind, it's still very easy to scrap that documentation. So I think if it were me, I would still go ahead and document it. I think it's that piece about discoverability that's calling to me so strongly where that's where I want to then highlight the things that are in use. So even if there's not an explanation, people can find the resources very easily. Because you're right, you did say a lot of interesting bits in describing this pattern. And the fact that we're talking about it now also just deepens my suspicion that it would be nice to comment somewhere, and perhaps a repo is a perfect place for it and just get it out there, and then it can always be revisited later and improved. CHRIS: Okay. I like that you are keeping me honest on this because I do think there's a certain amount that I'm just being lazy here and not wanting to do that because it is actually really hard to try and document something like this. Like, what are the important pieces versus what are the extraneous details that people don't actually need? I do wonder, so the pull request that did this refactoring and introduced this base command object that does have the explanation captures the point in time and whatnot. And so I wonder, is there a version of tagging important pull requests that tell the story of the application? A lot of things are just going to be like; this is adding a feature. It's the same as the other 30 pull requests recently that added a new feature. But this one is special from an architecture perspective. And so let's tag this, let's add a label. I don't know what it is but something that allows for discoverability of the story of how this application became what it is today because anything else I worry will go out of date almost instantly. But this pull request is true fundamentally in that same way that we say commit messages should capture as much of that detail. So I did do that writing for the pull requests/the commit message. And I wonder if maybe that's the best artifact for this moment but then the question of surfacing it and making it discoverable because otherwise, it's just lost in the sea of other pull requests. So I don't know. But I do like the slight push back that you're giving me here of like, yeah, but what if you did something though? And I'm like, yeah, that's fair. I should probably do something. STEPH: Being able to pin those specific PRs that have significant architecture changes sounds really novel, but I'm going to take this opportunity for me to be lazy. And if I'm joining a project, I don't want to read through what has happened. I just want to know what's true now. And if I go back and look at those PRs, I won't know if all of that is still relevant and how it's changed. So it sounds neat from telling the story of how an application has evolved. I like that sort of developer lens, and what are the things that we have tried and then changed over the years? But from I am onboarding to this application, I just want to know what's true today? What are the things that you want me to follow? What are the patterns that are going to be really helpful for me to look at? And so then, I don't know if I would use it in that context. And this may be one of those areas where I'm feeling overly skittish in response to the number of things that you said and the use of inheritance. Because I have felt so much pain of where I'm going up the tree to figure out what the heck is happening in the world and then to understand all of those pieces, and then swimming all the way back down to the class that I'm actually working in. So it could just be past experiences that are now influencing how I want to document or work with inheritance. It probably is. [chuckles] That's probably a big factor of it. It doesn't mean I disagree with it because those painful experiences are meaningful. [chuckles] CHRIS: Yeah. I think the foundational thing...I tried to start this with the context of like; I did a thing. This is another example of good idea, terrible idea; my favorite segment on The Bike Shed. I stand by it. I think it was useful. It does use things that we have traditionally moved away from. I say we because, again, I think we have a shared approach to development at this point. But I think it's worth it. I hear everything that you're saying about the documentation, but I've been burned by that so many times where the documentation is like, here's what's true now. And you're like, no, there isn't even a class called that anymore, and no less does it work that way. And so, my inclination is not to go that way. The solution that I have in mind is when someone is onboarding into the application, I don't expect there to be documentation and other things that I can hand them so that they can run. I expect to sit down with them and work with them. I'm going to pair with people when they join a team for a long time. There's a period where that's true, I think, and then you get to a certain size of an organization, and you're onboarding enough people regularly enough that that's a thing that you should get better at. But for I think a surprisingly long time, my answer I'm more than happy for it to be, yeah, we're bringing someone new into the team. Let's sit down with them. Let's spend the time. Let's tell them what's true because I know currently, and I can give them an up-to-date version of that. And ideally, as part of that, then update the static documentation, the repo, the README, the other things based on the conversation that we have and recognize oh, that that link is very out of date. Let me change that one real quick. But I'm not expecting to have comprehensive documentation for that. I'm expecting to use real human interaction to fill that gap. STEPH: Yeah, I really like that you're also calling out how fallible documentation is and how it has misled us so many times. I also love what you highlighted where when somebody new is joining the team, we are more than often going to sit with them and then explore the app together. And it just made me revisit that phrase that you used earlier about the just-in-time education. Because for this command object, you may join the project and not need to interact with this design pattern for your first couple of weeks, first couple months, who knows? So then it comes back to the idea of how when someone is in the space of where using a command object feels like the right approach, then how do we introduce them to this pattern and then make sure that they have the tools that they need? And if someone is accessible to then sit down and go with them, that's great. But if someone is not accessible, then I still want them to have at least a few of the resources that they need to dive into some of the more complex things that are being included. So, yeah, it's a tricky one. I like this thought experiment. CHRIS: But yeah, overall, I'm happy with it for now. I'm hopeful it will work out for us moving forward, and I'm hopeful that it will also be a sufficiently discoverable or teachable thing within the application. But again, I will certainly report back and see how that one plays out for us. But yeah, that's what's up in my world. What else is going on in your world? STEPH: Something else that's up in my world is I have pulled in a tool that I've used in the past, and I really like it. So I'd really like to talk about it here for a bit because I just find it so useful. And now that I've added it to this new project, it's just really top of mind for me. So I found that when working on a project, there are often times where I want to run something right after a deploy has happened, and I want that to be automated. I can do it manually. I can hop in, but then perhaps if you're deploying across many environments or many systems, you don't want to have to do all that manual work, or you also just want the convenience of you can set it and forget it. And that way, you know something's going to happen. So perhaps it's something where you want to change some data, or if you want to enable a feature flag, then this is really helpful. So the gem I've been using for this is called afterparty, where you can write automated deploy tasks that essentially behave very similar to migrations. So you can write a Rake task. It has a timestamp. You can implement the logic that you want to be run right after your code has deployed, and then afterparty itself, we'll check the timestamp. It will see if it has been run. If it's already been run, it won't run it again. Or if you like, you can set it up so that way, you can tell after_party to say, "Hey, after every deploy, I want you to run this particular task," but it's such a nice improvement to the workflow. And the other thing that I really like about this that I feel is a bit contentious is separating changing data outside of migrations. So I am a big fan of migrations are focused on changing your schema itself. But if there's actual data that you need to change, I really like when that is separated outside of the migration. There are definitely times that I understand it's really nice to just do it all at once, and it's easier. But anytime it starts to get even a little complex, I immediately want to write tests for it. And I can't test my migration. But if I'm changing some meaningful data on production, I want tests to back it up to make sure that I'm scoping correctly, that the outcome is exactly what I expect. It also makes it easier for other people to review. And after_party gives me that functionality so then I can have my migration. But then I'm like, oh yeah, but I still want to automate changing this data because that's often one of the complaints that I hear from people when I do ask them to separate into a Rake task, changing the data. They're like, "But I don't want to have to then follow up and then run this task later." And I'm like, that's cool. Afterparty has you, and you can automate it and not worry about it. So afterparty has been one of my favorite gems to add to applications. CHRIS: That's interesting. There's a bunch of layers to everything that you just said. I think I've worked with after_party on a project. I think we were working together on that project, if I'm remembering correctly. I have no bad memories of it, which given the nature of the tool, makes me think it did its job very well because its whole point is just like, oh cool, now you can just do this thing, and you don't even really have to think about it. Because there are plenty of other times where I've had to orchestrate or do a deploy. And then I SSH tunnel into production, which is a bad idea, and then I'm running Rake tasks manually. And so, I think the fact that I don't have any pointed memories of this is a really good sign for a tool like this. So that's a weird vote in its corner for me. You did say something that was interesting that I want to poke at a tiny bit which was you can't test migrations, and I think that's true. Like, I don't know of any way. And it feels like a thing that is sort of fundamentally deeply true. But I do wonder, is there any gem out there? Has anyone done a weird science experiment to figure out like, I would actually really like to be able to test my migrations? So I think the idea of having to pull data change out of migrations for the reasons that you said totally makes sense. But there are often times where I want to convert from non-nullable to nullable. And in the process, I want to backfill with a given value or something to that effect. And I like to encapsulate that altogether such that if it fails or succeeds, it's transactionally consistent. And I do wonder, could I wrap a test around that? I don't know of a way, and I think it may actually be the Rails testing infrastructure is just like no, we prepare your schema for you in the background, so it's just up to date. And therefore, you don't even have a way to be in a state where the migration hasn't run. But it's an intriguing one. STEPH: Yeah, that's probably a hard absolute that I said where you can't test it, and I'm sure there is a way to test it. How friendly or how easy that is to do, I'm really not sure of. It also feels like one of those areas where it feels like I'm testing this other service that I should trust fully, so then I'm not necessarily testing the migration itself. I'm testing some logic that I've added inside of the migration where I'm changing some data. And the example that you provided is perfect because that's one of those that I'm inclined to include in a migration. It's more like where we want specific users who have this value or in this category. And then, we want to migrate them from this data to the other data. And when we start getting complicated in our migrations, that's when I'm like, this is a bit much, and I'd really like a test that documents that we're doing this correctly. That's where I get squeamish about having data changes in migrations. But you do raise a good point. I don't know; I've never tried to test one. I've just always reached for this other approach, but that is more the pain point of if I could test this data change inside of migration, then that would work for me. That would solve my problem. CHRIS: I wonder if an alternative approach would be to just introduce an object or a class that does this work. So like a command object as it were, to do a call back to earlier in the episode, that does that data transformation because it's exactly what you're describing, for this subset of users do this. But if they're in this state, then do these things and create two new records for any user like this. That sort of stuff is really complicated. Definitely want to have some tests around it. But you're talking about a gem that allows you to extract it into a Rake task-like situation. But I wonder, could we just have a class for that? And I used to be a big believer in your migration should live forever, and they should always be runnable from the beginning of time. I've given up on that belief. That's one of the things that I've been like; I don't know. It turns out I've never done that. It's not an important thing. Just DB schema load is going to be fine most of the time. It's great for the past ten migrations to be around just to tell a little bit of a story. But I'm not tied to migrations being runnable forever. So the idea of you introduce this class, it encapsulates that data transformation. You can test it because it's its own thing. It will still be run within the context of the transaction of the migration. And then you throw it away down the road along with the migration, and you do that migration roll-up thing. It's just a different thought there, although I do like the...well, I guess that would also run automatically, but that runs as part of the deploy as opposed to after the deploy, which is meaningfully different than what after_party does because there might be one of these migrations that takes a long, long time to run because you've got a ton of data. And you want to decouple it from the true deploy release sequence that happens and the time limits that are there. So I think I've now talked myself in three circles, and I'm going to stop. STEPH: I like how you highlighted that part where it does decouple you from the deploy process where it's still automated; it runs afterwards. But say if it's something that doesn't need to hold up the deploy, you don't need to wait for this data to be migrated before the deploy can go out. Then that's a nice separation because then it can happen afterwards. Or if you do need it to happen part of the deploy, yeah, there's lots of interesting bits there. I feel like you and I could talk about it for a while. But we have a listener question that I'm really excited for us to talk about. So I'm going to hard pivot over to our listener question. This question comes from Jonathan. And Jonathan wrote in, "Hey, gang, longtime listener, first-time emailer. I've heard you reference retrospectives a few times as part of your normal development practice. In my limited experience with them, I often find retrospectives don't feel productive because team members are reluctant to raise issues without seeming critical or blaming another team member. I would love to hear you describe how you typically run retrospectives to foster open discussion and make it a productive use of time. Bonus points," oh, I love bonus points "if either of you have experienced rescuing an existing team that was not having productive retrospectives. P.S. Thank you for ongoing participation in the Ruby and Rails communities. I look forward to seeing a new episode pop into my podcatcher each week." All right, retrospectives. I love this question because I've definitely been part of teams that are really struggling to have a productive retro. So I think it would be helpful, as Jonathan highlighted, to go ahead and share how thoughtbot runs a retro. And then I'd also love to touch on some of the areas where I have seen teams really struggle to have a productive retro. So with the thoughtbot format, there are really two questions that we focus on. The first question is, what went well? And this starts the meeting on a positive note, which can help people get engaged before then we move on to heavier topics like concerns and issues. When we run a retro, we ask each person these two questions. So that first question, we go around to the room, and we say, "Hey, what went well for your week or for your last two weeks?" And then we document all of those positive things that people say. The next question is, "What concerns do you have, or what are you worried about?"And the goal here is to highlight issues early, which then gives us the chance to address them as they come up rather than waiting till an issue has grown out of control. And it's usually during the concerns portion that I often see retrospectives fall apart. The reason for that is hearing someone describing a concern is often something that can stir up a lot of emotions. And I know for me, it certainly triggers my instinct to where I really want to dive into that issue, and then I want to solve it. But by reacting to a specific issue and then trying to solve that issue, I'm interrupting that retrospective flow to then focus on that issue. And we may not get to a bunch of other important issues that people had. So that's often where I see retrospectives fall apart. And the way to fix that is to then have the team consensus that hey, this is a space where everybody gets to air concern. We're going to go around the room, so everybody has a chance to speak. We're going to document it, but then we're going to move on and then come back to this later. So when do we talk about concerns? So once everybody's had a chance to share their concern and that's been documented, during that process, you're often upvoting other concerns. So someone may bring up a concern that I also have as well. So when it's my turn to speak, I'll say, "I'd like to plus-one that particular concern," and then maybe add my own or just plus-one some of the others. So then, by the time that everybody's had a chance to speak, you already have an idea on…whoever's taking notes or if it's being ideally shared so the whole team can see. You can already see the concerns that most of the team is identifying with or that are the more popular concerns. So then, as a team, you can say, "Hey, we're going to focus on the top two concerns because that's really the amount of time that we have," and that way, we're focusing on concerns that impact the majority of the team. So at that point, then we can start talking about those specific issues and how we'd like to address them. And then out of that conversation is then the next part of the retro format, our action items. And then action items are where we can capture the things that we would like to try during our next iteration of work until our next retro. This is our experiment area. So then we can say, "Yes, we'd like to try something different, or we'd really like to monitor how this goes." And then one other fun thing that I typically include in retros are housekeeping. So then we can talk about time off, team celebratory events, anything like that that's helpful to highlight to the team. That's a quick overview of how typically I myself run a retro. Chris, do you have anything you'd like to add or anything that I've missed? CHRIS: No. I think that that mirrors pretty well the best retros that I've been a part of. There are a couple of things that I think I would add or emphasize in that. So one is foundationally, with a retro, what are we doing? What's the goal? And the goal with a retro is to identify and evolve our process. So identify where there are any bottlenecks or things that aren't working, and then ideally change things over time. I've been on many teams where just the same issues get brought up over and over in retro, and nothing changes. And that will just completely deflate the team. And so, if that is happening, that's a fundamental thing that we need to fix. And I can totally understand folks being like, "Retro is awful. We just sit down and say the same things, and then nothing ever changes." If that's happening, we have to fix that at a more fundamental level. That is going to be more than a retro's worth of effort. But ideally, retro is now this structured space each week, each iteration, whatever it is where we are discussing what's going on and ideally, slowly, incrementally making the process slightly better. In my experience, it's something that I really love because I come to associate it with stuff is going to get better now. That's what retro means. If that's not the feeling you have, then I totally get why you wouldn't want retro. But I promise that that can be a reality. And then to touch on some of the particular procedural points, everything you said definitely maps. And I've found that structure works really well, but there's a lot of subtle things in that structure that I think are important to highlight. So one, going around the room and actually asking everyone individually for their thoughts, I find to be so useful because it's very easy for one or two more vocal individuals to just dominate the conversation. So particularly by starting with what went well and then also by actually going around the room and requesting "Everyone reply to this question please," even if it's just like, "Yeah, you know what? It just felt like a good week." That's an answer we'll accept but ideally, a little more structure or a little more meat to it. But I find that to be really important. Likewise, I have found that having a facilitator, so someone who is guiding the retro but not actually a part of it. They're not going to be saying what went well or what didn't go well. They are just directing the conversation and somewhat critical as you're going around and asking for concerns. They are the person whose job it is to prevent the team from starting to try and address the concern when it's first voiced. So ideally, we're just collecting the concerns. We're collecting the plus-ones so that we know which are the more prominent ones, and then we can focus on those. And I think that idea of the plus-oneing of concerns and then really focusing on the ones that have more folks that are concerned about it feels really critical in my mind. So ideally, we are a team. We're working as a team, and if one person has this gripe that they really feel deeply, but nobody else really cares about it; ideally, we find a way to help that person not feel that way. But that's not necessarily where the team collectively should put all of their energy. So yeah, that's a bunch of little pieces. Also, just as a note, we'll include these in the show notes, but there are a couple of previous episodes, so Episode 132: “What Went Well?” is a discussion between Derek and Sage, previous hosts of the show, talking about retros. Episode 172: “What I Believe About Software” was the first guest visit by a certain Steph Viccari. And so that is a wonderful episode in which we dug into retro because it's one of our favorite topics. Also, Episode 299: “Is Agile Over?” We definitely touched on...that was a pretty recent one, but we touched on retro. Then there's also a video on Upcase called “Running a Retrospective” that basically describes exactly this process and shows actually an example retro and running through it. So there are lots of other things that we can point out here. But again, I think fundamentally, what are we doing, and how are we doing it? If we can answer those questions well, retro is going to be great. If not, it's probably not going to be that great. STEPH: I appreciate you calling out all of those important nuances because those nuances are what lead to then a retro feeling more productive. And to address Jonathan's other question around if people are feeling timid to bring up an issue because they don't want to blame anyone, then I think to address that one; specifically, you have to come to retro with a WE mindset. And I think HBO accidentally sending a test email is a really good example of that. Because in the Twitter thread, a bunch of other I presume developers were commenting and responding in support of the person that sent that out to say, "Hey, you discovered a missing safety net in the system," or the fact that it was fairly easy to make this mistake and send it out. So if you come to retro with this mindset of if a mistake was made, how can we as a team improve this so then it's less easy to make that mistake? Then you won't have the sense of we're blaming this on one person, but instead, we as a team are responsible for helping each other out. CHRIS: It's interesting to have that conversation in the context of retro because I don't necessarily think of retro in exactly this way. But there is the idea of blameless postmortems, which come out of the Google Site Reliability Engineering; I think it's a book, maybe it's a website. We can include a link regardless. But that idea of blameless postmortems of collectively as a team, this thing made it out into the world, this bug, this problem. So we need to own that as a team, and we need to have a blameless conversation around that, just talking about what happened. And there are subtleties there. And that's a nuanced idea that needs to be evolved, but that is at least some writing that exists in the world that talks specifically to that part of it. That said, I wonder if a true postmortem, so a distinct meeting just dedicated to those more pointed issues, might be more relevant, and then retro is more of a shared overall conversation. But if there are smaller versions of that, then I think using that framing could be really helpful in retro. STEPH: Yeah, I think you said that perfectly where there needs to be team ownership over all of the issues that are being discussed. And I think there is one other very tricky area to navigate with having a productive retro. And I don't know of a better way to say this. But you have a grumpy goose on your team. You have someone who doesn't like retros, and they're going to be negative, and they're going to be vocal. And that is a hard one. I have been there before. And I often approach that situation by speaking with them specifically around what are your concerns with retro? Are you willing to at least buy-in and give this new format a chance? But you essentially need them to buy in or have leadership buy-in so then they know to follow suit as well that this is a team process that we're going to improve and work on together. And if you don't like it, then that's what retro is for. So how we can make this a better, more productive meeting? But just showing up and being grumpy isn't helpful. And then helping people who have been burned by retros overcome that negative reaction to retros is something that takes time. CHRIS: Oh yeah. The grumpy goose just affects everything on the team. But definitely retro is one where I've seen that particularly pointed. I think in those cases, the best luck I've ever had is to, like you said, have a separate conversation but have the conversation at a higher level. So the question isn't about do we have retro or do we have it in this shape? The question is, do we think we are operating at our best? Do we think everything is going perfectly? And almost never will the answer be "Yeah, this is great. We have no bugs. We're moving as fast as we possibly can. Everyone is happy. No one is burnt out." And so if we get to an agreement that is like, well, yeah, sure, there are things that we could improve, then I think that's a toehold that we can then build on and say, "Okay, so how do you want to go about that? I am fine to explore a different approach than retro as a meeting to continually improving and evolving our process. I'd love to know what thoughts you have, Mr. Goose." But if they don't have an alternative, retro is the most effective structure that I've found for this continuous feedback loop around the process. I'm very happy to find an alternative, but I critically think we need something like that. And so if they're going to be pushing back on retro specifically, then I'll bump up to the higher level and say, "Okay, how do you want to be improving our process? Let's try something else, but let's make sure we are asking the question of how do we improve our process and is that succeeding?" And also, stop being so grumpy. Come on, what are you doing? STEPH: [chuckles] I recognize that approach so much because then it really gets to the heart of the purpose of retro whether it's actually called retro or how we handle it is not significant, but the fact that we together as a team can get together and discuss how to improve. That's really the important thing that we're after. And retro just happens to be the format that I use and really enjoy. But like you said, it's always open to each team's interpretation. On that note, Jonathan, I hope this quick overview of the thoughtbot retro has been helpful. And we will also include some other links that also highlight how thoughtbot runs retros and some other discussions that we've had about retrospectives. But on that note, shall we wrap up? CHRIS: Let's wrap up. The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review on iTunes, as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us @_bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey. STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Bye. Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.

    302: Observability with Charity Majors

    Play Episode Listen Later Jul 27, 2021 38:53

    Tune in as Co-founder and CTO of Honeycomb, an observability platform, Charity Majors joins Chris to drop some knowlege bombs such as: Thinking of observability as being about the unknown unknowns: Allowing for high cardinality, high dimensionality, ad hoc queries at any point in time. Comparing instrumentation to a muscle: It's a habit that needs to be developed and fostered. Sincere continuous deployment: 15 minutes or bust. And bunches more, since y'all know you hear her name come up at least once during every other episode! Honeycomb.io (https://www.honeycomb.io/) o11ycast (https://www.heavybit.com/library/podcasts/o11ycast/) Charity's blog (charity.wtf) (https://charity.wtf/) Charity on twitter (https://twitter.com/mipsytipsy) Charity's post on cost of not doing continuous deployment (https://charity.wtf/2021/02/19/how-much-is-your-fear-costing-you/) Charity's post - The Engineer Manager Pendulum (https://charity.wtf/2017/05/11/the-engineer-manager-pendulum/) Transcript: CHRIS: Hello, and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey. And this week Steph is taking a quick break, but while she's away, I was joined by a special guest, Charity Majors. Now, folks who've been listening to the show lately will know I've been mentioning one idea or another from Charity almost every episode these days. Charity's work spans from the deeply technical through to the deeply human. And across all of it, she brings such a wealth of experience in pragmatism while consistently providing grounded, actionable advice about how we can improve all aspects of our work. And to give a bit more context for those who aren't as familiar with Charity's work, she is the co-founder and CTO of Honeycomb, which is an observability platform that we talk about more in the episode. Charity is also a prolific blogger, tweeter and speaker, and general leaver of digital breadcrumbs for the rest of us to hopefully follow. And Charity is also one of the hosts of the o11ycast podcast. That's observability, o11y podcast. And in fact, in the intro to the first o11ycast episode, Charity provides a beautiful summary of her approach to the varied work that we do. Quote, "I'm someone who's always been drawn to where the beautiful theory of computing meets the awkward, messy reality of actually trying to do things." And that quote rang so deeply true to me when I heard it and really encompassed what I see across the variety of work that Charity has shared with us. And frankly, I've been so impressed with the quality and quantity of wonderful content that Charity has shared over the years. I was really just thrilled to get the chance to sit down and talk with her directly. So without further ado, here's our conversation with Charity Majors. Thanks so much for joining us today, Charity. CHARITY: Thanks for having me. It's great to be here. CHRIS: As I've mentioned on many an episode, I've been following your work for a while now. And at this point, I would say that just about every Bike Shed episode has a reference to you and some piece of work that you have put out into the world, whether it be a tweet or a blog post, or a conference talk or something. So I'm so grateful for all the work that you put out into the world and for taking the time to chat with us today. CHARITY: That's so exciting. Yay. I feel right at home here then. [chuckles] CHRIS: Fantastic. Well, I want to dive in. I think it's sort of the core of some of the conversation that we'll be having, which is around instrumentation and observability, and observability as a newer, noveler form of how we think about this space. But to give a bit of context, I was hoping you might be able to give just the quick summary for anyone who might not be as familiar with observability as a concept and what that means now, and Honeycomb as a product and how it offers affordances around observability and pushes that envelope forward. CHARITY: Yeah, I think of the observability as being about the unknown unknowns. For a long time, all of the complexity was really bound up in the app. You had the load balancer, you had the app, and the database. And all the complexity you could just attach to a debugger and step through it if you had to. But then we kind of blew up the app, the monolith, and now it's in services scattered to the winds, and you can't just trace it. And so observability is a way of passing that context along hop by hop so that you can actually slice and dice in real-time. And the hardest problem is not usually debugging the code. It's finding out wherein the system is the code that you need to debug. And observability, if you accept my definition, which is it's about unknown unknowns, that you should be able to ask any question of your systems, understand any internal state just by observing it from the outside, well, then a lot of things proceed from that, in my opinion. Like, you need to be able to handle high cardinality, high dimensionality. You need to be able to string together a lot of these high cardinality dimensions. You need to... any kind of schema or indexing scheme in advance is verboten because you don't know what questions you're going to need to ask. And so there's a lot that flows from that definition; arbitrarily-wide structured data blobs is the source of truth, et cetera. But at its heart, it's just about the concepts, that our problems are getting harder and harder. We don't get paged to go, "Oh, that again? Oh, that again?" CHRIS: [chuckles] CHARITY: Ideally, we fix those things. But we still get paged. What the hell is this? It's about allowing engineers, empowering them in a reasonable amount of time to be in constant conversation with that code that's out there in the world because most problems honestly we never get paged about. They're too subtle until they snowball, and they pick up other problems. It's like a hairball under your couch until it gets so big and so impacting that it actually does alert someone. And then you just start picking up the rock and be like, oh God, what's that? Well, we've never understood this. And that's why ops has such a reputation for masochism. [chuckles] CHRIS: Absolutely. There are so many little pieces in what you just said that really deeply resonate with me, although there is one facet of some of the way that you talk about observability that I find interesting. I'm someone who likes to cling to the perhaps unrealistic these days ideal of a monolith of what if we were to just keep everything in the same place and all the data lived together in one database, and I could have foreign keys, and consistencies, and asset compliance? CHARITY: Which you should do for as long as you possibly can. You should never impose more complexity on yourself than you absolutely need to. And I would say that it's never not better to have observability than the older paradigms of monitoring and so forth. Some of Honeycomb's biggest and best customers still use monoliths. But they still find it really valuable to be able to apply the principles. I think that it's the microservices revolution, if you will, that forced this set of changes. It was inevitable. The steps that I started talking about, like, somebody would have because the older way just became untenable when you started adopting containerization and a lot of these things that made everything suddenly a high cardinality including the number of applications you have. But it's never not better to have high cardinality tools and to be able to instrument your code for spans and tracing. Tracing is still valuable even in the monolith. CHRIS: Yeah. As I've observed and started to play around with Honeycomb, that's definitely what I've seen is I'm almost exclusively working in the context of monoliths and, like I said, clinging to them for as long as I possibly can, which isn't going to be forever. CHARITY: It's true. [chuckles] CHRIS: I recognize that truth, but already I see the value. And so Honeycomb is a platform that you've built that allows for this high cardinality, high dimensionality ad hoc queries at any point in time. And so the idea that I can come into the tool and say, "Huh, I've got a new novel problem today." I don't need to re-instrument my code. I can just ask a new question, and the system will responsively be able to answer that question, ideally. And that feels like it holds true in a monolith all the more so, like you said, in an SOA architecture. But even in my safe little playground of everything is in the same space, I still don't know how everything's working all the time if we're being honest. So being able to answer those questions feels meaningful. CHARITY: Totally. I think that one way of thinking about the SOA or microservices is that it pushes a lot of what was in the operations realm into a realm of development, and suddenly you're responsible for a lot more of the operating of your services, things like retries and backoffs, and load distribution, and thundering herds, and all these things that ops traditionally took care of. Well, now you have to think about them. So you need some ops tools, too. What I like about...of course I like everything about Honeycomb because we designed it for this problem. But it speaks in the language of variables, and endpoints, and functions, and not in the low-level language of proc IPv6 timeouts and stuff where I feel like ops has also traditionally been the translation layer between software engineers and their actual code in production. And it's time to start giving software engineers those tools in their own language. CHRIS: Yeah. I love that. And I'm very happy to have Honeycomb as part of an instrumentation stack, which actually shifts me to the next question, which as I look at Honeycomb, very quickly the first time I saw it, I was like, oh okay, this makes sense. I want this in the world. CHARITY: Oh, I like you. [laughs] Not all people are like you. CHRIS: It might have been my second or third look, but it was definitely...once I got it, I was like, oh yes, I absolutely want that. But now, the question that I have is I typically will have a collection of tools that exist in this space. And there's a weird Venn diagram overlap of well, there's logging, and there's error tracking, and there are APM performance tools, and there's metrics, dashboards. And my sense is that Honeycomb perhaps can or an observability tool more generally can subsume a bunch of those, but it's not clear to me exactly. I think I probably still want logging. I think I still want error tracking as a discreet service tool that I'm using but maybe not APM and maybe not metrics as a distinct thing. Maybe I can infer those from a tool like Honeycomb. But I'm wondering what's the current thought on that? CHARITY: Well, part of what you're seeing is just observability tooling is very new, and we haven't had time to grow up. And here I'm like, officially, we play very nicely with all other vendors, and none of us would ever try to compete or take away from each other's faces. But I do think that ultimately, logging pretty much the only real use case for it is security stuff, the security archiving, just keep every log light. It's gotten cheap enough, but it's not actually useful for debugging or understanding your system, not really. It's useful for compliance. It's useful for proving that you did something in the past. Most logs are just a pile of trash, but they can be useful trash. And I understand people's emotional want to hold onto them for a while, and there's nothing wrong with that. There's nothing wrong with keeping some trash around for a while, while you make it...[laughs] Sorry, not to totally slam on logs, but they are trash. CHRIS: I love the analogies that we're going for. [laughs] CHARITY: But the thing about observability is I do think the kind of center of the world is these arbitrarily-wide structured data blobs from what you can infer logs, from which you can infer metrics, from which you can roll-up. So I do think that well metrics are the right first tool for understanding infrastructure. Like if you're Amazon and you're responsible for all this hardware and stuff, you should be asking yourself, is my service healthy? But if you're someone who's writing and shipping code on top of that service you care about, can my request complete? What is my user's experience? And that's observability's territory. So I think that ultimately, I do think metrics, logs, and traces all get subsumed under the observability umbrella and performance management, too, if the tools get built correctly. There will still be use cases. They will just get smaller, for logs, for standalone metrics tools. Honeycomb just launched our metrics product. Metrics is like a 30-year-old piece of technology. Prometheus and Datadog are going to be the last best metrics tools ever built. We have wrung the water out of this laundry. [chuckles ] But we aren't trying to compete with that. What we are trying to do is give people an on-ramp into Honeycomb. They've got decades' worth of stuff. They've been corralling metrics, structuring them. You rely on them. You don't want to give them up. So yeah, let's feed them in. Let's give them an overlay. And number two, the more interesting use case for me is when you're a software engineer who's writing and shipping code, you do care about did the memory usage just triple, or is the CPU completely buzzing after I shipped my last change? But there's really only like three or four of those metrics that you really care about as system metrics. The rest are mostly legacy. CHRIS: I like the idea that aspirationally, Honeycomb is moving towards a place where given sufficient input data, given this arbitrarily-wide data blob with high cardinality, et cetera, that we can infer basically all of those others from it. But also speaking to also observability is somewhat new, and so we got to build a lot of product to get there and that idea that there is perhaps a space right now where you might be bringing together a few of these tools. But if there is a future world in which I can have one of these tools that just handles everything and tells me about my code and directs me to the line of code that I incorrectly instrumented, that would be wonderful. Happy to do the work in the interim to cobble it together from the pieces. CHARITY: The place in the meantime that we're at where all of these big vendors are acquiring other vendors and trying to put together...they're like, we have three pillars. Coincidentally, we have three products to sell you. It's like, it's not good for the users because when you're...like, you're sitting in the middle here. You've got your metrics dashboard. It's telling you that there's a problem. Okay, if you can't slice and dice and figure out what it is, you have to jump over into logs and visually correlate based on the times and hope no timestamps are wrong and try and find the thing. And then, oh, okay, so you want to trace it. So you've got to copy over and try and find that in your tracing product and hope that that would get sampled in. It's not good. You can't follow the question from the beginning. I have a problem to the end. I have a solution and back. And it's not linear. You're going to be following a trail; then you're going to need to back up, then you're going to find another trail. And then you're going to want us to zoom out and see who else is impacted. And you really can't back your way into that with different products. You have to start with the arbitrarily-wide structured data blob. What does confuse me is I know that New Relic is built on this. New Relic has these. And we almost didn't start Honeycomb because we were just like, edit data, and New Relic is going to figure it out. Here we are like six years later, and they still haven't fcking figured it out. [laughs] But like Datadog, they aren't based on that arbitrarily-wide structure, so they are really...and I know that they're trying to get...all of these big vendors are trying to get to where Honeycomb sits technically faster than we can grow up and become a business. CHRIS: The race is on. CHARITY: Yeah. It's fun. CHRIS: One of the related things that I've seen you talk about a few times is the idea that instrumentation is a muscle. It's a habit that needs to be developed and fostered, and that rings very true to me. At the same time, a lot of my instrumentation work has been more in a reactive space. If we're being completely honest, something went wrong; we can't figure it out from the information that we have available, so then we go in, and we add a new logging line. We wrap the code in some way. And so I'm wondering if you can talk a little bit more about that. What does that look like in practice or perhaps some examples or something? But how can we tease that apart and understand that a little bit better? Because it sounds wonderful to me. CHARITY: I think of instrumenting a lot like commenting your code. It's a way of thinking to the future and reverse engineering; what am I going to care about? What is someone else going to care about? And I really do think of commenting as just a less true version of instrumentation, honestly. It's you talking about what you think the code should be doing, but you've left production out of the loops. You don't know what the code is doing. [chuckles] But ideally, they're kind of the same muscle. It's why you're writing your code. You've just developed a monitoring thread almost in your brain. It's like, yeah, this is going to be valuable. Oh, this is going to be valuable. And so I do think that it's on vendors to make sure that we do as much for you as possible. And this, honestly, is the long winding journey to Honeycomb finding product-market fit, which took almost three and a half, four years. And for a long time, I was like, it's not magic. You have to understand your code. You have to blah, blah, blah, which is true. But also, we need to walk closer to the user. We need to make it easier. We need to do the beeline, which will initialize the event, pre-populate it with a bunch of stuff, create the framework so that all you have to do as a user is just printf now and then just stuff this in the blob, vendors making it as easy as possible, as automated as possible. We have more to do. We really should be pre-populating it with all of the language internals and all of the stuff about the environment. We'll just be glad to tap that well. But there's something that we can't do for you, which is understand what you're trying to do and what is important. Honestly, here's a story from the past. The reason that New Relic was so big, they hit the ground, and they super hockey-sticked everything was because they dovetailed with the rise of Ruby and Rails because Ruby allows for so much fcking monkey patching. Every web app looks the same. You can just be like, we assume all this crap, and so we could make it just like magic for you. You just install this library. Boom, you're off to the races. Well, try as you might, I want to say a type language like Go, you can't do that stuff with. You can't make it as magical. You have to think a lot more about how you're structuring things for better or for worse, which is why their growth slowed because those languages just aren't so popular anymore. So it's trade-offs all the way down. Yes, everybody should be an expert in forecasting the future and understanding all the subtle things that you don't know you're going to know, but you're super are going to want to know. But as you've discovered, most of your learning comes from being in the trenches, which is why it's so good for devs to be on call and be close to their code and be in this constant conversation with it because you develop a sixth sense. I can't tell you exactly why I know it's going to be a problem, but I'm just going to wrap it because I'm pretty sure it is. CHRIS: There was a tiny bit that I was hoping that you would have some very specific like, oh, you just do X, Y, and Z. I kind of knew that wasn't going to be the answer, but it also represents something that I so appreciate about your thinking and the work that you put out into the world, which is it's realistic. Sometimes you're like, you know what? There's going to be some tacit knowledge involved here. You got to put in the work. You got to learn the thing, and that's just true sometimes. And so I appreciate your willingness to be like yeah, you know what you got to do? You got to do the work. And then after that, you'll know...and so there's sort of a virtuous cycle that can happen here. There is a feature, as far as I understand it, of Honeycomb, too if I can briefly hype up your products slightly but the idea that you can observe the series of questions that another developer asks. So if they were in a debugging session, you can see like, oh, they asked this, and then they asked this, and then they filtered on that. CHARITY: It's like your Bash history but for debugging. [chuckles]. CHRIS: I want this for everything. CHARITY: Right? CHRIS: Let's have a shared hive mind of the developers on a team, both in terms of our observability tool but also just kind of everything. CHARITY: What did you do? CHRIS: Yeah, what did you do, and why? What were you thinking? I saw you went down a road there, but then you stopped and backed up, and you went a different way. That's interesting to me. CHARITY: This is why we keep trying to build things into the product that will incentivize people to write texts about what they're doing, whether it's retroactively applying tags or writing a breadcrumb to yourself. Why was this meaningful? As you're putting it in your bookmarks, why are you putting it in your bookmarks? Collaboration is just as much about collaborating with your past self and your future self as it is with the rest of your team. I don't remember why the fck I did that two years ago. I don't know. I don't know why I did that two months ago. But the more you can leave breadcrumbs for yourself and then surface that to the team, you're right; it's transformational. I wanted this so selfishly because I have never been that person on the team who loves graphs. I hate graphs. I don't think visually very well at all. I've been working with my friend, Ben Harts, off and on for like 10, 12 years now. He's always the person I've hired repeatedly. He's always the person who comes in and makes the graphs. And then I look over his shoulder, and I bookmark them. I can be up all night making the perfect dashboard. And then I'm like, great, mine. [chuckles] So there's room in the world for both of us. But the point is that not all of us should have to go through that effort. [chuckles] We should be able to learn from each other. Only one person should ever have to have to craft the perfect query, and then the rest of the team should be able to effortlessly piggyback on it. CHRIS: Yeah, absolutely. And again, I want that but for everything. I dream of a future in which that's true. CHARITY: And so much of debugging is this wandering path where you go down the wrong place, and you need to be able to zoom back to all right; where did I first know that I had a beat on it? CHRIS: There's a corollary that I see to pair programming where one of the things that I find so valuable is, what Google query do you type in when you hit that wall? When you're like, oh, this isn't working as I'm thinking, and then you type something and I'm like, whoa, wait, I wouldn't have even thought to ask that question of the internet. CHARITY: Oh, I love that. That's fantastic. CHRIS: But now you've productized that, and I love that. So thank you for building that thing in the world. CHARITY: Excellent. CHRIS: Shifting gears slightly, one of the other themes that you really pushed for in the world is the idea of continuous deployment and not like yeah, you should ship your code pretty quickly after you merge it, but true, sincere continuous deployment. CHARITY: 15 minutes or bust. CHRIS: 15 minutes of bust, test in production. There are some really wonderful if we're being honest, scary themes that you talk about. I love the ideas that you're putting out there, but they're probably the things that I look at, and I'm like, ooh, that seems like a whole thing right there. CHARITY: It assumes a lot. Let's put it that way. It assumes a lot. CHRIS: It definitely does that. I desperately want to get to that world. I want to get to the place where there's that confidence. And similarly, there's a theme that you've talked about around Friday deploy freezes and why that's not a good thing. And the empathy for humans that part's good, but maybe we're applying it in the wrong way if we say we're not allowed to deploy code on Friday. Because it's like yeah, deploying code is terrifying and scary. No, let's solve that problem. But I wonder if you can talk a little bit about that. How do you get there? How do you get to the place where continuous deployment is a realistic outcome for you? CHARITY: Yeah, that's a very good question. There are no easy answers, unfortunately. And the answer is always going to depend on where are you starting from? Are you starting from a clean slate? Are you starting...a lot of the advice that I give sounds like Looney Tunes to someone who's coming from enterprise because they're just like, "You don't understand the constraints that I am operating under." And I'm like, "Yeah, you're right. I'm not of your world. That probably shows." [chuckles] So I think the easiest way, though, is always when you're starting a new project that what you do on day one would be to set up your CI/CD and deploy it to prod before you've even started building. My favorite analogy to that is to like...you know the myth about Alexander the Great and his horse how when he was a little boy he would pick it up every day before he had breakfast? And so, by the time he was an adult, he could pick up his horse because he picked it up every day, and it was never hard. When you start deploying that way, it's never hard. When you're just like, okay, anytime this gets above 10 minutes, we're going to put in a couple of hours of work, and it's never hard. It's just the easiest thing in the world. And everything's easier because you get to watch what you're doing and in real-time, and you develop that muscle of I'm merging it to main. I'm going to go look at it in a couple of minutes. And you don't feel done in your gut until you've looked at it. And that's doing it on easy mode. And you can do this in a hybrid way. Even if you have like, well, I'm paying for a deploy. Nobody is saying you have to sign up for a long, painful deploy process when you got to spin up a new project. And I've seen it gain momentum. If you start something that's clearly the new way, everybody sees how fast this team is executing. Everybody wants a piece of it. And so you start learning from the way that you are able to do it in your unique environment. You're the best evangelist to the rest of your team members because you know the subtleties. You know the problems. So that's the easy answer is start fresh. [laughs] CHRIS: [laughs] That makes sense. I do, again, I appreciate the pragmatism or the realism of the way that you approach a lot of the topics. CHARITY: Another answer, though, it's just that the engineering work involved in taking a deployed pipeline down from hours, days, to 15 minutes it's just engineering work. It is just labor. It can be done. The political problems are the hard ones. I mean, in the past, sometimes our deploy probably would get up to two or three hours, and we were just like, oh God, this is not…put in the work. You just start instrumenting your pipeline, and you start looking at where the tests are taking time. And it will pay dividends every bit of time that you pay down, which is why I really see these long…our own pipelines is it's a vacuum of engineering leadership that they've allowed it to happen because there's nothing fancy about it. You just put in some work. CHRIS: Yeah, the solvability of the technical challenge feels very true, but what you're saying of it's people problems which again, that's always true of the tech stuff. CHARITY: It is people problems, but I also hate it when people are just like, oh, it's people problems. That means mysterious and unsolvable. Now, most of the time, when you see this, it's a lack of collective confidence in themselves. They see this as being as just for the elite engineers, or only ex-Googlers are allowed to do this or something. Or they go to conferences, and they hear about it, and they're just like, God, I wish I was allowed to do that, or I wish we could do this. But the thing is that engineers have more power than they realize. We build these companies. They wouldn't exist if it's not for us. We have all the power if we just choose to use it. I know that a lot of these people who I've talked to that were just like, "Oh, I wish we…" I'm like, "Have you ever lobbied for it?" And they're like, "No, I just know we could, or that's someone else's decision." I'm not going to promise you that you can get whatever you want. But I promise you that if you start speaking up if you start talking to your colleagues and being like, "Wouldn't it be nice?" And they start speaking up...if a quarter of the engineers want something in the company, it gets done. [chuckles] CHRIS: That definitely feels true. And to the topic of actually lobbying for this and having the hard conversations internally and working on the people problems, you have done, I think, a really fantastic job of providing actual benchmarks in terms of timing and what does this look like as a practice and what are the multitasks? CHARITY: It's so expensive. It's so costly to organizations. And it's the easy answer for any engineering leader to be like, "Well, we need to hire." That is the laziest answer in the world. You probably don't. You probably just need to fix your CI/CD system and then bask in the resources that you suddenly freed up. [chuckles] CHRIS: You have a wonderful blog post that really I think does such a good job of highlighting the cost that you're talking about there, the human costs for every slowdown in your deploy process, it has this downstream ramification. And having that as sort of a piece, a bargaining chip in the conversation of here's a voice that is saying a very clear thing about this cost of not doing this work, which granted, it's always trade-offs. Everything is an optimization. But here is a way to actually measure the cost of not going with this approach. And again, I appreciate you're putting that out there in the world so that the rest of us can be like, "Look, on the internet, it says so." CHARITY: [chuckles] Exactly. I'm happy to be the internet for you. But it's so true because other people in your business don't want you to suffer too, either. They don't want everything to get slow. They just aren't equipped to understand the cost of this slowness the way that engineers are. And I feel like sometimes this is...it's like we're always lamenting like, why does product get to own all the engineering cycles? Where aren't we allowed to do all this other stuff? I promise you're allowed to. You just have to make the case because the case is righteous and justified. But you have to explain to them the cost that it's incurring your organization in terms of your ability to execute and in terms of your ability to hire and retain people. You just have to explain those costs. And engineers are just like, "Well, we only say it once, right?" Well, that's not how you win arguments. You have to say it. You'll probably lose. And you say it again, and you'll probably lose. You say it a third. And you will win eventually because you control all of the creative labor of the technical organization. So just make the fcking case. [chuckles] I don't know. I make it sound simple; it's not. CHRIS: I love the sound bite of the cause is righteous, and that is the kernel of the thing here, which is like, just to be clear, this is a virtuous path that you were going down, battle for it, work towards it, absolutely. So I think a related topic here, so continuous deployment is one of those things that you want to get to and a practice that you want to evolve to. But in exploring some of your other work, one of the things that I was exposed to is the DORA metrics, which is not something that I hadn't seen before. But for anyone who's unfamiliar, the DORA metrics is a set of four key metrics to track developer and team productivity, so their deployment frequency, lead time for changes, change failure rate and the time to restore the service. And they are deeply interesting because frankly, I have for a long time felt like developer productivity was not really a quantifiable thing. CHARITY: It's not, yeah. CHRIS: Individual developer productivity I still feel like this is a bad thing. Don't do that. But team productivity these metrics actually are like oh, actually, as I look at those, those seem like the good ones. We should do that. I'm wondering, what does that look like in practice when you see that actually employed within an organization? What are the feedback loops, and how does this appear in the world? CHARITY: Yeah. We all owe a huge debt of gratitude to Jez Humble, Gene Kim, and Nicole, who worked on this for years and got this out into the world, just putting some actual research behind the stories that we were telling ourselves about productivity. And people who haven't read Accelerate...a lot of people are always asking me, do we have any stories? Do you have any research? Do you have any proof or something? I just always point to the book Accelerate. That's where it all comes from. Yeah, it's true because it's such a noisy world. When you're an engineering org, and there's just so much going on, and there's so much stuff that bugs you personally, and some of the stuff that you have true beliefs about. And it's hard to just cut through the noise. And I feel like that's the great gift of the DORA metrics. If you start focusing on one of them, you will lift your org out of poverty, and the others will get better too. And it provides just this wonderful focus point for teams that aren't sure where they stand or aren't sure how to get better because it can be so mystifying. When you're in the trenches, and you're just like, why does everything feel so hard? Why is it that we thought this would take two days, and here it is two months later, and we can't ship anything? And it feels like the more we ship, the farther behind we get. These are the beacon of hope. It's like, you pay attention to these, your lives will get better. You can dig yourself out of this ditch. That's certainly been true for the teams that I've been on. And high-performing teams, I think we all have this idea in our heads that high-performing teams are ones where the great engineers join when in fact, those great engineers could join your team, and they wouldn't get any more done than you are. Because most of our productivity is defined not by the data structures and algorithms that you know but by these social-technical systems that we swim in every day, it's the water around us. It's the friction involved in getting that code to production. If it takes the magical engineer from Google 24 hours to get their code changed out, well, they're not a member of a high-performing team either. You mentioned earlier all these people are out there who haven't experienced a world like this don't live in a world like this. And in my experience, they often lack a lot of confidence because they don't think they're that good, or they don't think that they can have nice things. And the DORA metrics that's your ticket to a better life. It's like go to college and graduate because it kicks off these virtuous feedback loops, these cascading cycles of things getting better for everyone and people getting more excited and energized. And they just don't get burned out by shipping too much code. They get burned out by not being able to ship code. And if you're a leader in any type of organization, and I don't just mean manager, I mean any type of senior engineer or manager or whatever, then it's part of your job to pay attention to these metrics, lobby for them, track them, track them on your own if you must, and try to make them better because every engineering team has two customers or two...whatever. I'm blanking on the word. But it's your customers and your engineering team. You're responsible to both of them. And I've never seen one of those sets deliriously happy and the other set miserable. They tend to rise and fall in tandem. CHRIS: I'm just nodding along for anyone in the audience who can't see what my head's doing. But I love so much all of the things that you're saying and, again, the passion and conviction that you bring to this conversation because these are amorphous, hard to pin down ideas. But I appreciate the North Star that you're setting across all of these different things that as I'm reading, I'm like yeah, that sounds true. I want that. Those things are the things that I want. But interestingly, one of the other threads that I see weaving through a lot of your work is obviously we've talked a bunch about just deeply technical topics thus far, but also a lot of your work spans across to the interpersonal. And frankly, even dividing in that way is not representative of the world because it's a Venn diagram mishmash of some days it's technical, some days it's personal, some days it's both. But one of the things that you've talked about is the engineer manager pendulum which I find super interesting. I think every engineer at some point has that question, that internal oh, do I want to go engineer track or manager track? And this distinct idea or the idea that management is a promotion and any other movement would be different, and you have wonderful things to say about that. The other thing that you've pointed out is that former managers can often make great engineers after the fact because of the earned empathy that they have now from looking at things from a slightly different angle. CHARITY: Amazing engineers. CHRIS: But I'd love to hear a little bit more of your thoughts on that because I think it's such an important space, and I've definitely previously operated under I'm an engineer, and then I guess I got to be a manager, and then I guess I don't know where I go from there, but it's this very linear path. And you shook that worldview of mine, and again, I appreciate that shaking. But yeah, I'd love to hear a little bit more about that. CHARITY: The best people that I've ever worked with have been engineers who had been managers for a while and then went back to engineering, and it's not just empathy, although there's a lot of that too. It's also a deeper understanding of the business and the reason that we do things. So much of being a powerful engineer is choosing the right work to work on so that you get a lot done very efficiently and quickly, and you don't spend a lot of time just foundering, which you've mastered, and you know the basic technical principles. And how do you get better? A lot of it is just getting better at identifying what to do and what not to do because we have to not do so much more than we can ever do in order to move forward. I wrote a blog post as a present for a friend of mine who was a director of engineering at the time, and he was suffering. He was just miserable, and he kept thinking about going back to engineering, just kind of dragging his...because he wasn't in an org where that was really celebrated or anything. When you've been there from the beginning, you built the organization; you're like a senior director and everything. It feels like a long way to fall. And I wrote that post for him. And he did end up going on to be an engineer after that. And he was so much happier. But I think he was surprised at how he didn't fall at all. He actually probably had...I think the engineers had a higher opinion of him afterwards when he was one of them again. And he still had this vaunted voice because he could speak to how the system had been there since the beginning. And he basically got to look around and look out farther than the engineers who were heads down every day and go, "This is going to bite us. I'm going to take a small team. We're going to do this forward-looking security product." I don't want to identify details, but that for me really just kind of cinched...It was like the more we can strip hierarchy out of these discussions; the healthier everyone's going to be because we're just monkey brains. And the monkey brain in our skull hates losing hierarchy, hates losing power or stance or anything. And I think that the thing that you learn after you've been a manager is a lot of it is just the wizard behind the curtain, the idea that you have more power as a manager. You have more of some types of power, and you have a lot less of other types. And you're just as constrained as the engineers but in other ways. And the path moving forward is not to dominate people or be above them but to combine your powers for good and self-sort to find a place that actually gives you the most joy. CHRIS: It's a wonderful philosophy. And actually, a thing that you said in there really stuck out to me, which was you wrote that blog post as a gift to someone, and that is such a kind thing to do. And it also, again, reflects what I see in your work overall. You're really clearly leaving a trail of breadcrumbs behind you to help other folks that are traversing a similar path by questioning aspects of it. Or how do we do this well? Why is everyone sad, and why is it bad? And so again, I so appreciate all of that work that you've done. CHARITY: I think that that comes from my lifetime in the trenches of operations. [chuckles] Ops is notorious for the pain that we bring upon ourselves and try to solve. But I would just like to add a pitch out there for other ops engineers of the world and our colleagues. I was fortunate enough to rise up through the ranks in organizations that really respected operations. We always felt we ruled the roost. We felt like we were way above all the other developers. We got to say what went into production and what didn't. And I feel like ultimately...if you have to have an imbalance of power, I think that's slightly healthier than the developers ruling the roost. Ultimately, there shouldn't necessarily be any imbalance of power. But I just want to pitch it; this whole no-ops thing really got my goat for a while there because operations is just the engineering workaround delivering value to users. I think the second wave of DevOps is now about okay, software engineers; it's your turn. It's time to learn to write operable software. And so I just wanted to throw in my hat in the ring for all the ops people out there. You're just as good. You're just as good as anyone else. [chuckles] CHRIS: I mean, it's sort of a theme that I've seen in your writing of everybody's doing good, important work and breaking down hierarchy and just collaboratively moving in the same directions and trying to choose the right North Stars to aim towards. And yeah, it's all fantastic. And so with that, I think we probably reached a perfect spot to wrap up. But Charity, if folks want to keep up with more of your work online, where are the best places to find you? CHARITY: My blog post is at charity.wtf, and I'm @mipsytipsy on Twitter, and of course Honeycomb.io and our blog. CHRIS: We will include links to all of that and many of the blog posts, and other podcasts interviews that you've been on, and a bunch of just various things that I collected as I was preparing for this episode because, again, you've produced such a wealth of information on the internet that I want to point as many folks as possible towards those things. But yeah, thank you so much for taking the time. CHARITY: My pleasure. CHRIS: The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review on iTunes,; you as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us @bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey. STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Bye. Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success._