In this guest episode, Justin chats with Brian Casel. Bootstrapped Web podcast ZipMessage Brian's other projects What should we talk about next? Twitter: @buildyoursaas, @mijustin, @jonbuda Leave a review/comment on Podchaser; it's like Reddit, but for podcasts. Email us: firstname.lastname@example.org Thanks to our monthly supporters: Anton Zorin from ProdCamp.com Mitch Harris Kenny, Intro CRM podcast Oleg Kulyk Violette Du Geneville Take It EV podcast Ethan Gunderson Diogo Chris Willow Borja Soler Ward Sandler, Memberspace Eric Lima James Sowers (like Flowers) Travis Fischer Matt Buckley Russell Brown Evandro Sasse Pradyumna Shembekar (PD) Noah Prail Colin Gray Josh Smith Ivan Curkovic Shane Smith Austin Loveless Simon Bennett Michael Sitver Paul Jarvis and Jack Ellis, Dan Buda Darby Frey Samori Augusto Dave Young Brad from Canada Sammy Schuckert Mike Walker Adam DuVander Dave Giunta (JOOnta) Kyle Fox GetRewardful.com ★ Support this podcast on Patreon ★
4PM - Alec Baldwin: 'I didn't pull the trigger' of gun on 'Rust' set // John Schneider rails against Alec Baldwin for claiming he 'didn't pull the trigger' // Mistaken identity at a Marc Broussard concert // Crowd told to redo applause after Bidens show up late to National Christmas Tree lighting See omnystudio.com/listener for privacy information.
In the second hour, Dan Bernstein and Leila Rahimi were joined by Mike Florio of Pro Football Talk to discuss the college football coaching carousel's effects on the NFL. He also previewed Week 13 in the NFL. After that, Bernstein and Rahimi reacted to the news that MLB used two different types of baseball in the 2021 season -- without telling anyone. Later, they conducted the Midday Midway, with the topics including Gwar and a woman breastfeeding a hairless cat. See omnystudio.com/listener for privacy information.
Steph gives an update about RSpec focus and how she often forgets to remove the focus feature from tests. She figured out two solutions: one using Rubocop, and the other from a Twitter user, suggesting using a GitHub gist. She also suggests that if you're one of those people who misses being in an office environment, you check out soundofcolleagues.com for ambient office noise selection. Chris has been struggling to actually do any coding and is adjusting to doing more product management and shares some strategies that have been helping him. They answer a listener question about dealing with large pull requests and how it's hard to recognize a good seam to break them up when you are in the thick of one. This episode is brought to you by ScoutAPM (https://scoutapm.com/bikeshed). Give Scout a try for free today and Scout will donate $5 to the open source project of your choice when you deploy. Twitter note re: rspec-retry (https://twitter.com/jasonrudolph/status/1458416077726158852) soundofcolleagues.com (https://soundofcolleagues.com) mailcheck (https://github.com/mailcheck/mailcheck) Inertia.js (https://inertiajs.com/) Svelte (https://svelte.dev/) devise (https://github.com/heartcombo/devise) clearance (https://github.com/thoughtbot/clearance) Become a Sponsor (https://thoughtbot.com/sponsorship) of The Bike Shed! Transcript: CHRIS: One day, I'll grow up. It's fine. I look forward to that day. But today, I don't think it's that day. Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey. STEPH: And I'm Steph Viccari. CHRIS: And together, we're here to share a bit of what we've learned along the way. So, Steph, what's new in your world? STEPH: Hey, Chris. Well, in some fun news, Utah started his professional training as of this morning, which I'm very excited about. Because we've been working with him to work on being good with walking on a leash, FYI, he's not, [laughs] and also being good about not jumping on people. And essentially, being a really good roommate. And he started training today, and we are using an e-collar, which initially I was really hesitant about because I don't want it to hurt him in any way. But now that I have felt the e-collar myself and we've had a first day with it, it's going super well. I'm very excited for where this is headed. CHRIS: That's very exciting. When does he start paying rent? STEPH: Ooh. I'll have to check with him, or I guess I have set those boundaries. That's my job. CHRIS: I just figured that's a core part of being a good roommate. But maybe we've got baby steps or doggy steps to get there. But that's exciting. I'm glad [laughs] that the first day of training is going well. STEPH: Yeah, it's going great. And the place that we're going to the trainer they have horses, and mules, and goats. And so now I have a very cute video of him trying to play with a goat, and the goat was having none of it. But it's still all very cute. In tech-related news, I have an update for when you and I were recently chatting about the RSpec focus and how I mentioned that I often forget to remove the focus feature from tests. And so then that goes up to a PR, and I have to rely on a kind human to let me know, and then I remove it. Or worst-case scenario, it gets merged into the main branch. And for anyone that's not on Twitter, I just wanted to share an update because I also shared something there. But the resolution for what I was looking for there's already a rule that's written into Rubocop, but it's specifically written in the Rubocop RSpec codebase. And with that rule, you can essentially just say, hey, let me know anytime that a test is using the focus metadata, and then make sure to let me know and fail. And then if you don't want to actually include all of Rubocop into your project because Rubocop is pretty opinionated, you can still add Rubocop to your project, but you can specifically add Rubocop RSpec, and then you can say, hey, all other rules disabled by default, but then you can enable that specific rule. So then, that way, you will catch all of your focus tests. There's also another approach that someone on Twitter shared with us recently from Marz Drel. And Marz shared specifically a really nice simple GitHub Gist that documents or exemplifies that you can add an environment variable that checks to say, hey, if we're in CI mode, then add a before hook. And then that before hook will look for any examples that are using that focus metadata, and then it's going to raise. And then if we're not in CI mode, then don't do anything, don't raise, and carry on. And that's just a really nice simple addition if someone didn't want to pull in Rubocop into their project. CHRIS: Both of those definitely sound like great options. I don't think we have Rubocop on the current project that I'm working on. But I think the RSpec focus thing, the metadata one, seems like it'll work great. More generally, I just want to thank folks out there who listen to the show and then write back in like, "Hey, this is probably what you want." There was a similar thread that someone shared around the RSpec::Retry stuff that I was talking about recently and the failure mode there and trying to get that into the Junit Reporter. And so they had some suggestions around that. Jason Rudolph on Twitter reached out, sharing just his initial exploration and thoughts on how it might be possible to extend the XML reports that are generated and capture a flaky test in that way. So that's really interesting. And again, just really love that folks are listening to the things that we say and then even adding on to them and continuing the conversation. So thanks to everybody for sharing those things. STEPH: Yeah, it's incredibly helpful. And then one other fun thing that I'd love to share, and I found this out from someone else at thoughtbot because they had shared it recently. But it's a neat website called soundofcolleagues.com. And I know you've got your laptop in front of you. So if you'll go visit it, it'll be neat to see as we're talking through it. For anyone else that wants to pull it up, too, we'll include a link in the show notes. But it's a neat project that someone started where you can bump up the sounds that you would normally hear in an office. So maybe you want to bump up background noise of people or an open window. There's one specifically for printers and a coffee machine, and keyboards are on there as well. [laughs] I have discovered I am partial open window and partial rain, although rain is just always my go-to. I like the sound of rain for when I'm working. CHRIS: Gentle rain is definitely nice white noise in general. I've seen this for coffee shops, but I haven't seen the particular one. Also, yes, I definitely know how to spell the word colleague on the first of three tries. Definitely didn't have to rely on Google for that one. But yeah, nice site there. I enjoy that. STEPH: I tried the keyboard option that's on there because I was like, oh yeah, I'm totally going to be into this. This is going to be my jam. I don't think it is because I realized that I'm very biased. I like the sound of my own keyboard. So I had to shush the other one and just listen to the rain and the open window. But that's some of the fun things that are going on in my world today. What's new in your world? CHRIS: I'm just now spending a moment with the keyboard sound. It's a very muted keyboard. I want a little more clackety. STEPH: A little more clackety? CHRIS: I was assuming it would be too much clackety, and that would be the problem. But it sounds more mushy. Maybe we can pipe in some of the sound here [laughs] at this point. Or we can link to these sounds, and everyone can dial up the keyboards to 100. But I, too, am partial to the sounds of my own keyboard. But what's new in my world? This past week and I think probably even a little bit more of the prior week, I've been noticing that I've been struggling to actually do any coding, which has been interesting to observe. And again, trying to observe it, not necessarily judge it, although if that's not the thing that we want to be doing, then try and improve that. But mostly trying to observe what's going on, what is taking my time. A lot of it is product management type work. So I am spending a good amount of time trying to gather the different voices and understand what is the work to be done, and then shape that into the backlog and make sure that that's clear and ready for the team to pick up. And then, thankfully, the other two developers that are working on the project are fantastically prolific. So they're often very quickly working through the work that has been set up in front of them. And so I'm trying to then be proactive and respond to the code. But there's almost a cycle to it where I'm just staying out in front of them, but they're catching up with everything that's going on. So it's something that I'm trying again to be intentional about, name, share some of that back up with the group. If there are things that I'm doing that I don't uniquely need to be doing, then let's share as much of that knowledge as possible. But one thing that I will say is the product management, shaping the backlog work is exhausting. I am astonished by just how drained I am at the end of the day. And I'm like, I don't even really feel like I did anything. I didn't write any code, but I am just completely spent. And there really is something to when the work is clear, just doing the work, I can actually find energizing. And it's fun, and I can get in flow state. And sometimes, I'll be drained in a certain way. But the work of taking a bunch of different slack threads, and communications, and meetings, and synthesizing that down, and then determining what the work needs to look like moving forward, and providing enough clarity but then not over constraining and not providing too much clarity. And there are so many micro-decisions that are being made in there. And I'm just spent at the end of the day, and I have so much...I've always had a lot of respect for product managers and folks that are existing in that interstitial space and trying to make sense of the noise, especially of a growing company, but all the more so this week as I've been feeling some of that myself. STEPH: I totally agree. I have felt that having a strong product manager really makes or breaks a project for me where even though having technical leadership is really nice, I'd prefer someone that's really strong at the product knowledge and then helping direct where the product is headed. That is incredibly helpful. Like you mentioned, the work is exhausting. There's someone that joined the thoughtbot team fairly recently, and I was chatting with them about what type of projects they would be interested in working on. And one of their responses was, "I'd love to work on a project with a strong product manager because I have been doing that a fair amount for recent years. And I would love to get back to just focusing on coding." And so I think they enjoyed some of the work, but they just recognize it's exhausting. And I'd really like to just get back to writing code for a while. CHRIS: Yeah, I'm definitely in that space. And I think there's a ton of value to spending a little bit of time, like having any developer at some point in their career spend a little bit of time managing the backlog, and you will learn a bunch from that. But I'm also in the space of I would love to just turn on some music and code for a while. That sounds fun. There's a lot of work to be done right now. I'd love to just be in there doing the work. But sometimes, out of necessity, the defining of the work is the thing that's important. And so, I think I've been correctly assessing the most important thing. And that that has consistently for a while now been the defining and responding to the work that's in process as opposed to doing it myself. But, man, I really hope I get to dive back into the code sometime and use my clackety keyboard to its fullest extent. STEPH: Have you found any particular strategies that really help you with the product management work? CHRIS: I will say that I think this is a competency. This is a skillset and a career path that...again, I've been at plenty of organizations that I don't think respected the role as much as it should be. But it's an incredibly hard role and multidisciplinary communication at the core of it. And so I don't think I'm great at it is the thing that I'll say. So everything that follows is just to be clear; I'm not saying that I'm great at this, but I have been doing some of it. So here are some thoughts that I have. I think a lot of it is in reaction to where I felt like the work was clear. So I have a sense of what it looks like when I can go to the backlog, trust that it is in a roughly solid priority order, pick up a piece of work and immediately go to work on it. And understand what are the end-user implications of this piece of work? Where would I start on it like, how technically? What's a rough approach that I would have? And getting that level of specificity just right. So it's not overconstrained, but it's not under constrained. So having experienced that on the developer side, I try and then use that to shape some of the guidance that I'm putting into, say, the Trello tickets that I'm writing up here. We recently introduced Trello epics, which is I want to say like an add-on. And that allows us just the tiniest bit of product management, like one level up. So instead of just having cards and a list that is like, here's the work to be done, we now have an epics list that is separate to it, and it links between a card and its associated epics. So it's like project and action within that project. And just that little touch of structure there has been really, really useful to help look at like, okay, what are the big pieces that we're trying to move? And then how do they break down into the smaller pieces? So a tiny, tiny bit of fanciness in our product management tool, not Jira-like not going in that direction yet for as long as I cannot. But that little bit of structure. And then thinking about what has been useful to me as I pick up tickets. And then, as always, trying to just always be cognizant of what is the user's experience here? What problem am I trying to solve for them? What is their experience going to be? How will they know how to work with this feature? And just always asking that and then framing the work to be done in the context of that. STEPH: I like how you're adamant about a little bit of fanciness but not all the way to Jira-like. I also like how you highlighted end-users. All of that, I think, is awesome when developers are able to expand their role to experience all the other facets of building software. CHRIS: Yeah, definitely. I think that whole list of all of the different facets of where our work interacts with different groups. The more empathy or, the more experience that you can have there, the better that you'll be able to understand how to communicate there, how to express things in terms, et cetera, et cetera. So a huge fan of all of those ideas. I am ready to just get back in the code for a few minutes, though. But for now, for as long as necessary, I'll do some of this work. But I am trying to find my way to other things. In terms of actual feature work that we're working on, one of the things that we're doing right now is restructuring our onboarding. So when a user comes and signs up to the website and then subsequently has to fill out a handful of other forms, there's actually an external system that we've been working with that houses some of the core data of our application. And they have a hosted application form. So we can send the user over to them, and the user fills out the rest of the application on this other system's site. And then they get redirected back to us. And everything's got nice DNS entries for a particular subdomain and whatnot. So it looks roughly consistent. There's some branding. But it's still someone else's UI, essentially. And we were feeling enough pain from that experience. We were like; you know what? It's time. We're going to bring this back in-house. We're going to do all the forms ourselves. We're going to do a nice progressive little progress bar. You can see all the steps as you're going through onboarding. We're just going to own that more because that's a core part of the experience that we're building here. So biting the bullet, deciding to do that. But there's an interesting edge case that we run into, which is we are using Devise for authentication. Totally makes sense. We're in Rails context; there we go. It's the thing to use. But Devise exists in truly the Rails world. So like HTML ERB templates, the controllers have certain expectations as to what's going on. So thus far, we've just let that exist in that world and everything else we're building in Inertia and Svelte. But we're just now starting to feel enough of the pain, and that Devise exists in this other context. And for a while, we just kept saying, "You know what? It's not worth the effort to port it over. It's fine." Because we're using Tailwind, we have a consistent design language that we can use across them. That said, the components are drifting a little bit. And it's like, oh, this one's got a rounded corner like this, and that one's got this color. And we don't have the disabled style. But it is nice that it's not completely distinct. But we have finally decided it is time. We need to port this thing over because we feel like the onboarding and authentication type flows; they're actually a big part of the user experience or at least the first run user experience when someone's signing up to our site. So we want to own that a little bit more. One of the things that I ran into as I was trying to introduce Mailcheck, which is a library that I've talked about, I think in a previous episode...but basically, you can have it observe a field and if someone types in like, email@example.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 firstname.lastname@example.org 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.
In this bonus episode, Justin interviews his 18-year-old daughter, Sadie, about: A Gen Z perspective on podcasting Why women are the future of podcasting: Edison Research "Now, look at the rookies – 47% are men, but the majority, 53% are women." "Most women get their podcast recommendations from Spotify, social media, or their friends." We talk a lot about podcast advertising, podcast ads, and how the adtech industry should think differently about how they target women."Most podcast ads are just men talking to men." What should we talk about next? Twitter: @buildyoursaas, @mijustin, @jonbuda Leave a review/comment on Podchaser; it's like Reddit, but for podcasts. Email us: email@example.com Thanks to our monthly supporters: Anton Zorin from ProdCamp.com Mitch Harris Kenny, Intro CRM podcast Oleg Kulyk Violette Du Geneville Take It EV podcast Ethan Gunderson Diogo Chris Willow Borja Soler Ward Sandler Eric Lima James Sowers (like Flowers) Travis Fischer Matt Buckley Russell Brown Evandro Sasse Pradyumna Shembekar (PD) Noah Prail Colin Gray Josh Smith Ivan Curkovic Shane Smith Austin Loveless Simon Bennett Michael Sitver Paul Jarvis and Jack Ellis, Dan Buda Darby Frey Samori Augusto Dave Young Brad from Canada Sammy Schuckert Mike Walker Adam DuVander Dave Giunta (JOOnta) Kyle Fox GetRewardful.com ★ Support this podcast on Patreon ★
Nine Rails Arts Podcast Ep. 29 - Vida Muerte Justicia / Life Death Justice In Episode 29 of the Nine Rails Arts Podcast, we gather around the virtual picnic table to discuss Vida, Muerte, Justicia / Life, Death, Justice, an exhibition of twenty-four Latin American and Latinx contemporary artists whose work responds to relevant themes in relation to social and racial justice. The exhibited artists offer local, national and international perspectives through multiple disciplines including painting, sculpture, photography, installation, performance, digital art and more. Vida, Muerte, Justicia / Life, Death, Justice is presented in partnership with Weber State University's Mary Elizabeth Dee Shaw Gallery and is curated by Jorge Rojas and María del Mar González-González. We are joined by co-curators, Jorge Rojas and María del Mar González-González, as well as OCA executive director, Venessa Castagnoli, and the gallery director of WSU's Shaw Gallery, Lydia Gravis. Hosted by Todd Oberndorfer and produced by R. Brandon Long. Don't miss an episode of The Banyan Collective's Nine Rails Arts Podcast, as host and arts advocate, Todd Oberndorfer, explores what it means to be an adventurous creative. Hear the stories of Ogden's Nine Rails Creative District, recorded from the Banyan Collective studio, located in The Monarch Building in the heart of the creative district. Support the Podcast: https://www.buymeacoffee.com/banyanmedia
11/25/21 - Just popping in to let you know there's no new episode of Off the Rails this week. Have a happy and safe Thanksgiving!
In Episode 29 of the Nine Rails Arts Podcast, we gather around the virtual picnic table to discuss Vida, Muerte, Justicia / Life, Death, Justice, an exhibition of twenty-four Latin American and Latinx contemporary artists whose work responds to relevant themes in relation to social and racial justice. The exhibited artists offer local, national and international perspectives through multiple disciplines including painting, sculpture, photography, installation, performance, digital art and more. Vida, Muerte, Justicia / Life, Death, Justice is presented in partnership with Weber State University's Mary Elizabeth Dee Shaw Gallery and is curated by Jorge Rojas and María del Mar González-González. We are joined by co-curators, Jorge Rojas and María del Mar González-González, as well as OCA executive director, Venessa Castagnoli, and the gallery director of WSU's Shaw Gallery, Lydia Gravis. Hosted by Todd Oberndorfer and produced by R. Brandon Long. Don't miss an episode of The Banyan Collective's Nine Rails Arts Podcast, as host and arts advocate, Todd Oberndorfer, explores what it means to be an adventurous creative. Hear the stories of Ogden's Nine Rails Creative District, recorded from the Banyan Collective studio, located in The Monarch Building in the heart of the creative district.
Date: 07.12.2021 (Season 3, Episode 8, 1: 20:00 min.) To read the complete Utah Dept. of Culture & Community Engagement show notes for this episode (including topics in time, photos and recommended readings) click here. Interested in other episodes of Speak Your Piece? Click here for more episodes.Podcast Content:What can be encountered on one of the United State's most austere and vacant landscapes? A whole lot, including a largely “unknown national treasure,” an eighty-seven mile stretch of raised railroad grade, built across a breathtaking scenic and cultural landscape, winding around the Great Salt Lake, with views of the Promontory, Hansen, Hogup, Grouse Creek, Newfoundland and Lakeside Mountains. On this road you will experience a landscape largely as it would have been seen by travelers on the first transcontinental railroad; nothing like any surviving portions of the 1862-1869 transcontinental railroad. Speaking of their 2021 publication, Rails East to Ogden: Utah's Transcontinental Railroad Story (a BLM Utah, Cultural Series Publication) historical archaeologists Michael Polk (Aspen Ridge Consultants) and Christopher W. Merritt (Utah SHPO) interpreted over ten years of new research and discoveries, and offer fascinating descriptions concerning Chinese immigrant work camps and life (including later more substantial China towns); strewn and buried garage that document goods that traveled from mainland China, Ireland and Europe; ghost town where hundreds of people and families once lived and enjoyed homes, bunk houses, pleasure gardens, hotels, bakeries and even a public library; water lines made of hollowed redwood logs which once quenched thirsty steam locomotives; a half a dozen railroad facilities (now only rubble); and adjoining stagecoach roads that took people and goods to frontier Idaho and Montana; all adjacent to a railroad that was actively used from 1869 to World War II.Guest Bio: Michael Polk is a historical archaeologist for the Western United States. He is the principal and owner of Aspen Ridge Consultants, a heritage resources firm providing consultation in historical archaeology, history and architectural history. Polk has a long career in archaeology, serving in companies such as Sagebrush Consultants and Environment Consultants. He has been investigating Utah's diverse cultural and industrial landscapes for over forty years. Christopher W. Merritt is a historical archaeologist and the Utah State Historic Preservation Officer (SHPO), based out of the Utah Division of State History. Merritt is a leading advocate for historical archaeology throughout the western United States. He is the author of numerous studies, reports and academic articles, and is the author of the book The Coming Man from Canton: Chinese Experience in Montana, 1862 - 1943 (2017). Do you have a question or comment, or a proposed guest for “Speak Your Piece?” Write us at “ask a historian” – firstname.lastname@example.org
Nick is joined by David Yates, Newsboy of the Daily Mirror, to discuss the latest news and events from the horseracing world. The lead with the strange case of a strange race at Punchestown yesterday. In conversation with winning trainer Ronan McNally, Nick discovers him to be deeply critical of the perception that his built up around his gambled-on runners and also of his treatment at the hands of the Irish racing authorities. Nick and Dave discuss his thoughts, before moving on to recently familiar territory including the latest news on the Monasterevin raid samples, the BHA restructure and the commitment to better jockeys' room facilities, which is fleshed out by the PJA's Dale Gibson. Nick also talks to Brendan Powell jnr about his ride on Fiddlerontheroof in this weekend's Ladbrokes Trophy and to Fittocks Stud boss Sara Cumani about what it takes to prepare foals for the Tattersalls Sales, while JA McGrath brings news of great excitement from Hong Kong ahead of their big international raceday.
Nick is joined by David Yates, Newsboy of the Daily Mirror, to discuss the latest news and events from the horseracing world. The lead with the strange case of a strange race at Punchestown yesterday. In conversation with winning trainer Ronan McNally, Nick discovers him to be deeply critical of the perception that his built up around his gambled-on runners and also of his treatment at the hands of the Irish racing authorities. Nick and Dave discuss his thoughts, before moving on to recently familiar territory including the latest news on the Monasterevin raid samples, the BHA restructure and the commitment to better jockeys' room facilities, which is fleshed out by the PJA's Dale Gibson. Nick also talks to Brendan Powell jnr about his ride on Fiddlerontheroof in this weekend's Ladbrokes Trophy and to Fittocks Stud boss Sara Cumani about what it takes to prepare foals for the Tattersalls Sales, while JA McGrath brings news of great excitement from Hong Kong ahead of their big international raceday.
[00:00:52] The guys chat about being at RubyConf, how they recorded a live episode with six people, what they talked about, and something about a stellar ending. [00:02:50] Andrew and Jason talk about what happened from the first day of RubyConf and from then on, between meeting up with people, eating with friends, doing a lot of walking, hugging, and talking with so many people. [00:06:39] Jason tells us more about Matz's talk on the Ruby 3 Nexus.[00:10:49] Jason explains another thing Matz talked about regarding how there will not be a lot of language features focused on right now, but more performance and tooling. [00:12:38] Chris tells us about the new screencast he just did on the new load_async in Rails 7 you should check out. [00:16:25] We hear some funny stories from Jason about how he saw Andrew “Hella triggered” two times this week.[00:17:53] The guys discuss the best thing about being at conferences especially since they haven't happened in two years due to COVID. [00:20:37] The conversation turns to impromptu get togethers at the conference and some stories from Jason, and Andrew announces they scheduled some upcoming guests for the podcast from this conference so stay tuned. [00:24:01] Jason acknowledges the recent passing of Mike Rogers and all he did for the Ruby community. [00:25:51] New in the Ruby world, Ruby 3.1.0 the alpha came out and the changes with YJIT and how the app will be faster. [00:28:12] Find out what who was dressed in Adidas gear all week at the conference and two things that Jason doesn't like! ☺[00:29:47] Jason and Andrew tell us what their favorite part of the conference was.[00:35:20] Andrew gives a big thank you to Ruby Central for doing the conference, the Ruby community, and the organizers and sponsors. Also, Jason and Andrew tell us their favorite things they learned from some of the talks. Panelists:Jason CharnesChris OliverAndrew MasonSponsor:HoneybadgerLinks:Ruby Radar NewsletterRuby Radar TwitterRubyConf 2021Parallel ActiveRecord Queries with load_async in Rails 7-GoRails with Chris OliverRuby 3.1.0 Preview 1 Released-Ruby News
Welcome to Season 2. Riding the Rails, in the Lap of Luxury,Find out more...29 Railroaded
No holiday break on the recruiting front! Brittany and Brian catch up on the Rails recruiting trends. They discuss how companies need to up the ante now that so many are remote first, how interviews should be structured and whether it is worth getting in the door, if it is not for the role you want. Show Notes & Links: Mirror Placement (https://www.mirrorplacement.com/) Rubyconf 2021 Job Fair (https://rubyconf.org) Sponsored By: Honeybadger (https://www.honeybadger.io/) Honeybadger makes you a DevOps hero by combining error monitoring, uptime monitoring and check-in monitoring into a single, easy to use platform. Go to Honeybadger.io (https://www.honeybadger.io/) and discover how Starr, Josh, and Ben created a 100% bootstrapped monitoring solution. Atlantis Technology (https://www.atlantistech.com/careers) Atlantis is looking for great engineers! Why work at Atlantis? You'll work with great people. You'll work on projects that change the world. No matter where you are in your career, they're prepared to help you advance it. Find out more here (https://www.atlantistech.com/careers).
Vlado Cingel recounts his story where he needed common table expressions within SQL for a project he was working on and wrote a patch to AREL and ActiveRecord which he submitted to the Rails Core. Since it hasn't been accepted, he's supporting it as a gem. Vlado explains what Common Table Expressions (CTEs) are, how they work, and where they're used. Panel John EppersonLuke StuttersValentino Stoll Guest Vlado Cingel Sponsors Top End DevsRaygun | Click here to get started on your free 14-day trialCoaching | Top End Devs Links GitHub | vlado/activerecord-cteOrganising complex SQL queries in RailsGitHub: Vlado Cingel ( vlado ) Picks John- Digital Storm: Custom Gaming Computers & Gaming PCsLuke- Pitch PerfectValentino- Ruby TogetherValentino- Ruby CentralValentino- The Ruby VM a speedrun - Penelope PhippenVlado- The Wood Whisperer Guild - Online Woodworking SchoolVlado- Polished Ruby Programming Contact John: Rock Agile ConsultingGitHub: John Epperson ( kirillian )LinkedIn: John Epperson Contact Luke: GitHub: Luke Stutters ( lukestuts ) Contact Valentino: Doximity Technology BlogWork @ DoximityGitHub: Valentino Stoll ( codenamev )Twitter: V ( @thecodenamev ) Special Guest: Vlado Cingel.
Hosts: Shane and Tanis A Double XP care package arrives signalling the future ahead. Duel arena stakes are capped at 50m, numerous mythical Elder God Wars drop rates are buffed, and Croesus is getting a colourblind toggle. Also, do we really need a death cost rework? For detailed show notes visit update.rsbandb.com. You can also check out the forums for detailed discussion on each episode.Duration: 1:28:06
[00:03:24] Andrew went to a mall and he explains what it was like to shop in a mall in 2021.[00:05:17] Jason and Andrew are headed to RubyConf and they discuss what they are most looking forward to there. [00:07:30] The guys finally chat about Elixir![00:09:12] The topic of Hotwire is discussed, and Chris tells us what fascinates him with the Elixir of the LiveView. [00:16:51] Andrew tells us he was supposed to learn Elixir and why he hasn't learned it yet. [00:20:31] Jason announces he started shutting down HopeGrid and we find out why. [00:23:08] Chris tells us some cool things going on in the Ruby World with Andrew Hodson and redirect to an external URL is changed in Rails 7 that will be unsafe. [00:26:22] Brakeman just got updated and we hear all the details about it and Andrew and Chris chat about SSL. [00:34:02] Jason and Andrew are headed to Denver for RubyConf, and they will be recording their next podcast there! [00:35:06] Jason announces they are hiring at Podia if anyone is looking for a job, and the guys chat about some of the talks they are excited about seeing at RubyConf. Panelists:Jason CharnesChris OliverAndrew MasonSponsor:HoneybadgerLinks:Ruby Radar NewsletterRuby Radar TwitterRubyConf 2021Rocket LeagueElixirElixir-WikipediaPhoenix LiveViewHow We Got to LiveView by Chris McCord (Fly.io Blog)BrakemanAndrew Hodson TwitterHauling Buddies
Follow the speakers we mentioned!David Sherry: https://twitter.com/_brandswellItamar Marani: https://twitter.com/itamarmaraniColleen Schnettler 0:00 Every doctor is concerned about your vital signs, but a good doctor cares about your overall health. Your website deserves the same care, and Hey Check It is here to help- Hey Check It is a website performance monitoring and optimization tool- Goes beyond just core web vitals to give you a full picture on how to optimize your website to give your users an optimal, happy experience- Includes AI-generated SEO data, accessibility scanning and site speed checks with suggestions on how to optimize, spelling and grammar checking, custom sitemaps, and a number of various tools to help youStart a free trial today at heycheckit.comAUTOMATED TRANSCRIPT Michele Hansen 0:35 Hey, Colleen.Colleen Schnettler 0:37 Good morning, Michelle.Michele Hansen 0:39 It's so nice to see your face again, after seeing it in person. Last off at founder Summit.Colleen Schnettler 0:45 I know that was such a wonderful trip. And just amazing that we got to spend that time together.Michele Hansen 0:51 I keep thinking about how awesome it was like, I feel like they've set the bar really, really high for conferences in general as but especially post COVID.Colleen Schnettler 1:04 Yeah, I also think I will be impressed if they can replicate that experience next year, because everyone I know now wants to go. And I think part of what made that conference so special was that there were it was capped at 150 people. And I'm sure they're gonna get a flood of applicants to go next year. So I don't know what they're going to do how they're going to handle that.Michele Hansen 1:28 Yeah, actually, so Tyler tweet that he was like, oh, like, what if we did this in other cities? Oh, like to a year? Yeah. And I was like, Oh, that would be really cool. Yeah, good. Maybe we should talk about like, what made it so awesome. And like, kind of what are like, what are takeaways from it?Colleen Schnettler 1:44 Oh, yeah, girl, I have so many takeaways, all the takeaways. Okay. What were what? What would you lead with? What made it so special for you? Besides me? Of course. It's too easy.Michele Hansen 2:01 You know, so I mean, yeah, this is really hard thing to like, summarize. So I think it was, I mean, it was just so nice being in the same place with other people who are doing the same thing. You know, I think we've talked about how, you know, we initially connected one of the reasons was like, You're the only person I knew in my regular everyday life, who also did this, like weird internet business thing. And there's just like, aren't that many people in this world doing that. So it's just like, so nice to be around other people who are doing this. And you're not only not only do you feel normal, but like, it's such a good environment for like, throwing around ideas. And like, there was at one point when we were talking about, like, multiples for SaaS companies like making a couple $1,000 a month at one point, like on a on the bus to do the hot air balloon ride over to t Wuhan like, and I hope I'm pronouncing that right. I'm practicing so much. And we're like, you know what, we should just like, ask the bus, like this bus full of people would know the answer to this question and have a perspective on this. And like, and so that was really, really awesome. And I feel like there's so many people who introduce themselves. And then and then we like, you know, I'm so and so Oh, and I'm so and so on Twitter, and I'm like, oh my god, like, I've been tweeting with you for the past, you know, like, couple of years, and I finally meeting you in person. And. And so that was really awesome. And I mean, just getting so many ideas going about things. And also, you know, we had talked on our meta episode about how I want to talk more about negotiation, because that's something I do a lot of, and sales, but don't really talk about. And then a speaker was sick on the second day, and Tyler was like, Hey, can anybody give a talk this afternoon? And like, fill the spot and I was like, Yep, alright, I can do negotiation, talk and workshop. And, and, you know, just kind of kind of jumped at it. And it was, it was super fun. And I think I think the big thing I'm really thinking about that, you know, that activity did was like the, the, the, like the wheel where you had to, like rate different areas over your life from like, one to 10 like how they're going. So there was I think it was like occupational fulfillments like one to 10 which is work, right work. Yep. spiritual, emotional, environmental. Physical. Did I already say social? I don't think so. Social. Yeah, there was like five or six different things. Yeah, that'sColleen Schnettler 4:49 six. Um,Michele Hansen 4:52 and I think we both had really interesting results from that. Like they're very different like ours were like, Oh, yes, opposite one. And yeah, and really thinking about how like, you know, I like I gave like physical health like a one on that, right. And the goal of this activity was, you know, you give each area a score of one to 10. And then you set a goal of getting up to spots in the next 90 days. So not going from one to 10, which is often how I two things, just like totally like, balls to the wall focusing on something. But going, you know, from like, one to three, and so it's like, how can you have a plan to go from one to three or three to five? Or, or what have you in the next 90 days. And I remember you saying, when I was writing the book, you were like, Dude, you're like, moving so fast, like you're gonna run headfirst into a wall. And I did, and I haven't talked about that too much, but kind of like privately, I've talked to some people who definitely had this had a similar feeling after launching things. Yeah. Um, and yeah, just really, really thinking. I mean, like, literally even like today, like I got hiccups. 30 seconds before we got on recording, and I was doing literally everything I could to get them to go away, rather than being like, hey, maybe let's record another day instead, right? Like I make work happen no matter what. Even if it's at the the sacrifice of my physical health. And so I think that's something you know, I really need to focus on and I think, something Natalie from wild bit said on stage was like, you know, if the founder isn't happy, if the founder isn't healthy, then the company can't flourish. And so I think that's, that's, I mean, that's something I really, really need to work on. And it's like, kind of like work related, but it's like, it's not, but it also like it is in every sense of the word. So I think that's kind of been a thing I'm thinking about, but I don't I still don't really know exactly where I go with that.Colleen Schnettler 7:07 Like actionable steps. That's what you're still trying to figure out. Because if you want a warning, pretty bad, soMichele Hansen 7:12 yeah, it is. Yeah. I mean, I did order atomic habits, which is like one of those books that like I've never read before, never read a tie. No, it's like one of those books. I feel like that. And like Ray Dalio, his book, or like, books that everybody around me read and like, told me about, and I read about, so I felt like I read them. But I didn't, you know, like, I just didn't feel like I needed to, because it just everybody read it. And I'm like, No, I should probably like, sit down and think about like, not doing a whole scale turnaround, which is like, normally how I approach anything, and it's like, just just just way over the top. Yeah, um, but how, you know, how can I make small changes so that I don't get exhausted and like, move on to something else? And then then, which then exhaust me and then move on to something else? Like, it's, I see a pattern here. So, um, yeah, and I think I also thought, you know, a lot of people, even if they were in different groups really struggling with the idea of like, work life balance, and how do you, you know, how do you make it so that work doesn't become too much of your identity? And how, when when you really love what you do, like, it's really hard to pull yourself away from it, too,Colleen Schnettler 8:28 right? Yeah.Michele Hansen 8:32 I don't know. So I don't really have like, I'm just kind of all that's just still really marinating in my head. But it really, really got me going. And I think I really, really needed that push to like, um, I don't know, like, I guess like, prioritize my myself a bit.Colleen Schnettler 8:52 Sounds great. I mean, it sounds like that. It's funny sometimes to how you you've probably heard that from me or your spouse or your other friends. But there was something about the environment where everyone was sharing and being open and vulnerable in that big group that I felt really helped some of those points hit home because you saw so many people in the same situation you were in.Michele Hansen 9:13 Mm hm. And I mean, you're so like, you were totally opposite because oh, I have like a 10 for occupational like I feel like you know, for me, like this is exactly where I want to be like, last week I spoken in Mexico City twice. This week I spoke in Copenhagen I'm you know, like, like, this is just sort of in like the business is good. Like everything is really good there. But like you for occupational like I think you had like a 10 or a nine for physical health. But then you are much lower on occupational and that was the group that you were in.Colleen Schnettler 9:49 Absolutely. Yep. I think something you mentioned to me, which I think is true and was kind of cemented meeting so many founders is like I'm pretty good at taking care of myself socially. mentally, physically, I prioritize that. And so yeah, all that stuff was good for me. But yeah, my occupational score was lower. So my goal is to get that score, what do you say to two or three in the next 90 days?Michele Hansen 10:17 I'm just curious, what did you give yourself for occupational,Colleen Schnettler 10:20 I honestly don't remember probably like a seven. I love what I do. So I don't think I mean, I think if I was still working a full time job that I didn't enjoy, it would have been much lower. I love what I do with occupational in terms of like my job. So it was still a high score. But I think I what I really took away from the conferences is I was challenged in a way I haven't been challenged in a long time. And by that, I have a lot going on as to you as everyone. And I'm doing really, really well one of the executive coaches there who I was talking with, she described it as an avalanche of abundance, which is like a great problem to have, right? Like, I'm not gonna complain about it. It's an amazing problem to have. And I have all the things and I'm very happy. But I think I haven't really pushed it all on the business stuff. I've just kind of been resting, but I'm not tired. I'm ready to push. Does that make any sense? I guess what I'm trying to say is, I could be trying a lot harder. That's it. That's what I'm trying to say. Yeah, I think so I think that I'm not really trying. And I'm telling myself, I'm trying, but I'm not. So I'm going to start trying.Michele Hansen 11:40 So what is trying look like to you. There's a couple of really specific things. IColleen Schnettler 11:45 think there's a lot of personal stuff wrapped up in here too. Like something I took away was like identity. For example, I have this, this interesting. You and Rosie talked about identity on the podcast. Mine's a little different in that my children get out of school 230 In the afternoon, I thought I was going to try you know, I'll pick them up at 230 will come home and they'll do their homework. And I'll continue to work. And that that set up like from a very practical perspective, like what can I practically do in the next 90 days, that setup is not working because I hate stopping work at 2pm in the afternoon. Like that's just, you know, you're in the middle of something, I pick them up, and they need to be supervised, like they can't just be free. We don't have a backyard here. So they need to be supervised wherever they are. We live in California, so I want them to be outside. So it wasn't that I was picking them up and having super quality time with them. It was I was picking them up. We were going to the playground and I was just hanging out of the playground. Mm hmm. Like, very practically speaking. So practically speaking, that doesn't have to be me, that can be another person doing that. And so I can get more of a deep work in my work day. And so I hired after school childcare, I found a nanny. She's lovely. She's already started on Monday, and this week has been really great.Michele Hansen 13:04 Oh my god. Amazing. Yeah,Colleen Schnettler 13:06 it's like, it's amazing. And the thing is, I you know, I was really worried about upsetting the balance of my happy family life, children marriage with working more. But that's a fake fear. Because, first of all, if if something starts to get gnarly, and I start to upset the balance, I can always change what I'm doing. And second of all, the kids are at the age, as I said, where they just want to play in the playground. They're not we're not like having some amazing bonding experience after school, or give them a snack, we go to the playground.Michele Hansen 13:38 Does anyone have amazing bonding experiences after school? Like our like, our daughter gets home and she's just so tired. Like that, even like playing a board game is like, Yeah, butColleen Schnettler 13:49 just want to do they? I mean, my kids just want to play with their friends, right? Yeah, I want to do their thing. So. So the two very actionable things, I feel like I'm ready to push again, I think when I was learning to code, building up my kind of reputation as a Rails developer, you and I talked a little bit about this offline. Like, I worked all the time, and it was hard. And then I rested for like four years, like I just it was it was worth it that year to however it was probably two years of like, really intense work was worth it to have the four or five years of just getting paid a lot of money and doing good work, but like mostly being chill. And I feel like I'm ready to push again, is what I'm trying to say with all these words. And to do that, I see that as working. You know, I'm at my desk seven early, like I get here early. So working a long day, and then I'm picking two nights a week to work and I'm going to set those up with my spouse beforehand. So there's no there's no bitterness, or upsetness. Or I'm like, Oh, I got to work tonight. Oh, I got to work tonight. And he wants to hang out. So we've set aside two nights a week I'm going to work and we're going to do this for a month or two and see, see if I can move the needle on things. Just kind of like test it out. Yeah, right. Right. I mean, it's my life. I can Do whatever I want. So I'm going to try it out. I'm going to try I think I've been scared to try. That's the truth. I've been scared to try. Why have I been scared to try? I'm not quite sure. But it doesn't matter. That's what I've, so I'm going to change that up. And commit to working more. That's my goal.Michele Hansen 15:19 Feel like one of the talks that you I think you may be said was the best one that I actually missed? was one on fear.Colleen Schnettler 15:29 Right? Love this one. Do that a little bit? Yes, I'd love to. Okay, so this is a tomorrow's talk. Yeah, he is an executive coach. And he talked about so and I don't like personal development, like, I don't read self help books. Like I kind of roll my eyes at that whole area of study. So I just we'reMichele Hansen 15:53 so opposite. Like, I have like piles of like, books on on your, you're talking to the person with piles of books on like, empathy and boundaries. And like, all these kinds ofColleen Schnettler 16:08 read that I read your book, because I love you. But generally speaking, that's not my jam. So, so I went into this talk with low expectations, not that I thought he would be, you know, not a good speaker, but just like, Okay, I'm not gonna get anything out of this. And, you know, he talked about fear, which everyone talks about, but I thought he was gonna get up there and say, Oh, you have a fear of failure. Yeah, everyone has a fear of failure. We get it. That is not what he said. He got up there. And he talked about three fears. The first core fear being uncertainty. And as founders that's applicable to us, because we become control freaks. And we won't hire. Oh, I'm giving you eyeballs.Michele Hansen 16:49 I see. I see those eyeballs. I, I, hey, you know, whatever. What are the breakthroughs I had, I'm just just saying this in David's workshop on we should really use people's last names because they're so good. Yes. Um, but now if you like, you know, us know them. So anyway, so, um, David's workshop on, like, personal mission statements, but you also don't believe. And I was like, I've had a personal mission statement for 15 years, but also apparently never told anyone. But like doing that exercise with him, where I crystallize the thought that I am building a business, not an organization. And at this point in my life, I don't have the mental energy to run an organization. I love running a business, but dealing with like, people, politics and all that, like I mean, a lot of the stuff that like Rosie talked about, about hiring and people management, like I just I mean, with just managing, like the people in my own house is kind of the level of management that I'm like capable of. Anyway, yes. Not hiring. So that was the fear of uncertainty.Colleen Schnettler 18:03 Well, I mean, there were other things in that, but just generally, with what we do. There's so much uncertainty, and that is also a core fear. So that's something you really have to learn to manage. And I think what you just said about David, David, David's workshop is really good. Because you, you realize that for yourself. And you've kind of always known that, but I don't know if you verbalized it or crystallize it before, in that knowingMichele Hansen 18:26 that way. That workshop was awesome. Like, yeah,Colleen Schnettler 18:29 I loved David's to David sherry. Yeah, everyone. Yes. I love Dave. Oh,Michele Hansen 18:34 good. Yeah, it was basically like, people who are familiar with jobs to be done or who Google things about jobs to be done. The there's like the forces diagram working through the different like, pushes and pulls and anxieties and fears that someone has that keeps them in, in a situation from switching products. We basically applied that to like, our professional lives. And our companies. And it was yeah,Colleen Schnettler 19:01 it was it was really good. Like I was also Pooh poohing the mission statement thing, but it was,Michele Hansen 19:06 it was really, it totally called you out. In frontColleen Schnettler 19:10 of everyone. Thanks. It's fine. We were like a group of friends. By that point. It didn't feel awkward. It was yeah, it was so intimate. Okay, it was so intimate. Yeah. Okay, so the second fear. So this is Itamar. His second fear was worthlessness, which is a second core fear which I think we can all kind of imposter syndrome. And I'm not good enough. And I think we can all identify with that on some level. And the third core fear was abandonment, which is what will people think if I fail, and then he talked a little bit about the ways that we we try to deal with these fears without actually dealing with them, which is obviously a big one is numbing agents and vices, whether that's Twitter or buying things or alcohol or whatever, procrastination And he also talked about the motivation fallacy where if you don't actually handle these fears, you'll like so many of us have gotten in this spurt will actually basically just describe this, but it's like, I'm gonna get it before I am every day. And that's cyclical, like you can't do that forever. So you can do pushes, but eventually that motivation is going to wane. Unless you handle, you know, the, the root of some of these fears. So the solution of this is to minimize your fear and internal resistance. And a lot of people don't do this, because they're unaware that they even have those fears. And that's kind of where I was coming from. Like, he said, these things. I was like, oh, yeah, that that all makes total sense. But I was kind of unaware that those were going on subconsciously.Michele Hansen 20:42 Are there any of those fears that you feel like you really identify with as it relates to this whole?Colleen Schnettler 20:50 I think I mean, I think for me, part of the reason I haven't really wanted to push is like I said, like, I'm very blessed in my, my life is really good right now. So I don't want to do anything that upsets the balance of the happiness that I feel right now. But I think a lot of that too, might be abandonment, and it's not abandonment in this great big, like, I don't care what the internet people think of me. But you know, of my family. Like if I'm going to work more, how is that? What, what are what's going to happen with my relationship with my husband and my children? And those are the most important things. So I think that might have been a core fear for me. Yeah. Oh, man, all of them. Michelle, like and I don't even think I would have been like, I don't have any fears. I'm fine. Before this talk. Uncertainty. That's a big one, too. Because, as you know, as independent as entrepreneurs, we are constantly uncertainty. I mean, it's constant uncertainty, right? Every day, like, what should I do? I don't know what to do. Is this gonna work? Is this gonna work? I have no idea. I have no one to ask. So that's a stressful thing. Like it's not a bad thing. But it is. It's kind of a constant stress. Like, I don't know if this is gonna work. Yeah. So yeah, I took away from it. And I was I was feeling it. I was digging it. It soundsMichele Hansen 22:03 like it was an awesome talk. And I feel like I joined everyone else who wished that they had been at founder summit and having a little bit of FOMO, about missing that. But at the same time, it was like right after my, basically spur of the moment negotiations workshop that I had, like, maybe 20 minutes to plan out in my head during lunch. And I had so much adrenaline after that, that I got through the next talk, which was a great panel on sales for founders. But I like I had so much adrenaline I couldn't sit still. And I was like, I just like I have I have to go like walk like I need to like walk back to the hotel. And I ended up like walking back with some other some other people. And it was like a half hour walk. And I just like really needed that because I was like, jumping out of my skin with energy.Colleen Schnettler 22:57 Yeah, well, you did a great job. I loved your negotiation talk. I learned a lot out of that, too. I don't know if I told you that. Oh, yeah. So it was interesting, because you set us up to do the sample negotiation. It's one thing to talk about negotiation, I think it's another thing to do it. So what's give a quick read, I'll give a quick recap, you basically set us up where we were the person who lived under the person who was a piano player, and the piano player wanted to play his piano every night at 10pm. And we had little children, and we wanted him not to play his piano every night at 10pm. And so I'm talking to the person I'm paired up with. And he's talking about playing his piano. And I immediately just got so angry, and like, I'm not really an angry person. And I like in my head, like, I can see I can see my my mental energy, like rolling my eyes, like, oh my god, he was pretending to be like, 20 right? He was not actually 20 But um, you know, just mentally rolling my eyes like, oh my god, millennials. Give me a break. Stop playing your piano. You're such a anyway. Yeah. So that was really enlightening for me. Because I think I pride myself on like, being very good at having self awareness about my emotions and controlling my emotions. And like, I could not I almost rolled my eyes at him. SoMichele Hansen 24:15 yeah, the the, the sort of setup was it was actually that that activity, we did it in my Danish class. And I was like, this is a great negotiation. Like, it wasn't the purpose of it. But it was, you know, you have one person who's a music student who can, because of their schedule, they can only practice at 10 o'clock at night. But per the apartment building rules, they don't have to be quiet until 11. And then you were the parent whose children are getting woken up. And then you you all had to like talk through it. It was it was really fun. And I think after that I had a couple people be like, oh, like, is this your next book? And like, I'mColleen Schnettler 24:53 like, no, because I'm taking care of my personal health. Not ready to write another book, but okay, that was notMichele Hansen 24:59 the end. answer I gave you like, maybe should have been, why not? No. I mean, like, I started working with teaching people about customer interviews and customer research, like, four years ago, like, because like my friends and I ran a job speed on meetup in DC. And I started talking to other founders about it and stuff like that. So I like before I ever sat down to write, I not only had, you know, years of like, personal experience with it, and personal learning and learning from other people and whatnot, but also years of, of, of learning how to teach other people about it, and what are the common hiccups with it? hiccups? And you know, what, like, like, what resonates with people like all that kind of stuff? Well, before I ever sat down to write, versus like, I don't think I'm nearly the same level of, of expertise in negotiating. Like, I have a lot of practice in it. I've taken classes on it. Like, I guess that was, I don't know, I guess, like 334 years ago now. But like, that was the first time I have ever attempted to teach anyone else about negotiating.Colleen Schnettler 26:19 And what great, did a great job,Michele Hansen 26:21 thank you. Um, but I think I think I need to like a lot, a lot more time before I even get the point of of like thinking about whether that's a book or whatnot, though I am like, I did talk to other people there, who are also interested in like enterprise sales and negotiating and stuff like that. And so we actually will have some people on in the coming months, who will, we'll kind of like, talk more about that stuff. Because I think that's a big part of kind of going from, you know, the sort of stage you're in which I feel like is sort of like the under 10k a month, Mr. Phase, going 10 to 20 is really like for me, it was a lot about learning how to do sales, and definitely going from like, 20 to 50. Like you. I don't think I would have gotten to that point. Had I not had a better understanding of sales and negotiating. Yeah. So, so, yeah, I'm gonna I'm going to talk more about that. But But no, like, no book yet. I still haven't even hit your like, 20 podcast goal for promoting deploy empathy, like you're doing? Well,Colleen Schnettler 27:35 I think you have been on quite a lot. 10 or so. Okay. 12 IMichele Hansen 27:40 think I just recorded another one. The other day, I think, yeah, I just did one yesterday. And then I have two scheduled. Nice, I need to like have a spreadsheet and keep track.Colleen Schnettler 27:57 Yeah,Michele Hansen 27:59 um, you could do that. I could. Yeah. That would make sense. It's getting weirdly hard to track how many books I've sold, because like amazon online will only show me 90 days at a time. So I can't just go and like see all that's weird sold. Like I maybe again, if somebody like knows about this, like, let me know. But I'm in like the KDP reports dashboard. And then the reports beta and like, I sneak looks like I might need to like do it manually? Or at least like by month. And then. Yeah, so I don't I don't know. I'm also starting to give some more like, like, sort of private workshops with the book, like, I'm going to be speaking to an MBA class tomorrow online. And a friend asked me if like, I would speak to their marketing team, like do like a workshop. So we'll kind of see how that goes. I don't think I want to go too much in that direction. Like I don't want to be like, you know, selling like a day long workshop thing. Like we've talked about how I really don't want to do consulting,Colleen Schnettler 29:05 right? You have mentioned that a few times.Michele Hansen 29:10 But like maybe doing a workshop and you know, then they buy like 50 copies of the book. You know, I guess I'm cool with that.Colleen Schnettler 29:15 Yeah, seems like a good use of your time. If you enjoy it.Michele Hansen 29:19 Yeah, but I think I you know, I think for me, the big thing is like what does balance even mean? I mean, I I don't know.Colleen Schnettler 29:29 Yeah, I understand the question. But I think it's James clear has this really interesting thing about the how balance isn't a real before burners theory, the downside of work life balance. Have you seen this?Michele Hansen 29:44 Oh, that sounds familiar that like you have one burner going and then you can't have Okay,Colleen Schnettler 29:49 ready? Here it goes. four burners like your stove. The first burner represents your family, the second burners, your friends, the third burners, your health, and the fourth burner is your work. The four burners theory says that in order to be successful, you have to cut off one of your burners. And in order to be really successful, you have to cut off to anyway, here's a whole article about it. It's an interesting, interesting idea. But the idea is there isn't a real thing such as balance, there are times where you shift your focus. Like, for example, you this would be a good time for you to shift your focus from work, because you've been working so much for 610 years, to maybe health or whatever it would be right. And maybe it's time for me to shift my focus back to work. But the idea is, it's like, you really can't have balance. It's a lie. You can just have, you know, areas that are shifting and priorities. I can't have everything on five. Right, right, exactly. You can't have everything on five. Yeah. It's kind of interesting. And it kind of makes us all of us who are so hard trying to find balance a little bit better, because you're like, oh, okay, this sounds about right. This seems reasonable.Michele Hansen 30:56 Yeah, I guess. I mean, he's the habits guy, right. Like he's the habits guy. Yeah. So I guess I need to finally read that book. So yeah, so So that's our 90 day plan. Right? So you're gonna Yeah, you've got my herd nanny now. I mean, always, you've got your plan in action.Colleen Schnettler 31:17 I'm an act and I'm gonnaMichele Hansen 31:19 continue marinating. Oh, my God, it sounds like you. You were like, I'm gonna read more about this and think more. Like, I was like, I'm gonna do this now. Already done. I did it before I talked to you. Yeah, happening?Colleen Schnettler 31:38 I know, right? It's good, though, right? Because we both have, it's good, I guess. Yeah, I'm already in action. I've already posted more content. And I am making a video tutorial page. And I'm doing all kinds of things. And oh, the only thing I really got out of it, Michelle was a real focus, thinking more long term. So I think one of the things is we met a lot of people who have been running their businesses. I mean, I know you're kind of in this group. But I've been running their businesses for many, many years. And there were many people I met who aren't really trying to have some big exit, like they want to build a sustainable business that they can work on for as long as they want. And so that really helped me focus in terms of like thinking about where I want to spend my time and my energy and what I want my long term outlook from, like, for my career to look like? So I found that to be really beneficial.Michele Hansen 32:33 Was there any, like insights that you feel like are? Yeah, I think his point,Colleen Schnettler 32:39 what I found is, so I told you, I'm going to I'm really gonna push on simple file upvote, simple file upload for the next three months, simple file up vote, that sounds interesting. For the next couple months to kind of see what I can do with that if I really work at it. But I think long term, I am more interested in pursuing the opportunity, like really leaning into what to the Hammerstone team. Because when I think of the long term business I want to build, I can't think of anything better than doing really technically challenging work with my friends. Like I love as we've talked about when I joined Hammerstone, like I love having co workers or co founders. And that's really where I want to go. Right now I'm doing okay, splitting my time. But that's not sustainable in the long term. So I'm not sure what that looks like in a year. But it looks like my focus being more on Hammerstone. I thinkMichele Hansen 33:29 something else we talked about was, you know, the fact that you like you guys are funded for a year. And like the fact that you are funded for a year made you feel like you can take a year to get some stuff done, and how you can get more than that done in a year, too.Colleen Schnettler 33:51 So Jimmy from banal got up there talking about this was a founder summit about how to sell something that doesn't exist. Now his product is very specific, and it was very targeted was, you know, targeted to a very specific group of people. But I am not doing so I don't have the rails component for this query builder that I'm building with Hammerstone. But I also haven't really been doing anything to get the word out about it. And so yeah, we're funded for a year and I feel like the work is filling the time allotted. And the work doesn't necessarily need to fill the time allotted. I think I could be a little more efficient and a little more focused. Not that I'm not focused just there's more I could be doing on the Hammerstone side that I'm not and so it really kind of opened my eyes to like there's a lot of other opportunities here. You could get a content machine going now even if you can't sell it for six months, I could be writing articles about all this really interesting sequel stuff I'm doing whatever it may be point being like there's there's things I can put in place earlier. You know, as as I build this component,Michele Hansen 34:52 you know, hearing you talk about like it being time to push it almost. I feel like you're conceptualizing it as like this, like, switch, you can flick, like that, like, Okay, now like now you're gonna push like, do you feel like that is? How it's gonna work? So IColleen Schnettler 35:15 don't know, but a little bit like, let's go back to simple file. I've been a little bit mopey about it, what should I do? What should I do on Monday? Like, I know exactly what to do, right? It's like, I haven't been really trusting my own intuition here. I've been asking for permission or advice. And these are all good things. Advice is good. But why am I asking people for? Like, I want someone to say that's a good idea. Colleen, you should do that. No, I don't need it. It's my business. I get to do whatever the hell I want with it. So, you know, people like you shouldn't do this. You shouldn't. Um, I Okay. I appreciate everyone's advice, and I solicit it. But also, I think I you know, I just really, it's a very small product still, like, I'm just going to go with my gut. And I'm just going to do what I think is best. And I haven't really been doing that, because I have been so careful about overworking myself, I guess.Michele Hansen 36:06 And so I feel like that that I mean, that comes back to that like fear that we talked about, like waiting for somebody else. To say that your plan of action. Your idea is your decision. Good was a good one. Yes. subjective opinion, to massage your fear. That yes, it was totally and is that like, you know, uncertainty about the about the decision or all these other things? I don't know.Colleen Schnettler 36:36 Yeah, no, totally. I think for me, I'm really worried about making a decision that is going to be a waste of time. That's what it's about. Because my time feels so So, so limited. So I'm like, should I write this article? Is this article worth writing? Like, if it's gonna take me three hours to write it? Is that going to be worth it? Right, I just wrote the freakin article on the airplane home for Mexico. Oh, while I was stuck in DFW for 12 hours and then and then flew to a different city and then bus to my city that I actually live in the graveyard.Michele Hansen 37:03 Both took both of us 14 hours to get home yet I went across like, two continents. Oh my goodness. But also it was a bazillion times worth it to travel 14 hours to and from to be there.Colleen Schnettler 37:18 And I think something else. Speaking of founders comp, being amazing. The quality of everything was just so much better than your typical tech conference. OhMichele Hansen 37:26 my god. Yeah,Colleen Schnettler 37:27 everything was better.Michele Hansen 37:28 The food was amazing. The venue like I loved how I mean, you were saying how like a lot of conferences, you're just in the hotel. And we were like, out and about in the city like everything all over the city. And it was such a cool city too. And I feel like we really got to experience like culture and and just in a way that yeah, you're you're not just like stuck in a hotel ballroom for three days.Colleen Schnettler 37:51 Like, okay, so this is not a dig because I love rails comp. But I remember it was the last rails comp I went to before COVID. They're like, Oh, it's in Minneapolis. Minneapolis is a great city, blah, blah, blah, literally, you stay in the hotel, and then you walk through the breezeway to the ballroom, you never go outside, ever. And point being like yeah, of course, you can go outside but, but all of the activities are like you you never leave it you don't ever have to leave the hotel. And so I loved how founders comp really made an effort to get local venues, support, you know, local businesses, and actually see Mexico City loved it.Michele Hansen 38:29 I I really, really hope they have it in Mexico City next year. Like dude,Colleen Schnettler 38:33 I hope we get to again get in because there's going to be freaking every one is going to want to go it's going to add the fight to the death and who gets to go. Geez.Michele Hansen 38:45 Well, I think I think that about wraps up our recap, though. I feel like we're gonna be talking about this. And like, Oh, yes. So many learning summit for a long time. Yeah, so many learning, and also having people come on the show who we met at founder Summit, and no, and no three founders Summit, too. Because there's also the the online community, which you should totally be in a mastermind group, by the way.Colleen Schnettler 39:13 Yeah, I'm thinking about that. Like, I, I think that's probably a valuable thing. I'll probably do that. And IMichele Hansen 39:18 think that would help with you're like, Should I do this? And then people are like, yeah, and you're like, Yeah, okay.Colleen Schnettler 39:26 I feel like a lot of this is just trusting your gut, which I'm usually pretty good at. But like, with the business since it's all new, like I just haven't really just been doing what I think is best. Like I said, I've been asking permission just to random people, which is kind of weird, because I don't want to make a huge misstep. But the truth is, all of these things, none of them are going to be huge missteps and they can all be changed if it's a bad decision. So so that's really this week. I've been crushing some life, but by work work, is what I mean by that. Like, I've just been like, I've been I've just been like really crushing it and it feels great. SoMichele Hansen 39:58 it's awesome. Awesome well so next week I interviewed Matt wensing was super fun so then we will chat again in two weeksColleen Schnettler 40:12 sounds great talk to you then
[00:00:32] Andrew tells us they shipped a new project at work this week they've been working on for a few months, and although it went pretty smoothly, he explains some bumps they had along the way and dealing with crunch time. Chris shares an issue and why he's been postponing the launch of the new Hatchbox. [00:04:13] We hear more about propagating the DNS and how long it took.[00:08:28] Andrew mentions using the Proxyman app and what it does. [00:09:15] Chris tells us about his new Mac, and he can't believe how fast it is![00:13:56] Andrew talks about some issues with installing Ruby 2.6.3 and building things in Docker on a new M1 Mac that a developer on his team just got.[00:17:24] Chris explains his upgrading issues on an older app he was working on this week and realized it was a Sass change he made. Ironically, Andrew ran into something very similar with Sass as well. [00:20:57] We hear about the Ember CLI Rails gem and Chris brings up that there is no solution on how to take an abandoned project like this and just keep maintaining it and he wishes there was a better solution. [00:25:43] Andrew mentions every time you add a gem, you need to be aware of the amount of code debt you will have, and he shares what happened to him when he was a beginning developer. Chris explains why he would rather build it from scratch in the app to tailor it to exactly what they need. [00:29:48] Chris announces a new GoRails Screencast coming up with Kasper and what they'll be talking about.[00:35:25] Find out more about the awesome and very thorough tutorial on “Deploying a Rails application to Kubernetes” that you should check out! [00:39:25] Chris and Andrew chat about the importance of being Rails Developers and not working on DevOps stuff. Panelists:Chris OliverAndrew MasonSponsor:HoneybadgerLinks:Ruby Radar NewsletterRuby Radar TwitterProxymanGlassWireGoRailsGoRails-YouTube SassDeploying a Rails application to Kubernetes-By Marco ColliEmber CLI Rails-GitHubRubyConf 2021
Summary On this special episode of COMMERCE NOW, Steve Kremer, Director of Sales in the Payments division at Diebold Nixdorf, and Sarah Grotta, Director of Debit and Alternative Products Advisory Service at Mercator Advisory Group, sat down with PaymentsJournal to discuss the most popular payment method, both in the United States and globally: Debit. Listen in for a discussion of why modernizing debit payments is crucial in both the banking and retail sectors. Related Content: https://www.dieboldnixdorf.com/en-us/banking/insights/blog/get-your-message-out https://www.dieboldnixdorf.com/-/media/diebold/files/banking/insights/qa-faq/mindshare-payments-innovation.pdf Related Links: https://www.paymentsjournal.com/the-time-to-revitalize-debit-rails-is-now/ LinkedIn Profiles - Steve Kremer Sarah Grotta Transcription: Speaker 1: On this special episode of COMMERCE NOW, DN Steve Creamer, Director of Sales in the Payments Division joins the PaymentsJournal's, Ryan Mac, for a discussion on why modernizing debit payments is crucial in both the banking and retail sectors. Speaker 2: Welcome to the PaymentsJournal Podcast. In here is your host, Ryan Mac Ryan: Welcome to the PaymentsJournal Podcast, I'm your host Ryan Mac. Now, debit is the most popular form of payment in the US and globally and it is influenced by the growing popularity of digital payments and preferences of millennials. Now, it is projected that debit transactions will continue to grow and remain the highest transaction type of consumer payment. Now, modernizing these payment systems will become table stakes. And solutions that have reusable technology that can support multiple channels are key when implemented in phases, especially when starting with one that has the high rewards and low risks, AKA debit. To unpack this further, I'm joined by Steve Creamer, who is the Director of Sales for the Payments Division at Diebold Nixdorf and Sarah Grotta who is the Director of the Debit and Alternative Products Advisory Service at Mercator Advisor Group. So, there's certainly a lot of information to unpack on today's episode. Ryan: So, without any further delays, let's start the show. So, Steve and Sarah, it's an absolute pleasure to have you on today's episode. And I'm really excited to talk about our subject to hear today that's really focusing around debit because of all of the interesting news and statistics that we've started to see come out of just the debit side of the paintings' ecosystem here. Now, to get our conversation started here today, we've got this fantastic chart provided to us by Mercator Advisor Group that's taking a look at MasterCard and Visa Debit and prepaid volumes versus credit and charge card volumes in the United States. So, Steven, if you could, maybe you could kind of unpack this chart for our audience here today and maybe pull out some of the kind of the key highlights or what you find interesting of what this data is representing. Steve: Thanks, Ryan. In seeing this data, I really had to pause for a moment and let this information sink in. It certainly is very interesting that in United States, the dollar amount spent with debit cards increased by 14% in 2020, and also that debit card transactions continued to outpace credit cards two to one, the terms of number of transactions. We may all have our own personal bias on preference between debit and credit and some of us may have a preference for using credit over debit for certain types of transactions, but we need to be careful not to our own views, to administer relevance of the data on the continued strong debit usage. Steve: Did the impact of the pandemic and stimulus money have some impact on increase of debit usage in 2020? I think it did, but I also think that the pandemic also accelerated the consumer migration to digital payment channels and debit is still the most popular form of retail payment, and it's not going away at any time soon. Once you really look at the information that Sarah summarized so well, it really makes a lot of sense, especially when including the influence of younger generations that are growing in importance and how debit is leveraged on a global basis. Close to 83% of younger consumers use a debit card and not credit and that's understandable at their age. Many may have not had the ability to obtain credit, and they also seen or heard so many negative stories about how credit card debt that they formulate a consumer behavior outside of credit usage. Steve: Given the high percentage use of debit now, and with the ever-growing payment e-commerce options, we can really see why debit usage continues to grow. An important note is that the continued popular debit is by no means unique to United States. For instance, in India, I think there are 900 million debit cards versus only 55 million credit cards. And in Europe it varies by country, but debit continues to make a very, very strong showing. From a consumer convenience standpoint, we can see the advantages of using debit over other payment rails. And then finally for the retailer, there are real economic advantages of debit based processing solutions as debit interchange fees are typically much lower than for credit cards. I think at this point, it probably be good to turn over to Sarah and allow her to provide some additional insights into her report. Sarah: Yeah. Thanks so much for that. And really, I liked your overview, particularly the comparison with other countries. Certainly, I think the US is somewhat unique in its history, its legacy of being very credit card-focused that isn't necessarily the case around the world. And certainly, things like the economics play into that. The fact that particularly in the US, we really, really love those credit card rewards. So, it was kind of interesting, I agree, I think this was really pushed by the pandemic when we saw the debit card volumes for the first time tip over in above the credit card numbers. And let me clarify, looking at this chart, that we are looking at debit card purchases. We did make some calculations to extract some of the debit push payments, right? So, that would be MasterCard send or Visa Direct. Sarah: So, we're really looking at something closer to an apples-apples comparison of just debit card purchases from MasterCard and Visa in comparison to what's happening on the credit card side. So, I think as we look forward and as we start to see purchasing habits maybe coming back to something that looked a little bit more like pre-pandemic patterns, so more things like purchases for eating out purchases, for travel in particular, I think that we'll start to see the credit card numbers start to come back up again. But I do think for many of the reasons that you pointed out Steve, I think that we will still continue to see very, very strong debit card growth for the foreseeable future. Ryan: Steven and Sarah, thank you so much for that. Now, to kind of just recap a lot of what was said there, obviously historically, in the US we have seen debit cards outpace credit in terms of transaction volumes. But also, then as we were kind of pointing out, in 2020, we did see that percentage gap changed dramatically with debit card volume seeing that 14% growth over 2019 numbers. Now, Steven, as you pointed out, I think that there's a fair amount of that double digit growth was related and due to the pandemic. And as Sarah kind of stated there at the end that she foresees this growth in debit being a continuing trend. But beyond the pandemic, are there other reasons that you could kind of sight or maybe glean to, of why it is that debit may remain a preferred payment method of choice for consumers? Steve: Yeah. Ryan, I think that's a great question. And in that, I think it's always important to keep the customer experience in the forefront. And the thing about debit is that it's a 24/7 always-on experience. Consumers expect to seamlessly get cash out of, if they're using an ATM or if they're making a purchase, they expect it to be approved right away. And that's true if it's in-person or if it's a debit being used online. As noted in Sarah's report, 40% of debit transactions, I think in US were made in a card-not-present mode. So, consumers want to make sure their cards and data are safe and that they can quickly pay for what they want. But what we're hearing from our customers, both banks and retailers, but primarily the banks, are that the debit networks are being challenged with new payment types and they're spending a lot of time and money on the overall upkeep and maintenance of their debit networks. Steve: As you know, the debit system has been around since the early 1970s and many of the systems that are used to process these cards have really not changed since, or if they have, it's been for band aid updates for their old technology. Legacy debit payment platforms were designed to quickly and securely approve and process of payment or withdrawal, which has always been authenticated with a card. The future payments is not so straightforward. The method of authentication may be different based on the channel, for example, tokens, biometrics, things like that. And the funding could combine payment methods including 'buy now pay later', or other variations. Modernizing this payment infrastructure, and not necessarily just the debit side, is really the key for banks to remain relevant. Steve: Diebold Nixdorf has been a global leader in the processing of debit-based solutions for the last 40 years. And now we're leveraging this experience with our Vynamics payment solution. Vynamics payments is a modern system that it's built using cloud-native technology and microservices architecture that allows banks and processors to not only improve their debit channel, but quickly and efficiently handle other newer payment types and innovations like request to pay and buy now pay later. Which is where we see things moving, will help kind of perpetuate the predominance of debit going forward. Just time out. I'll turn it back over to Sarah for her insights on that same question. Sarah: Yeah. I think that the whole idea of core and payment modernization is really very interesting. And sort of tying that back to debit, it is kind of interesting even though to your point, debit has been around for a really long time. There are still things that we can do as an industry to improve that user-experience, that kind of dovetails into the ideas and concepts around modernizing the infrastructure. So, I talk to issuers about things like making sure that they can digitally issue debit cards as an example, so that they could really make that seamless transition for immediate account acquisition or provide a really great experience should a debit card ever get lost or stolen, or for whatever reason needs to be replaced. So, I think that's a very interesting part of the payment ecosystem right now, is sort of the intersection of things like debit cards and more modern infrastructure. Ryan: Yeah. So, I think that it's really interesting. And one of the keywords that I kind of hear a lot is that the modernization side of things here, and obviously as we continue to look as Sarah pointed out to kind of add enhancements to kind of really improve that consumer experience here. And then Steven, at the end of your commentary, you had broadened up a little bit about your organization, Diebold Nixdorf here, and how it's kind of going through a little bit of modernization here and what it's doing to help their consumers. So, I want to dive into that a little bit more because I think it's certainly fine to talk about it at a high level, but I really kind of want to get into some specifics. And with your insight into the industry, maybe you can give us a few more examples of what you're seeing that your customers are doing to revitalize kind of their debit rails, so to speak. Steve: Yeah, that's a great point, Ryan. Thank you for asking. Really when, when Diebold Nixdorf set out to develop our next generation payments platform, we try to approach payments with a fresh perspective. We ask where would it make the biggest impact and provide the greatest opportunities for our clients? And as you ask, as an example, we recently began a multi-year, multi-phase implementation with a top 10 US bank. This bank is using Vynamic payments to deliver substantial TCO benefits to their organization. They are currently using our terminal software as well as our device handling in the Vynamic's platform for approximately 16,000 ATM's. And the bank has also started to deliver on their roadmap to provide switching and cloud processing as the next phase in their migration to Vynamic payments. Steve: And by doing this, they're taking a modular multi-phase approach and we have successfully maximized their greatest opportunity, which in their case started with the debit rails. And now, we have laid a foundation to scale for the future. In the age of technology, limitations on handling the current demand of transactions and the expense for trying to keep it up-to-date has oftentimes made the debit network the best place to start. And at Diebold Nixdorf, our cloud-native microservices architecture has enabled new functionality, such as handling the card-not-present transactions and digital wallet-based transactions. Steve: We also add the ability to reuse certain components or services such as authorization, routing, and authentication, that provides a single platform that can easily transition to credit or real-time payments or other payment rails. It's truly a build once but use often design that will reduce over-operational costs and pre-speeder market for alternative payment methods. And I'll turn over to Sarah for her perspective on that. Sarah: Yeah, actually, I think I've got another question for you given those comments, if you don't mind. I hear a lot of financial institutions in particular, talking about the need to modernize their technology infrastructure so that they can be more responsive, particularly at the user-experience layer, thinking about things like breaking down silos to better manage data and better manage data for fraud. But when financial institutions are thinking about modernizing their infrastructure, do you see that payments is often an instigator for a lot of these modernization demands or the idea that financial institution wants to move forward with a modernization project? Steve: Sarah, I think it does. And I know I threw on this term 'build once, use often' is kind of a code word for modernization, and it does sound simple enough to build once and use often. However, really the benefits are very, very powerful and widespread. As we talked about with mobile and contact-less payments, continuing to grow and support for QR codes, digital currencies, request to pay and peer to peer payment applications are added, many larger banks are opting to build separate in-house silos to process these new payment types. And given the large number of dedicated channels that are required to process this vast array of payments, it quickly becomes a very complex undertaking that generates significant cost to support. Steve: Meanwhile, smaller banks are tackling the same challenge by outsourcing services to vendors. While this may work in a short term, it too, can become very expensive and really stifles differentiation and creates barriers to innovation with this 'build once, use often' as the goal to consolidate these single use channels by deploying a payments platform, it is built with the microservice architecture and API connectivity. These platforms really do enable banks to realize the desired end state of building once, but using across multiple payment rails. And to be a bit more specific, if a bank's priority is to start with the modernization of their debit platform, which is part of our topic today, and by the way, often is a logical place to start given that 1st Generation debit payment platforms are quite cumbersome and channel specific. Steve: And really these older debit platforms are edging closer to critical [Inaudible], and effectively the end of life. There are many ways that 'build once, use often' methodology yields significant benefits to the deploying institution. And some examples of that is to add credit to the same system that's used for debit, the settlement and clearing services can really be reused. Another example is in the fraud area where fraud mitigation and some of the limiting safeguards can be implemented once and then used often across multiple channels. Steve: So, with Vynamic payments, we're able to later on the promise of 'build once, use often'. And Diebold Nixdorf is really kind of moving digital payments processing to a new era, introducing an open APIs integrating with best of breed FinTech solutions across banking and retail, and really delivering seamless customer-centric journeys on a state of the art platform. So, quite simply, it is a great time to speak with Diebold Nixdorf about the future of retail payments. Ryan: Excellent Steven, I think that was absolutely fantastic. And I think we'll end it there on that note. Oh, so, Steven, Sarah, thank you so much for taking the time today for speaking to us about the debit rail here and also the very interesting consumer changes that we've seen in the industry of the debit versus credit. And I hope to have you both back on the podcast real soon. Steve: Pleasure. Sarah: Thanks Ryan.
Jorge Manrubia is a Security developer at BaseCamp. He discusses the encryption features added in Ruby on Rails and explains where they fit into the ecosystem for Hey.com. The panel jumps in to help discover how to help raise the privacy bar for your Ruby on Rails applications to protect personal and private information. Panel Darren BroemmerJohn EppersonValentino Stoll Guest Jorge Manrubia Sponsors Dev Influencers AcceleratorLevel Up | Devchat.tv Links GitHub | attr-encrypted/attr_encryptedThings to consider before using attr_encryptedOpenSSL::CipherGitHub | chaps-io/public_activityJorge ManrubiaJorge ManrubiaGitHub: Jorge Manrubia ( jorgemanrubia )Twitter: Jorge Manrubia ( @jorgemanru ) Picks Darren- More Ruby MagicDarren- Java Creator James Gosling InterviewJohn- CalendlyJohn- GitHub | chaps-io/public_activityJorge- GitHub | whitequark/parserValentino- MJML, a parser, and a template engine for Ruby - Isabelle LafontValentino- If you maintain open source software as part of a team, we'd like to give you free @tuple for life!Valentino- GitHub | codenamev/.pryrc Contact Darren: Twitter: Darren Broemmer ( @DarrenBroemmer ) Contact John: Rock Agile ConsultingGitHub: John Epperson ( kirillian )LinkedIn: John Epperson Contact Valentino: Doximity Technology BlogWork @ DoximityGitHub: Valentino Stoll ( codenamev )Twitter: V ( @thecodenamev ) Special Guest: Jorge Manrubia.
Jorge Manrubia is a Security developer at BaseCamp. He discusses the encryption features added in Ruby on Rails and explains where they fit into the ecosystem for Hey.com. The panel jumps in to help discover how to help raise the privacy bar for your Ruby on Rails applications to protect personal and private information. Panel Darren BroemmerJohn EppersonValentino Stoll Guest Jorge Manrubia Sponsors Dev Influencers AcceleratorLevel Up | Devchat.tv Links GitHub | attr-encrypted/attr_encryptedThings to consider before using attr_encryptedOpenSSL::CipherGitHub | chaps-io/public_activityJorge ManrubiaJorge ManrubiaGitHub: Jorge Manrubia ( jorgemanrubia )Twitter: Jorge Manrubia ( @jorgemanru ) Picks Darren- More Ruby MagicDarren- Java Creator James Gosling InterviewJohn- CalendlyJohn- GitHub | chaps-io/public_activityJorge- GitHub | whitequark/parserValentino- MJML, a parser, and a template engine for Ruby - Isabelle LafontValentino- If you maintain open source software as part of a team, we'd like to give you free @tuple for life!Valentino- GitHub | codenamev/.pryrc Contact Darren: Twitter: Darren Broemmer ( @DarrenBroemmer ) Contact John: Rock Agile ConsultingGitHub: John Epperson ( kirillian )LinkedIn: John Epperson Contact Valentino: Doximity Technology BlogWork @ DoximityGitHub: Valentino Stoll ( codenamev )Twitter: V ( @thecodenamev ) Special Guest: Jorge Manrubia.
Chris regains several of his developer merit badges and embarks on a perilous CSRF (Cross-Site Request Forgery) adventure. Steph shares highlights from Plucky, a management training course, including ways we can "click" and "break apart" from our current role, and how to have hard conversations. They also discuss how software development processes change at different team sizes, processes that break down as teams grow, and processes that are resilient at any team size. This episode is brought to you by ScoutAPM (https://scoutapm.com/bikeshed). Give Scout a try for free today and Scout will donate $5 to the open source project of your choice when you deploy The Nightmare Before Christmas - What's This (https://youtu.be/QLvvkTbHjHI) Giant Robots Smashing into other Giant Robots - Plucky with Jen Dary (https://www.giantrobots.fm/search?utf8=%E2%9C%93&term=plucky) Plucky (https://www.beplucky.com/) Services are Not a Silver Bullet (https://thoughtbot.com/blog/services-are-not-a-silver-bullet) Become a Sponsor (https://thoughtbot.com/sponsorship) of The Bike Shed! Transcript: STEPH: Boom. I'm recording. Magic is happening. [singing] What's this? What's this? It's a Bike Shed episode. What's this? What's this? CHRIS: You did that on the mic. [laughter] So you just started recording too, so it's not like you're like, "Oh, I forgot I was recording." STEPH: Oh, I didn't have a finishing line that rhymes with shed. CHRIS: Head, dead, bread, spread. STEPH: [singing] Is TDD dead? I don't know. [laughs] CHRIS: Cool. I liked it. STEPH: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Steph Viccari. CHRIS: And I'm Chris Toomey. STEPH: And together, we're here to share a bit of what we've learned along the way. Hey, Chris, what's new in your world? CHRIS: What's new? I had a fun experience over the past week or two of regaining some of my developer merit badges, which is always enjoyable. So one was I had to configure AWS, specifically S3 and IAM such that I could upload files to an S3 bucket, which seems like one of those things that a developer should be able to do, and it's just not that hard. And, man, I failed so many times, and I stared at the screen. And the ARNs I think that's another acronym that I had to try and figure out what it means and fight against. Anyway, I got there. So that's one merit badge earned. I really hope [laughs] I correctly and securely configured access to an S3 bucket such that we could upload files in our Rails app. Cool, neat. Moving on, the next merit badge that I went for was restoring the sea of green dots. Our RSpec output had gathered some noise. There was a whole bunch of noise across a variety of things. There were some dev tools that were dumping some stuff in there. And there was something related to apparition, which is the...I want to say it's the Capybara feature spec driver that we're using now, which sits on top of ChromeDriver or something like that. I don't really understand the details, but it was complaining about something. And I found a fix, and then I fixed it and whatnot. But it was one of those. I did this on a Saturday because I was just like, you know what? This will be cathartic and healing. And then I got to the sea of green dots, and I was so happy to get to it. STEPH: This is me...I'm giving you a round of applause. CHRIS: Well, thank you. Arguable whether it delivered any real value to users, but again, this was Saturday effort, so I was allowed to indulge my fastidious caretaker of the code role. STEPH: Sorry, before we move on to more serious, can we pause to talk about developer merit badges? I really, really want cute felt badges that we can...I mean, I can't design them. I don't have the talent. But I think between us and other folks, we could design amazing merit badges, and then people could collect those. I'm very much in love with that idea. CHRIS: I love the idea. I am now certain that if we were to really pursue this, that we would fall into the deepest of bike sheds as we try and define well; what are all the merit badges? And what are the different levels? STEPH: [laughs] CHRIS: And how many do you need to collect before you can get to what are the different...There are just so many different taxonomies that we could introduce, and, oh man, I could spend a couple of weeks on that. STEPH: [laughs] It has a very strong Pokémon vibe too of you got to catch them all. CHRIS: Absolutely. STEPH: Okay. All right. We won't digress into bikeshedding merit badges, but I'm still very, very interested in that idea. CHRIS: Indeed. If anyone out there in the listener space wants to just make these, that would be great. This is the way that I avoid bikeshedding now is I just say I'm not allowed to make these decisions or even think about it. But if these happened into the world, I would be happy about that. STEPH: Oh, I just remembered we do have something similar at thoughtbot. They're not physical where you can hold them, but I think we've talked about turning them into physical badges. But we have our internal tool hub that we used to track our schedules. And one of the fun Ralphapalooza events that we had, a team came up with the idea of introducing badges in the tool hub, so then you could award people badges. You could give people badges. And it's very cute. So they could probably help us with the taxonomy. They've probably already figured out a number of badges we could get started with. CHRIS: And of course, this is where my brain went initially to like, oh, what would the taxonomy be? But I think that's how this goes bad. And if we just keep it in the this is cute and fun, and what are all the possible merit badges, but they're all equal, and the points are made up anyway, and then it's just a fun thing, then I'm like, I'm super into this. Let's do that. Have you used a regular expression to parse HTML? Congratulations, you get a merit badge. Have you not used regular expressions to parse HTML? You get a different merit badge. [chuckles] STEPH: [laughs] I feel very positive that I could be chief of cute and fun. I could manage that department. CHRIS: Yes, that feels like definitely a role that you could really excel at. But shifting around ever so slightly, I did run into a fun bug this week. And it was a mystery tour of, I'm going to say, sadness and then eventual learning and understanding, and I think we've come to a better place. But I want to tell a story, take us on a quick tour of the adventure that I went through. So we recently saw a handful of exceptions come through in our exception monitoring service and then piped into Slack, where we see those around CSRF token expiry. So this occasionally happens in a Rails app. The CSRF token that was on the page gets rotated. And therefore, when someone...if they have an older version of the page open and they try and submit a form or something like that, then CSRF protection is going to kick in. And you do get some false negatives there or some cases where like, nope, this is actually a fine user, this is not hacking, this is nothing bad. It's just that that user had a tab open or something like that. I'll be honest; I want to understand better the timeline of expiry and how Rails expires those and whatnot. But it's one of those things; it's deep enough in Rails that I trust that they are doing a very reasonable thing. And I think the failures that we're seeing that's part of the game. And so, mostly, we wanted to add a nicer handling around that. So thankfully, Inertia actually has a really wonderful page in their docs about handling Cross-Site Request Forgery expiration token, this whole thing. This is a particular failure mode that your app might have. And so it's nice to be able to provide a nicer user experience. And so what we ended up doing is if we catch that exception, we have a rescue_from in our application controller that will instead of having this be a 500 and just a full, like, something went wrong error page, we instead respond in an Inertia-like way to basically show a flash message that says, "This page has expired. Please refresh the page to continue." And if the user just refreshes the page, then they will get a new CSRF token. And from there, everything is going to be fine. So it's not ideal. But it is, I think, both secure and now a nicer user experience. STEPH: Yeah, that sounds really nice. When they refresh the page, do they lose all that form data? I'm curious how painful of a flow that is for the user. CHRIS: Currently, yes. Inertia actually has a really nice feature for remembering form data. If you've ever been on GitHub and you're filling in a box, and then you go away to a different tab, and you come back, and it's still there, and you're happy about that, it's that sort of thing. So we could configure that. At this point, we don't have...most of our forms are pretty small. So this is not something that we opted to do proactive management around. But that is definitely something that we could add but not something that's default or anything like that. STEPH: Cool. Yeah, that makes sense. I was just curious because yeah, either small form doesn't really matter, or also, this may be just a small enough error that only a handful of people are experiencing it that it's also just not that big of a deal. CHRIS: Yes, this definitely should be an edge case. And we've also recently been working on functionality to log folks out after a period of inactivity, which would also, I think, obviate this in a different way. So all total, this shouldn't be a big deal. And this was basically a quick, little snippet of code that we thought we could just drop in, and everything would be great because it shouldn't happen much. But then I was testing out a different feature on staging, and everything I tried to do was popping up this little alert flash message that was like, "Hey, your page is expired." And I was like, that seems bad. And then I realized literally every action, any non-GET request, was getting this response that the CSRF token didn't match. And I was like, well, this seems bad. Luckily, it was only on staging and hadn't made it to production. But it had made it to staging, which meant it had gotten through CI, which was very concerning because we have a pretty robust set of feature specs at this point. We built up a bunch of fakes for all of the external data systems that we're interacting with. And we're really putting the app through its paces and trying to do so in a very production-like way. And so I was like, this is such a deep fundamental breakage. I don't know what's going on here. And so I started to investigate. And it turns out that in a recent commit, I had started using Axios, which is a little wrapper around the Fetch API. They may not actually use the Fetch API under the hood, but it allows you to have a nicer interface to make XHRs. And we implicitly had that in our package already by virtue of Inertia. Inertia uses it under the hood, but I wanted to make it explicit because now I was using it directly. So I figured that's cool. I will yarn add Axios, and then I will continue on with my day. And I worked on my feature and everything was great. And then I pushed it up into a pull request, and everything was great, and CI passed. And I got it onto staging, and everything was very sad. So then I started on the adventure of like, what is going on here? It turns out that somewhere between version 0.21.1 of Axios and 0.23.0, which there's a bunch of things about those version numbers that make me uncomfortable but here we are, somehow the behavior where you can configure the XSRF header name, which is what they're calling it on their side, the configuration stopped working. And so our override that says this is what our CSRF or XSRF token should be called when it's sent back up to the server in a header that was getting lost. And so they were falling back to their default name, Axios was. And, therefore, Rails was like, "There's no CSRF token here. So this is going to be a no for me. I'm going to reject all of the requests." So the fix was relatively easy to roll back and to pin the version of Axios to the previous version that we had been using. I didn't actually intend to upgrade it. I just intended to make it an explicit dependency. But by doing that, I accidentally upgraded it. I don't love that there was this pretty deep breakage in that. I haven't done the good work of trying to open an issue. I still want to scan through and see if there is an open issue or a conversation around this before I start making any noise. But I think if I don't find anything, this is the sort of thing that should be reported because I can't imagine I'm the only one running into this. Likewise, I was very sad that my test suite did not find this. Turns out in Rails, CSRF protection is just turned off in test mode, which may be overall makes sense. But for feature specs, in particular, I definitely want to have it. And so, it was nice that I was able to find the relevant configuration. And we introduced an RSpec configuration that says, "If it's a feature spec, save off the existing configuration and enable CSRF. And then after the spec, go back to whatever the previous was." So now all feature specs run with CSRF. And I did make sure to push up that as a singular change to CI, and CI was very unhappy with me. Many, many features-specs failed, which was good. That was what we were going for. They failed for the right reason because things were fundamentally broken. And then, I was able to update the package-lock or the package.json on the yarn lock, pin the version, fix everything. But man, there was this period of like, oh man, the app is broken in such a fundamental way. Users just can't do stuff anymore. They can view anything, but they couldn't change any data. And it just snuck through CI. And that feeling is the worst feeling. We had, at this point, built up a lot of trust in our test suite. It was really telling us when stuff was wrong, and if it was green, I felt very good merging. And suddenly, this just really shook me to my core on that front. STEPH: I love these journeys that you take us on. I mean, they're painful for you, and I am sorry to hear that. But I love these journeys that you take us on. [chuckles] CHRIS: I usually only take us on them when I've figured out the answer. And I'm like, all right, here's where we're at. It was rough for a little while, but now we are happy. And thankfully, the one configuration of saying, hey, Rails, also, please include this as part of our production like, configuration for test mode. So I feel better that moving forward, this breakage won't happen again. STEPH: We should add that as another merit badge for telling a bug story. All right, I'm taking off my hat of chief of fun and cuteness. So this may not be terribly relevant to all the things that you just shared. But I am curious where you mentioned that with Axios because you'd specified the name of the token, and then that overriding behavior is what then broke. And so then that's what led to this whole adventure that you went on. I'm curious, why did y'all customize the name of that token? CHRIS: A, this is a great question. B, I'm not super sure. C, I think the reason is because we were trying to align to Rails. So we have a little middleware on the Rails side that will serialize the CSRF token into a cookie. And then that cookie value gets read by Axios and sent back up as a header on the request. So this is the way that with Inertia CSRF just kind of works and is good. And it's different than Rails' normal. We put a hidden input into any form. And so Rails holistically knows about both sides of that, and everything works fine. But now I have to manually round trip the CSRF token. And Axio's default configuration is a header name X-XSRF-TOKEN, and we needed X-CSRF-TOKEN because that's what Rails is looking for. I probably could have configured it the other way on the Rails side. But one way or another, I had to get Rails and Axios to come to an agreement, to meet at a table, and to agree to collectively protect the app. And so I had to mediate that discussion, and that's what ended us here. STEPH: A meeting of the minds. [chuckles] Cool, cool, cool. Yeah, that makes sense. I was just curious because then that would have changed the whole journey. But yeah, that is super interesting. And I definitely resonate with the idea of when you've really invested in your test suite, and you trust it that then when it doesn't catch something that obviously breaks the application, then that feels like something worth prioritizing and digging into and then figuring out how to bring back that parity. I don't know that I've turned on enable CSRF for feature spec. So I'm also very interested in looking at that configuration and considering if I need that for any of my future client projects if that's something that I need to remember for the future because that's very niche but good to know about. CHRIS: I feel like this only really comes up if you're working in the...it's called the odd middle ground that Inertia ends up occupying. If you're in a traditional Rails app that is generating HTML server-side, forms are generated. They got the CSRF token inlined there in a hidden input. And then when you post that form, it's coming back up. The names automatically are going to match. You don't need to worry about it. And it's probably fine to not have it included in test mode. And if you're at the other end of the spectrum and you've got API interaction, and that's the way you're doing everything, then you have a different auth mechanism and cookies, and whatnot just don't apply in the same way. And so it won't really matter on that side but for a different reason. And it's only because we're in this interesting middle ground, which, again, I really love. And it's the thing that I love about Inertia. But this is a rare case where it's like, oh, we do have to bring the two sides to meet in the middle. And this is a case where, unfortunately, due to a very subtle breakage on a minor release of...a package that we're using silently broke so, yeah. But yeah, thankfully, everything is back to working. And again, we've been able to enhance the test suite in that little way that I feel confident again because this won't sneak in another time. We have coverage around this. We're good to go. So while I was very scared when this initially happened, I feel better now. I'm happy to go into the weekend feeling better about this. But that's my story. What's new in your world? STEPH: So I feel like I've been having one of those weeks where I have less code adventures. In fact, it's one of those days where I went to thoughtbot's daily sync...because we often have our client daily syncs, but then we still have a thoughtbot sync as well. And I went to the group, and I was like, I get to write code today. It's going to be a great day. All the other things I'm doing are also interesting, but I get particularly excited when I get some maker's time and get to write some code. So I feel like I've had less coding adventures recently and more hiring and process-related adventures. And specifically, I just completed the Plucky Manager Training, which is a program that's founded and led by Jen Dary, who was recently on thoughbot's podcast, The Giant Robots Smashing Into Other Giant Robots. I'll be sure to include a link in the show notes for anyone that's interested. CHRIS: I believe this was the third time she was on. It's at least the second, possibly the third. And all of them are great listens, just as an aside, so we should include links to all of them. STEPH: Yes, I think she's one of the rare guests that has been on the show three times. And I think I've only listened to the first couple minutes of that episode. But I think they talk about the fact that this is her third episode, which is really, really cool. And I'm still frankly synthesizing all the information and the ideas that I've collected from the course. But I do have a few quick takes that I'm interested in sharing with you. So the first one is my cohort...we were the Panda Cohort, so go, Pandas. And some of the things that we talked about were…, and I think that this may have been the first day. So it was three days, and it was three hours for those three days. And they're spread out over a couple of weeks, which is really nice because then you show up for those three hours of the class, but then you leave with some ideas and some things to experiment with. You get a week to then try out an experiment and then come back to class next time and talk about this is how it went; it went to wonderful, or it went terrible. And you get to share that with others and work through it. And in the first class, we talked about coaching versus managing, which I found just a helpful definition to review. So managing is more direct, and telling someone what to do while coaching is encouraging someone to determine their own path and find their own solution. And I find that as a team lead at thoughtbot, I'm very often more in that coaching space than I am in that managing space. I think it's frankly pretty rare that I actually need to put on a manager's hat. And I often feel like I'm wearing my coaching hat instead. And some of the other things we talked about one of them is what is work? Which is a fun question to ask. And Jen had an analogy for this speaking about imagine that you have a plastic Easter egg. So it's got two sides, and side one is all the skills and desires and things that you're fulfilled by. And side two is a company that needs those skills. And it's great when those line up and click together, like when you take a job or get a promotion. Have you ever played...do you know what I'm talking about? Those little plastic Easter eggs. Have you ever played with those as a kid? CHRIS: Yes, certainly. STEPH: [laughs] I realize I just launched into that analogy. [chuckles] And then Jen goes on to say that's totally normal for then those sides to unclick. And Jen continues to say that it's totally normal for them to unclick. So maybe the company changes direction, the company is acquired. You've fallen out of love with something that you do about your job, or you have kids, and that has changed the things that you are fulfilled by and what you're looking for. And that's not necessarily bad. So it can be like, hey, you are working on x now, and you're not fulfilled by that anymore. But then another company comes along and says, "Hey, we're working on this, and you are fulfilled by that." So then another click happens. And essentially, it's a nice analogy to represent someone's career path and the ways that we are going to shift and re-prioritize what we're interested in. But it's also a really nice way to help it feel less personal because both sides are allowed to change. The company can change. You, as an employee, can change. And then you can look for that next click that is going to match up with a company that meets your skills and things that help you feel fulfilled. One of the other topics that we talked about are hard conversations, which I love that we dug into this one because that's certainly one that I struggle with or...I mean, we all get that feeling if you have to confront someone if you have to have that uncomfortable discussion with someone. It is a very hard thing to do. And so we had some very honest conversations around what is a hard conversation? What does that represent? And essentially, they represent that there is stalled progress and something can be improved. So Jen likens a hard conversation to a tool. It's something that you can use to then help something move forward again if something feels stalled or if there's something that needs to change. And during those hard conversations, you may not get to the resolution that you're looking for. So you may be looking for a specific outcome. But you also have another person that needs time to respond and to take in everything that you have said and process that information. So when you have a hard conversation, you may actually only move forward an inch. So if you had a lofty goal of we're going to talk and then we're going to have this hard conversation, and we're going to get to this space...But instead, you actually just make incremental progress. Like, okay, at least this person is now aware of this concern. That might be your win for the hard conversation versus actually tackling; how are we going to address it? I just want them to be aware of this concern. And it's a very vulnerable conversation, and they often take time before you can get to that ideal resolution. But essentially, the idea is get in the game, start the conversation, and then have follow-up conversations for that hard conversation. And I really appreciated that framing because I often will think of hard conversations of oh, we have to have this hard conversation and get to this specific outcome. But if you shift the goal line to be like, no, I really just need to at least make this person aware of a concern, that makes it a lot more approachable. And then also probably yields more fruitful outcomes because that gives the other person time to think about what you've shared to also come to the table with their own ideas and then work together to then get to that ideal resolution. CHRIS: I like that framing a lot. I can definitely see the case where you, as someone who has recognized something that needs to change (perhaps you're a manager),lineup you've now thought about that a good bit; you've observed it, but the individual that you're bringing that to this may be novel. This may be a surprise for them. And so if you come into that interaction both about to share this information but then also trying to resolve it and trying to get to I need you to internalize it, and I need you to fundamentally change your behavior as a result of this conversation we're going to have, that's quite possibly not a realistic outcome. And if you're trying for that, it might inherently lead to just a bad outcome because that individual is not in a position to do that. But they are potentially ready to hear it. And so you can just achieve step one and then later have step two. So I like that a lot. STEPH: Yeah, in general, I found the course incredibly helpful, very insightful. It was also really nice to hear from other managers that are facing similar problems or perhaps novel problems and then getting to weigh in and help each other. So it's a wonderful course. I'll be sure to include a link in the show notes for anyone that is interested. And I'll probably come back with some more insights from the class because it's really...we just wrapped up. So I'm sure I still have some ideas that will percolate over time, and I want to come back and share those with the group. Mid-roll Ad And now a quick break to hear from today's sponsor, Scout APM. Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more. Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform. See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed. STEPH: Pivoting just a bit, we have a listener question that I'm excited to dive into. This question comes from the one and only, the Edward Loveall, fellow thoughtboter. And Edward wrote in, "How does the process of software development change at different team sizes? What's a process that breaks down soon after the team starts growing? What's a process that is resilient at all sizes? And by process, I mean anything that involves other people including organizing tasks, code review, deployment, or anything else that isn't you alone writing code in a vacuum." I'm really excited about this question because I think there's a lot here. And there's actually one part that I'm struggling with a bit, so I'm curious to see what you think, Chris, about it. But I'm going to start off with saying that I think there are a number of management processes that definitely break down as a team grows. But in the spirit of Edward's question, I'm going to focus more on the software development process and how those might need to change and what starts to break as your team grows. So starting off with processes that break after the team starts growing, this one, frankly, what really starts to break is not a process specifically, but it's the lack of process that really starts to become visible and painful. So, how do we track work? Before, maybe the product manager or someone would just send you a message and say, "Hey, can you work on this?" or "Hey, can you fix this thing?" And how does code need to be reviewed before being merged? Does it need to be reviewed? Are people just merging as they get stuff done? How are deploys performed? Oh, we have a super urgent production fix that needs to go out, and the only person that knows how to deploy is out sick today? Cool. That's the type of process that I think that really breaks down, or at least you start to notice when the team starts to grow. What are your thoughts? CHRIS: I definitely feel that first one very strongly. We're feeling it right now on the team, which is still very small. There are only three developers working on the project, and then we have a product manager. And each week, we're slowly iterating, and tweaking, and honing, and trying to introduce just enough process in terms of how we define the work to be done, communicate the status of it, all of that fun stuff. We started with Trello. And we just had a board with some columns, and then we had more columns, and then we got rid of a few of them. And then we recently added a Power-Up to the Trello board, which allows for epics. So there are cards which are epics which tie to sub cards. And I'm staring at it, and I'm like, how long until we're Jira? How long can I hold out here and not be Jira? But it does feel like we're slowly iterating towards a more useful process for this team rather than process for process' sake, which I feel like is a really useful distinction. There's also a question of like, what can be known or what can be adequately measured and whatnot versus what can't be? So we've talked many a time on the show about estimation and velocity and trying to track that and the pitfalls inherent with that. And so there's, in my mind, two different camps. There's the process we want to avoid. And again, to reference German Velasco's wonderful blog post, Say No To More Process. And I really feel like there is a tendency often when things go wrong to then try and paper over that with process. Oh, this team didn't use the design system. So we need to write ESLint rules to make sure you can't import from the directories that aren't the thing. And it's like, we can do that, and I've definitely done that. And I will do that again in the future. But I always have the lens of do we need this? Is it worth the trade-off, the cost, the overhead, the complexity that it's bringing in? But definitely, organizing and communicating tasks is one of the ones that becomes really difficult. The more people that are working on something, the more you need probably more than one person staying out in front of them and trying to define the next bit of work that needs to be done after that. Code review feels like it probably should stay similar, with the exception that I lose the ability to review all code at some point. Right now, I'm trying to review every single PR that goes through or close to it. At some point, I'm just going to have to give up on that. But for now, that's my goal. But fundamentally, code review, I think, will hopefully take the same shape. Deployment, similarly, like, I've talked about the merge queue thing. I want to get a little bit of process in there but not too much. There is definitely some necessity for change. But I definitely want to resist the urge to change everything and to just say, like, slowly over time; we're going to have to be a big Byzantine organization with lots of rules and standard operating procedures and all of that. I've heard anecdotally, and I don't know if this is true, so maybe someone out there on the internet can correct me if I'm wrong, but my understanding is that at Google, they're pretty tight in terms of what languages and frameworks can be used and what processes, and workflows, and build tools and all of that whereas Facebook, as a counterpoint, is relatively lax. Obviously, React is used very heavily on the core web application. But there's some flexibility in terms of different languages and frameworks and things for sub-projects or small individual teams having a little bit more autonomy. And I think that's a really interesting thing of are you one large, cohesive, organized company or do you try to act like a bunch of small disparate but roughly connected teams that share good ideas but can work independently? And that changes how I would think about this question. STEPH: I really like how you're describing the addition of process. It sounds like a just-in-time process. So as you're learning that something needs to be added, then that's when you look for answers. And then you sprinkle on a bit of process that everyone agrees that feels very helpful within also the right to review and see if that still makes sense for the team. There's one additional area where I think the lack of process really shines through in addition to the number of ways that you've mentioned is also onboarding. So if you have a very small team and you are onboarding, it's likely that...Chris, you can let me know if I'm wrong, but when someone's joining the team, there's probably a good chance that they get to pair with you at some point, or they even get welcomed by you to the team. And then, they get an overview of the product and the codebase. And there's probably this really nice session where they get to ask you questions, and then they have that onboarding session. Does that sound about right? CHRIS: Yes. But I would go so far as to say it's not just a day or a session, but it's probably a couple of days. So yes, and. STEPH: That's even better. And with some of the smaller teams that I've seen, that onboarding process is where they are pairing with that lead person on the team. And that's going well until suddenly that lead person can't pair with everybody. And nobody has really thought about how to streamline that onboarding or how to coach or teach someone else to be a really good onboarding pair. And I have strong feelings about this area because we often focus so much on hiring, but then we drop the ball when it comes to onboarding that new, wonderful colleague that we've worked so hard to recruit. And at the end of that day, someone's going to reach out to them and say, "Hey, how was your first day?" And it makes a big difference for that person's retention as to how those first couple of days ago. So I think onboarding is another really important part that when you're a smaller team, you probably don't need much process because you have more of that personable onboarding experience. But as the team grows, there needs to be more of a process to help other teammates join the team. CHRIS: It's interesting. I think I totally agree with you that over time, there is a necessity to be more intentional and to have a little bit more structure in the process. And I don't think you're saying this, but I just want to make sure we are saying the thing that I think we believe, which is that shouldn't replace the human that helps you onboard. Like, I still like the idea that everybody gets a pair for some amount of time when they start at a new company. And you're working together on a feature, or you're working together on bug fixes. You're shipping to production as soon as possible. But you're not doing that based on some guides in a wiki. You're doing that with another human that's helping you. There should also be guides, and a wiki, and documentation, and formalization as the organization grows but not in place of having another person that you get to talk to. STEPH: We're just going to send you a little yellow rubber duck and then with a little Post-It note that says, "Good luck [laughs] with your onboarding process." Definitely. I agree with everything you said. It does not replace that human element where there's someone that's helping you onboard. I just see that onboarding is one of those things that gets forgotten, or we often point someone to a README which I do think is great because then it is battle-testing our README. But then there still needs to be someone that is readily there to say, "Hey, how's it going? What are you struggling with? Can I pair with you?" There still has to be that human element that is helping guide you through the process. And I think smaller teams may forget that they actually need to assign somebody to you to make sure that you have someone that you know. Like, hey, this is who I can reach out to with all my questions. Because they're probably not going to be comfortable posting in the company channel at that point or a larger communication to say, "Hey, I'm stuck on something." CHRIS: There's one other area that comes to mind, or I guess it's more of an anecdote that I have heard, but it speaks back to GitHub's early, early days. And they were somewhat famous for being very flat in terms of the organization and very self-organized, and everybody's figuring it out, and you're working on the thing that's most important in your mind. And for a long time, this was a celebrated facet of the company and a thing that they talked about rather publicly. And then I think there was this collective recognition, and maybe they reached a tipping point where that just didn't work anymore. Or maybe it actually hadn't been working for a bit, and there was just the collective realization of that. But it was interesting to watch from the outside as GitHub added more formalization, more structure, more managers, and hierarchy, and career ladders, and things of that nature. And I think there's a way to do all of those things in a complicated, overloaded, heavy way. But I think a different version of it is...like, you were using the word coaching earlier. Having formal structures within your organization to encourage people on their career path, to help them grow, to have structure around that, I think is a really difficult thing to get right. But I think it is critical, and I think just not having it can't be the answer past a certain probably pretty small size. So that is an interesting one where I think you do need to introduce some process and formalization around how you think about the group of people and how they work together within your organization. STEPH: I agree. I think where some folks may see a lack of hierarchy; others feel a lack of support. And adding levels of management should really be focused on the outcome is that we're helping people feel supported. So even getting feedback as you're adding those different levels of management, like, hey, did we make your life better? Did we make your life worse? I think that's a great question for management to ask as they're exploring a less flat structure. CHRIS: So, Steph, I have a question for you now on a variant of this topic. In general, we seem to be fans of having a codebase. Probably a Rails app that's got a database behind it, and that's where you put the data. Everybody commits to that same repository. It's all kind of one collected thing. And often, organizations grow to a certain size, and they're like, this is untenable. We cannot have this many people working on this same codebase. So we shall do the logical thing, which is we will break it up into small pieces. And those pieces will communicate over HTTP, and it will be great because then our teams can be separate from each other and can manage their little piece of the world. What do you think about that? Is there truth there? Is it not true at all? What do you think? STEPH: All right, so your team is getting too big, and to the point that you feel like you need to split it out so then you can have small teams, and they can all work independently on different parts and services of the codebase. I don't love the idea. I'm trying to think through because I feel like there's a lot of nuance here. But I don't love the idea that that's the driving force as to why are we making the change? And that is often a question that comes to mind whenever we are making a big change, either architecture or process-related is like, what's driving this? And then how are we going to measure it? And if we are driving it just because we have a large team, let's talk more. Why are people blocked? Why can't people work together? What's preventing people from being able to contribute to the same codebase? Are people blocked for a long time because they're having to wait on someone else to complete that work? I have a lot of questions that I don't know if I can fully answer your question. But my instinct is to say let's not break up the architecture just because our team grew in size. CHRIS: Yeah, I think I definitely agree with that. There's probably a breaking point where it's just too many individuals, and there'll be too much contention. But I think resisting that or at least naming that as like, okay, that's what we're saying but is that really what's true? Or are we actually feeling that this system is so deeply coupled that there's no way to change some small piece of the code without impacting other parts of it? Like, is the CSS completely untenable because we're just using global class names, and it's leaking everywhere? Okay, do we need a different solution there? And then it's actually fine. We don't need to have different services that have their own different style sheets. We just need a different approach to CSS. That's a particularly easy one to go for because there's inherently a global namespace there. But the same thing is true in a lot of different contexts. So services are a way to break things apart and enforce those boundaries. But if inherently coupling is your problem, then you're just going to be coupled over HTTP, and I think it's going to be difficult. There's a wonderful blog post by Josh Clayton, which I think does a better job than I'm doing in this moment of highlighting some of the questions I would want to ask. The blog post is titled Services are Not a Silver Bullet. And so Josh goes through and enumerates a bunch of the different versions of the story that he's heard throughout the years of well, we need to go to services because x, because our test suite is slow because pull requests are constantly having merge conflicts and whatnot, because the code is very deeply coupled and any change here affects everything else. And a fix over here broke something over there. This is no good. And so he does a really good job of presenting alternatives or at least questions that you can ask to say, like, is this the problem, or is this a symptom? And we need to address the more underlying cause. And so I think there is a point where you just can't have 1,000 people trying to commit to the same Rails codebase. That feels like it's maybe too big. But it takes a while to get to 1,000 people. And there will be times where extracting a service makes sense or integrating with an external service that exists. Like, I've talked about Stripe before as my canonical like, yeah, it's actually deeply intertwined with the data model, but they're just dealing with such a distinct complexity set over there. And they have such expertise on that that I'm happy to accept the overhead of the fact that that service lives outside of my core application, and I need to deal with synchronizing state and all of that. I will take on that complexity, but it's not worth it for everything, and it's not a silver bullet. Again, to reference the name of Josh's blog post there, Services are Not a Silver Bullet. And so, coming back to Edward's original question, I would say that having a monolithic codebase works for a really long time, but there is probably a breaking point somewhere well along, but fight it for as long as you can. I think. STEPH: I really like how you touched on coupling because it really helps ask those questions to get to the heart of what are the pain points that you are feeling? And it is less of a decision that is based on people and process but more if you're going to split out a portion of your architecture. It is in response to an actual business need and a business value versus some other pain points that you're trying to fix. A particular example might be like maybe you have a portion of your application that really just needs to spend a lot of time crunching data. And it's really not as specific to your application; it's something that can happen on its own. And then it's beneficial to move that outside so it can scale and relate it to the work that it needs to perform versus keeping it in-house with the application. I do want to circle back to another question that Edward included which is what's a process that is resilient at all sizes? And the ones that really come to mind for me...and these are a bit amorphous intentionally because it will look different for each company. But three areas that are very resilient at all sizes, whether you are 1 to 2 employees versus you've got hundreds or thousands it's communication, testing, and accountability. So communication, where are we headed, and how do we know what we're working on? For testing, it's how do we test our changes? Do we write tests? Do we use QA? Do we have a staging environment? What does that look like? What's our parity between staging and production? And then how do we know what's in progress, and how do we know when it's done? Those are three core areas that, regardless of your team size,,I think are very crucial to the team success. What do you think? What are some of the processes that are resilient at all sizes? CHRIS: I actually really like the list that you just provided. That is a wonderful trifecta, and I think it will take you very far, so probably not much to add from me. But I guess on that note, should we wrap up? STEPH: Let's wrap up. CHRIS: The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes, as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey STEPH: Or you can reach us at email@example.com 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.
[00:01:32] Joe, Chris, and Dylan tell us what they do at Polywork.[00:02:34] Joe shares things that make a good Rails Developer and what type of person would be best to join their team. [00:05:47] Find out all about Polywork. Andrew mentions checking out Brian Lovin's Polywork page. [00:07:16] Joe tells us how they rebuilt the application on Rails 6.1, Turbo, and Stimulus, and how it has paid off for them.[00:11:49] Andrew asks the guys what they're using Turbo for, what kind of wins is it giving, and if they've upstreamed anything that they found into Turbo. [00:15:49] Chris asks Dylan what their thoughts are on how handle or think about the navigations stuff on the mobile stuff. He also tells us something they are working on now at Polywork.[00:23:41] Dylan tells us if they are able to get away with writing very little Swift or if that's still kind of a core piece, and if they do OAuth, do they go Native in Native Swift OAuth or if that's web-based.[00:27:41] If the guys were not using Turbo for building the app, would they end up building a hybrid app, like a React Native type of thing if they didn't have Turbo for the web and mobile?[00:28:57] Andrew wonders if the guys are in a place where they'll be ready to upgrade when Rails 7 comes out or a shorter update process since they've done all this groundwork already. Also, we find out if the guys are happy they stuck with Rails.[00:35:35] We hear an interesting story behind celebrity emoji keyboards and Kanye.[00:38:57] Polywork is hiring so check the link below for openings! Panelists:Chris OliverAndrew MasonGuests:Joe FerrairoChris PolkDylan GinsburgSponsor:HoneybadgerLinks:Ruby Radar NewsletterRuby Radar TwitterJoseph Ferrairo LinkedinJoe Ferrairo GitHubChris Polk LinkedinChris Polk TwitterDylan Ginsburg LinkedinDylan Ginsburg TwitterPolyworkPolywork job openingsPolywork Twitter Brian Lovin
On today's bonus episode of The Chase Thomas Podcast, Fangraphs' Jon Tayler sits down with Chase to talk about the NLCS, how the Braves went up 3-1, issues with the Dodgers, the Astros going up 3-2 on Boston, why the Red Sox are in trouble and much more (4:00). Then, Hammer and Rail's Travis Miller on Purdue taking down No. 2 Iowa last weekend, David Bell's special play at wideout, the revolving door at QBs, how they match up against Wisconsin this weekend and much more (30:00). Host: Chase Thomas Guests: Jon Tayler, Travis Miller Learn more about your ad choices. Visit podcastchoices.com/adchoices
On today's episode of Bucky's 5th Podcast, we've got a huge Big Ten West showdown to breakdown as the Badgers head to West Lafayette to take on the Purdue Boilermakers. To start, we get into how the Wisconsin offense will look to move the football against a much improved Purdue defense. After that, we discuss how to stop this Purdue offense aka stopping wideout David Bell. Later on, we get into some other key matchups and then give a score prediction for the contest. In the back half of the show, we are joined by Casey Bartley of Hammer and Rails to get an in-depth look at Purdue. In our conversation, we discuss more about David Bell, Purdue's 3 quarterback system, defensive standout George Karlaftis, and much more. Enjoy! Learn more about your ad choices. Visit podcastchoices.com/adchoices
Today we talk about the first two games in the Iron Rails Series by Capstone Games and begin a discussion on Capitalism. Irish Gauge Ride The Rails 18xx Games Ticket to Ride Iberian Gauge (Please note we have received and played Iberian Gauge and are looking forward to reviewing it as well.) Ratings Rob - Irish Gauge - 2222 - Ride the Rails - 2222 Adam - Irish Gauge - 222 - Ride the Rails - 222 Kyle - Irish Gauge - 222 - Ride the Rails - 222 Combined - 2222 Capitalism Socialism California Gold Rush Current World Population as of the publishing of this podcast - 7.753 Billion and rising Adam Smith Magna Carta Many of the links in today's notes are to Wikipedia articles. While Wikipedia is a great place to start, we remind you that it is not a completely accurate source for information. Do your research! Music today by: Adam Lavazza, Lavazza and Layne, and the song Shrutie Pie is by Zachariah Hickman Hosts: Adam, Kyle, Rob
Steph talks about binging a few Things Worth Learning podcast episodes and particularly enjoyed an episode that featured one of thoughtbot's design directors, Sameera Kapila. Sam shared her expertise about management and inclusion, and Steph shares her favorite parts. Chris shares the story of a surprising error and the resulting journey through database transactions and Sidekiq that eventually resolved the issue. He also shares some follow up on the broken build and the merging process changes they introduced (spoiler, the process changes have been rolled back). Leading Inclusively, with Sameera Kapila - Things Worth Learning Podcast (https://www.youtube.com/watch?v=eiV6_3pZFc0) How to Skim a Pull Request (https://thoughtbot.com/blog/a-smelly-list) Isolator (https://github.com/palkan/isolator) aftercommiteverywhere (https://github.com/Envek/after_commit_everywhere) timefora_boolean (https://github.com/calebhearth/time_for_a_boolean) Transcript: STEPH: Oh man, I'm about to stop eating my pop-tart. I'll put it away. It's within distance. I'm going to eat it. CHRIS: Your high-fat content unfrosted pop-tart. STEPH: You know, surprise Sunday twist: it has icing on it. CHRIS: Steph, who even are you? STEPH: [laughs] CHRIS: There are a few canonical anchor facts that one knows about other people, and when one of those... STEPH: I like to keep everyone, including myself, on their toes. CHRIS: Or you've just secretly accepted that the icing adds another textural flavor adventure component. It's just better with icing. STEPH: All right, all right, all right. There's a complicated answer to this. And the complicated [chuckles] answer to this is that the more organic ingredients that I recognize when reading about pop-tarts are by a particular company, and they all have frosting on them. And the more generic pop-tarts that don't have frosting on them, I don't know how to pronounce a lot of those ingredients. So I'm like, no, but okay, I still eat them. But I prefer the ingredients I can pronounce. So I either go with the ingredients I can't pronounce or have a little bit of frosting on my pop-tart. And I'm going with the non-cancer route for today. CHRIS: For today, in this moment, and accepting the frosting. Okay, all right. Well, that is complicated. [laughs] It's tricky out there. Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey. STEPH: And I'm Steph Viccari. CHRIS: And together we're here to share a bit of what we've learned along the way. So, Steph, what's new in your world? STEPH: Hey, Chris. So the weather, I'm going to talk about the weather for a little bit. [chuckles] It's been almost non-stop rain for the past several days, which is fine. I'm sure it's great for plant life. But it's really hard on my dog Utah because then we can't go outside for our normal walks and playtime. Although he is my four-legged water baby because he absolutely loves water, and puddles, and playing in the rain. So he's very fine with going outside and playing for a long time. But then I have to essentially give him a full-on bath before I want to bring him back in. So not wanting to have to give him a bath each time, in the spirit of improvising, we started finding more indoor games to play. And I've started teaching him to play hide and seek. And he's not great at it mainly because he will only stay until I'm out of eyesight, and then he will come and find me. And so I have to be really, really fast at finding a hiding spot to like dash around a corner or hide behind the door. But I think he enjoys it because he will find me and then he seems very excited. And we go back, and we play again. And so I just have to work on teaching him to wait a bit longer so I can find better hiding spots. CHRIS: When you said that, at first, I was like, how did you teach him to hide? But I realize he's only playing the seek part of the game, and you're only playing the hide part of the game. STEPH: [laughs] CHRIS: I'm just so used to you exchange roles back and forth. First, you hide, then you seek, and then you switch it up. That would be a lot to get your dog to be like, now I'm going to secretly hide. STEPH: [laughs] I'd be very impressed. Yes, we have very distinct roles in this game. I am the one that always counts and hides. But he's a very good seeker. So that's been fun. We just got to work on getting a little better at it. But on a more tech-related note, one of the design directors at thoughtbot, Sameera Kapila, who also goes by Sam, was a guest on the podcast Things Worth Learning, which is hosted by Matt Stauffer. And Matt is also the host of The Five-Minute Geek Show and The Laravel Podcast. And in the show Things Worth Learning, Matt meets with individuals that are excited to share something that they're deeply passionate about; maybe it's tech, maybe it's not. And I've binged a couple of those episodes. And I really like how you can choose between the podcast format or the YouTube format. So then you can really watch the conversation unfold, which I know you and I a couple of times have thought it would be fun if people could see us because there are so many facial emotions and gestures that go along with conversations. So it was really delightful. And speaking of delightful, Sam shared her expertise about management and inclusion. And I definitely recommend listening to the episode because I can't share everything that Sam shared. But a couple of the topics that Sam mentioned that I really enjoyed and would love to chat about, so the first one is about helping someone, in this case, someone that you manage that comes to you with a concern. So there's often a presumption that just because someone comes to you with a concern or an issue that they've experienced at work, that they're the ones that will also want to work to address that concern, and that's often not true. It can be true; maybe that person wants to be involved. But they're often coming to you in the leadership or management role to say, "Hey, I've had this issue," and they really want help with that instead of walking away with homework for it. Because then that trains people to essentially be in this mindset of well, if I bring up this concern, then I'm going to be the one that has to address it, even if I'm the one that's most negatively impacted by this. And addressing this concern could be actively harmful to me. And she shared a really great real-world example from her own experience where her and another co-worker had noticed a concern about the hiring process. And her and that co-worker got together, and they talked about the concerns. They even rehearsed for the meeting because they were trained by the tech industry to say, "Hey, if you bring up a concern, you're going to be responsible for addressing and then resolving that concern." And so they had that meeting with the person in leadership. And they were pretty nervous about how it was going to go. And that person in leadership said to them, "Thank you both so much for sharing that. That must have been such a burden. And this is my responsibility to fix. And here are what my next steps are." And that was amazing because it allowed Sam and the other person to go back to client work. And they also received follow-up conversations about how that issue was being addressed. So there was even that feedback loop as to how things were going to change. And I have a personal example that...I really resonated with the example that Sam provided because I remember there are different teams that I've been a part of, where often I was one of the few women engineers on the team. And so we often have conversations about how do we get more women engineers into the company? And they're wonderful conversations. But there's a part of me that always felt resentful about, like, why am I here? Why am I the one fixing this? I understand I have some more insight and expertise, and experience in this area. But I was also frustrated by the fact that I was the one that was in that meeting often with other women, and it felt like our responsibility to fix this. And I used to feel bad about feeling resentful towards that. Because I was like, shouldn't I want to help other people? And I do. But Sam's example really helped remind me and clarify that yes, just because there's a concern doesn't necessarily mean you should be the one to address it. And it really takes everybody involved, or it takes leadership to step up and address that concern. CHRIS: Oh, that's really interesting the way Sam is framing that and describing the situation of not having any problem that you bring in be now your work to solve. Like, oh, I found the issue, and now we've got to go do this. But the idea that you can bring something to light and then be able to walk away from it. And the particular thing that you were saying that if your interaction is always that when you reference something when you bring in a concern that then your manager works with you to figure out how you can solve it, then you get this mental block of like, well, do I even want to say anything? Because I don't want to try and deal with big, amorphous unclear issues. So maybe I just won't even say anything. And so this as a way to make sure that there's room for all of the conversation is a really interesting framing that I hadn't really thought about, frankly, but it's very interesting. I haven't seen this interview either. So I'm definitely excited to give this a look because Sam is wonderful. And the topic that you're describing here sounds fantastic as well. STEPH: Yeah. There was an important moment for me where...one of my managers is Matt Sumner, who's been on the show. And when Matt was my manager, at one point, we were having a one on one, and we would often go for walks for our one on one. And I mentioned something about "I have this concern, or I have this problem, but I don't really know how to fix it. So I'm not sure I'm ready to talk about it." And Matt, in his delightful way, was like, "We can still talk about it. You don't have to have an answer or a solution." I'm like, "Yeah, but I feel like I should be able to fix it. Like, if you have a concern, or if you have something that you want to gripe about, then you should come to the table with solutions for it." And Matt was like, "No, you don't need to do that at all. We can totally gripe about stuff or talk about concerns and then either figure out the solutions together or go to other people for ideas." And that was really important to me because, like you'd mentioned, otherwise, it felt like this mental block where then it feels like you can't air out some of the things that you're worried about or have concerns about because then you think you're the only one responsible. And you may not be able to come up with the best solution. You may need other people to then help you strategize and come up with ideas. And I just love, love, love that part of Sam's discussion. And oh, there was one other part about the conversation. Well, there are lots of parts that were amazing. But another one in particular that blew my mind is about Comic Sans, the font, the font that everyone loves to hate. [chuckles] And I learned that it's one of the most legible fonts for kids. And it's one of the more accessible fonts for people with dyslexia. And it's actually recommended...I think there are still more academic studies that need to be done to really classify fonts that are best for people that have dyslexia. But Comic Sans is recommended by The British Dyslexia Association and the Dyslexia Association of Ireland. And there are some other really great posts that talk about the benefits of using a font like Comic Sans because the typeface has long ascenders and descenders and generous letter spacing and asymmetrical lowercase b and d to then help distinguish those letters. And I just thought that was so cool. This font that everybody wants to rip apart because it seems whimsical, unprofessional gets overused. There are lots of reasons, I suppose. [laughs] But there's a really big benefit to it, and it can help others. And I just found that very whimsical in itself. CHRIS: I love the idea that there are multiple levels of knowing about Comic Sans. First, you're just like, I don't even know the name, but it's that comic book-looking font. And then obviously, the next step is to be like Comic Sans? How could you ever use that? It's an atrocity. And then it's like, but actually, Comic Sans has some things going for it. And it is a really interesting consideration and something that you wouldn't necessarily think of. But then once you learn it, you're like, okay. Man, I wonder how many other things in the world have this interesting shape to them? Hmm. STEPH: Do you know the history behind Comic Sans? CHRIS: I do not. STEPH: I read about it fairly recently, but I'm probably going to botch some of the details. But I believe it was designed or created by Vincent Connare. And it was created for Microsoft. And Vincent was working on a project where I think there was a dog that was essentially going to have these bubbles that would then show you different parts of the application and walk you through the different features. And the dog had a very comic book feel to the character. And so then Vincent designed a font to go along with that comic book character, this dog and came up with Comic Sans. I don't think the dog actually launched with that particular font. But since the font was still developed, it was released as part of the available fonts. And there we go, there is the birth of Comic Sans. And then it just received so much love and ire all throughout history. [chuckles] CHRIS: There's something that you said there that I want to loop back on when you were talking about chatting with Matt Sumner and saying, "Here's this thing, but I don't know how to solve it. So I don't even want to bring it up." I really liked the framing that you gave and the fact that Matt was like, "No, no, we can still talk about it. We can at least explore this thing, have a conversation." I think that's really wonderful. There's a very similar thing that I experience a lot when doing code review, particularly when I'm in more of a leadership role within a team, which is I often want to highlight something that feels a little bit off to me in the code, but I may not have a specific solution. Like, I may see a variable name, or I may see a controller action that feels like it's the wrong shape or something. And I'll often name it but explicitly say, "I actually don't have a better idea here. So feel free to continue on with this, but I want to name it. So in case that sparks something in you, if you were also feeling some incongruousness, maybe it's worth you spending another minute to think about it, but I want to make sure my comment isn't blocking or otherwise making you feel uncomfortable." If I just come to you and I'm like, "This feels wrong," and that's all I say, that to me is unacceptable code review. Because now I want all of my code review feedback to be very actionable, it's either here's the thing that I feel strongly I think we should definitely change this. If you disagree, let's have a conversation. But yeah, this one definitely needs to change. Here's the thing that, like, I don't know, maybe we could break this into two lines and split it up. But if you don't like that, that's fine. Do whatever. And so then it's I've given the person my thoughts but given them clarity and a free rein to do whatever they want with that information. And then there are ones where I'm like, I don't even know what I think we should do here, but I think something. But if you don't have any ideas...like, I don't have any ideas specifically. If you don't have any ideas, it's fine. We'll continue on with this and maybe revisit it down the road. But I want to make sure each of those different tiers is actionable for the other person, and I'm not just giving them homework or something to be sad about because that would be bad code review. STEPH: I'm just imagining a PR comment that says, "I don't know what we should do here. But I don't think this is it," [laughs] and that just creating sadness. That's so interesting to me because I have flip-flopped with that opinion in regards to there are times that I very much resonate and do what you just said where I will point out to someone where I'm like, "I'm not sure why, but I just have concerns about this. And I don't know if you also ran into anything that was weird about this and would like to talk about it. I don't have any really great ideas, so I think this is good for now. And we should keep moving forward, so we're not blocked on it," but just wanted to, as you mentioned, highlight it in case it sparks something for the other person or for someone else that's reviewing the code. And then there are other times where I'll look at something, and I'm like, "Yeah, it's not great. There's something that feels brittle or potentially maybe hard to maintain or things like that. But I don't have a better idea." And I don't comment on it because I'm like, I don't want to distract that person or block them. And I do think it's good enough, and I don't have anything to add to the conversation, so I just leave it out. So it's interesting to me where is that line of when I feel like it's important enough to comment to then potentially spark some conversation versus just letting it go so then I don't add any distraction to their work? CHRIS: I think it's when the spidey-sense gets past 47%. It's a very specific number. I do the same thing where there's something, and I'm like, you know what? I can't even clearly express what about this makes me feel something off, and so I won't even comment on it, and I agree. And then there are things that trip past some magical line in the sand. And I'm like, you know what? I think I'm going to say something here, but I don't even have a recommendation. And then there's a whole spectrum of the nature of code review and, again, 47% being the specific number. STEPH: There's actually a thoughtbot blog post that correlates nicely to that concept of spidey sense. It's written by Mike Burns, and it's titled How to Skim a Pull Request. But essentially, grabbing from one of the lines here is where Mike presents an unexplained, incomplete, and arbitrarily grouped list of keywords that will cause us thoughtboters to read your code with more care and suspicion. [laughs] That feels perfectly aligned with that idea of spidey sense, spidey-sense 101. I'll be sure to include a link in the show notes. Or, you know, 40%. CHRIS: I think it was 47%. It's a very precise number. [chuckles] STEPH: Very precise nonsensical number. Got it. [laughs] CHRIS: If I'm making up fake statistics, I'm not going to have them round to an even 10. [laughter] STEPH: Makes it seem more legit somehow. CHRIS: Exactly. STEPH: But that's really the novelties that I wanted to chat about. Mid-roll Ad And now a quick break to hear from today's sponsor, Scout APM. Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more. Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform. See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed. STEPH: What's new in your world? CHRIS: I have some follow up on a recent topic that we talked about. So we had a kerfuffle which I described where we had a branch that got merged and the rebase some stuff got out of hand. And so we introduced some process, the protected branch configuration within GitHub that required the branches to be up-to-date before they can be merged and CI to be passing. And everybody was happy. It was like, this is great. Turns out it was never turned on. That's actually the day I was like, man; this is really straightforward. There's been no annoyance here. And then I got to the point where it was like; this seems weird because we just merged a lot of things in rapid succession. I went and checked, and it turns out what I thought was the name of the branch protection rule in GitHub's UI is, in fact, a regular expression pattern. It might not be a full regular expression but like a wildcard pattern for the branch name to match to, and so it's specific. I created this rule, and in small, gray text underneath, it said, "This applies to zero branches." I missed that the first time but then the second time going back, I was like, oh, I actually wanted it to apply to more than zero branches. So I went back in and changed that. It's a great example of very subtle UI that just slipped past me. STEPH: I was going to say in your defense, the very subtle gray font to say, "This applies to zero," feels tricky. CHRIS: That...also, going through the work of creating this thing and if that results in zero branches that would match, maybe that's the thing to emphasize on creation. I would love that. Because in my case, I was trying very specifically to target an existing branch. There is the ability to say, "Oh, any bugfix-* named branch," if you're using branch naming strategies like that, you can use this for that sort of thing. So it may be that currently, there are no branches with that name. But in my case, I was just like, please, main, anytime anything is happening on main, that is what we want to do. I just needed to put the word main there. But anyway, once I actually turned it on, insufferable, absolutely not, cannot survive in this world. We have a relatively small team. There are three of us, and not everyone is even full-time, and my time is pulled in a lot of different directions. So I'm actually not pushing as much code as I might otherwise. Even with that, nope, absolutely not. Our CI is like; I don't know, five-ish minutes per run. Turns out, especially Monday mornings, we have a volley of things that will have been reviewed and trickled in through Friday afternoon. And then there's a bunch of work we want to land Monday morning. And then, just at any point, it turns out, yes, this was untenable. So we have turned it off. I would like to revisit this down the road and introduce the MergeQueue functionality, so the idea of being able to say, "Yeah, you just name when you want something to go in, and then the system will manage the annoying finicky work there." But for now, I had to give up on my dream of everything running on CI, on a feature branch, before it gets merged. STEPH: Ooph, that phrase, "I had to give up on my dream," that breaks my heart for you. [laughs] CHRIS: I may be going a little bit fanciful with my language but, like, a little. STEPH: [laughs] CHRIS: I liked this thing. I want to exist in that world. But it is not feasible given the current state of the world. And that will only get worse over time, is my expectation. So I get to revisit this when I have the time to more thoroughly figure a thing out. But for now, I don't know, merge whatever; it will be fun. STEPH: There's a small part of me that feels a little reassured that it was a terrible time, although I hate that it was a terrible time. But I have felt that pain on so many other projects where I am constantly waiting, and I'm constantly checking to be like, can I merge? Can I merge? Can I merge? And then I can merge, but then someone beats me to it. And I'm like, oh, then I got to restart. And I got to wait, and I'm constantly checking. So that feels like it helps validate my experience. [chuckles] I am excited for that MergeQueue. I would be super excited to try that out and hear about how it goes just because that seems more like the dream where you can just say, hey, I want this PR to go whenever it can go. Just take care of it. I want it to be rebased, whatever the flow is, and have it be merged, so I don't ever have to check on it again. CHRIS: But once we configured this, there was a new thing that appeared in the GitHub UI, which was auto-merge. And so that was a button where I could say like, "Hey, merge this whenever CI passes," which was a nice upgrade, but it didn't have the additional logic of and rebase as necessary. Or the more subtle logic of like, you don't actually want to rebase where you have five different branches that are all trying to merge, and they keep rebasing. You want to have the idea of a queue, and so you get in line. And you rebase when it's your turn, and then you run the CI. And you try and be as smart as possible about that. If anyone at GitHub is listening, I would love if you all threw this into your platform, and then you could ping Slack if anything went wrong. But otherwise, there are, like I said, existing tools. At some point, I will probably, I don't know, over a long weekend or something like that, sit down with a large cup of coffee and explore these. But today is not that day. STEPH: I'm excited to hear about that day. CHRIS: So that is a tale of woe and sadness. But luckily, I get to balance it out with a tale of happiness and good outcomes. So that's good. The happiness and good outcome story does start with trouble, as they always do. So we had a bug that occurred in the application where something was supposed to have happened. And then there was an email that needed to go out to tell the user that this thing had happened. And the bug popped up within AppSignal and said something was nil that shouldn't have been nil. Particularly, we're using a gem called Time For a Boolean, which is by Caleb Hearth. And he's a former thoughtboter and maintains this wonderful gem that instead of having a Boolean for like, is this thing approved, or is it paid? Or is it processed? You use a timestamp. And then this gem gives you nice Boolean-like methods on top of that timestamp. Because it turns out, very often just having the Boolean of like, this was paid, it turns out you really want to know when it was paid. That would be a really useful piece of information. And so, while you're still in Postgres land, it's nice to be able to reach for this and have the affordances of the Boolean-like interface but also have the timestamp where available. So anyway, the email was trying to process but that timestamp...let's pretend that it was paid as the one that matters here so paid at was nil, which was very concerning. Because this was the email that's like, hey, that thing was processed. Or let's say it was processed, actually, because that's closer to what it was. Hey, this thing was processed, and here's an email notification to tell you that. But the process timestamp was nil. I was like, oh no. Oh no. And so when I saw this pop up, I was like, this is very bad. Everything is very bad. Oh goodness. Turns out what had happened was...because I very quickly chased after this, looked in the background job queue, looked in Sidekiq's UI, and the job was gone. So it had been processed. I was like, wait a minute, how? How did this fix itself? Like, that's not the kind of bug that resolves itself, except, in this case, it was. This was an interaction that I'd run into many times before. Sidekiq was immediately processing the job. But the job was being enqueued from within the context of a database transaction. And the database transaction had not been committed yet. But Sidekiq was already off to the races trying to process. So the record that was being worked on, the database record, had local changes within the context of that transaction, but that hadn't been committed. Sidekiq then reads that record from the database, but it's now out of sync because that tiny bit of Sidekiq is apparently very fast off to the races immediately. And so there's just this tiny little bit of time that can occur. And this is also a fun one where this isn't going to happen every time. It's only going to happen sometimes. Like, if the queue had a couple of other things in it, Sidekiq probably would have not gotten to this until the database transaction had fully closed. So the failure mode here is super annoying. But the solution is pretty easy. You just have to make sure that you enqueue outside of the database transaction. But I'm going to be honest, that's difficult to always do right. STEPH: That's a gnarly bug or something to investigate that I don't think I have run into before. Could you talk a little bit more about enqueueing the job outside the database transaction? CHRIS: Sure. And I think I've talked about this on a previous episode a while back because I have run into this one a few times. But I think it is sufficiently rare; like, you need almost a perfect storm because the database transaction is going to close very quickly. Sidekiq needs to be all that much more speedy in picking up the job in order for this to happen. But basically, the idea is within some processing logic that we have in our system; we find a record, we do some work. And then we need to update that record to assign this timestamp or whatever it is. And then we also want to inform the user, so we're going to enqueue a job to send the email notification. But for all of the database work, we are wrapping it in a transaction because we want it to either succeed or fail atomically. So there are three different records that we need to update. We want all of them to be updated or none of them to be updated. So, therefore, we wrap it in a transaction. And the way we had written, this was to also enqueue the job from within the transaction. That wasn't something we were actively intentionally doing because those are different systems. It doesn't really mean anything. But we were still within the block of ApplicationRecord.transaction do. We're now inside of that block. We're doing all of the record updates. And then the last piece of work that we want to think about is enqueueing the job to send the email. The problem is if we're still within that database transaction if it's yet to be committed, then when Sidekiq picks up that job to run it, it will see the prior state of the world. And it's only if the Sidekiq job waits a little bit that then the database transaction will have been committed. The record is now updated and available to be read by Sidekiq in the correct updated state. And so there's this tiny little bit of inconsistency that can happen. It's basically because Sidekiq is going out to Redis, which is a distinct system. It doesn't have any knowledge of the database transaction at play. That's why I sometimes consider using a Postgres-backed background job system because then actually the job can be as part of the database transaction. STEPH: Cool. That's helpful. That makes a lot of sense the way you explained the whole you're actually enqueueing the job from inside that transaction. I'm curious, that prompts another question. In the case where you mentioned you're using a transaction because you want to make sure that if something fails to update so, everything gets updated together, in the event that something does fail to update because you were previously enqueueing that job from the transaction, does that mean that the update could have failed but that email would still have gone out? CHRIS: That does not. And the reason for that is because we're within dry-monad world. And so dry-monad will implicitly capture the ActiveRecord rollback, which I think is an exception that gets raised or somehow...But basically, if that database transaction fails for any reason and ends up getting rolled back, then dry-monads will not continue processing through the rest of the sequential operation. And so, therefore, even if we move the enqueuing of the email outside of the database transaction, the sequential nature of that processing and the dry-monad stuff that we have in play will handle that. And I think that would more generally be true because I think Rails raises an exception on rollback. Not certain there. But I know in our case, we're fine on that. And we have actually explicitly checked7 for that sort of thing. STEPH: So I meant a slightly different question because that makes sense to me everything that you just said where if it's outside of the transaction, then that sequential order won't fire because of that ActiveRecord migration error. But when you have the enqueuing inside of the transaction because then that's going to be inside of the sequential order, maybe before the rollback error gets raised. Does that make sense? CHRIS: Yes. I think what you're asking is basically like, do we make sure to not send the job if the rest of the stuff didn't succeed? STEPH: I'm just wondering from a transaction perspective, actually. If you have a transaction wrapped block and then you have in there, like, update this record, send email, end block, let's say update...well, I guess it's going raise because you've got probably like an update bank. Okay, so then yeah, you won't get to the next line. Got it. Got it. Got it. I just had to walk myself through that because I forgot that you probably...I have to visualize [laughs] as to what that code probably looks like. All right, that answered my question. CHRIS: Okay. So back up to the top level then, this is the problem that we have. And looking through the codebase, we actually have it in a bunch of different places. So the solution in any one of those cases is to just take the line of code where we're saying enqueue UserMailer.deliver_later take that line of code, move it outside of the database transaction, and make sure it only happens if the database transaction succeeds. That's very easy to do in one case. But my concern was this is a very easy failure mode to end up in. And this is a very easy incorrect version of the code to write. As far as I can tell, we never want to write the code where this is happening inside of the transaction because it has this failure mode. But how do we enforce that? That was the thing that came to mind. So I immediately did a quick look of like, is there a RuboCop thing I can do here or something? And I actually found something even more specific, which was so exciting to find. It's a gem called Isolator. And its job is to detect non-atomic interactions within database transactions. And so it's fantastic. I was like, wait, really? Is this going to do the thing? And so I just installed the gem, configured it where I wanted, and then ran the test suite. And it showed me every place throughout the app right now where we were doing this pattern of behavior like enqueueing work from within a database transaction, which was great. STEPH: Ooh, that's really nifty. I kind of want to install that and just run it on my current client's codebase and see what I find. CHRIS: This feels like something like strong migrations where it's like, yeah, this is great. I kind of want to have this as part of my core toolset now. This one feels even perhaps slightly more so because sometimes I look at strong migrations, and I'm like, no, no, no, strong migrations, I get why you would say that, but for reasons, this is actually fine. And they have configurations within it to say, like, no, this is okay. Isolator feels like it's always telling me something I want to know. So this, very quickly, I'm like, I think this might be part of my toolset moving forward on every single app forever. And actually, there's another gem that I used. It's made by the same team. So this is from the folks over at Evil Martians, which is another Rails consultancy out there in the world. And the Isolator gem is one thing that they've produced. And then I think the same author of it who is an Evil Martian's employee created the aftercommiteverywhere gem. So aftercommit is one of Rails' ActiveRecord callbacks. But in this case, it allows you to use it everywhere, as the name implies. And so rather than actually having to take that line of code out of the database transaction block, which is naturally where we would write it because that's how we think about the code and how we want to express it, you can just use this aftercommit method, wrap the call in that, so it's after_commit, and then a block. So either braces or do..end. That enqueueing of the email now just gets wrapped in that. And so what that does is it says, "Defer this until after the transaction commits. If the transaction does not commit, if we roll it back, then don't run it." And what was nice is the actual code change when I finally submitted all of this was add the gem to the gem file. And then everywhere that we're doing the wrong thing, which running the test suite told me, I just went in, and I wrapped that line in after_commit and a block. And it was such a nice, clean...like, I didn't have to move the code around or actually shift the lines, which was my first attempt at this. I was able to just annotate each of those lines and say, "You're special, you're special, you're special," And then I'm done. And again, the first gem told me every case where I needed to do that. It's like, well, this is a wonderful little outcome here. STEPH: That's really nice, yeah, how you can make the changes and then, like you said, re-run the test or re-run that gem, and it lets you know what else still needs to be updated. I'm intrigued where you mentioned you didn't have to move any lines, though. Maybe I just need to look at the gem and see it, but I'm still envisioning that you have your transaction do block. And then you're doing some things; you're updating records, and then you have your end. And then after that, it's when you want to enqueue the email. And with this after_commit, you actually added that method call inside of the transaction but then wrapped the call to Sidekiq to send the email inside of that block. CHRIS: Correct. Yeah. So it's basically like saying, "Here's almost an anonymous function." If you think about a Ruby block in that nomenclature, you're saying, like, here's some work to do when and if the transaction succeeds. And so it meant that I was able to keep the code in the way that we as humans would talk about it but deal with the murky details, and edge cases of database transactions, and Sidekiq, and whatnot. Sort of just handle it by saying like...it almost feels like an annotation or a decoration or something like that. But it was this, in my mind, almost like a perfect melding of I don't want to think about this. Oh, cool. Okay, here's a quick, easy way to deal with it but to not have to fundamentally change how I write the code. STEPH: Interesting. So I like all the things you're saying. I'll be honest, I'm not totally sold, and I'm trying to think of why. I think the benefits...one, as you mentioned, it's something you don't have to think about or at least signals to others that hey, maybe you should think about this to the extent that you use after_commit. And so that way, you don't have these asynchronous events taking place inside the transaction. So I like that visibility and communication to the rest of the team. Putting it inside of the transaction feels interesting. I don't know why; I feel a little weird about this. [laughs] I'm bringing my true self. CHRIS: That's fair. So if we're being honest, I solved this first by finding the Isolator gem. Well, I solved it first by just doing it manually. I went through the app, and I found all the places. And I was like, you know what? I'm worried that the next person authoring code like this, it's so easy to fall into this trap. Like, this is such a subtle little thing that our brains are not thinking about. And so I had first fixed it, and so I had a diff that involved moving lots of lines of code, every instance of this moved from being in the database transaction out of it. And that was fine. I was fine with that as a solution. But it was a little bit noisy because I was moving a bunch of lines. So then I brought in the Isolator gem. I actually reset that, and I went back to before I had made the fix, ran the test just to make sure Isolator was actually finding every instance. They did; that was great. So I was like, all right, cool. This is better because now I have this thing that will tell anyone when this happens. So I'm very happy about that. Because frankly, this is some hard-earned knowledge that I had to read Sidekiq and remember how database transactions work and convince myself of what was going on here and finally come to what I believe the solution is. And now Isolator is just like, cool, that's encapsulated. And it gives a very nice failure message in the test suite. So it's like, excellent. I really like this. But still looking at it, the diff, the amount of code that I had to change, it's like, well, naturally, this is how we want to write this code, but for reasons, we can't. And it's appeasing the computer more than it's appeasing the reader or the author of the code. And so then I happen to be reading through the Isolator gem's README, and they mention the aftercommiteverywhere gem. And I was like, oh, that's interesting. So one more time, I reset. And then I really tried fixing it with after_commit. And the look of the diff there felt nice to me because the lines got a little more on them, but they didn't move. And so it's like, this is how we naturally would have authored it, and now it works correctly. And I liked that. But I understand your hesitation because you're like, but the thing is, it's wrong. And so you've made the wrong not wrong anymore, but you didn't...and so I get your hesitation. I still like the fancy version. STEPH: Yeah, I think you just helped me figure out my grumpiness with it or why I'm not totally sold on it. And it was in regards to adding a dependency to avoid a noisy diff is the oversimplified version that I was processing or the reason that I was a bit grumpy about adding this other gem for that. But then you also just brought a lot of other really good reasons. One thing that you said that I do really like is adding tools that help us author code in a more natural style, the way that we want to highlight this process, and how this application does work, and how this business logic flows. So given in that light, that makes me feel better about it. But yeah, I think that was my initial grumpiness. I was like, it'll be a noisy diff. It's okay. CHRIS: I think I definitely share your hesitation, or you're like, hmm, that's an interesting reason to bring more code into the application. But at the same time, I think the counterpoint that comes to mind for me is we're using Ruby because of its expressiveness; at least, that's why I'm using Ruby. I really want the code that I write to be as close as possible to the thing that I would say to another human about like, oh okay, when a user signs up for the application, we need to create a record in our system, and then we need to send them an email. And then we need to do this other thing. And so, the closer that our code is to those words that I would use to describe to another human, the happier I am. And I will put in some pretty significant effort to hold that line as long as the code can also be correct. And so, the Isolator gem here does a great job of enforcing that correctness. And then after_commit allows me to still maintain that expressiveness and not have to think about the murky details as much or not have to reshape my code to match the murky realities of different persistence engines. But I do agree. I think it's a good thing to look at and ask, like, is it worth it? Are you sure? And in this case, I will say, "Yeah, I think so," but with that amount of certainty in my voice, [chuckles] which is not a ton. STEPH: I think this is going back to my days of working with dependency bot PRs where every time there was an upgrade for a gem, I always ask, what do you do here? [chuckles] Do we need to upgrade you? Can we just remove you from the codebase? So I'm fairly...I don't know, resistant is a strong word. I'm skeptical of when we're adding stuff in, and I just want to question the value that it's adding. But I want to circle back to something that you said, and that is hard-earned knowledge. And that part I understand so much where when you have gone through a fair amount of work to uncover an issue, and then you want to make sure that others don't have to go through that. This is a really nice way to highlight; hey, there's something that's tricky about computers and software here, and we need to watch out for that. And I want to help you lookout for that. Versus this is just inherit information where this needs to happen outside or after that transaction. And so that makes a really nice entry point where someone can look to say, "Why did we add this gem?" And then there's a commit message that goes with it that explains this is why we use this after_commit gem because we're specifically looking to avoid this type of bug. And I love that. CHRIS: Yeah, I think more lines of git commit message than diff on this one. So yeah, I wrote a short novel describing all of the features, describing the different pieces that are coming together. And then it's actually a +28 -6 diff. So it's a very small code change. But yeah, lots of story captured there. STEPH: And if you had just moved the lines, you could still have that commit message. But it's not likely that someone's going to look up that git commit change or that message that went along with it because they're not going to know to blame that one. But if they look at that particular edition of after_commit, they're more likely to find that historical context. So long story short, I think you have walked me through my initial grumpiness and provided some really good ways to avoid that really tricky failure mode for other developers. CHRIS: Well, thank you. I'm getting Steph's seal of approval starting from grumpy places. [laughs] I feel good. All right. STEPH: I'll have some special Stephanie's approval stickers designed and printed for you. CHRIS: I hope you're not joking because I very much want a yellow heart that says, "Steph-approved." STEPH: [laughs] CHRIS: And I can put it on PRs, and I can put it on the wall. [laughs] STEPH: Well, now I have to find a sticker designer and make a...well, it's just a yellow heart. I can probably handle this. I'm going to use Comic Sans. That will be the approved part. [laughs] Yellow hearts and Comic Sans for everybody. CHRIS: Well, with that absolutely fantastic call back to earlier parts of the episode, shall we wrap up? STEPH: Let's wrap up. CHRIS: The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes, as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey STEPH: Or you can reach us at firstname.lastname@example.org 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.
On this episode meet Kim who recently completed an epic solo bikepacking adventure by completing the Katy Trail on her bike after being inspired by a female colleague who did the same adventure while back. At nearly 240 miles long, the crushed limestone Katy Trail spans nearly the full width of Missouri and is the country's longest continuous rail-trail, intersecting with rural farmland, scenic small towns, and centers of commerce and government on its route paralleling the Missouri River. And if you listened to episode 89 with Kevin Belanger from the Rails to Trail Conservancy, we talked a bit about the Rail Trail Hall of Fame. Back in 2007 the Katy Trail became the second member in the Rail-Trail Hall of Fame. Kim, who is a well versed solo female traveller, took a little over 5 days to pedal from Clinton, Missouri to Machens, Missouri, staying in hotels and bnbs along with way while carrying everything she needed in her waterproof and dustproof Ortlieb bike panniers. So here is Kim to talk about her Katy Trail bike adventure. www.murphologypodcast.com www.Patreon.com/Murphology
This week Jon and Justin discussed: Tweet: what should we talk about? Justin's daughter wrote an article for the Transistor blog: https://transistor.fm/gen-z/ Customer case studies Dynamic audio insertion Integration with Descript Book: Range by David Epstein What should we talk about next? Twitter: @buildyoursaas, @mijustin, @jonbuda Leave a review/comment on Podchaser; it's like Reddit, but for podcasts. Email us: email@example.com Thanks to our monthly supporters: Mitch Harris Kenny, Intro CRM podcast Oleg Kulyk Violette Du Geneville Take It EV podcast Ethan Gunderson Diogo Chris Willow Borja Soler Ward Sandler Eric Lima James Sowers (like Flowers) Travis Fischer Matt Buckley Russell Brown Evandro Sasse Pradyumna Shembekar (PD) Noah Prail Colin Gray Josh Smith Ivan Curkovic Shane Smith Austin Loveless Simon Bennett Michael Sitver Paul Jarvis and Jack Ellis, Dan Buda Darby Frey Samori Augusto Dave Young Brad from Canada Sammy Schuckert Mike Walker Adam DuVander Dave Giunta (JOOnta) Kyle Fox GetRewardful.com ★ Support this podcast on Patreon ★
Chris evaluates the pros and cons between using Sidekiq or Active Job with Sidekiq. He sees exceptions everywhere. Steph talks about an SSL error that she encountered recently. It's officially spooky season, y'all! sidekiq-symbols (https://github.com/aprescott/sidekiq-symbols) Transcript: CHRIS: Additional radiation just makes Spider-Man more powerful. STEPH: [laughs] Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Steph Viccari. CHRIS: And I'm Chris Toomey. STEPH: And together, we're here to share a bit of what we've learned along the way. Hey, Chris, what's new in your world? CHRIS: Fall is in the air. It's one of those, like, came out of nowhere. I knew it was coming. I knew it was going to happen. But now it's time for pumpkin beer and pumpkin spice lattes, and exclusively watching the movie Hocus Pocus for the next month or so or some variation of those themes. But unrelated to that, I did a thing that I do once, let's call it every year or so, where I had to make the evaluation between Sidekiq or Active Job with Sidekiq, as the actual implementation as the background job engine that is running. And I just keep running through this same cycle. To highlight it, Active Job is the background job system within Rails. It is a nice abstraction that allows you to connect to any of a number of them, so I think Delayed Job is one. Sidekiq is one. Resque is probably another. I'm sure there's a bunch of others. But historically, I've almost always used Sidekiq. Every project I've worked on has used Sidekiq. But the question is do you use Active Job with the adapter set to Sidekiq and then you're sort of living in both worlds, or do you lean in entirely and you use Sidekiq? And so that would mean that your jobs are defined to include Sidekiq::Worker because that's the actual thing that provides the magic as opposed to inheriting from Application Job. And then do you accept all of the trade-offs therein? And every time I go back and forth. And I'm like, well, but I want this feature, but I don't want that feature. But I want these things. So I've made a decision, but I want to talk ever so briefly through the decision points that were part of it. Have you done this back and forth? Are you familiar with the annoying choice that exists here? STEPH: It's been a while since I've had the opportunity to make that choice. I'm usually joining projects where that decision has already been made. So I can't think of a recent time that I've thought through it. And my current project is using that combination of where we are using Active Job and Sidekiq. CHRIS: So I think there's even a middle ground there where that was the configuration that I'd set up on the project that I'm working on. But you can exist in both worlds. And you can selectively opt for certain background jobs to be fully Sidekiq. And if you do that, then instead of saying, "Performlater," You say, "Performasync." And there are a couple of other configurations. It gives you access to the full Sidekiq API. And you can do things like hey, Sidekiq, here's the maximum number of retries or a handful of other things. But then you have to trade away a bunch of the niceties that Active Job gives. So as an example, one thing that Active Job provides that's really nice is the use of GlobalID. So GlobalID is a feature that they added to Rails a while back. And it's a way to uniquely identify a given record within your system such that when you say performlater, you can say, InvitationMailer.performlater and then pass it a user record so like an instance of a user model. And what will happen in the background is that gets serialized, but instead of serializing the whole user object because we don't actually want that, it will do the GlobalID magic. And so it'll turn into, I think it's GID:// so almost like a URL. But then it'll be, I think, your application name/model name down the road. And the Perform method actually gets invoked via the background system. Then you will just get handed that user record back, but it's not the same instance of the user record. It sort of freezes and thaws it. It's really nice. It's a wonderful little feature. Sidekiq wants nothing to do with that. STEPH: I'm so glad that you highlighted that feature because that was on my mind; I think this week where I was reviewing...somebody had made the comment where they were concerned about passing a record to a job and saying how that wouldn't play nicely with Sidekiq. And in the back of my mind, I'm like, yeah, that's right. But then I was also I'm pretty sure this got addressed, though. And I couldn't recall specifically if it was a Sidekiq enhancement or if it was a Rails enhancement. So you just cleared something up for me that I had not had time to confirm myself. So thanks. CHRIS: Well, to be clear, this works if you are using Active Job with Sidekiq as the adapter, but not if you are using a true Sidekiq worker. So if you opt-out of the Active Job flow, then you have to say, "Perform_async," and if you pass it a record, that's not going to work out particularly nicely. The other similar thing is that Sidekiq does not allow the use of keyword args, which, I'm going, to be honest, I really like keyword arguments, especially for background jobs or shuttling data through your system. And there's almost a lazy evaluation. I want some nicety to make sure that when I am putting something into a background job that I'm actually using the correct call signature, essentially passing the correct data in the correct shape. Am I passing a record, or am I passing the ID? Am I passing a list of options or a single option? Those sort of trade-offs that are really easy to subtly get wrong. I came around on this one because I realized although Active Job does support keyword arguments, the way it does that is it just has a JSON serialization format for them. So a keyword argument turns into a positional array with an associated hash that allows for the lookup or whatever. Basically, again, they handle the details. You get to use keyword args, which is great, with the exception that when you're actually calling performlater, that method performlater is a method missing type magic method. So it does not actually check the keyword arguments at that point. You're basically just passing an options hash as opposed to true keyword arguments that would error because they don't match up. And so when I figured that out, I was like, oh, never mind. This doesn't actually do the thing that I care about. It's a little bit nicer in terms of the signature of the method when you're defining your background job itself, but it doesn't actually do any logical checking. It doesn't give me any safety or robustness within my system. So I don't care about that. I did find a project called sidekiq-symbols, which does some things under the hood to how Sidekiq serializes and deserializes jobs, which I think gives largely the same behavior as Active Job. So I can now define my Sidekiq jobs with keyword arguments. Things will work. I can't use GlobalID. That's still out. But that's fine. I can do a little helper method that basically does the same thing as GlobalID or at least close approximation. But sidekiq-symbols lets me have keyword arg-like signatures in my methods; basically, it is. But again, it doesn't actually do any check-in when I'm enqueueing a job, and I am sad about that. STEPH: Yeah, that's another interesting distinction. And I'm unsurprisingly with you that I would favor having keyword args and having that additional safety in place. Okay, so I've been keeping track. And so far, it sounds like we have two points because I'm doing a little scorecard here between Active Job and Sidekiq. And we have two points in favor of Active Job because they offer a GlobalID, which then allows us to pass in a record, and then it takes care of the serialization for us. And then also, keyword args, which I agree with you that's a really nice feature to have in place as well. So I'm curious, so it sounded like you're leaning towards Active Job, but I don't want to spoil the ending. CHRIS: Yes, I could see why that's what you would be taking away from the conversation thus far. So again, just to reiterate, Active Job and Sidekiq with this sidekiq-symbols extension they both support keyword args, kind of. They support defining your job with keyword args and then enqueueing a job passing something that looks like keyword args. But it ends up...nobody's actually checking anything, so it's mostly like a syntactic nicety as opposed to any sort of correctness, which is still nicer, but it's not the thing that I actually want. Either way, nobody supports it, so it is not available to me. Therefore, it is not a consideration point. The GlobalID thing is nice, but it is really, again, it's a nicety more than anything. I have gone, and I'm leaning in the direction of full Sidekiq and Sidekiq everywhere as opposed to Active Job in most cases, but then Sidekiq when we need it. And that's because Sidekiq just has a lot more power and a lot more functionality. So, in particular, Sidekiq has a feature which allows you to say...it's a block that you put at the top of your Sidekiq job that says retries exhausted or something. I think Sidekiq retries exhausted is the actual full name of that at that point, which is really unfortunate in my mind, but anyway, I'll deal. At that point, you know that Sidekiq has exhausted all of the retries, and you can treat it as failed. I'm going, to be honest, I went on a quest to find a way to say, hey, I'm going to put some work into the background. It's really important for me to know if this work succeeds or if it fails. It's very easy to know if it succeeds because that just happens in-line in the method. But we can have an exception raised at basically any point; Sidekiq does a great job of catching those, of retrying, of having fundamental mechanisms there. But this is the best that I can get for this job failed. And so Active Job, as far as I can tell, does not have anything for this in order to say, yep, we are done. We are not going to keep working on this. This work has failed. It is dead. Dead is; actually, I think the more correct term for where we're at because failed is a temporary state, and then you retry after a failure. Whereas dead is, this has gone through all of its retries, and it will never be run again. Therefore, we should treat this as not having run. And in my case, the thing that I want to do is inform the user that this operation that we were trying to do on their behalf has not succeeded, will not succeed. And please reach out or otherwise deal with the fact that we were unable to do the thing that they asked us to do. That feels like a really important thing for me to be able to do, to be able to communicate back to my users. This is one of those situations where I'm looking at the available options, and I'm like, I feel like I can't be the only one who wants to know when something goes wrong. This feels like a thing that's important. But this is the best example that I've found, the Sidekiq retries exhausted block. And unfortunately, when I'm using it, it gets yielded the Sidekiq JSON blob deserialized, so it's like Ruby hash. But it's still like this blob of data. It's not the same data that gets passed into perform. And so, as a result, when I want to look up the record that was associated with it, I have to do this nested dig into the available hash of data. And it just feels like this is not a well-paved path. This is not something that is a deeply thought about or recommended use case. But again, I don't feel like I'm doing something weird here. Am I doing something weird, Steph, wanting to tell my users when I was unable to do the thing they asked me to do? [chuckles] STEPH: That feels like a very rhetorical question. [laughs] CHRIS: It does. I apologize. I'm leading the witness. But in your sincere heart of hearts, what do you think? STEPH: No, that certainly doesn't sound weird. I'm actually thinking back to some of the jobs that cause me stress in regards to knowing when they failed and then having that communication of knowing that we've exhausted all the retries. And, of course, knowing when those retries are exhausted is incredibly helpful. I am intrigued, though,, because you're highlighting that Active Job doesn't have the same option around setting the retry. And I'm trying to recall exactly how it's set. But I feel like I have set the retry count for Active Job. And maybe, as you mentioned before, that's because it's an abstraction, or I'm not sure if Active Job actually has that native support. So I feel a little confused there where I think my default instinct would have been Active Job does have that retry capability. But it sounds like you've discovered otherwise. CHRIS: I'm not actually sure what Active Jobs core retry logic or option looks like. So fundamentally, as far as I understand it, Active Job is an abstraction. And under the hood, you're always connecting an adapter. So it's either going to be Sidekiq, or Resque, or Delayed Job, or other. And each of those systems, whichever system you have as the adapter, is the one that's actually going to be managing retries. And so I know Sidekiq happens to have as a default 25 retries. And that spans, I think it's a two-week exponential back off. And Sidekiq has some very robust logic that they have implemented as the way retries exist within Sidekiq. I'm not sure what that would look like if you're trying to express it abstractly because it is slightly different. I know there was some good work that was done on Sidekiq to allow the Sidekiq options that's a method at the top level of the job, even if it's an Active Job job to express the retries. So that may be what you've seen, or there may be truly an abstraction that exists within Active Job, and then each adapter needs to know how to handle retries. But frankly, the what can Sidekiq do that Active Job can't? There's a whole bunch of stuff around limiting when you would retry limiting, enqueuing a job if there already exists one, when and how do those records get locked. There's a whole bunch of stuff. Sidekiq has a lot of power under the hood. And so if we want to be leaning into that, that's why I'm leaning towards let's just be Sidekiq all the time. Let's become Sidekiq experts. Let's accept that as a deep architectural decision within the app as opposed to just relying on the abstraction. Because fundamentally, if we're just using Active Job, we're not going to have access to the full power of Sidekiq or whatever the underlying system is, so sort of that decision that I'm making, but I don't know specifically around the retries. STEPH: Okay, thanks. That's really helpful. It's been a while since I've had to make this decision. I'm really enjoying you sharing your adventure because I'm trying to think what's the risk? If you don't use Active Job, what are the trade-offs? And you'd mentioned some of them around the GlobalID and keyword args, which are some niceties. But overall, if you don't go with the abstraction, if you lean into Sidekiq, the risk is then you want to migrate to a different enqueuing service. And something that we talk about is mitigating that risk, so then you can swap it out. That's also something I have never done or encountered where we've had to make that change. And it feels like a very low risk in my mind. CHRIS: Sidekiq feels like the thing you would migrate to, not a thing you would migrate from. It feels like it is the most powerful. And if anything, I expect at some point we'll be upgrading to Sidekiq pro or enterprise or whatever the higher versions that you pay for, but you get more features there. So in that sense, that is the calculation. That's the risk trade-off in my mind is that we're leaning into this technology and coupling ourselves more closely to it. But I don't see that as one that will reassess in the same way that people talk about Active Record and it being an ORM. And it's like, oh, we're abstracting the database underneath, and I'm like, no, I'm not. I'm always using Postgres. Please do not take Postgres. I'm not going to switch over to MySQL next week. That's totally fine if you start on MySQL. It's unlikely you're going to port over to Postgres. We may port to an entirely…like it's a Cassandra column store with a Kafka queue, I don't know, something weird down the road. But it's not going to be swapping out Postgres for MySQL or vice versa. Like you said, that's probably not a change that's going to happen. But that I think is the consideration. The other consideration I have in my mind is Active Job is the abstraction that exists within Rails. And so I can treat it as the lowest common denominator, and folks joining the project, it's nice to have that familiarity. So perform_later is the method on the Active Job jobs, and it has a certain shape to it. People may be familiar with that. Mailers will automatically use Active Job just implicitly under the hood. And so there's a familiarity, a discoverability. It's just kind of up the middle choice. And so if I can stick with that, I think there's a nicety there. But in this case, I think I'm choosing I would like the power and consistency on the Sidekiq side, and so I'm leaning into that. STEPH: Yeah, that makes a lot of sense to me. And I liked the other example you provided around things that were not likely to swap out and Postgres, MySQL, your database being one of them. And in favor of an example that I do have for something that...I do enjoy wrapping. It's not something that I adhere to strictly, but I do enjoy it when I have the space to make this choice. So I do enjoy wrapping HTTPClients, not just because then I can swap it out for a different HTTPClient, which frankly, that's also rare that I do that. Once I choose an HTTPClient, I'm probably pretty happy, and I don't need to swap it out. But I really like being able to extend to the API specifically if they don't handle error responses in a way that I would like to or if they raise, and then I want to change the API to have a more thoughtful interface and where I don't have to rescue those errors. But instead, I can interact with this object that then represents an error state. So that was just one example that came to mind for things that I do enjoy having an abstraction around and not just so I can swap it out because that feels like a very low risk, but more frankly, so I can extend the API. CHRIS: I definitely share the I almost always wrap APIs, or I try and hide whatever the implementation detail whether it be HTTPParty, or Faraday or whatever it is that I'm using and trying to hide that deeply within the system. And then I have whatever API client that we define. And that's what we're interacting with. It's interesting that you bring up errors and exceptions there because that's the one other thing that has caused me this...what I'm describing now seems perhaps like, oh, here's just a list of pros and cons, a simple decision was made, and there we are. This represents some real soul searching on my part, if we will. And one of the last things that I ran into that was just so frustrating is that Sidekiq is explicitly built around the idea of exceptions; Sidekiq retries if there is an exception raised in the job, otherwise, it treats it as success, and that's it. That is the entirety of it. That is the story. But if you raise an exception in a job, then you can't test that job because now it's raising an exception. You can't test retries or this retry exhausted block that I'm trying to lean into. I'm like, I want to put that in a feature spec and say, oh, this job goes in the background, but it's in a failure state, and therefore, the user sees the failure message. Sorry, I can't do that because the only way to actually fail a job is via an exception. And I've actually gone to some links in this application to try to introduce more structured data flow. I've talked a bunch about the command objects and the dry-monads and all those things. And I've really loved them where I've gotten to use them. But then I run into one of these edge cases where Sidekiq is like, no, no, no, you can't do that. And so now I have parts of my system that very purposefully return data as opposed to raising an exception. And I just have to turn around and directly raise that failure as an exception, and it just feels less expressive. I actually just ran into the identical thing with Pundit. They have a little bit better control over it; I can choose whether or not I want the raising version or not. But I see exceptions everywhere, and I want a little more discrete data flow. [chuckles] That is my dream. So anyway, I chose Sidekiq is the summary here. And slowly, we're going to migrate entirely to Sidekiq. And I'm going to be totally fine with it. And I'm done griping now. STEPH: This is your own little October Halloween movie, that I see exceptions everywhere. CHRIS: They're so spooky. STEPH: [laughs] That's cool about Pundit. I'm not sure I knew that, that you get to essentially turn on or off that exception flow behavior. On one hand, I'm like, that's nice. You get the option. On the other hand, I'm like, well, let's just not do it. Let's just never raise on people. But at least they give people options; that seems really cool. CHRIS: They do give the option. I think you can choose different strategies there. And also, if we're being honest, I'm newer to Pundit. And I used a different thing, which was to get the Policy Object and ask it a question. I wanted to ask, is this enabled or not? Can a user do this or not? That should not raise an exception. I'm just asking a question. We're just being real chill about this. I just want to know some information. Let's flow some data through our system. We don't need exceptions for that. STEPH: Why are you yelling at me? I just have a question. [laughs] CHRIS: Yeah. I figured out how to be easy on that front. Sidekiq apparently has no be easy mode, but that's fine. You know what? We're going to make it work, and it's going to be fine. But it is interesting deciding which of these facets of the system that I'm building do I really care about? Which are the ones where I'm like, whatever, just pick something, and we'll move forward, it's not a big deal? Versus, we're actually going to be doing a lot of work in the background. This is the thing that I care about deeply. I want to know about failure and success. I want to really understand that and have a robust answer to what our architecture looks like there. Similarly, Pundit for authorization. I believe that authorization will be a critical aspect of our system. It's typically a pretty important thing. But for us, I think we're going to have different types of users who can log in and see different subsets of data and having a consistent and concrete way that we have chosen to implement that we are able to test, that we're able to verify. I think that's another core competency within the app. But you only get to have so many of those. You can only be really good at a couple of things. And so I'm in that place where I'm like, which are our top five when I say are the things that I care a lot about? And then which are the things where I'm like, I don't know, whatever, just run with it? STEPH: Just a little bit ago, I came so close to singing because you said the I want to know phrase again. And that, I'm realizing, [laughs] is a trigger for me and a song where I want to sing. I held it back this time. CHRIS: It's smart. You got to learn anytime you sing on mic that is part of the permanent record. STEPH: Edward Loveall at thoughtbot, since I sang in a recent episode, did the delightful thing where then he grabbed that clip of where you talk a little bit, and then I sing and then encouraged everyone to go listen to it. And in which I responded, like, I would highly recommend that you save your ears and don't listen to it. But yes, singing on the mic is a thing. I do it from time to time. I can't hold it back. CHRIS: We all do. But since it doesn't seem that you're going to sing in this moment, I think I can probably wrap up my Odyssey of choosing between Sidekiq and Active Job. I hope those details were useful to anyone other than me. It was an adventure, so I figured I'd share it. But yeah, that about wraps it up on my side. Mid-roll Ad And now a quick break to hear from today's sponsor, Scout APM. Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more. Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform. See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed. STEPH: So, I would love to talk about an SSL error that I encountered recently. So one of the important processes in our application is sending data to another system. And while sending data to that other system, we started seeing the following error that the read "Certificate verify failed." And then in parens, it states, "Unable to get local issuer certificate." So upon seeing that error, I initially thought, okay, something is wrong with their SSL certificate or their SSL configuration. And that's not something that I have control over and can fix. So we should reach out and let them know to take a look at their SSL config. But it turns out that their team already knew about the issue. They had recently updated or renewed their SSL cert, and they saw our messages were no longer being processed, and they were reaching out to us for help. So at that point, I'm still pretty sure that it's related to something on their end, and it's not something that I can really fix on our end. But we can help them troubleshoot. Maybe there's a workaround that we can add to still get messages processing while they're looking into their SSL config. It seemed like they still just needed help. So it was something that was still worth diving into. So going back to the first error, I want to talk a little bit about it because I realized that I understand SSL just enough, just the surface to get by as a developer. But then, every time that I run into a specific error with it, then I really have to refresh my understanding as to what could be wrong, so then I can troubleshoot more effectively. So for anyone that could use a refresher on that certificate verification process, when your browser or your server is connecting to a site that uses SSL, then your browser server, whichever one you're using, is going to download that site certificate and verify a couple of things. So it's going to check does the certificate contain the domain name of the website? So essentially, you gave us a certificate. Is this your certificate? Does it match the site that we're connecting to? Is this cert issued by a trusted certificate authority? So did someone that we trust give you this certificate? And is the cert still valid, or has it expired? So that part is pretty straightforward. The second part, "Unable to get local issuer certificate," so that's the part I was less certain about. And I took this to mean that they had passed two of those three checks that their cert included the site's name, and it had not expired. But for some reason, we aren't able to determine if their cert was issued by someone that we should trust. So following that journey, my next question was, so what are they giving us? So this is a tool that I don't get to use very often, but I reached for OpenSSL and, specifically, the s_client command, which connects to a specified domain and prints all certificates in the certificate chain. You may already know this, but the certificate chain is basically a fancy way of saying, show me all the certificates necessary to prove your site certificate was authorized by a trusted certificate authority. CHRIS: I did not know that. STEPH: Okay, I honestly didn't either. [laughs] CHRIS: I liked that you thought I would, though. So thank you, but no. [chuckles] STEPH: Yeah, it's one of those areas of SSL where I know just enough. But that was something that was new to me. I thought there was a site certificate, and I didn't realize that there is this chain of certificates that has to be honored. So going back and looking through that output of the certificate chain, that's what highlighted to me that their server was giving us their certificate and saying, hey, you should trust our site certificate. It's legit because it was authorized by, let's say, XYZ certificate. And so if it were a proper certificate chain, then they would give us that XYZ cert. And essentially, we can use this chain of certificates to get back to a trusted authority that then everybody knows that we can trust. However, they weren't actually giving us a reference certificate; they were giving us something else. So essentially, they were saying, "Hey, look at our certificate and look at this very trustworthy reference that we have." But they're actually failing to give us that reference. So to bring it all home, we can download that intermediate certificate that they reference; that is something that is publicly accessible. That's why we're able to then verify each certificate that's provided in that chain. We could go and download that intermediate certificate from that certificate authority. We could combine that with their site-specific certificate, include that in our request to their system, and then complete the certificate chain. And boom, we're back in business. But it was quite a journey. CHRIS: That is quite the journey. And yeah, I definitely knew very little of that, although everything you're saying makes sense. And I have a bunch of cubbyholes in my brain for SSL knowledge. And the words you said all fit into the spaces that I have in my brain, but I didn't know a bunch of those pieces. So thank you for sharing that. SSL and cryptography, more generally or password hashing or things like that, occupy this special place in my brain where I'm both really interested in them. And I will occasionally research them. If I see a blog article, I'll be like, oh yeah, I want to read more about this password hashing. And what's a Salt? And what's a Pepper? And what are we doing there? And what is BCrypt versus SCrypt? What are all these things? This is cool. And almost the arms race on the two sides of how do we demonstrate trust in a secure manner on the internet? But at the same time, I am not allowed to do anything with this information. I outsource this as much as humanly possible because it's one of those things that you just should not do yourself and SSL perhaps even more so. So I have configured aspects of my password hashing. But I 100% just lean on the fact that Let's Encrypt exists in the world. And prior to that, it was a little more work. But frankly, earlier on in my career, I wasn't dealing with the SSL parts of things. But I'm so grateful to Let's Encrypt as a project that exists. And now, on almost every platform that I work with, there's just a checkbox for please do the SSL work for me, make it good, make it work, and then I will be happy. And I'm so glad that that organization exists and really pushed the envelope also. I forget what it was, but it was only like three years ago where SSL was not actually nearly as common as it is now. And now it is pervasive and everywhere. And all of the sites have it, and so that is a wonderful thing. But I don't actually know much. I know that I should have it. I must have it. I should force it. That's true. So I push that out… STEPH: Hello. CHRIS: Are you trying to get me to sing? [chuckles] STEPH: [laughs] No, but I did want to know if you get the reference, the Salt-N-Pepa. CHRIS: Push It Real Good the song? Yeah, okay. STEPH: Yeah, you got it. [chuckles] CHRIS: I will just say the lyrics. I shall not sing the lyrics. I would say that, though, that yes, yes, they do that. STEPH: Thank you for acknowledging my very terrible reference. Circling back just a little bit too in regards to...I'm with you; this is a world that is not one that I am very deeply technical in and something that I learned a fair amount while troubleshooting this particular SSL error. And it was very interesting. But there's also that concern where it's like, that was interesting. And we worked around the issue, but this also feels very fragile. So we still haven't fixed it on their end where they are sending the wrong certificate. So then that's why we had to do more investigative work, and then download the certificate that they meant to send us, and then send back a complete certificate chain so that we don't have this error anymore. But should they change anything about their certificate, should they renew anything like that, then suddenly, we're going to break again. And then, the next developer is going to have to go through the same journey. And this wasn't a light journey. This was a good half-day journey to figure out what was going on and to spend the time, and then to also get that fix out to production. So it's a meaningful task that I don't want anyone else to have to go through. But we are relying on someone else updating their configuration. So, on one hand, we're in a good spot until they are able to update. But on the other hand, I wrote a heck of a commit message for the next person just describing like, friend, just grab some coffee if we're going to chat. It's a very small code change, but you need to know the scoop. So should you need to replicate this because they've changed something, or if this happens…because we work with a number of systems that we send data to. So if someone else should run into a similar issue, they will understand some of the troubleshooting techniques that I used and be able to look up that chain and find out if there's a missing cert or something else they need to provide. So it feels like a win, but I'm also nervous for future selves, future developers. So there's another approach that I haven't mentioned yet, but it was often a top recommendation for when dealing with SSL errors. And specifically, it was turning off SSL verification. And I saw that, and I was like, well, that won't work. I'm definitely sending sensitive, important data. And I need to verify that who I'm sending this to is really the person that I want to send this data to. So that was not an option for me. But it made me very nervous how often that was an approach that people would recommend and be like, oh, it's okay, just turn off SSL. You'll be fine. Like, don't worry about it. CHRIS: I feel like this so perfectly fits into the...some of our work is finding the information and connecting the pieces together and making it work. But some of it is that heuristic sense, that voice in the back of your head that is like, wait, I'm sorry, what? You want me to just turn off the security perimeter and hope that the velociraptors won't come in? That doesn't seem like it's going to end well. I get that that's an easy option that we have available to us right now and will solve the immediate problem but then let's play this out. There are four or five Jurassic Park movies now that tell the story of that. So let's be careful. STEPH: It always ends super well, though, right? Like, it's totally fine. [laughs] CHRIS: [laughs] Exclusively. Although it's funny that you mentioned OpenSSL no verify because just this past week, I used that very same configuration. I think it was okay in my case; I'm pretty sure. But it is interesting because when I saw it, I was like, oh no, can't do that. Certainly not that. Don't turn off the security feature. That's the wrong way to deal with the issue. But in the particular case that I'm working with, I'm using Redis, Heroku Redis, in particular, in a Heroku configuration. And the nature of how Heroku configures the Redis instances and the connectivity to our app into our dyno...I forget why. I read an article. They wrote it; Heroku wrote it. I trust them; they're good. I've outsourced my trust to people that I do trust. The trust chain actually maps really well to the certificate trust chain. I trust that Heroku has taken security deeply seriously. And for some reason, their configuration of Redis requires that I turn on OpenSSL no verify mode. So I'm using this now both in Sidekiq, and then we're using our Redis instance for our Rails cache as well. So in both cases, I said, "It's fine. Don't worry about it." I used the Don't worry about it configuration. And I didn't love it but I think it's okay. And partly, I'm trying to say this into the internet radio right now just in case anyone's listening who's like, no, no, no, you can't do that. That's bad. So I'm willing to be deeply wrong on the internet in favor of someone telling me and then I get to get out in front of it. But I think it's fine. Pretty sure it's fine. It should be fine. STEPH: I love love love that you gave a very visual example of velociraptors, and then you're like, oh, but I turned it off. [laughs] So I'm going to start sending you a velociraptor gif each day. CHRIS: I hope you do. I hope the internet holds you accountable to that. STEPH: [laughs] CHRIS: And I really look forward to [laughs] moving forward because that's a great way to start the day. Well, it doesn't need to start the day, but I look forward to them. STEPH: [laughs] I am really intrigued because I'm with you. Like you said, there are certain entities that are in our trust chain where it's like, hey, you are running this for us, and so I do have faith and trust in you that you wouldn't steer me wrong and provide a bad recommendation. Someone on Stack Overflow telling me to turn off SSL verify uh; that's not my trust chain. Heroku or someone else telling me I'm going to take it a little more seriously. And so I'm also interested in hearing from...what'd you say? You're speaking into the internet phone. [laughs] What'd you say? CHRIS: I think I said internet radio. But yeah, in a way. I mean, we're recording over Skype right now. So in a manner of speaking, we're on the internet phone to make our internet radio show. STEPH: [laughs] Oh goodness, the internet radio. I'm also intrigued to hear if other people are like, oh, no, no, no. Yeah, that sounds like an interesting scenario. Because I would think you'd still want your connection to...you said it's for Redis. So you still want that connection to be verified. But then if Redis itself can't have a specific...yeah, we're testing the boundaries of my SSL knowledge here as to how the heck you would even establish that SSL connection or the verification process. CHRIS: Me too. And it also exists in an interesting space where Heroku is rather clear in their documentation about this. And it was a surprising claim when I saw it. And so, I don't expect them to be flippant about a thing that is important. Like, if they're like, "No, no, no, it is okay. You can turn off the security thing, don't worry." I trust that they're not just like, oh, we didn't think about it too much. But we figured why not? It's not a big deal. I'm sure that they have thought about it deeply because it is an important thing. And so in a weird way, my trust of them and the severity of what this thing represents, I'm like, oh yeah, I super trust that because you're not going to get a major thing wrong. You might get a minor, small, subtle thing wrong. But this is a pretty major configuration change. As I say it, I'm now getting more worried. I'm now like, I feel fine about this. This doesn't seem like a problem at all. But then I keep saying stuff, and I'm like, oh no. That's why I love having a podcast; I find out things about myself as I talk into a microphone to you. STEPH: We come here to share our deep, dark developer secrets. Chris: Spooky developer therapy. STEPH: But just to clarify, even though you've turned off the SSL verify, you're still connecting over SSL. CHRIS: Yes, I believe that's the case. And if I'm remembering, I think the nature of how this works is they're using a self-signed certificate because of shared infrastructure or something, something that made sense when I read it. But it was the idea that they are doing a self-signed certificate. Therefore, to what you were talking about earlier, there isn't the certificate authority in the chain of those because it's self-signed. And so, they are not a trusted certificate authority. Therefore, that certificate that they have generated would not be trusted. But it does still allow for the SSL handshake and then communication to happen over SSL. It's just that fundamental question of trust. I'm saying, in this case, for reasons, it's okay. Trust me that I trust them. We're good. Which, again, I don't feel great about, but I think yes, it is still SSL, but it is a self-signed certificate. So we have to make this configuration change. STEPH: Yeah, all of that makes sense. And it certainly sounds like you have been very thoughtful about that change and put in some investigative work. So on that note, I have a very unrelated bad joke for you. CHRIS: I'm very excited. STEPH: All right, here we go. All right, so what do you call an alligator wearing a vest? CHRIS: I don't know. What do you call an alligator wearing a vest? STEPH: An investigator. [laughter] On that note, shall we wrap up? CHRIS: Oh, let's wrap up. We should also include a link in the show notes to the episode where you told the joke about the elephant hiding in the trees because that's one of my favorite jokes. You slayed me with that one. [laughs] But on that note, yes, let us wrap up. The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes,,as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey STEPH: Or you can reach us at firstname.lastname@example.org 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.
The Great American Rail-Trail, launched by Rails-to-Trails Conservancy nearly three years ago is a proposed network of nearly 4000 miles of off-road trails linking Washington, DC to the outskirts of Seattle, WA. Back in 2019, we chatted with Kevin Mills of RTC to get the scoop on this exciting project and what to expect in the years to come. Originally podcast February 7, 2019.