The Bike Shed

thoughtbot
undefined
Dec 7, 2021 • 44min

318: Successful Skills with Edward Loveall

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. 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 Scribe GitHub - mendel5/alternative-front-ends: Overview of alternative open source front-ends for popular internet platforms (e.g. YouTube, Twitter, etc.) Become a Sponsor 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.Sponsored By:Scout: Scout APM is leading-edge application performance monitoring 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 performance abnormalities -- like N+1 queries, slow database queries, memory bloat, and 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 worldwide call Scout their best friend and try our error monitoring and APM free for 14-days, no credit card needed! And as an added bonus for Bikeshed listeners: Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed.Support The Bike Shed
undefined
Nov 30, 2021 • 42min

317: Burn The Ships!

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. 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 soundofcolleagues.com mailcheck Inertia.js Svelte devise clearance Become a Sponsor 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.Support The Bike Shed
undefined
Nov 16, 2021 • 40min

316: Constrain and Refactor

Chris finally got his new computer! 🎉 🎉 🎉 He gives his initial review. He's also super excited that GitHub announced a beta for pull requests merge queue, and even more excited that multiple people who listen to this show very kindly pointed that out to him on Twitter! Steph discovered something that is quite niche, but she's excited to tinker with it more, called CookLang. It's a markup language that's designed for cooking and recipe management so you can store recipes and text files and there's no database required; making it easy to have control over recipes versus storing them in a separate application. Then they answer a listener question about refactoring murky legacy code. This episode is brought to you by ScoutAPM. Give Scout a try for free today and Scout will donate $5 to the open source project of your choice when you deploy. CookLang – Recipe Markup Language Pull Request Merge Queue Limited Beta | GitHub Changelog After_party - Automated post-deploy tasks for Ruby/Rails Therapeutic Refactoring by Katrina Owen Unused - Identify unused code in Rails, Phoenix, and other types of applications. Become a Sponsor 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. 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 in my world? Well, we've talked about it before, but it has finally happened. I finally got a new computer. STEPH: Yay, yay. CHRIS: Five years in the making. I held out, I waited. The new computer is fantastic. I'm in that transition phase of trying to set everything up and get it all...the particular thing holding me back is actually this recording and some dongles. I need to live that USB-C life now. Everything needs new connections and whatnot, particularly my external monitor. STEPH: I'm now realizing how old your current laptop is. CHRIS: [laughs] Did I just date myself? Yes. STEPH: You did. You just dated it with a USB-C. I thought you were still on the USB-C life. CHRIS: I'm pretty sure it's a 2016. I'm currently recording on a 2016 MacBook Pro. But yeah, I'm very excited with the new one. The shape of them is weird. I did not expect this because I've seen the 13-inch MacBook Pros that have the touch bar and other things that I didn't really want. But the shape of that laptop was more familiar to me. And this one, I don't know, it's weirder and rounder and bulkier in ways that I didn't expect. And it's heavier than I expected. I got the 14-inch, as an aside. I went with a slightly smaller version assuming that my 16-inch with a giant bezel, because it's from the past, would have a similar amount of screen real estate to a 14-inch with no bezels or with the screen going almost out to the edges. As an aside, the notch in the top of the computer screen is ridiculous. I've dealt with it on the phone for a while now. I accepted that I live in the land of notches. But somehow, it's way, way worse on the computer like when I take my terminal full screen most of the time, and so stuff just gets lost. I don’t know, I got to deal with this or not, maybe I can just not care. But it is covering things that I want to read. And I'm like, well, this is annoying. But yeah, beyond the notch, everything else is great. It's a nice form factor. It seems to have great battery life. It's very fast. It goes very fast. It also has...there's more RAM in it. There's more hard drive space and whatnot, so a bunch of the things that I use. Often as we start this recording I'm like, oh no, I wonder if I have enough hard drive space for the recording we're about to do, which I should probably be past that at this point in my life. Well, now I think I am, except I haven't yet ported my recording setup. Nonetheless, I'm very excited. And particularly, a lot of the development workflow tasks like starting up the dev server of the project that I'm on just moves a lot more quickly. It's a lot snappier, and everything is just speedier. The fans don't really turn on. It doesn't get too hot even when I'm doing challenging things, downloading everything from the internet and compiling from source code. It's like, yeah, cool; I can do that. That seems like a thing that's well within my wheelhouse. And I'm like, cool, computer, good job. Glad to have you on the team. STEPH: So I learned something about you recently because hey, we were hanging out in person recently since I was in Boston for a week. That was amazing. And I learned that we have a similar thing where we both like to start our machines from scratch, and slowly (or at least correct me as I'm going through this), we bring things over. But it's not an immediate just port everything from my current laptop over to my new laptop. And I'm fascinated because I thought I was the only one with this sickness. But it turns out that you, my friend, also have this in your life. CHRIS: Well, yes, you are correct. That is the thing that is true. And also, to reiterate, it was really lovely seeing you in the human world as opposed to just in a Skype window as we so often do. But yes, I start fresh every time. But to be clear, it's been more than five years since the last time I did this. So I feel like I can make a bit of an event of it each time I do it. So I'm fine with that. But I do like starting from fresh reinstalling everything rather than trying to copy over an image of the system. I felt a little bit shamed by the operating system because there's the like, welcome to your new Mac. What's your language? What's your WiFi? What do you want to migrate over? And I'm like, nothing. But there wasn't a button for no, thank you. [chuckles] There were buttons that were like...there were two different options, but neither of them were no. And I'm just staring at it, and I'm like, but I would like to not though. I would like to just start fresh. STEPH: [laughs] CHRIS: And I got it from here. I appreciate the effort. Turns out they were hiding it in the bottom left corner, but it wasn't a button. It was like link text, but it was barely emphasized. And on the right were where all the action buttons for every previous step and subsequent step were. So this was like no one would ever want to do this. So we're just going to hide the option over in the corner. Yes, I very much like starting fresh. I like to get the chance to shed some of the mistakes of the past and only bring forward the things that are bringing me joy in the modern-day, so here we are. A lot of stuff doesn't work, by the way. [laughter] I brought over my dotfiles, and things did not work super great. Or I opened an application, and it's like, oh, that hasn't worked for years, and I'm like, I was living in the past. All right, this is fine. I'll update my workflow. It'll be okay. STEPH: I like how you said make an event of it because I haven't really found the right words for it, but that's perfect. I have a fresh laptop, and it's an event, and I want to spend that time setting it up and shutting the mistakes of the past. [laughs] That too, that also resonates. CHRIS: Yep. It's really about the mistakes of the past. I don't want to live there anymore. I want to move on from them. But overall, yeah, it's going well. I think I'll be able to work with it. I'm actually unfortunately limited in that I can't connect it to my monitor right now or to the keyboard that I have and whatnot. So I can't quite integrate it into my home office setup. I can use the laptop itself, and it's working fine. I've got my current project running on it. So I was able to install Ruby and figure out how do I trick it into using the Homebrew things versus the M1 things versus which architecture and yadda yadda yadda? That actually went better than I expected. I thought it was going to have more issues there, but stuff just kind of worked. And I had to find one weird Stack Overflow and copied and pasted as one does when you're setting up new computers or all the time as a programmer. And then yeah, we're off to the races. But yeah, unfortunately, right now, the limitation is a physical cable. I need a couple of new cables. So I'm excited to get those in the near term. STEPH: Yeah, that'll be nice to have it set up and feel like you can fully transition to the new setup. CHRIS: But in slightly other news, so computer is great, very happy about that. Perhaps I’m even more excited that GitHub has announced a beta for pull requests merge queue, and even more so excited that multiple people who listen to this show very kindly pointed that out to me on Twitter. And I was like, this is the dream. I just rant about stuff on a podcast, and then people tell me when the world has solved the problem that I complained about. This is so great. But it's a public beta, but you go on an invite list and whatnot. So I'm on that list right now. And I'm trying to just mention it as much as possible, especially near any friends I know that happen to work at GitHub; just be like, "Hey, if you happen to know how to find that list...and I will give wonderful feedback. I will be an active member of this beta." But I would really love to get to try out that feature. So I'm excited. We'll include show note links to the blog post announcing this new feature. So I'm really excited that it is built into the platform and will sort of be there. And I'm hopeful that GitHub has done a great job. This is actually a really interesting feature in my mind. It's one of those things like, oh, it's pretty straightforward. You just make a queue, and then you merge things. It's like, oh yeah, but what about all the ways it can go wrong? It's a great I think iceberg feature where the simple, happy path is wonderful. And then there are so many different failure modes like, oh, what do you do when the PR fails to rebase? Or should you proactively rebuild the sequence of them? Do you stack them up and start preemptively rebuilding the other PRs that are next in line in the queue after that? But what if then it fails? And et cetera, et cetera. There's lots of fun stuff that can go wrong. So I trust that GitHub will do a wonderful implementation. I would love to get to try that, but currently, I've yet to get in. STEPH: Have they shared how to get access to the limited beta? Is it just random selection, or can you specifically request? It sounds like you can't, based on what you're saying, but I'm curious. CHRIS: There is a waitlist. Particularly, they had me put the repo that I was interested in, so like, I would like to be in the beta. And this repo, in particular, is the one that I would like to put into the beta. So I've submitted that, but now I'm just in a list. I don't know where in the list I am. I have no visibility into that. So again, I'm just saying things out into the void and seeing if the universe then reflects anything back at me, and by that, I mean people that work at GitHub. Hi, friends. STEPH: I totally believe that if you speak things into the universe, the universe will give that back to you, or that's probably not true. So here's hoping that you get into the beta list. CHRIS: Here's hoping. One other tiny thing I have been using Afterparty a bunch lately, which is a gem that you have recommended to me, I believe, in a previous episode not that long ago. But we started doing feature flags. Feature flags are great. We're using Flipper. It's wonderful. But Flipper stores...the way we've configured it, we're storing them in the database. And so, when we get to the point where we want to fully release a feature, we dial-up so that everyone has access to it. So at this point, the feature flag system is still running, but everyone is getting access to that feature. And so then there's a code change that removes any references to the feature flag, any checks for it. And subsequently, we want to then clean up after ourselves. Afterparty has been fantastic. I'm really happy with the way that that works and that we can just include the Afterparty data migration associated with that, delete the record from the database, and then everything consistently works together. This does poke at the edge, though, of how Heroku does deployments and the fact that there is that latency where it will basically restart with the new code, needs to run all migration steps, et cetera, et cetera. And then it's running on the new code, which is great. That's what I want in this case. But it does have a cost, and I would love to figure out true blue-green deployments sometime in my usage of Heroku such that we can have zero downtime deployments is actually the way to phrase it. Using Afterparty for this, I think, is leveraging the idea that it's not a big deal. It'll be fine. Because if we had zero downtime deployments, I think temporarily, we would be in a space where feature flag has been deleted; therefore, no one is in the feature. Therefore, no one would see it for that weird second. I'm safe from that. But it's this weird trade-off that I have in my mind of I want blue-green deployments, but I'm appreciating that I don't have them right now and that there is a consistent...and I think that's the reason that Heroku makes the choice that they do. But, man, everything's complicated. Why can't stuff just be simple? STEPH: Everything is complicated. So I'm thinking back through to now my previous client's setup since I'm about to transition to a new project. And we have AWS. We have rolling deploys, so we don't have that specific downtime. We are using Afterparty. So I think based on everything that you're saying that yes, there's a slight period of where we are rolling out a feature flag or potentially dropping it, and that could put some users into a weird state if they're active and then the code suddenly changes. I'm thinking through out loud and singing it because apparently, that is what I do. We haven't run into any issues with that. But I am now trying to think through of when someone might end up in a weird state because of that. CHRIS: You almost certainly won't run into any issues because we're talking about a matter of seconds where the code is in an inconsistent state. But the same thing applies to migrations like database migrations where if you're doing rolling deployments and the database migration hasn't happened yet, but there's new code that's running that expects that database state, then you're in this subtly inconsistent mode. And I think if you really want to adopt this idea of rolling deployments or zero downtime deployments, you have to separate data changes from the code that uses that data change such that both versions of the code when the migration goes out are fine. And then later, you deploy the code that uses the migration, but then that's like a whole bunch of more steps. And you got to think about it, and you have to probably put in some pull request review step to check on it. And so again, it's just complicated. STEPH: So that's one of the reasons we did change our feature flag implementation was because we realized it was a pain. Because anytime that we wanted to drop feature flags, we first issued a PR that removed any references in the code to that feature flag, let that deploy. And then we'd issue a separate pull request that went out in a different deploy that went and dropped that column. So that way, we didn't have any situations where maybe ActiveRecord has cached to that column, and then there's code that's looking for it, but then it's not actually there. And then you run into that funkiness and complicated behavior. So we were at a point where removing a feature flag required two PRs and two deploys, and that was awful. So we switched up how we were handling feature flags specifically so we could avoid that and started storing them in JSON files because we took the more bespoke approach to feature flags versus using Flipper. CHRIS: Bespoke artisanal feature flags. STEPH: I don't know that I'd recommend it. It's working. It's been a journey, and there are things working well about it. But it's definitely still in that space where it's like, I'm a little uncomfortable of like, how far should we go in this bespoke world and at what point we should reconsider and use something like Flipper. I would say stay tuned, but I'm not on that project anymore. So I'll just never know. [laughs] Sounds like a devious laugh. I will know probably from some friends that are on the project, but I won't be there for it. [laughs] CHRIS: Cool. Well, yeah, I think that sums up things in my world. What's new in your world? STEPH: I have discovered something that's quite niche, but I'm excited to tinker with it more. It's called CookLang. And it's a markup language that's designed for cooking and recipe management. So you can store recipes and text files, and there's no database that's required. So it's easy to have control over your recipes versus storing them in a separate application, which is currently how I store my recipes. Which for the record, I'm happy to pay for software. I am very appreciative of when people make my life easier. And so I very much enjoy that. But I also still love the it's mine, and I can just have it stored somewhere in the cloud, and I'll never lose it. And I don't have to worry about renewing memberships to keep access to something. So there's a part of me that is very drawn to the idea that I can just have everything in the text file. I can store it anywhere that I want. And then, for this particular CookLang markup language, it lets you define certain qualities of your recipe. So you can define the ingredients, the quantity, cookware, timers. It'll help you create shopping lists, and you can set metadata. So maybe you want to include the total prep time or the type of meal, or the number of people that the recipe serves. And they also have an iOS app that is in beta. So speaking of beta, this one is closed at the moment because they've had a pretty overwhelming positive response or interest. So they have shut it down for now in terms of accepting new people to the beta; at least, that's my current understanding. But the iOS app does look like it'll be really nice. It's going to read from your files; I think stored in iTunes. But I'm just excited for all of this. It looks very interesting. And it looks like something that's just fun to play with. So I haven't moved anything over to start really investing and creating these .cook files that you use for the cook language. But it all seems very cute, very niche, and something I'm totally into. CHRIS: I have not seen this, but it looks absolutely fantastic. I'm just reading the brief syntax snippet that they have at the top and the way that they're inferring semantic meaning from plain text recipes. And then you can generate a shopping list, super cool. You can just be like; I’m going to cook these things from my recipes. And then they'll tell you the shopping list, and it's grouped. And this feels like what software should be in my mind. This doesn't feel like we're going too far with it, which is very easy to do. But it's like, no, no, we've annotated just a little bit of semantic meaning on top of something. And then with that, we can do wonderful things. Look at all the good stuff that falls out of it. We can have an iOS app. We can generate shopping lists. It's great. But it's also minimal and contained, and not locked in a proprietary format. And this is fantastic. STEPH: There's also the nice part where they've already started highlighting that people can just store their recipes on GitHub. And then you can just fork recipes, or you can import everybody else's recipes. And I love that. I want more open-source recipes, although frankly, there are tons of just free amount of work and recipes that people have on the internet. But I love this because then I could skip all the ads that go with it. And I can just grab the stuff that I care about. CHRIS: You mean you don't want to hear the person's life story before every single recipe. You don't want to hear about the walk that they took along the river when they were thinking about seasonal gourds, and then they decided to make a particular -- [laughs] STEPH: [chuckles] I would normally...previous Stephanie would have been snarky about that in regards to all of that backstory that's given for a recipe. But then I saw somewhere maybe a friend was telling me about someone who had asked, "Why do y'all do this? Why are you putting so much information? Why can't I just have the recipe?" And they're like, "Well, frankly, Google's going to rank us a lot higher if we give you this whole backstory and if we look like there's more content to this page than just a recipe." And I'm like, dang. Okay, so it's Google that I have to be snarky about because they're doing their best in terms of trying to get you the recipe that you care about and make it very searchable. CHRIS: Oh, yes. Absolutely. It's both a self-imposed problem. But also, I don't think Google's doing anything wrong here either. Google's part of their algorithm is they penalize duplicate content. And so there's what they view as the canonical source, the thing that's telling the truth. And then recipes look very much the same because they are kind of the same most of the time. This is how you make bread. This is also how you make bread. Two people now have almost identically the same content on the internet. And Google will penalize one that it determines to be copying essentially, which I think is a good thing broadly. I've seen so many Stack Overflow...I want to say clones, but they're not even that. They're just literally taking the content and then republishing it entirely new. And that is a very bad thing that happens constantly and takes away from creators and whatnot. And so, in a way, Google's trying to do the right thing here, I think. But it leads to really just so much summary about recipes. It's one of those weird...is this a tragedy of the commons? I don't know. I've never quite understood that one. But I think it might be. STEPH: Yeah, I don't know. That's my off-mic answer. [laughs] CHRIS: That's fine. Someone on the internet will tell me whether or not this is a tragedy of the commons. But either way, I do not blame the recipe authors. I do not blame Google? You'll note the question in my voice. But I think I stand by that. I'm not sure who to blame. Maybe it's us. But here we are. [laughs] STEPH: Yes, I like that final takeaway of let's not blame the people that are trying to give us wonderful, helpful content. Circling back a bit to some of the code that is powering CookLang or some of the interesting bits about CookLang, for anyone that's interested, you can also visit the GitHub repos they have. I believe everything is open source. There's a particular repo called spec. And you can view the issues, and you can see all the conversations around how should we annotate an ingredient? Or should we have comments in the language? And how should we handle this type of metadata? And I find that interesting because I haven't really participated in any of the language crafting forums for Ruby or some of the other languages that I use. So it's neat to watch how some of this is being done in public to say, hey, we're just making this new markup language, and we're not really sure how we want to annotate everything. So what do people think? What's working for you? What's not? And I'm enjoying that conversation and reading along. CHRIS: It really is such an interesting microcosm of an example of a language, an ecosystem, a community, a specification, and all of the stuff that is true of all of the other languages that we use more generally. But I'm looking down here, and there's the parser implementation. There's a Swift canonical parser. But then Rust, somebody is rewriting this in Rust because, of course, they are. But you know what? It's going to parse your recipe so fast, and it's going to be great. [laughter] But it does have the shape of everything that I've seen from other programming language conversations. And how do we evolve the language, and what syntax do we accept versus what do we not? And this is so interesting. STEPH: Yeah, it's really neat. I'm really into it, and I'm really enjoying it thus far. 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, changing gears just a bit, we have a listener question that frankly is a doozy of a listener question. It's a bit long, but I feel like all of the content in here is important. And I feel like most people are going to be able to relate to this scenario that the question is describing. So this question comes from Michael Kopinsky and Ben Rosenbach from Philadelphia. And they write in, "There's one area of our codebase which has a lot of skeletons." I'm already empathizing. "The UI is error-prone jQuery soup, and the UX doesn't entirely make sense. Test coverage is close to non-existent. And the expected behavior isn't clear and has lots of edge cases. We've thought over the years of how we can redo it, but it's never a priority. Redoing it would be a huge lift, and...it works usually. We get bug reports occasionally, which inevitably get closed as won't fix workaround provided. But a few months ago, we received a bug report, and I decided to start cleaning things up. I opened a merge request with a set of factors extracting some behavior into a service object, making explicit some things that were implicit and adding test." Side note, that's some hero work. I appreciate that right there. "It's gone through a few cycles of code review and pairing each time suggesting additional cleanups to do, requesting additional test coverage and that sort of thing. But the more we do, the more we discover that needs to be done. So at this point, the merge request has been open for about eight weeks. I've paired with two other developers for probably 12 hours. The user is impatient, and we're tired of this darn thing and want it to go away. But it feels so bad. It really is severely lacking in test coverage. And the expected behaviors still aren't clearly defined. And it just doesn't meet the normal quality standards that we try to hold ourselves to. We could sit for another 8 to 40 hours and write more tests or documentation, but we're so drained from this whole thing. So overall, we're really struggling to balance two things. We want to get things out the door, have short-lived PRs, and focus on incremental improvement. However, we still don't have defined requirements of how the feature is supposed to work across all permutations. And we can't write proper tests until expected behavior is defined more clearly. It feels like that's a baseline requirement before being able to merge or refactor. We'd love to hear any thoughts. Sincerely, Michael and Ben." Ooh, friend, there is so much we can dive into here. Would you like me to get started, or would you like to start? CHRIS: Yeah, I've got a handful of thoughts because, as you highlighted, this is all of the stuff. This is the murky pile of complexity that writing code and delivering value in an organization is made up of. I'm going to start at a random place and then just start saying things because I think there is not a singular answer to this is an important starting line. We're not going to say, oh, if you just did X, then it would be fine. Obviously, this is a number of different complexities and situations, both person or both interpersonal human, and then code, and et cetera, et cetera. So one of the things that actually came in the latter part of what you were reading there is we do not have defined requirements as to how this feature is supposed to work across all permutations of how it can be used. And that one is really interesting to me because right now, I wonder if there's something that can be done there. So often, you have code that does some stuff but also could do other stuff. And it's not clear if it's actually intended to do that other stuff or if that's just something that falls out of overly permissive like, we'll take any data you throw at us, and then we'll do some stuff. Typically, we don't actually want that. We want a more constrained system that's doing something. So that particular part was really interesting. Some of the conversations about testing were really interesting. I think one of the things I would do is I would really ask, is this worth the effort? This code is kind of doing its thing. It's been around for a while. It's business-critical, but nobody really understands. It's like, is there a version of just leaving it at rest? Probably not. I typically would not do that. But it is a question that I think is worth asking because it can be really hard to make these changes on an under-defined system written in legacy technologies and whatnot, especially ones that we don't necessarily have as much...like, I haven't worked in jQuery for a while. So I wouldn't be quite as good at that. I wouldn't be able to understand that code as intuitively. That might be similar for this team. So is there a version of just letting it lie? That is the first question I would ask. Presuming that's not the case, then I think I start to look at what is the attack that I would take to approach this. And I would definitely start with, hopefully, some small but meaningful introductions of test coverage but as a standalone thing. It's not part of the big change of a pull request. It's merely trying to lock in the code as it exists. Again, I think I've referenced this talk perhaps more than any other, but Katrina Owens'Therapeutic refactoring is a really wonderful story and talk and really talks through this idea in a great way, but also it's just fun watch. But in it, Katrina talks about her approach to a similar thing where she was like, there's some code, and nobody really knows what it does. So I'm going to try and lock it down. And the first thing that she does is wraps test coverage around this code. So at least whatever it's doing now, we've constrained it a little bit. And actually, via the testing that she does, she ends up using that as a mechanism to sort of what does this system do? And finds a way to exercise the system and determine what its behavior actually is because nobody really knows that at this point. So I would start with the testing. And then I would ask the question of we don't really know what it does across all permutations. Is there a way to actually constrain that? And say, let's actually lock some stuff down. Let's add a tiny bit of code that looks at the inputs being requested or coming into this code path or whatever it is but actually explicitly delineates what we think is the expected inputs and rejects or at least logs things that are surprising and that are like, we don't think it should do any of this. And then suddenly, if you see that showing up in the logs, you're like, I guess it does need to do that. Now we have a better idea of what is the actual target that we're trying to hit. But really, both of those in my mind are ways to try and constrain the problem to try and add a little bit of support before tackling the hard work of the refactor because, just to be clear, you're probably going to break it in the refactor. I've broken every single system like this that I've tried to refactor without question. And there's a certain amount of organizational trust that you need to have. And it just gets to be a very complex time. And so anything that I can do to provide some guide rails, some support, something to help me in that time is something that I'm going to start with before I even go near the refactor itself. So those are some thoughts scattered around throughout the question. What do you think, Steph? What comes top of mind for you as you hear this question? STEPH: I think those are great thoughts. And to expand on what you're talking about determining the expected behavior, that's also one of the bits that jumped out to me. And I love that you asked the question, can we leave it at rest? It sounds like yes, but there are some user concerns that come through or some bug reports. And then the team has to collectively say, "Yes, we are going to put someone through a difficult time to either do maybe a gross fix or implementation." And then we're making this area of the codebase feel worse and more accepting of different flows and adding to the number of flows that we have. Or we document it as won't fix and then provide a workaround. So I really like that you said, "Can we leave it at rest?" Because I think that helps a team make a decision together as to like, what is the understanding of this part of the codebase functionality? How important is it to the business? If we decide that it's not that important to the business, then it's frankly not worth anybody's time working on it even if it feels really bad and you know there's this gross code over here, and you really want to go work on it. But if it's not important to the business, then it just shouldn't be done. And it needs to be left alone until the business decides this is important to our functionality. We do want to prioritize this work, and we're going to work on it together. And I still think there are a couple of nuanced strategies even from there. So if you're looking for the more incremental improvements of we can't totally let this lie...we do have to improve it. But we're also not willing to invest in an overhaul situation. So some of the incremental improvements would be, as you'd mentioned, adding some test coverage to it to at least start to lock in the behavior that's already there and establish a baseline of understanding and then document that behavior. I've also found that really helps for context switching. So if you go in and you just document one part of that system as something that it does, then it frees you up. You can add something. You can issue a smaller merge request. You can get that merged because you're just adding test coverage. So it's not going to break anything. You're not making code changes. But then you can nearly let that go. And you can jump to something else that the team or the business has decided that's more important. Some other areas that I've used in the past for working in these types of legacy or just bug-prone areas is to look for flows that are no longer in use. So if there's something that stands out to me as like, I'm pretty sure users aren't using this, or this code just looks unused. Maybe it's running a tool like Unused, which we can link to in the show notes, and see if there's truly something that's unused that you can just immediately remove. Or maybe it's logging a message to Rollbar or something similar. So that way, you know this is actually being used, but you can have it log whenever that's being run. Let that live for a month and then go back and check to see if that flow is ever executed. As for the larger overhaul approach, that really has to be a team effort. So this has to be one of those moments of like the company decides this is important. And there may be smaller wins you can look for, but I do think it's going to require at least a developer or the product manager to be invested and ideally a designer as well. And then some small steps there may be looking for reducing responsibility of that feature. So maybe it's this really verbose long form that's complicated. And maybe you can collect some of that information somewhere else in the app. So you can start to chip away at some of the responsibilities in that portion of the application. Or maybe you have a mini design sprint. You may realize this is a very important part of your application. We should really have this be a better experience for users. And let's really take a hard look at what this does and start to document. And that's the bigger like we're going to rebuild this, or the whole team is going to focus on this and improve this portion of the application. So that was in response to some of the lovely things that you said that you made me think of. The other thing that really jumped out to me is this merge request that's sitting because this person, Michael or Ben, they've already done some really hard work where they have decided to add test coverage. They've cleaned up some things. And I can certainly relate to you issue a pull request and someone...because you've started cleaning up a space, people are like, "Oh, what about that cobweb? And then you missed a spot. What about over here?" And so, how do you make progress when you're in that state? And I would say move the goal line and merge the pull request. So your goal line sounds like right now is trying to address everything which doesn't feel humanly possible. So instead, move the goal line. Figure out okay, I just want to add these couple of tests, or I just want to add this refactor to a function or something that documents this part of the system. And if people are nervous about merging the current merge request because it has gotten so big and people have made so many small requests, is to then break it up into smaller, more focused PR. So then it makes it easier for people to say, "Yes, that does improve the state of this codebase. Please merge it." And I will often prefix my PRs with that. I'll say, "Dear reviewer, this PR is intended to improve the state of the world. It does not improve everything because I can't, but this is the goal of this." So that way, people go in with the mindset of they'll realize they're still going to see some cruft. But this is still leading us towards a better place. And unless there are strong concerns about the changes made in that specific PR, any other requests need to be noted and then can be captured somewhere else, but we're not going to address it right now in this PR. CHRIS: I agree so very much with all of the things you just said. For anyone at home who cannot see us on the Skype call that we're on, I was just aggressively nodding my head the entire time Steph was saying all of that. [chuckles] You touched on I think all of the additional points that I would want to make specific to this merge request is out there in the world and whatnot. The one other tiny bit that I would add to it is I have definitely been the person, and then I've also been on the other side of it where people get attached to the code that they've written. "But I've already written the merge request." And you're like, "Yeah, but can you break it up?" And they're like, "Yeah, but it already is a thing. And I did a bunch of work. And now I'm emotionally invested in this pile of work getting across the finish line and breaking it apart..." We can get caught up in our code. And this is a really great example of this thing just got away from you. This is too big of a refactor. It's too much of a risk. And so again, I have struggled with this personally where I'm like, I'm so proud of this pile of work that I just made. And people are like, "Yeah, but that's a big pile of work there." I'm like, "You're right. You're right. I should break this up. I will break this up." But I can feel that resistance in myself to doing that, what feels like extra work, what feels like almost undoing of work. It's like, "No, no, no. I think it's ready." I'll be like, "I don't know, I'm not convinced. Can we break it apart?" And that's almost always the right decision. But it can be painful. And so, just knowing that and having that in the back of your head as a thing that my brain will tell me the opposite. My brain will be like, no, no, go with it. It's great. We're proud of this. But being open to the idea that breaking things up is good, smaller pieces are good, et cetera, et cetera, can be a useful psychological aspect of this conversation because,, of course, there's one more facet. There are so many facets to this question. STEPH: I like that anecdote about that you haven't regretted breaking things up because I also relate to that where there's that initial like, I've already done this much work. And now you're asking me to do more work. And it's going to have the same outcome where it's still going to be the same code. It's still going to be the same set of changes, but you're asking me to break it up into smaller changes. And I just feel exhausted from this work already. And I don't want to have to break this up. So I understand and relate to that initial resistance. But I also really like the idea that all of these changes and everything going into the codebase is managed by a team. So we really want there to be a level of comfort from the team that this is what's going in. And as the author of the changes, I am far more comfortable with everything that's about to get merged in because I've spent so much time with it. So for me, whenever I do feel that initial resistance, I have to ask myself, well, what's the value? Will this make it easier for folks to review? Maybe it will show some areas that I didn't add test coverage because it felt like it was already getting so large. And so I started to negotiate with myself as to like, well, maybe I don't need to test that because this is already getting so big. And I don't want to add more to it. So I really think through what's the value of if I break it up? And will it make the team more confident in this change? And ultimately if it does, then to me, that's always a resounding yes. So it's just going through what's the value versus what's my initial oh, this is a waste of my time to oh no, this is a good use of my time because it really benefits everyone else. Circling back to something else that was said in the question was the message that we're just so drained from the whole thing. And I really don't want to take that for granted because that's really important. And it sounds like someone has taken their own time and hopefully company time to work on this. But it's not a team initiative. So this does feel like one of those areas where it feels like the team needs to prioritize whether this gets worked on or not. And it's okay if the team says, "Yes, this is important, but six months from now because we need a break from it." But as long as it's something that the team worked on together to say this is important, or it's not, I feel like that's an important part. And also to recognize that we don't have to fix all of this right now. That's really important for the company to buy into it. I have two small things that I want to add, sort of the what not to do because we've been talking about some things that we would do. And so one thing that I definitely wouldn't do is avoid having one person going off and trying to fix this part of the codebase. Don't have one person, either a designer, developer, just a single soul who's like, I can fix this, and tackle it, and define all the things, and improve it. That's going to go poorly. Don't do that. And then also, I would avoid refactoring just to refactor, which I think goes a little bit against Therapeutic Refactoring, which is a talk that I absolutely love. But if we're really invested in proving this part of the codebase, then I think it is very helpful and important to have a fixed user deliverable goal driving your refactor because that's also going to help shape and influence your PRs and encourage the team to take the time to review those PRs and get them merged. So there's a nice coupling there where you want something driving that goal. Granted, it could be different for different teams. Therapeutic Refactoring may work wonderfully. But I've just seen so many people sink a lot of time into something, get very frustrated, then nothing gets shipped. So I would favor leaning more until we have this very focused thing that we're going to deliver, whether it's adding a test or two tests. Have a goal in mind when you start that refactor. CHRIS: Again, I find myself nodding aggressively with everything that you're saying. And in addition, I really like the subtlety that you're bringing to one of my favorite talks. I've mentioned many times that this is one of my favorite talks. But I think you've added a really interesting like, yeah, but also, in the way that everything depends, it also depends. And I think you framed that really well that refactoring for refactoring sake can be fun and therapeutic, and cathartic for an individual. But we have to make sure it's part of the overall work that we're doing. And you've now, I think, really well captured the human side of this work that is captured in what is such a complicated, nuanced question that I think also does such a good job of just highlighting the work. This is what it looks like. This is a particular almost perfect storm of the work, but that happens. But each little piece of this that we've talked about is this is the day-to-day of software development interestingly. I always thought it was just going to be writing for loops. I haven't written a for loop in years. I don't even know how to write a for loop. But this stuff is what I do every day. [laughter] STEPH: The most challenging part for me in software I realized is when a problem has escalated to the point where it's like, I can't just write code to fix this. I need to go to the team. I need to get buy-in. And that's where I start to realize this is where software to me really gets hard because then I need other people to contribute and to get their opinions. And it turns out way better for it. But yes, that is definitely the intersection for me where I can write code up to a certain point to then I really need people to help make really great software and fix some of the underlying issues that we're facing. On that note, Michael and Ben, thank you so much for writing this in to us. I'm very interested to hear how this turns out for your team. And thank you so much. I wish you the best of luck. 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: 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.Sponsored By:Scout: Scout APM is leading-edge application performance monitoring 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 performance abnormalities -- like N+1 queries, slow database queries, memory bloat, and 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 worldwide call Scout their best friend and try our error monitoring and APM free for 14-days, no credit card needed! And as an added bonus for Bikeshed listeners: Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed.Support The Bike Shed
undefined
Nov 9, 2021 • 41min

315: Emotions Are A Pendulum

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. 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 Cassidy Williams - It Depends - GitHub Universe 2021 Say No To More Process StandardRB Become a Sponsor 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.Sponsored By:Scout: Scout APM is leading-edge application performance monitoring 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 performance abnormalities -- like N+1 queries, slow database queries, memory bloat, and 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 worldwide call Scout their best friend and try our error monitoring and APM free for 14-days, no credit card needed! And as an added bonus for Bikeshed listeners: Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed.Support The Bike Shed
undefined
Oct 26, 2021 • 41min

314: Communication, Testing, and Accountability

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. 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 Giant Robots Smashing into other Giant Robots - Plucky with Jen Dary Plucky Services are Not a Silver Bullet Become a Sponsor 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.Sponsored By:Scout: Give Scout a try for free today and Scout will donate $5 to the open source project of your choice when you deploy.Support The Bike Shed
undefined
Oct 19, 2021 • 42min

313: Forty-Seven Percent

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 How to Skim a Pull Request Isolator after_commit_everywhere 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 after_commit_everywhere gem. So after_commit 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 after_commit 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 after_commit_everywhere 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.Sponsored By:Scout: Scout APM is leading-edge application performance monitoring 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 performance abnormalities -- like N+1 queries, slow database queries, memory bloat, and 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 worldwide call Scout their best friend and try our error monitoring and APM free for 14-days, no credit card needed! And as an added bonus for Bikeshed listeners: Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed.Support The Bike Shed
undefined
Oct 12, 2021 • 39min

312: Spooky Stories

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 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, "Perform_later," You say, "Perform_async." 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 perform_later, you can say, InvitationMailer.perform_later 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 perform_later, that method perform_later 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.Support The Bike Shed
undefined
Oct 5, 2021 • 38min

311: Marketing Matters

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 Test-Driven Development in Swift with SwiftUI and Combine by Gio Lodi 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.Sponsored By:Scout: Scout APM is leading-edge application performance monitoring 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 performance abnormalities -- like N+1 queries, slow database queries, memory bloat, and 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 worldwide call Scout their best friend and try our error monitoring and APM free for 14-days, no credit card needed! And as an added bonus for Bikeshed listeners: Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed.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 and 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 co-working spot in your city. The tech stack of the main Orbit app is Ruby on Rails with JavaScript on the frontend. If you are 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.Support The Bike Shed
undefined
Sep 28, 2021 • 39min

310: Schedule Shut Down, Complete

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 Drastically Reduce Stress with a Work Shutdown Ritual Iceland's Journey to a Short Working Week Burnout: The Secret to Unlocking the Stress Cycle 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.Sponsored By: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 and 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 co-working spot in your city. The tech stack of the main Orbit app is Ruby on Rails with JavaScript on the frontend. If you are 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.Scout: Scout APM is leading-edge application performance monitoring 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 performance abnormalities -- like N+1 queries, slow database queries, memory bloat, and 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 worldwide call Scout their best friend and try our error monitoring and APM free for 14-days, no credit card needed! And as an added bonus for Bikeshed listeners: Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed.Support The Bike Shed
undefined
Sep 21, 2021 • 35min

309: Naming the Change

Steph talks about a new GitHub feature and Twitter account (@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 RubyCards Resilient Management The Manager's Path 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.Sponsored By: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 and 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 co-working spot in your city. The tech stack of the main Orbit app is Ruby on Rails with JavaScript on the frontend. If you are 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.Scout: Scout APM is leading-edge application performance monitoring 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 performance abnormalities -- like N+1 queries, slow database queries, memory bloat, and 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 worldwide call Scout their best friend and try our error monitoring and APM free for 14-days, no credit card needed! And as an added bonus for Bikeshed listeners: Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed.Support The Bike Shed

The AI-powered Podcast Player

Save insights by tapping your headphones, chat with episodes, discover the best highlights - and more!
App store bannerPlay store banner
Get the app