Distinction between alphabetic letters in taller, "upper" case and shorter "lower" case
POPULARITY
Hosts Will Larry and Victoria Guido are joined by Wes Bos, a full-stack developer, course creator, and podcaster. Wes shares his web development journey, from blogging and creating a successful book on Sublime Text to developing his popular online courses and hosting the Syntax podcast. He talks about the spontaneous start of his teaching career, his approach to creating content that is both approachable and practical, and the importance of making web development accessible to all learners. Wes discusses the evolution of his career, detailing his experiences in teaching at Ladies Learning Code and HackerYou and how he transitioned into selling online courses. He emphasizes the significance of offering quality content in his free and paid courses, ensuring his teachings are relatable and helpful for real-world applications. Wes also delves into the technical aspects of managing his course platform, discussing the benefits of having complete control over his content and the challenges he faces, such as content theft and logistical issues in distributing his popular sticker packs. The conversation shifts to the role of AI in web development, where Wes highlights its impact on coding efficiency and the need for developers to adapt to AI integration in applications. He advises beginners in web development to be wary of over-relying on AI, emphasizing the importance of understanding the fundamentals of coding. The episode concludes with Wes offering advice for content creators in the tech space, stressing the importance of sharing knowledge and its positive impact on the community. He encourages listeners to stay passionate and continuously learn in the ever-evolving field of web development. Wes' Online Courses (https://wesbos.com/courses) Sublime Text Power User Book (https://wesbos.com/sublime-text-book) Syntax Podcast (https://syntax.fm/) Ladies Learning Code (https://www.canadalearningcode.ca/) HackerYou (Now Juno College) (https://junocollege.com/) Follow Wes Bos on LinkedIn (https://www.linkedin.com/in/wesbos/) or X (https://twitter.com/wesbos). Visit his website: wesbos.com (https://wesbos.com/). Follow thoughtbot on X (https://twitter.com/thoughtbot) or LinkedIn (https://www.linkedin.com/company/150727/). Become a Sponsor (https://thoughtbot.com/sponsorship) of Giant Robots! Transcript: WILL: This is the Giant Robots Smashing Into Other Giants Robots podcast, where we explore the design, development, and business of great products. I'm your host, Will Larry. VICTORIA: And I'm your other host, Victoria Guido. And with me today is Wes Bos, a Full-Stack Developer, Coursemaker, and Podcaster. Wes, thank you for joining us. WES: Thanks for having me; stoked to be here. VICTORIA: Can you tell me, you know, on top of all of these skills that you have, podcasting, you're making courses; you're also doing development full-time; I heard that you've also picked up a new hobby in making stickers and, like, designing merch for aligning with some of your marketing goals. WES: Yeah. All right. So, my name is Wes Bos. I'm a full-stack developer from Canada, and I do primarily two things: I make web development training courses, and I have a podcast called Syntax in which we release three episodes a week and talk about everything related to HTML, CSS, JavaScript, Node, just web development and things that surround it. WILL: I want to see how you started in those courses. I know a little bit about your story because I remember when I first started in development. I think it's gotten a little better, but I was the only junior at one of the first companies I started at. And I went through a bootcamp and then became a junior. And I was like, how do I develop? Like, how do I get better? And they were like, "Wes Bos, his course. WES: [laughs] WILL: Go to Wes Bos." [laughs] And so, I did that, and it helped me tremendously. But it's interesting. I just want to see how you started. I know some of your background with ladies who code, and I think HackerYou. So yeah, wherever you want to start, bring us into the beginning of Wes Bos. WES: So, I've been a web developer forever, a good chunk of my life. And back in, like, the blogging days, I was doing a lot of posting blog posts and whatnot. And I had a couple of the blog posts do super well. And back in the day, it was like, you get tons of traffic, and you try to, like, seize the moment. Like, oh, there's, like, 50, 000 people on my website right now. Like, how do I, like, take advantage of that? So, what I did was I threw up a quick, little...it was a blog post about Sublime Text, which was the hot, new editor at the time. And I threw up a little thing. I'm like, I'm writing a book about Sublime Text. And I threw up a little sign-up where people could pop their email in and hear a little bit more about it. And I got, like, 2,000 signups for that in a matter of a couple of days. And I thought like, oh, all right, well, now I got to make this thing, you know, like, I just [chuckles] I didn't have any plans to make it. I had kind of been going around in my head, but I decided to write the book. And then as part of the book, I gave a bunch of videos, and I realized I liked the video part a lot better. And it makes a lot of sense to show people what you are doing when you're talking about code and code-related things. So, I came out with a bunch of videos for that as well. People loved the videos, and I thought, oh, let's just keep doing this. So, I made a bunch of free courses, a bunch of paid courses. And kind of at the same time as well, I was teaching at this thing called Ladies Learning Code, which kind of transitioned into a bootcamp that I did the initial content for, which was called HackerYou. And, like, people kept giving me the same feedback into like, I'm not a traditional teacher. I'm just a web developer that has learned on his own and figured things out. And a lot of people said, like, " I really like the way that you explain things. Like, it makes so much sense the way that you explain it." And I figured out that, at least for some people, they really like the way that I explain something, and I will continue to do that. So, that's pretty much how I got into it. It's just explaining how it works in my head, putting it onto video, and putting it out there for web developers to learn from. WILL: Yeah. And that was one of the reasons why I think I was so successful in my career is because there's a...Just learning development is hard; let's be honest. It's just hard. And I would run into people that would honestly just talk over my head, and I was like, I have no idea what you're saying, but okay. But your courses, it was like, oh, okay, I understand that. That makes sense. Like, I can't remember the name of it, but the React beginner course I've been to that one probably three times just because I'm like, it's making sense. And every time, I get more and more and more out of it. So, I can definitely agree that the way you teach your courses it brings it down to earth. Like, I think maybe anybody could pick it up, I would say, because it's like you're talking to them, so yeah. WES: It's really important to me that everything is approachable. And I will often explain things, like, I'm the same as you. There's extremely smart people out there, and they'll just talk at you about all of these things. And it's just like, I have no idea what you're talking about. Those words don't make any sense to me. And it's not that I dumb it down. It's just like, the way that it makes sense in my brain is not the same way that they're talking. So, the way that I explain it is just how it makes sense to me, and people tend to really enjoy that type of thing. And I really hope that I can make a lot of this web development stuff approachable. And sometimes it's not the, like, exact perfect explanation of how something really works, the explanation you need to understand how these pieces fit together and when you would actually use something. That's the other part of a lot of the stuff that I teach as well is that I have this big thing on one of my course websites, which is like, no foo bar baz. Because when you're learning to code, you stumble across all these foo bar baz where people are making functions and passing the values in, and they're called meta-syntactic variables. The whole idea is that because foo bar baz mean nothing, you're able to take it out of context and focus on what is happening, and I'm quite the opposite. Show me a real example of a bunch of dogs, or a sandwich, or a button that you can click on that fetches data. And I always try to make my examples something that is real world enough that you could understand, okay, I see where this might be used rather than something in isolation because I find that myself very frustrating. VICTORIA: What's one of your favorite examples or, like, example scenarios that you use when you're designing a code problem to teach people? WES: It really comes down to, like, what you're teaching, but the ongoing joke on the podcast that we have is that I always use sandwiches because a sandwich is a great metaphor for a lot of things in life. So, for example, when we talk about streaming versus buffering, and we talk about, like, you're eating the sandwich as it's coming into your house versus you're cutting it into pieces and eating it. Or in my upcoming TypeScript course, I have a bunch of examples where there can be multiple types of food, and a sandwich can be one of them, and a pizza can be another one. And that kind of shows how to use generics, right? Like, you might have a database entry that is a food entry, but you want to further that to be a sandwich or a pizza, and not all of them are that simple, right? Like, a lot of them are also just related to web development, which is like, here's buttons that you need to click on, and here's data that you need to fetch, and here's a database schema that needs to happen. And if that's the case, I try to, like, make it real world enough where you can say, okay, I understand that this is how it works. Now, how can I apply that to my own idea? Because often, people learning to code have their own ideas. They just want to make something to solve their own problems. WILL: How did you learn to code? Because I don't think you did a traditional route. I remember on one of your podcasts, you said your dad was in IT, but I don't think you went to a traditional route. So, how did you learn to code? WES: It's a really long story. But the story is that I got into computers at an early age. I got into designing T-shirts and CD art for a lot of, like, hardcore bands in the music scene when I was in high school, and that parlayed into Myspace. Myspace taught me CSS. And then I've always been, like, fairly entrepreneurial, so that I parlayed into running my own business, making websites. And I've just been at it for so long that I've sort of taught myself all the pieces that I need over the years. I do have a degree in what's called business technology management, which is, it's a business degree but no coding or things involved. It was more, like, higher level. There was some, like, networking IP addresses, and then there was a lot more, like, business management teams, procurement, SAP, things like that, so none of the web development stuff I have learned comes from that degree. It's all self-taught. VICTORIA: So, you found that you had the skill around explaining web development concepts, and then that led to you creating your own business and having your own, like, coursework out there and everything through your podcast. So, maybe you could share a little bit what that journey has been like. WES: It's been a very long journey. I'm not sure which part you want to hear about, but I've been selling courses for probably about nine years. And I have sold quite a bit because I also offer about half of them for free. So, I have a bunch of free ones where people take it, and they're like, "Oh, this is amazing. I'm going to take the paid one that he has as well." And I spend a lot of time making sure that the free ones and the paid ones are the same quality. Like, it's not just some crappy 10-minute course that I'm using as a lead magnet to get you in the door. Like, they're actually pretty good. So, it's been really fun. Like, I've built a whole course platform that sells all of my courses, and you can view them and stream them, and there's invoicing and checkouts built into it. So, like now, if somebody wants to get into selling courses, there's lots of options out there where you can sign up for some SaaS and upload your course, and you're up and running. But at the time when I had done it, there was nothing like that out there, so I had to build my own whole course platform. And I've really enjoyed working on that over the years and upgrading it, and changing it, and rewriting, and adding features to it. VICTORIA: Yeah, that's really interesting. I like that you kept the quality the same on the free and the paid versions. That's a really interesting, I think, like, a reflection of your own values. And then, I'm curious: now that there are other hosting options out there, is there anything that would make you decide to switch to one of those platforms? Because it also sounds like you're getting a lot of enjoyment about managing the one you have yourself, and there might be some other benefits to that. WES: Yeah, probably not. First, because they take a cut, and a lot of these course platforms are not there to promote your business. They're there to promote their own business. And it's the same thing with YouTube. When your YouTube video ends, what does YouTube recommend? They usually recommend what you think you're going to watch, which is sometimes somebody else's video, right? And not having full control over how the courses are sold and consumed, to me, can be a little bit frustrating because you can't do different ideas that you have. So, like, one of the ideas I had early on is I was getting lots of email from people in different countries, you know, in Argentina, and in Brazil, and in India. And they say, "Hey, like, I would love to take your course, but the cost of the course is a day, a week's wages, and that's way too expensive for me." So, I implemented this thing called parity purchasing power. I didn't come up with the economic concept of it, but I was the first person to offer different prices based on the country that the user was coming from. And, A, that's a cool thing to do for people, and B, it helps sales tremendously. And if I was using some course platform, some of the course platforms now have that in place; it's table stakes, right? But at the time, I don't think I would have done as well if I hadn't coded that in myself. So, having full control over absolutely everything is really important to me. And also, like, nobody wants a teacher who doesn't actually build stuff, you know? No one wants to learn from the guy who just, like, skimmed the docs and came up with a crappy, little example. Like, you want to learn from people who are daily writing code and building real-world applications that, like, I have to support my family on this application, you know, it's pretty important, and it's pretty real world. WILL: Yeah, and just following you, I think...and I don't know if you would describe yourself like that, but I think you're, like, a tinkerer. Like, you just...some of the ideas you have is just like, let me just try it out and see if it works. And so, that's amazing that you're able to do that. Where does that side come from? Was it from your dad being in IT, or where did that come from? WES: Probably. Apart from growing up and seeing my dad just fix stuff and do stuff, but I'm just a constantly curious and hungry guy. And I absolutely love dipping into different tech and not even just tech but, like, I built this whole recording studio that's soundproofed. I built the whole thing myself just because I love to learn new things and to dive deep and learn how everything works. And I think a lot of developers very easily burn out. And I always like to say, like, my competitive advantage is not burning out. So, I'm very cognizant of that might happen at some point. And part of the cure for me is I need to be excited about this type of stuff, and I need to be using it. And being able to build new things, and dip into tech, and learn constantly is what keeps me excited and motivated about web development. WILL: Wow. So, you say you built your office. So, you built the entire, like, from concrete up? WES: Not concrete up. So, this was like a...I'm in a basement right now, and I put up some walls. And I talked to a bunch of sound engineers about soundproofing. So, the whole ceiling is not mechanically fastened to the actual ceiling. It's like kind of, like, a floating ceiling, which is pretty cool. And then there's soundproofing material in the walls and outside the walls, and special drywall, and all kinds of interesting stuff to make it sound as good as possible and be as quiet as possible in here because I have three kids. WILL: [laughs] I totally understand the three kids... WES: [laughs] WILL: And the noise that that brings. So, that's amazing. And I think you bring up something that we don't talk about enough in development is that mental health side. Like, just trying to figure out, what do you like to do outside of your computer, away from your computer? So, that's neat that you're working on that, and that that's probably why you haven't burnt out compared to other people. But yeah, kudos to you. That's yeah, that's pretty interesting that you have hobbies outside of that. WES: Yeah, I find that pretty important to sort of keep that balance. Otherwise, if you're doing it day in, day out, especially if you're working on the same thing...like, another benefit I have is I'm always dipping into new stuff, and that keeps it really interesting. But there's plenty of other creators out there that go too hard, and they go 24/7 on it, and then you don't hear from them for six months. And it's because they got burnt out on it, which is very scary to me that that might happen to me at some point. So, I try...I don't know if I've got it figured out, but I try to combat that as much as possible. VICTORIA: And I'm wondering how you balance just that need to create content because it seems to me that web development is constantly changing, right? And so, content that you created a year ago, maybe you got to go back and update everything. So, how do you manage that and keep your content fresh with all the ongoing changes in web development? WES: Yeah, unfortunately, sometimes it means you just have to deprecate content, or you say, "Hey, this is not the content you should be taking right now," because some of the courses take four or five months to record, and after a year or two, they can be out of date. So, I'll mark them as deprecated if they need to be. But I'm just kind of always working on something new, both with my courses as well as, like, the podcast. We always just have...that's the kind of the benefit of the job as well is that, like, yeah, it changes all the time, but there's always new stuff to talk about. As somebody who makes a living explaining how new things work, it's kind of nice. VICTORIA: That's great. You got a good pipeline of content to talk about [laughs] and to update for, so that's great. Mid-Roll Ad: As life moves online, bricks-and-mortar businesses are having to adapt to survive. With over 18 years of experience building reliable web products and services, thoughtbot is the technology partner you can trust. We provide the technical expertise to enable your business to adapt and thrive in a changing environment. We start by understanding what's important to your customers to help you transition to intuitive digital services your customers will trust. We take the time to understand what makes your business great and work fast yet thoroughly to build, test, and validate ideas, helping you discover new customers. Take your business online with design‑driven digital acceleration. Find out more at tbot.io/acceleration or click the link in the show notes for this episode. VICTORIA: You know, you're creating this content for web developers, and you have this kind of global audience now. What's on the horizon for you? What are you planning for in the next couple of months or in the next five years? WES: Yeah, next couple of months, I have a TypeScript course I've been working on for over a year now. I've been sort of cranking on it, and that will be out. And then we have a podcast that we are going to be launching a video version of pretty soon, which I'm pretty excited about. We've been kind of going pretty hard. We just hired a producer. We've been going pretty hard on, like, the social clips type of thing. So, that's coming down the pipeline as well. And five years, I have no idea. I think I always say, like, a five-year plan is a five-year guess. You know, like, you can plan ahead for six months, a year, and have some good goals. But in web development, like, a year ago, AI, maybe a year, like, 13 months ago, the AI stuff was nothing but a murmur, right? And now, the AI stuff is a good chunk of what I talk about and what I teach. So, you just kind of got to react to it; otherwise, if you have a five-year plan, then you're not going to be able to catch these new things that pop up. WILL: How do you pick? Because I know you said you have a TypeScript course coming out. How do you pick new topics to talk about? Because there are so many. There's testing you can talk about. There's React Native. There are so many areas you can go to. How do you pick and choose that? WES: It's actually pretty easy because it's what I'm excited about and what I want to tell people and teach people, like, what they should be learning. So, like, every single one of my courses is tech that I myself am using and that I want to help teach other people, so it's pretty straightforward. It's not like I have some sort of, like, stats of, like, what is the most popular framework out there, and, like, obviously, that does play into it like a Next.js course. I've used Next.js in a couple of my courses. I'll probably do another Next.js course. But that's both because I enjoy it and because it's stable enough and popular enough that people would want to buy it. I'm not going to be creating a Java course or a Rust course or something like that because I know that's popular right now, and it would probably sell well. It's just not something I know enough about, or I'm excited about. VICTORIA: Yeah, and I'm curious to go back to your comment about AI and just ask you, how are you talking about it in your courses? What are, like, the things you think it's really important for developers to know right now about AI and web development? WES: There's kind of, like, two parts to it. First, there's the part of, like, using AI to help you code. So, there's all these, like, coding assistants that get in your editor, and you can send them your code, and it can help you decipher it, and it can scaffold out code. Those things are really, really good. And I know a lot of developers are hesitant about it because, like, "Who knows what kind of code it's generating? And you still have to be able to understand it. And I prefer to write it by hand." And that's a valid opinion, but, like, I don't think that that's going forward. And I think that this AI stuff is making us so much more efficient in writing code that if you're not picking it up, I think that you might be at a little bit of a disadvantage there. So, there's that [SP] hunk. And then there's also the, like, we're going to have to start implementing this stuff into the apps that we build, and whether it's just pinging in an AI service and getting data back or creating a bunch of embeddings so you can have related, like, for a blog post or for a podcast, we want related podcasts. Or if you want to use AI to, like...group tagging on a blog is a really annoying thing. Nobody uses tags well enough. But, like, what if the tags could just be automatically generated based on the words in the post or the words that we speak on the podcast? So, there's just, like, so many, like, new features that will make it better. Your product is going to be better for your end user. And even starting now and, like, when those features are not enabled, like, it's not, like, necessarily an AI feature, but it's like, wow, I wish this had better grouping of podcasts, or I wish that you had better tagging, or that your search is not very good because it's just a text match whereas there's a lot more depth that could be added with AI. So, integrating AI into our websites and our applications that we're building is going to become just another skill that you, as a web developer, have. VICTORIA: No, I think that's a really interesting take on it. And I'm curious if you've also seen AI used to even, like, suggest better standards for code or certain design patterns and, like, tools that help you, like what you said, kind of get better at coding faster. WES: That's the thing people are talking about. Like, if you're learning to code, should you use these types of things? Because, like, you can just hit Tab a couple of times, and it might look good. And it certainly can bite you. Especially if you need to be able to go back and edit that code to fix it, you need to understand how it works, so there's that part of it. But, man, does it make you faster for doing a lot of common things that you will be doing over again. It just really helps you out, so I'm a big fan of it. I have lots of complaints about it as well, but I think it's here to stay. VICTORIA: [laughs] Yeah, it's here to stay. And I've talked to founders who are really excited about it, and maybe they weren't, you know, they don't have years and years of React development experience, but they know the functions that their app needs to do. And they're able to use coding prompts and tools to kind of create at least a minimal product of what they want to build, so it's really exciting. WILL: I totally agree with AI because I use some, especially with the coding, and it makes it so much faster, but I do think you still have to know what you're doing. Because I think you posted on it, like, in one of the coding helpers that I use in VS Code, it still doesn't know how to close out the end of the line. You have these extra backticks or whatever. And it is like, so, as a new developer, you still have to understand your code, or that's going to drive you crazy every time that you use it [chuckles]. WES: Yeah, that's extremely frustrating, the backticks. I've had an issue open on GitHub Copilot for about a year now. They've said they fixed it, and a couple of little situations, it's been fixed. But I would love to, like, talk to somebody about, like, the actual issue because if you give the broken code back to the AI and say, "Fix it," it fixes it. So [laughs], it knows what's wrong. I just, I don't know. Yeah, you still have to know these things. WILL: You taught at Ladies Learning Code and then HackerYou. Did that help you overcome the imposter syndrome of teaching? I don't know if you knew how big your courses were going to become. But what did the imposter syndrome look like for you during that time, or did you even have it? WES: To a certain point, yeah. I think everybody has imposter syndrome, and that's good. Because if you're so confident that you're so amazing and blessed at this specific thing, then your head is probably too big, and [chuckles] you probably don't know what you don't know. But with a lot of my stuff, I'll often just ask people who know better than me. Like, that's a big part of what it is, is you can just consult experts or like, "Hey, what do you think about this?" Or "Is this the best approach?" Or "Here's my code. Do you mind running through it really quickly and see if there's anything that sticks out?" People are often, like, you can pay them, or people are often willing to help, so there's that. And like, also, you have to just know that this is for the people who enjoy it. Like, I'm not making courses for people who are better developers than I am. I'm making courses for people who like the way that I explain specific things. And then, like, another thing that probably really helped me is that I have, like, a 100% money back, no time limit on it. And that just makes me feel good about like, hey, like, if this is not actually good, if you do not think that this is good, or if you just don't jive with the way that I explain things, no sweat, you know, here's your money back. You keep going. And that makes me feel a lot better because it's not like I'm trying to fleece somebody for money and trick them into buying the course. Like, I feel pretty good about it, and if you feel pretty good about it, then we're both happy. WILL: Yeah, that's amazing because I feel like there's certain things that I would love to get started, but that imposter syndrome and also, like, the opinionated developers out there, like, you know what we are talking about. But it just seems like it would be hard to start with that. So, that's why I asked that question. WES: Yeah, I've learned that, like, a lot of these people that have these extremely harsh opinions are, A, they lack all the social skills, so there's something with them that they just don't have it. And you have to understand that that's just something that they have, and they may not be trying to be a jerk. That's just kind of the way they are. And if people are overly opinionated, it's usually because they're, like, covering for their own insecurity of what they want, not always. But a lot of times, I feel pretty good about people telling me, "Oh, you could do it this way," or "No, why are you doing it this way?" Like, I feel pretty confident in my skillset, but I also am always willing to learn and always willing to be corrected and learn new tips and techniques because that's how you get better. So, the people that are constantly being angry online and throwing around opinions and saying things are garbage, that's very scary for beginners because they think, oh, like, am I learning the wrong thing? I don't want to waste my time here. Like, am I going to lose my job if I don't learn it? And the reality is it's not that cut and dry, you know, it's a lot more easygoing. So, I try to convey that as well. And I don't put too much into these silly people who get really angry at semicolons or something silly like that. WILL: That's good advice. That's good advice. Because I think there's been some stuff that I want to do, that's held me back. So, that's really good advice. I appreciate it. WES: Yeah, just do it, like, you never know. Like, if someone's calling you out for putting yourself out there, like, that's a really big jerk thing to do. And I've called people out as well. Like, I don't get it as much anymore, and that probably has to do something with the fact that I've sort of established myself. But several times in the early days, people would be, like, mean. And I would just be like, "Hey, like, just call people out, like, nicely, but, like, hey, you don't have to be mean about it. I'm just trying to share what I've learned here." And that usually gets them. VICTORIA: Yeah. It's like, what are your intentions with providing this feedback to me right now? Like, are you trying to help? [laughs] Because it doesn't really feel that way. No, I appreciate that. And, you know, I'm also...part of thoughbot we've traditionally put out a lot of trainings, a lot of, you know, Upcase things on Ruby on Rails. And with my team, I'm looking at putting together some workshops around site reliability engineering and things that would be helpful for developers to learn how to instrument their code. So, speaking of advice that you would give to maybe any engineer or any developer who's looking to share their expertise, or put together a course, or even a blog post about what they're learning, like, what would you advise someone who's trying to create content like that? WES: Put it out there. When I released my Sublime textbook, keep in mind, a book about Sublime Text that's a pretty niche thing, there was already two books out there on that exact topic. And a couple of times, I was like, is anyone going to want this? There's already one of them out there. Should I even write this blog post? There's 70 out there. And just keep in mind that, like, the way that you explain it or the specific issue that you hit or whatever, it might be the way that really clicks for somebody else. So, I always tell people just put it out there. You never know what is going to come of it. It's likely going to be a net positive for the web development world in general. So, don't ever feel that you shouldn't put yourself out there because you might not know absolutely everything about it. Just share what you know. That's how we get better. VICTORIA: Yeah, I had a friend many years ago who we used to organize Women Who Code, and she said, "Do you think anyone would really be interested in, like, a cloud series of these topics?" And we're like, "Oh, maybe not." In the first event we had around Cloud for Women Who Code, I think, like, 30 people showed up. So yeah, put it out there, see who's interested, and go from there. That's great advice. WES: Yeah. On the same topic, is like, 'Will somebody want this?' is a huge question. People always come to me and they say, "Hey, do you think if I make a course on X, Y, and Z, will people buy it?" Or they'll put out a tweet that says, "Hey, would you buy this, or would you attend this?" And everybody's always like, "Yes, yes, yes," just trying to be supportive. But at the end of the day, you have to test these things by actually putting things out there. So, for me, how did I know the first thing I wanted to do was Sublime Text? It's because I put out blog posts on probably 20 different topics, and those were the posts that just hit really well, and they really resonated with people. So, like, if you're trying to understand, like, will it work? You can test those things very easily by putting a YouTube video up, putting a couple of TikToks up, write a blog post, put a couple of tweets up. And, eventually, when you put out enough content, you're going to start to see a trend in a specific area, and that will give you a little bit of guidance as to what it is you should pursue. WILL: That's great advice. Have you had any hurdles through your journey of online courses and the podcast, releasing podcasts? WES: I feel like I'm always, like, course-correcting. I've never had, like, a flop. And, like, I've had courses I've shelved. Early on, after Sublime Text, I was like, I'm going to do a gulp course, which was, like, a build tool for JavaScript. And then webpack started to get a little bit more popular, and I was like, okay, well, maybe I'll just make a tooling course in general, but I was like, ah, that's kind of way too big. And after, like, working on it for a couple of weeks, I was like, you know what? Like, I'm going to scrap this because I don't think that this is it, you know? So, just kind of always listening, always feedback, and course correcting is probably my biggest advice there for the hurdles. There's stuff that comes up, like people stealing the courses. And, like, I had early access to one of my courses once, and somebody bought it with a stolen credit card and then put it up online. And, like, that's incredibly deflating because now there's your unfinished course out there before people could even buy it. And people will spam you and run DDoS attacks on you and lots of stuff like that, where people are just...they see that. And that's always really frustrating, but you kind of roll with the punches and kind of keep working on it. WILL: Wow. That's interesting. So, someone bought the course with a stolen credit card, and they released it early to the public? WES: Yeah. I don't know if I should say this or not, but there's a very large Russian website that is...literally, they have a paid membership, and the whole point is that you pay for the membership, and you get access to every course ever. Sometimes, they use paid cards, and sometimes it's stolen cards. WILL: Oh, wow. WES: They just buy every course by every creator, and they put it up on this thing. And you can get it for free for the first, like, three months, and then it goes under their paid thing. And that stuff was really frustrating to me at first, but I've learned just to...the web development community is incredibly supportive, and I have nothing to complain about, really. People who do want to support you will support you. WILL: That's neat. That's really neat. VICTORIA: Yeah. And speaking of the web development community, are there events or conferences you go to or different, like, places where you really connect to the web development community? WES: Yeah. Conferences are fantastic. I really enjoy that those are back. So, React Miami is coming up. It's going to be a really fun one. But I go to a couple of conferences a year, and I usually speak at them. We also do meetups every now and then with Syntax where we'll rent out a bar and get a bunch of merch and stickers and just kind of chit-chat with everybody. That's honestly, my favorite is just going to a meetup where there's no talks or anything. It's just a bunch of interesting people in a room, and you get to talk with all kinds of cool people. VICTORIA: That's fun, yeah. I've been organizing a monthly CTO lunch down here in San Diego, and it's like, we just get together and have lunch and, like, talk about different stuff [laughs]. WES: Love it. VICTORIA: And it's really great. I used to organize those meetups with, like, two speakers, and then there was pizza and drinks and all that stuff to coordinate. And it's a lot easier just to kind of get everyone together and talk, which is what most people want anyways [laughs]. WES: I'm always bummed when you go to a conference and the, like, after party has, like, a band or, like, music is bumping. It's like, I just want a quiet room with some drinks that I can talk to people and have a good conversation, you know. VICTORIA: Yeah, I go to a lot of events, a lot of conferences, a lot of events. I see a lot of different types of stickers and design and anything like that. So, I thought it might be fun to ask you about that. Like, you know, I don't know if you can share us a link of what your stickers look like. Or how do you make it fun and interesting for you to have that kind of thing to hand out? WES: Once a year, once a year and a half, I make these sticker packs, and they have, I don't know, 15 or so stickers in it, various web development things. And it's a pretty big production because I get a lot of them done. So, the last time I sold 11,000 packages of them, and I sell them for five bucks shipped anywhere in the world. And it's, like, a huge logistical hurdle to try to make that happen because there's so much to it. But it's really fun for me because I'm able to do something that is fun. A lot of people aren't able to go to conferences and get the stickers, and they want that. They want to feel part of a community, and everybody loves getting a pack of stickers. So, I've been doing that for probably seven years now. Just right now, I'm just doing a little bit of research into what the next pack is going to look like and some new materials that have hit the sticker world [laughs], so it's pretty fun. The website is bos.af with, like, bos.af. That might not work anymore. I got note that the people who I registered the dot AF domain name from have lost contact with the Afghanistan domain authorities. So, it's possible I might just lose that domain name, which is a bit of a bummer because that's a really cool domain name, but that's where I sell them once a year. And, usually, they're only for sale for about a week, and then they're done selling, and I do the whole shipping thing around the world. VICTORIA: Wow. I did not think you were going to say, "Sold 11,000" sticker packs. That's really impressive [laughs]. WES: Yeah, it's crazy. It's almost 200,000 stickers if you think about it. VICTORIA: That's, like, a major production. I bet when you got into web development, you didn't think you'd also have a side hustle making stickers off of it [laughs]. WES: Yeah, it's crazy. Like, I was, like, sending them out with stamps, and it's just like, I was holding in one single hand, like, $4,000 worth of stamps. It's crazy to think. VICTORIA: I can imagine going into the post office and being like, "I need $4,000 worth of stamps [laughs]," but that's great. WES: The first time I just started dumping them into mail, I would cross the border because I'm in Canada, and the USPS is much cheaper. So, we would just cross the border, and then we just dumped them into mailboxes. And it was okay. But they were like, "Hey, like, next time, just, like, bring it to the post office, and, like, we have processes for this much mail." I don't mail them out of the U.S. anymore because there's some weird stuff around crossing the border. You have to do all this crazy stuff. But it's pretty crazy buying that many stamps. They usually look at you funny when you go to the store and say, "Hey, I need this many stamps." [laughter] VICTORIA: They're like, "Well, what are you doing?" [laughs] Well, great. I think, let's see, we're coming up at the end of our time here. So, are there any final takeaways for our listeners today? WES: Check me out. I'm at wesbos.com; podcast is at syntax.fm if you want to give it a listen. We post three times a week. And I just encourage everyone keep learning, keep excited about web development because it's a pretty cool industry. VICTORIA: Awesome. Thank you so much for taking time to chat with us today. I really enjoyed our conversation. You can subscribe to the show and find notes along with a complete transcript for this episode at giantrobots.fm. If you have questions or comments, email us at hosts@giantrobots.fm. And you can find me on X, formerly known as Twitter, @victori_ousg. WILL: And you could find me on X @will23larry. This podcast is brought to you by thoughtbot and produced and edited by Mandy Moore. Thanks for listening. See you next time. AD: Did you know thoughtbot has a referral program? If you introduce us to someone looking for a design or development partner, we will compensate you if they decide to work with us. More info on our website at: tbot.io/referral. Or you can email us at referrals@thoughtbot.com with any questions.
We released episode one of this podcast on June 11, 2012. Now, more than a decade later, we're celebrating the 500th episode of our show. In honor of this milestone, Victoria, Will, and Chad caught up with each of the past hosts of the show: Ben Orenstein, Chris Toomey, and Lindsey Christensen. We chatted about what they're up to now, what they liked and learned from hosting the show, their time at thoughtbot, and more! Follow thoughtbot on X (https://twitter.com/thoughtbot) or LinkedIn (https://www.linkedin.com/company/150727/). Become a Sponsor (https://thoughtbot.com/sponsorship) of Giant Robots! Transcript: VICTORIA: This is the Giant Robots Smashing Into Other Giant Robots Podcast, where we explore the design, development, and business of great products. I'm your host, Victoria Guido. WILL: And I'm your other host, Will Larry. CHAD: And I'm your other host, Chad Pytel. We released episode one of this podcast on June 11, 2012. Now more than a decade later, were celebrating this: the 500th episode of our show. In honor of this milestone, Victoria, Will, and I caught up with each of the past hosts of the show: Ben Orenstein, Chris Toomey, and Lindsey Christensen. We chatted about what they're up to now, what they liked and learned from hosting the show and their time at thoughtbot, and more. First up: Ben Orenstein. Ben was the very first host of the show back in 2012 when he was a developer at thoughtbot. He is now the co-founder and Head of Product at Tuple, a remote pair programming tool for designers and developers. Ben, it's great to talk to you again. It's been a while since you and I talked. How have you been? BEN: I've been decent, yeah. It's fun to be back to my roots a little bit. I told some folks that I work with that I was coming back to the pod for the 500th Episode, and they were stoked. So, it's kind of a treat to get to be on these airwaves again. CHAD: What have you been up to since you left this show and thoughtbot? BEN: Well, I started a company. So, I was at thoughtbot for a while; I think it was seven years. And I eventually sort of struck out to start my own thing–had a false start or two here and there. And then, I ended up starting a company called Tuple, and we still exist today, fortunately. Tuple is a tool for doing remote pair programming. We started off on macOS and then wrote a Linux client. And we're launching a Windows client now. But it's sort of, like, screen sharing with remote control for developers who are actually writing code and want to have great, low latency remote control and who care about screen share quality and that sort of thing. I started that about five years ago with two co-founders. Today, we are a team of 11, I think it is. And it's been going well. Our timing was really great, it turned out. We launched a little bit before COVID. So, remote work turned into a lot more of a thing, and we were already in the market. So, that helped us a ton. It was quite a wild ride there for a bit. But things have calmed down a little lately, but it's still fun. I'm, like, really enjoying being a co-founder of a software company. It was what I've always sort of wanted to do. And it turns out it actually is pretty fun and pretty great. Although there are, of course, the ups and downs of business ownership. It is never quite as calm or relaxing as being an employee somewhere else. CHAD: You started Tuple instigated by...full disclosure: thoughtbot's an early customer of Tuple. We're still a customer. We use it a lot. BEN: Woo-hoo. I appreciate that. Thank you. CHAD: If I remember right, you started and were sort of instigated to create Tuple because there was a prior product that then Slack bought, and then it started to degrade. And now, it no longer exists in the same way that it did before. BEN: Yeah. So, there was this tool called Screenhero, which I actually started using -- CHAD: [inaudible 02:14] BEN: Yeah, first at thoughtbot. Some other thoughtboter introduced me to it, and we would use it for pair programming. And I was like, oh, this is nice. And then yeah, Slack kind of acqui-hired it and more or less ended up shutting the product down. And so, there was this gap in the market. And I would ask my friends, I would ask thoughtboters and other developers, like, "What are you using now that Screenhero is gone?" And no one had a good answer. And so, after a while of this thing sort of staring me in the face, I was like, we have to try to solve this need. There's clearly a hole in the market. Yeah, so we were heavily inspired by them in the early days. Hopefully, we've charted our own path now. But they were definitely...the initial seed was, you know, let's do Screenhero but try to not get bought early or something. CHAD: [laughs] How did you or did you feel like you captured a lot of the Screenhero customers and reached them in those early days? BEN: I think so. The pitch for it was sort of shockingly easy because Screenhero had kind of blazed this trail. Like, I would often just be like, "Oh, we're making a thing. Do you remember Screenhero?" And they'd go, "Oh yeah, I loved Screenhero". I'd be like, "Yeah, we're going to try to do that." And they'd be like, "Nice. Sign me up." So, it for sure helped a ton. I have no idea what percentage of customers we converted. And they were a pretty large success, so probably a small fraction, but it definitely, like, made the initial days much easier. CHAD: Yeah. And then, like you said, COVID happened. BEN: COVID happened, yeah. I think we had been around for about a year when COVID hit. So, we were getting our feet underneath us. And we were already, like, the company was already growing at a pretty good rate, and we were feeling pretty good about it. I don't think we had quite hit ramen profitable, but we were probably pretty close or, like, flirting with it. Yeah, the business, like, I don't know, tripled or quadrupled in a matter of months. We had a few big customers that, like, just told everyone to start using Tuple. So, we had, like, thousands and thousands of new users kind of immediately. So, it was a crazy time. Everything melted, of course. We hadn't quite engineered for that much scale. We had a really rough day or so as we scrambled, but fortunately, we got things under control. And then had this, like, very nice tailwind. Because we started the company assuming that remote work would grow. We assumed that there would be more remote developers every year. And, you know, it's probably maybe 5% of dev jobs are remote or maybe even less, but we expect to see this number creeping up. We don't think that trend will reverse. And so, COVID just, like, it just yanked it, you know, a decade in the future. CHAD: You haven't tripled or quadrupled your team size, have you? BEN: No. Well, I mean, I guess, I mean, we started as 3, and now we're 11, so kind of. CHAD: [laughs] Yeah, that's true. BEN: Expenses have not grown as fast as revenue, fortunately. CHAD: That's good. That's basically what I was asking [laughs]. BEN: Yeah, yeah. We're still a pretty small team, actually. We have only, like, four or five full-time engineers on the team at the moment, which is kind of wild because we are now, you know, we have three platforms to support: Linux, Windows, and Mac. It's a pretty complicated app doing, like, real-time streaming of audio, webcams, desktops, caring about OS-level intricacies. So, I think we will be hiring more people soon, although we haven't said that for a long time. We sort of have always had a bit of a hire-slow mentality to try to get the right team members and, like, feel a real pain before we hire someone into it. But we have been getting a bit more aggressive with hiring lately. VICTORIA: Well, I really appreciate Tuple. I installed it when I first started working here at thoughtbot. And we have random pairings with everyone across the company. So, I'll randomly get to meet someone halfway across the world who's working on similar projects. And I think they really enjoy that I have a tool they like working to share what they're working on. So, I want to thank you for that. And I'm curious about when you really started to scale during COVID, what were some of the technology architecture trade-offs you came across, and where did you land with it? BEN: Well, we got fairly...I don't know if it was lucky, but we...for a long time, for years, even through COVID, maybe the first four years of the company, all Tuple calls were purely peer-to-peer. And there was no server that we owned intermediating things. This was, like, kind of one of the keys of, like, not having expenses. The scale of revenue was we could have lots more calls happen. And it wouldn't cost us bandwidth or server capacity. To this day, still, for any calls with three or fewer participants, they're purely peer-to-peer. And this is nice for latency purposes because it just...we can find the most direct path to the internet between two people. It's also nice from our cost perspective because we don't need to pay to send that data. And that was hugely useful as call volume went up immensely. Didn't have to worry too much about server load and didn't have to worry too much about bandwidth costs. CHAD: Today, is there a central service that makes the initial connection for people? BEN: Yes, yeah, yeah. So, there is a signaling server. So, when you launch the app, you sign in, and you see, like, oh, which of my co-workers are online? So, there is actually a Rails app that handles that, actually, increasingly less the Rails app. We have now...I think it's a Go service that actually manages all those. I'm further and further from the code every year. Some of the technical questions might be a little bit beyond me, or I might have slightly out-of-date info. But back to the architecture question for a second, we did a pretty big refactor when we decided to go from just being a Mac client to supporting other platforms, where we split out a cross-platform real-time communication engine written in C++ so that we could use that for all of the heavy lifting, all the managing of the connections, and the tricky bandwidth estimation, and all this stuff, and use that across different platforms. And so, today, you have the cross-platform engine, and then on top of that is a, like, a less specific layer for each of the operating systems that we support. CHAD: So, you mentioned you're less and less in the code these days. So, what do you spend your time doing then? BEN: It's a mix of things. These days, it's basically mostly -- CHAD: Just cocktails on the beach, right? BEN: Cocktails, yes [laughs], cocktails on the beach, appearing on podcasts trying to sound important and impressive, yeah. Mostly product work. So, right before this, I just got off a call with some folks from The Browser Company. They are some of our first alpha users for our new Windows clients. So, I hopped on the call with them and, like, watched three of them install the product and inevitably run into some bugs. And, you know, chatted through those with the engineer that was working on it, prioritized some stuff, made some decisions about what's coming up next, and what we're going to ignore. So, mostly product work these days. For the first five years of the company, I was CEO, so I was doing kind of everything: marketing, and also hiring, and also product. About two months ago, I stepped down as CEO, and one of my other co-founders, Spencer, stepped up. And so, now my focus has narrowed to be mostly just product stuff and much less on the marketing or hiring side. VICTORIA: Yeah, you mentioned that it was a little more comfortable to be an employee than to be a founder. I don't know if you could say more about that because, certainly, a lot of engineers are smart enough and capable enough to run their own company. But what really informed your choice there, and do you regret it? [laughs] BEN: I definitely don't regret it. thoughtbot was a close second in terms of wonderful professional experiences. But running my own thing has been the most interesting professional thing I've done by a big margin. It has also been more stressful. And, Chad, I don't know if you remember, I think, like, maybe eight years ago, you tweeted something like, if you want to sleep well at night, and, like, value that, like, peace of mind, like, don't start a company or something. I have experienced that. CHAD: [laughs] BEN: A lot more, yeah, like waking up in the middle of the night worrying about things. It feels a little bit like the highs are higher; the lows are lower. Being an employee somewhere, it's like, if this company fails, I know I can go get another job, right? Like, you're a developer. You're extremely employable. But as the owner of the company, if the company fails, like, a huge chunk of your net worth is gone. Like, this thing you poured your life into is gone. It's way more stressful and traumatic to have that happen, or have that threatened to be happening, or just imagine that happening. So, overall, I have found the trade-off to be totally worth it. It's awesome to make your own decisions and chart your own path. And when it works, it can work in a way that being a salaried employee can't. So, I'm happy with those trade-offs. But I think that is a good question for people to ask themselves as they consider doing something like this is, like: is that the kind of trade-off that you want to make? Because it has significant downsides for sure. WILL: I am a big fan of Tuple also. I love it. It [inaudible 10:08] easy, especially with remote work. You hit the jackpot with COVID and remote work, so kudos for that [laughs]. Was there anything...because I know from our previous companies, about over...hopefully a lot more of the good stuff than the bad stuff. But was there anything that you learned? Because you were at thoughtbot for seven years. Was there anything that you're like, oh my gosh, I learned that, and it's helped me till this day while I'm running my company? BEN: Yeah, quite a bit, actually. I think it'd be hard to tease apart exactly which lessons, but I do...so I ran Upcase for thoughtbot and also FormKeep. So, I got a chance to kind of run a small division of the company, while still being a normal employee and, like, having not much of that risk. And I think that was a really wonderful opportunity for me to, like, practice the skills that I was interested in. Just, like, how do you market a thing? How do you design a product and have it be good? How do you prioritize user feedback? There were a ton of lessons from those days that I feel like made me better at running our company when we actually took a shot at it. So, there were, like, the specific things that I learned by the work I was doing there. But then just, like, I mean, I think I am the programmer I am today because of, like, the weekly dev discussions that happened. Like, spending so much time with Joe Ferris and, like, trying to copy as much of his brain as possible, like, really, like, imprinted on me as, like, a programmer. And also, just, like, a lot of the sort of cultural things from my time at thoughtbot of, like, you should be sharing the things you're learning. Like, writing blog posts is a great use of time. Like, doing open-source work is a great use of time. And maybe you can't directly trace how doing, like, working in public or sharing information benefits the company. It's hard to, like, attribute it from a marketing sense. But if you sort of have faith that in the large, it's going to work out, it probably will. That feels like a thoughtbot lesson to me, and I think it has served us really well; where I recorded a weekly podcast for a long time called The Art of Product. I'm recording a new podcast called Hackers Incorporated with Adam Wathan of Tailwind fame. And I don't ever think, like, hmm, how many new leads do we think we get per episode, and how many hours has that taken? What's the ROI? I just have this sort of reflex that I developed from thoughtbot time of, like, you should be putting stuff out there, or you should be giving back. You should help other people. And that will probably help your business and make it work in the long term. CHAD: That's a good lesson [laughs]. One of the other things, you know, while you were a host of Giant Robots, you were the first host. I remember, you know, encouraging you to be the first host, and I think we talked about that in one of the episodes along the way. But we also transitioned the format a little bit, especially as you started to work on products here; you know, it was more about the building of those products and following along with those. And one of the things that sort of half-jokingly defined, I think, your impact on a lot of products was pricing, experimenting with pricing, learning about pricing, increasing prices more than people were maybe comfortable doing so. How has that worked out with Tuple, pricing in particular? BEN: It's really hard to say. It's hard to know what, like, the other path would have been through the world-. We sort of decided from, like, the early days that we wanted to have, like, a fairly premium price. Like, we wanted to be the product that was really good and was, like, a little bit annoyingly expensive, but you still paid for it because it felt worth it. And I think people could debate in both directions whether we nailed that or not. We have had a price increase that we ended up rolling back. We went, like, a little too far one time and said, "You know what? I think we're a little bit over," and we reverted that. But I would say even today, we are still a fairly pricey product. I mean, I'm pretty happy with how the company has done. I can't prove to you that, like, if the price were half what it is, we would have, you know, better success or not. CHAD: I think it'd be very hard to make the argument that if it was half that, you would have double the number of customers. BEN: Yeah, that's probably not true. CHAD: Not with the customers that you have, who are companies that will pay for products that they use as much as Tuple. BEN: Yeah, I'm happy serving the kind of companies, and they end up being mostly tech companies that really value developer happiness. When their developers come to them and they say, "We don't want to pair over Zoom. We like this thing. It's better. It feels nicer to use," they say, "Okay," and they buy the tool for them. There are places where that's not the case. And they say, "We already have a thing that does screen sharing. You're not allowed to buy this." We don't invest a lot of time trying to sell to those people or convince them that they're wrong. And I'm pretty happy serving sort of the first group. CHAD: So, you've mentioned that you've still been podcasting. To be honest, I didn't realize you were starting something new. Is it live now? BEN: It is live now, yeah. CHAD: Awesome. Where can people find that? BEN: hackersincorporated.com. It's about the transition from developer to founder, which is kind of what we've been touching on here. Yeah, hopefully, the audience is developers who want to start something or have started something who are maybe a little bit further behind progression-wise. And it's kind of, like, I have some lessons, and Adam has some lessons, and, you know, we don't think that we're experts. But sometimes it's useful to just hear, like, two people's story and sort of see, like, what seemingly has worked for them. So, we've been trying to share things there. And I think people will find it useful. VICTORIA: I was going to ask you for a lesson, maybe give us a little sample about how would you advise someone who's built a product and wants to market it, and it's targeted towards developers since you mentioned that previously as well. BEN: Yeah, in a way, the question already contains a problem. It's like, oh, I built the product; now how do I market it? It's a little bit indicative of a very common failure mode for developers, which is that. They sort of assume, okay, after you make the product, you then figure out how you're going to market it. And marketing is sort of a thing you layer on later on when you realize that just, like, throwing it on Twitter or Product Hunt didn't really work. When we started building Tuple, I was out there marketing it already. So, I had two co-founders, so this is a luxury I had. My two co-founders were writing code, and I was out doing stuff. I was recording podcasts. I was tweeting about things. I was making videos. I was giving conference talks. And I was getting people to hear about our product well before it was done. In fact, I was even selling it. I was taking pre-orders for annual subscriptions to the app while it was still vaporware. So, I would say, like, you basically can't start marketing too early. If you start marketing early and no one really cares, well, then you don't really have to build it probably. I would actually even go a little further and say, like, I started marketing Tuple before we had a product available. But in reality, I started marketing Tuple seven or so years before that when I started publishing things through thoughtbot. It's like when I was traveling around giving talks about Ruby, and when I was making screencasts about Vim, and when I was running Upcase, I was, over time, building an audience. And that audience was useful for thoughtbot, and it also was useful for me so that when I left, I had something like 10,000 Twitter followers or something, a few thousand people on our mailing list. But there were a lot of developers that already sort of knew me and trusted me to make fairly good things. And so, when I said, "Hey, I've made a new thing, and it's for you," I really benefited from those years of making useful content and trying to be useful on the internet. And in the early days, we had people sign up, and they would say, "I don't even really think I'm going to use this. But I've learned so much from you over the years that I want to support you, so I'm going to pay for a subscription." VICTORIA: I like your answer because I think the same thing when people ask me, like, because I am an organizer for Women Who Code, and I know all these great people from showing up for years in person months over months. And so, then people will ask, "Oh, how do I recruit more women in my company?" I'm like, "Well, you got to start showing up [laughs] now and do that for a couple of years, and then maybe people will trust you," right? So, I really like that answer. WILL: How has your relationship with Chad continued to grow since you left? Because seven years at the company is a lot. And it seems like you're still on really, really good terms, and you're still friends. And I know that doesn't happen at every company. BEN: I mean, it was tough deciding to leave. I think, like, both of us felt pretty sad about it. That was the longest I'd ever worked anywhere, and I really enjoyed the experience. So, I think it was tough on both sides, honestly. But we haven't kept in that much touch since then. I think we've emailed a handful of times here and there. We're both sociable people, and we sort of get each other. And there's a long history there. So, I think it's just easy for us to kind of drop back into a friendly vibe is sort of how I feel about it. CHAD: Yeah. And the way I explain it to people, you know, when you're leading a company, which Ben and I both are, you put a lot of energy into that and to the people who are on that team. If you're doing things right, there's not really hard feelings when someone leaves. But you need to put in a lot of effort to keep in touch with people outside of the company and a lot of energy. And, to be honest, I don't necessarily do as good a job with that as I would like because it's a little bit higher priority to maintain relationships with them, the people who are still at thoughtbot and who are joining. BEN: What you're saying is I'm dead to you [laughter]. That's CEO, for you're dead to me. CHAD: No. It's just...no hard feelings. BEN: Totally. CHAD: I think one of the things that has been great about the show over the years is that we haven't been afraid to change the format, which I think has been important to keeping it going. So, there is sort of; in fact, the website now is organized into seasons. And I went back and re-categorized all the episodes into seasons. And when the seasons were made up of, like, sort of the format of the show or particular hosts...when we started, it was just an interview show, and it was largely technical topics. And then we started The Bike Shed, and the technical topics sort of moved over there. But it also went with your interests more under the product and business side. Then you started working on products at thoughtbot, so it started to go even more in that. And I think Chris joined you on the show, and that was sort of all about those topics. BEN: Yeah, that makes sense. I think if you don't let the hosts kind of follow their interests, they're going to probably burn out on the thing. It's not fun to force yourself, I think, to record a podcast. CHAD: Yeah. And then when you left, you know, I took over hosting and hosted by myself for a while, went back to the interview format, but then was joined by Lindsey for a little while. We experimented with a few different things: one, interviews, but then we did a whole, just under a year, where we followed along with three companies. And each month, we would have an interview episode where we talked to them, all three companies, about the same topic. And then, we also did an episode with just Lindsey and I talking about that topic and about what we learned from the startup companies that we were following along with for the year. And now we're back to interview freeform, different guests, different topics. It seems like we're going to stick with that for a little while. But, obviously, as Will and Victoria have said, like, we'll probably change it again in some way, you know, a year, two years, three years from now. VICTORIA: Yeah, and I'm definitely bringing my interest around DevOps and platform engineering, so you'll see more guests who have that focus in their background. And with that, sometimes my interview style is more; how do I ask a question that I can't read from your developer docs and that I might not understand the answer to? [laughs] That's kind of where I like to go with it. So yeah, I'm really excited about...it's probably one of my favorite parts of my job here at thoughtbot because I get to meet so many interesting people. And, hopefully, that's interesting to everyone else [laughs] and our guests, yeah. BEN: Totally. Well, I dramatically underestimated how awesome it would be to meet all kinds of cool people in the industry when I started the podcast. I didn't truly connect in my head, like, wait a second, if I have a 45-minute conversation with, like, a lot of prominent, awesome people in our field, that's going to be really interesting and useful for me. So, I think, yeah, it's nice to be in the hosting seat. VICTORIA: And it's so surprising how I'll meet someone at a conference, and I'll invite them onto the podcast. And the way it winds up is that whatever we're talking about on the show is directly relevant to what I'm working on or a problem that I have. It's been incredible. And I really appreciate you for coming back for our 500th Episode here. CHAD: Ben, thanks very much again for joining us, and congratulations on all the success with Tuple. And I wish you the best. BEN: Thank you so much. Thanks for being a continuing customer. I really appreciate it. CHAD: Next, we caught up with Chris Toomey, who had a run as co-host of the show with Ben throughout 2016. CHRIS: Hi there. Thanks for having me. So, we're talking with all of the past hosts. I know you joined the show, and you were on it with Ben. And then you moved over to The Bike Shed, right? CHRIS: Yeah. So, I had co-hosted with Ben for about six months. And then I think I was transitioning off of Upcase, and so that ended sort of the Giant Robots “let's talk about business” podcast tour for me. And then, I went back to consulting for a while. And, at some point, after Derek Prior had left, I took over as the host of The Bike Shed. So, I think there was probably, like, a year and a half, two-year gap in between the various hostings. CHAD: Are you doing any podcasting now? CHRIS: I'm not, and I miss it. It was a lot of fun. It was, I think, an ideal medium for me. I'm not as good at writing. I tend to over-edit and overthink. But when you get me on a podcast, I just start to say what's in my head, and I tend to not hate it after the fact. So [chuckles], that combination I found to be somewhat perfect for me. But yeah, lacking that in my current day-to-day. CHAD: Well, what's been taking up your time since you left? CHRIS: I had decided it was time to sort of go exploring, try and maybe join a startup, that sort of thing. I was sort of called in that direction. So, just after I left thoughtbot, I did a little bit of freelancing, but that was mostly to sort of keep the lights on and start to connect with folks and see if there might be an opportunity out there. I was able to connect with a former thoughtbot client, Sam Zimmerman, who was looking to start something as well. And so, we put our act together and formed a company called Sagewell, which was trying to build a digital financial platform for seniors, which is a whole bunch of different complicated things to try and string together. So, that was a wonderful experience. I was CTO of that organization. And I think that ran for about two and a half years. Unfortunately, Sagewell couldn't quite find the right sort of sticking point and, unfortunately, shut down a little bit earlier in this year. But that was, I would say, the lion's share of what I have done since leaving thoughtbot, really wonderful experience, got to learn a ton about all of the different aspects of building a startup. And I think somewhat pointedly learned that, like, it's messy, but I think I do like this startup world. So, since leaving Sagewell, I've now joined a company called August Health, which has a couple of ex-thoughtboters there as well. And August is post their Series A. They're a little bit further along in their journey. So, it was sort of a nice continuation of the startup experience, getting to see a company a little bit further on but still with lots of the good type of problems, lots of code to write, lots of product to build. So, excited to be joining them. And yeah, that's mostly what's taking up my time these days. CHAD: So, I know at Sagewell, you made a lot of technical architecture, team decisions. It was Rails in the backend, Svelte in the frontend, if I'm not mistaken. CHRIS: Yep, that's correct. CHAD: You know, hindsight is always 2020. Is there anything you learned along the way, or given how things ended up, that you would do differently? CHRIS: Sure. I was really happy with the tech stack that we were able to put together. Svelte was probably the most out there of the choices, I would say, but even that, it was sort of relegated to the frontend. And so, it was a little bit novel for folks coming into the codebase. Most folks had worked in React before but didn't know Svelte. They were able to pick it up pretty quickly. But Inertia.js was actually the core sort of architecture of the app, sort of connected the frontend and the backend, and really allowed us to move incredibly quickly. And I was very, very happy with that decision. We even ended up building our mobile applications, both for iOS and Android. So, we had native apps in both of the stores, but the apps were basically wrappers around the Rails application with a technology similar to Turbolinks native–if folks are familiar with that so, sort of a WebView layer but with some native interactions where you want. And so, like, we introduced a native login screen on both platforms so that we could do biometric login and that sort of thing. But at the end of the day, most of the screens in the app didn't need to be differentiated between a truly native mobile app and what like, mobile WebView would look like. So, we leaned into that. And it was incredible just how much we were able to do with that stack and how quickly we were able to move, and also how confidently we were able to move, which was really a nice thing. Having the deep integration between the backend and the frontend really allowed a very small team to get a lot done in a short time. CHAD: Does that code live on in any capacity? CHRIS: No. CHAD: Oh. How does that make you feel? [chuckles] CHRIS: It makes me feel very sad, I will say. That said, I mean, at the end of the day, code is in service of a business. And so, like, the code...there are, I think, probably a couple of things that we might be able to extract and share. There were some interesting...we did some weird stuff with the serializers and some, like, TypeScript type generation on the frontend that was somewhat novel. But at the end of the day, you know, code is in service of a business, and, unfortunately, the business is not continuing on. So, the code in the abstract is...it's more, you know, the journey that we had along the way and the friends we made and whatnot. But I think, for me, sort of the learnings of I really appreciate this architecture and will absolutely bring it to any new projects that I'm building from, you know, greenfield moving forward. VICTORIA: I'm curious what it was like to go from being a consultant to being a big player in a startup and being responsible for the business and the technology. How did that feel for you? CHRIS: I would say somewhat natural. I think the consulting experience really lent well to trying to think about not just the technical ramifications but, you know, what's the business impact? How do we structure a backlog and communicate about what features we want to build in what order? How do we, you know, scope a minimal MVP? All those sorts of things were, I think, really useful in allowing me to sort of help shape the direction of the company and be as productive of an engineering team as we could be. CHAD: A lot of the projects you worked on at thoughtbot were if not for startups, helping to launch new products. And then, a lot of the work you did at thoughtbot, too, was on Upcase, which was very much building a business. CHRIS: Yes. I definitely find myself drawn in that direction, and part of like, as I mentioned, I seem to be inclined towards this startup world. And I think it's that, like, the intersection between tech and business is sort of my sweet spot. I work with a lot of developers who are really interested in getting sort of deeper into the technical layers, or Docker and Kubernetes and orchestration. And I always find myself a little bit resistant to those. I'm like, I mean, whatever. Let's just...let's get something out there so that we can get users on it. And I am so drawn to that side, you know, you need both types of developers critically. I definitely find myself drawn to that business side a little bit more than many of the folks that I work with, and helping to bridge that gap and communicate about requirements and all those sort of things. So, definitely, the experience as a consultant really informed that and helped me have sort of a vocabulary and a comfort in those sort of conversations. WILL: How did Upcase come about? Because I know I've talked to numerous people who have gone through Upcase. I actually went through it, and I learned a ton. So, how did that come about? CHRIS: I think that was a dream in Ben Orenstein's eye. It started as thoughtbot Learn many, many years ago. There was a handful of workshops that had been recorded. And so, there were the video recordings of those workshops that thoughtbot used to provide in person. Ben collected those together and made them sort of an offering on the internet. I think Chad, you, and I were on some podcast episode where you sort of talked about the pricing models over time and how that went from, like, a high dollar one-time download to, like, $99 a month to $29 a month, and now Upcase is free. And so, it sort of went on this long journey. But it was an interesting exploration of building a content business of sort of really leaning into the thoughtbot ideal of sharing as much information as possible, and took a couple of different shapes over time. There was the weekly iterations of the video series that would come out each week, as well as the, like, longer format trails, and eventually some exercises and whatnot, but very much an organic sort of evolving thing that started as just a handful of videos and then became much more of a complete platform. I think I hit the high points there. But, Chad, does that all sound accurate to you? CHAD: Yeah, I led the transition from our workshops to Learn, which brought everything together. And then, I stepped away as product manager, and Ben took it the next step to Upcase and really productized it into a SaaS sort of monthly recurring billing model and took it over from there. But it still exists, and a lot of the stuff there is still really good [laughs]. CHRIS: Yeah, I remain deeply proud of lots of the videos on that platform. And I'm very glad that they are still out there, and I can point folks at them. VICTORIA: I love that idea that you said about trying to get as much content out there as possible or, like, really overcommunicate. I'm curious if that's also stayed with you as you've moved on to startups, about just trying to get that influence over, like, what you're doing and how you're promoting your work continues. CHRIS: I will say one of the experiences that really sticks with me is I had followed thoughtbot for a while before I actually joined. So, I was reading the blog, and I was listening to the podcasts and was really informing a lot of how I thought about building software. And I was so excited when I joined thoughtbot to, like, finally see behind the curtain and see, like, okay, so, what are the insider secrets? And I was equal parts let down...actually, not equal parts. I was a little bit let down but then also sort of invigorated to see, like, no, no, it's all out there. It's like, the blog and the open-source repos and those sort of...that really is the documentation of how thoughtbot thinks about and builds software. So, that was really foundational for me. But at the same time, I also saw sort of the complexity of it and how much effort goes into it, you know, investment time Fridays, and those sort of things. Like, a thoughtbot blog post is not a trivial thing to put up into the world. So many different people were collaborating and working on it. And so, I've simultaneously loved the sharing, and where sharing makes sense, I've tried to do that. But I also recognize the deep cost. And I think for thoughtbot, it's always made sense because it's been such a great mechanism for getting the thoughtbot name out there and for getting clients and for hiring developers. At startups, it becomes a really interesting trade-off of, should we be allocating time to building up sort of a brand in the name and getting ourselves, you know, getting information out there? Versus, should we be just focusing on the work at hand? And most organizations that I've worked with have bias towards certainly less sharing than thoughtbot, but just not much at all. Often, I'll see folks like, "Hey, maybe we should start a blog." And I'm like, "Okay, let's just talk about how much effort that [laughs] actually looks like." And I wonder if I'm actually overcorrected on that, having seen, you know, the high bar that thoughtbot set. CHAD: I think it's a struggle. This is one of my [laughs] hot topics or spiels that I can go on. You know, in most other companies, that kind of thing only helps...it only helps in hiring or the people being fulfilled in the work. But at most companies, your product is not about that; that's not what your business is. So, having a more fulfilled engineering team who is easier to hire—don't get me wrong, there are advantages to that—but it doesn't also help with your sales. CHRIS: Yes. CHAD: And at thoughtbot, our business is totally aligned with the people and what we do as designers and developers. And so, when we improve one, we improve the other, and that's why we can make it work. That is marketing for the product that we actually sell, and that's not the case at a SaaS software company. CHRIS: Yes, yeah, definitely. That resonates strongly. I will say, though, on the hiring side, hiring at thoughtbot was always...there was...I won't say a cheat code, but just if someone were to come into the hiring process and they're like, "Oh yeah, I've read the blog. I listen to the podcast," this and that, immediately, you were able to skip so much further into the conversation and be like, "Okay, what do you agree with? What do you disagree with? Like, let's talk." But there's so much. Because thoughtbot put so much out there, it was easy to say, like, "Hey, this is who we are. Do you like that? Is that your vibe?" Whereas most engineering organizations don't have that. And so, you have to try and, like, build that in the context of, you know, a couple of hour conversations in an interview, and it's just so much harder to do. So, again, I've leaned in the direction of not going anywhere near thoughtbot's level of sharing. But the downside when you are hiring, you're like, oh, this is going to be trickier. CHAD: Yeah. One of the moments that stands out in my mind, and maybe I've told this story before on the podcast, but I'll tell it again. When we opened the New York studio, it was really fast growing and was doing a lot of hiring. And one of the people who had just joined the company a couple of weeks before was doing an interview and rejected the person was able to write an articulate reason why. But it all boiled down to this person is, you know, not a fit for thoughtbot. Based on what they were able to describe, I felt very confident with the ability or with the fact that they were able to make that call, even though they had been here only a couple of weeks, because they joined knowing who we were, and what we stand for, and what our culture and our values are, and the way that we do things, and all that kind of thing. And so, yeah, that's definitely a huge benefit to us. VICTORIA: I've certainly enjoyed that as well, as someone who hires developers here and also in meeting new companies and organizations when they already know thoughtbot. That's really nice to have that reputation there, coming from my background—some really more scrappier startup kind of consulting agencies. But, you know, I wanted to talk a little bit more about your podcasting experience while you're here. So, I know you were on both The Bike Shed and Giant Robots. Which is the better podcast? [laughter] So, what's your...do you have, like, a favorite episode or favorite moment, or maybe, like, a little anecdote you can share from hosting? CHRIS: Well, I guess there's, like, three different eras for me in the podcasting. So, there's Giant Robots with Ben talking more about business stuff, and I think that was really useful. I think it was more of a forcing function on me because I sort of...Both Ben and I were coming on; we were giving honest, transparent summaries of our, like, MRR and stats and how things were growing, and acted as sort of an accountability backstop, which was super useful but also just kind of nerve-wracking. Then, when I joined the Bike Shed, the interviewing sequence that I did each week was just a new person that I was chatting with. And I sort of had to ramp them up on, hey, here's a quick summary on how to think about podcasting. Don't worry, it'll be great. Everybody have fun. But I was finding each of the guests. I was sort of finding a topic to talk about with them. So, that ended up being a lot more work. And then, the last three years chatting with Steph that was by far my favorite. There was just such a natural back-and-forth. It really was just capturing the conversations of two developers at thoughtbot and the questions we would ask each other as we hit something complicated in a piece of code or, "Oh, I saw this, you know, article about a new open-source repository. What do you think about that?" It was so much easier, so much more natural, and, frankly, a lot of fun to do that. And, two, I actually do have an answer to the favorite podcast episode, which is the first episode that Steph was ever on. It was before she actually joined as a co-host. But it was called “What I Believe About Software.” And it was just this really great, deep conversation about how we think about software. And a lot of it is very much, like, thoughtbot ideals, I would say. But yeah, Steph came in and just brought the heat in that first episode, and I remember just how enjoyable that experience was. And I was like, all right, let's see if I can get her to hang out a little bit more, and, thankfully, she was happy to join. WILL: What was your favorite position, I guess you can call it? Because you say you like the mixture of business and, you know, development. So, you've been in leadership as development director, CTO. You've been a web developer. You've been over content, like, with Upcase. What was your favorite position [inaudible 16:43] you were doing, and why was it your favorite? CHRIS: The development director role feels like sort of a cheating answer, but I think that would be my answer because it contained a handful of things within it. Like, as development director, I was still working on client projects three days a week. And then, one day a week was sort of allocated to the manager-type tasks, or having one-on-ones with my team sort of helping to think about strategy and whatnot. And then, ideally, still getting some amount of investment time, although the relative amounts of those always flexed a little bit. Because that one sort of encompassed different facets, I think that's going to be my answer. And I think, like, some of what drew me to consulting in the first place and kept me in that line of work for seven years was the variety, you know, different clients, as well as, even within thoughtbot, different modes of working in podcasts or video. Or there was a bootcamp that I taught, a session of Metis, which that was a whole other experience. And so, getting that variety was really interesting. And I think as sort of a tricky answer to your question, the development director role as a singular thing contained a multitude, and so I think that was the one that would stand out to me. It's also the most, you know, the one that I ended on, so [laughs] it might just be recency bias, but yeah. VICTORIA: Oh, I love that. Is there anything else that you would like to promote on the podcast today? CHRIS: No, although as you ask the question, I feel like I should, I don't know, make some things to promote, get back into some, I don't know, content generation or something like that. But for now, no. I'm, you know, diving into the startup life, and it's a wonderful and engrossing way to do work, but it does definitely take up a lot of my headspace. So, it's an interesting trade-off. But right now, I don't know; if folks are online and they want to say hi, most of my contact information is readily available. So, I would love to say hi to folks, anyone that listened in the past or, you know, has any thoughts in the now. Would love to connect with folks. But otherwise, yeah, thank you so much for having me on. CHAD: In 2017, I took over from Ben as solo host of the show but was joined by Lindsey Christainson as cohost in 2019. After some time away from thoughtbot, Lindsey is back with us and we sat down to catch up with her. VICTORIA: Why don't you tell me about your current role with thoughtbot? LINDSEY: I am currently supporting marketing and business development at thoughtbot, as well as working as a marketing consultant for thoughtbot clients. VICTORIA: Great. And I understand that you had worked with thoughtbot many years ago, and that's when you also came on as a co-host of Giant Robots. Is that right? LINDSEY: Yeah, a couple of years ago. I left thoughtbot in spring of 2021. And I forget how long my stint was as a co-host of Giant Robots, but over a year, maybe a year and a half, two years? CHAD: Yeah, I think that's right. I think you started in 2019. LINDSEY: Yeah. Yeah, that sounds right. And Chad and I were co-hosts, I think, similar to the setup today in which sometimes we hosted together, and sometimes we were conducting interviews separately. CHAD: And then we sort of introduced a second season, where we followed along with a batch of companies over the course of the entire season. And that was fun, and we learned a lot. And it was nice to have consistent guests. LINDSEY: Yeah, that was a lot of fun. I really liked that format. I don't know; they almost were, like, more than guests at that point. They were just like other co-hosts [laughs] that we could rely on week in, week out to check in with them as they're working on early-stage companies. So, every time we checked in with them, they usually had some new, exciting developments. WILL: I really like that idea. How did y'all come up with that? CHAD: I'm not sure. I think a few years before I had taken over hosting of the show, and I forget...my memory maybe is that I went to Lindsey and said, "You know, let's do something different." But I'm not sure. Does that match your memory, Lindsey? LINDSEY: Yeah, I think there were two main drivers; one was I think you were feeling like you were having similar conversations in the interviews every time. Like, you couldn't get to a certain depth because every time you were interviewing someone, you were doing, like, the, "Well, tell me your founding story." And, you know, how did you raise funding? It kind of got a little bit repetitive. And then, on the side, the few we had done together, I think we both really enjoyed. So, we were thinking, like, what's the format in which the two of us could co-host together more regularly? Because I'm a pleasure to talk to [laughter]. I think you were like, I need to talk to Lindsey more. [inaudible 3:13] VICTORIA: What is your hosting style? How would you describe your approach to hosting a podcast? LINDSEY: I mean, obviously, it's a podcast about products and business. I think as a marketer, I am, you know, drawn a lot to the marketing side, so tending to ask questions around go-to-market audience, users. That's always just, like, a particular interest of mine. But then also, like, the feelings. I love asking about the feelings of things, you know, how did it feel when you started? How did it feel when you made this tough decision? So, that's another thing I think I noticed in my interviews is asking about some of the emotions behind business decisions. VICTORIA: And I like hearing about how people felt at the time and then how they felt afterwards [laughs]. And, like, how people around them supported each other and that type of thing. That's really fun. I'm curious, too, from your marketing background and having to do with podcasts like; some founders, I think, get the advice to just start a podcast to start building a community. But I'm curious on your thoughts about, like, how does podcasting really play into, like, business and marketing development for products? LINDSEY: Oh yeah. It's become definitely, like, a standard channel in B2B these days. I feel like that it's pretty typical for a company to have a podcast as one way that they engage their audience and their users. In marketing, you're really vying for people's attention, and people's attention span is getting shorter and shorter. So, like, if you have an ad or a blog, you're getting, like, seconds, maybe minutes of someone's attention. And whereas something like a podcast offers a unique channel to have someone's undivided attention for, you know, 30 minutes, an hour, and if you're lucky, you know, checking back in week over week. So, it became a really popular method. That said, I think you're probably also seeing the market get saturated [laughs] with podcasts now, so some diminishing returns. And, you know, as always, kind of looking for, you know, what's the next way? What's the next thing that people are interested in in ways to capture their attention? CHAD: What is the next thing? LINDSEY: I don't know, back to micro-content? TikTok videos -- CHAD: Yeah, I was going to say TikTok, yeah. LINDSEY: Yeah, you know, 10-30 seconds, what can you communicate? VICTORIA: I see people live streaming on Twitch a lot for coding and developer products. LINDSEY: Yeah, I think we've seen some of that, too. We've been experimenting more at thoughtbot with live streaming as well. It's another interesting mechanism. But yeah, I don't know, it's interesting. It's another form of, like, community and how people engage with their communities. So, it's always evolving. It's always evolving, and sometimes it's not. Sometimes, people just do want to get in a room together, too, which is always interesting. WILL: What has been, in your experience, the good the bad? Like, how do you feel about the way that it has shifted? Because I think you started in, like, 2000, like, kind of earlier 2000, 2005, something around there. And it was totally different than now like you're saying. Because I feel like, you know, Channel 5 30-second ad, you know, with some of the marketing depending on what you're doing, to now to where you're, like, you're paying influencers to advertise your product, or you're doing an ad. Or it's more social media-driven and tech-driven. What has been your opinion and feelings on the way that it has grown and evolved? LINDSEY: Marketing, in general, yeah, I graduated college in 2005 and started my marketing career. And yeah, you could, like, actually get people to click on banner ads back then, which was pretty [inaudible 07:14] [laughs]. WILL: I forgot about banner ads [laughs]. LINDSEY: I don't know, yeah. I don't know. In order for myself to not just get too frustrated, I think I've got to, like, view it as a game kind of. What new things are we going to try? You know, what do we see work? But it can really depend. And I've always been in B2B side of things. And consumer, I'm sure, has its own kind of evolution around how people engage and how they consume content and byproducts. But in B2B, you know, it can really depend on industry too. You know, I'm working with a client right now in the senior living space, and they're really big in in-person conferences. So, that's how people consume, get a lot of their information and, make connections, and learn about new products. So, it's been interesting to work in an industry that what might be considered, like, a little bit more old-school channels are still effective. And then just thinking about how you weave in the new channels with the existing ones without ignoring them. They might get information in conferences, but they're still a modern human who will then, you know, search online to learn more, for example. VICTORIA: It reminds me of a phrase I like to say, which is that, like, technology never dies; you just have more of it. There's just more different options and more different ways to do things. And some people are always, you know, sometimes you have to be flexible and do everything. CHAD: So, tell us more about what you did in between...after you left thoughtbot, what did you do? LINDSEY: I was heading up B2B marketing for a company called Flywire, which is headquartered in Boston but is a global company now. And they were just kind of starting their B2B business unit, which, as I mentioned, B2B is my personal specialty. I had been connected to their CMO through the Boston startup community. And yeah, I was helping them kind of launch their go-to-market for B2B. The industries they were in before...they got their start in higher education and then expanded in healthcare and found a niche in luxury travel, and then we were figuring out the B2B piece. But yeah, I was there for about a year and a half. They actually went public the second week I was there, which was an interesting [laughs] experience. I knew they were, like, on that journey, but it was kind of funny to be there the second week, and people were, like, "Congrats." And I was like, "Well, I definitely didn't have anything to do with it because I just finished my onboarding, but thank you," [laughs]. CHAD: One of the things that really impressed me when you joined thoughtbot was the way in which you learned about who we were and really internalized that in a way where you were then able to pretty meaningfully understand our market, our positioning in the market, and come up with new strategies for us. I assume that's something you're good at in general [laughs]. How do you approach it? How did you approach it when you joined Flywire, for example? And how was it the same or different than how you approached thoughtbot? LINDSEY: Ooh, yeah, that's a good question. And I appreciate that comment because it's difficult. But I think, yeah, with any new organization that I'm joining, you know, I think starting out with your kind of mini-listening tour of your key stakeholders across, you know, the different departmental focuses to get a sense of, what are the challenges? What are the opportunities? It's actually like, you know, it's the SWOT analysis, kind of trying to fill in your own mind map of a SWOT analysis of where the company is. What are the major hurdles you're facing? Where are people trying to go? What have they tried that's worked? What have they tried that's failed? But then, like, I think for the culture component, I think a part of that maybe is, like, feel, and maybe something that I do have a knack for. Again, maybe this is, like, you know, emotional intelligence quotient, where it's like, you know, but it's the company, you know, who is this company? What is important to them? How do they work and go about things? I know thoughtbot is certainly very unique, I think, in that arena in terms of being, like, a really value-driven company, and one where especially, like, marketing and business work is, like, distributed across teams in a really interesting way. You know, I'm sure the fact that it fascinated me and was something I could get passionate and get behind was something that also helped me understand it quickly. CHAD: I was excited that...or it was sort of a coincidence because I had reached out to you and without realizing that you had left Flywire. And Kelly, who had been doing a combined sales and marketing role, was going on parental leave. And so, it was fortuitous [laughs] that you were able to come back and help us and provide coverage, like, Kelly was out. LINDSEY: Yeah, it definitely felt like stars aligned moment, which, you know, I'm pretty woo-woo, so I believe in [laughter]...I believe in that kind of thing. You know, yeah, it was wild. It really did feel like your email came out of nowhere. And, you know, I mentioned it, obviously, to my partner and my friends. And they were like, "Oh, he definitely knows, like, that you left your last company." And I'm like, "I actually don't think he does [laughter]. I actually don't think he does." Yeah, and then we started chatting about me coming back to help. And it was great. thoughtbot makes it hard to work anywhere else [laughs]. So, I was happy to come back. I missed the team. CHAD: And one of the exciting things, and you've mentioned it, is you're not just doing marketing for thoughtbot now. We have started to offer your services to our clients. LINDSEY: Yeah, I'm super excited about this. And it's something I'd started thinking about. I had decided to take some time off between Flywire and my next thing and had started thinking about doing marketing, consulting. And as I'm doing that, I'm thinking a lot about how thoughtbot does consulting and, you know, wanting to emulate something like that. So, I started back up at thoughtbot. That wasn't part of the plan. I was just going to, you know, fill in for Kelly and help with marketing things. But then, you know, a good opportunity arose to work on a client, and I was really excited. When, you know, Chad, you and I chatted through it, we came to the conclusion that this was something worth exploring under the, you know, thoughtbot umbrella. And it's been a really great experience so far. And we now have brought on another client now. And if you're listening and need early-stage B2B marketing support, reach out to lindsey@thoughtbot.com. CHAD: Definitely. And Lindsey is pretty good, so you're going to like it [laughs]. LINDSEY: Yeah, you're going to like the way you look. WILL: Yeah, definitely. Because I can even feel your presence here, you know, coming back. Because even like, you know, the market where it's at now and some of the suggestions that, you know, you've been helping us. For example, like, I do a lot of React Native, and you're like, "Hey, you know, blog posts have done a lot of traction, you know, let's get some more blog posts out in the market to help with the traffic and everything." So, the question I have with that is, like, thank you for even suggesting that because it's, like, those little things that you don't even think about. It's like, oh yeah, blog posts, that's an easy transition to help the market, clients, things like that. But with the market the way it is, what has been your experience working during this time with the market? I don't know if you want to call it struggling, but whatever you want to call it that, it's doing [laughs]. LINDSEY: Yeah, I mean, the economy is difficult now. We also went through a really tough spot when I was here last time. During COVID, you know, we faced a major company challenge. And, I mean, I'll let Chad speak to it, but I would imagine it's probably one of the bigger, like, economic inflection points that you faced. Would you say that? CHAD: Yeah, definitely. The thing about it that made it worse was how quickly it happened. You know, it was something that you didn't see coming, and then, you know, about 40% of our business went away in a single month. That's the kind of thing that was a real shock to the system. I think the thing that made it difficult, too, was then the aspects of COVID, where we were no longer able to go into our studios. We were all working remotely. We were isolated from each other. And so, that made executing on what needed to be done in order to make the company survive additionally challenging. LINDSEY: Yeah, so I think, like, going through that experience, also, and seeing how the team and the leadership team rallied together to get through it. And then, you know, ultimately, I think 2021 and 2022 have, like, really good years. That was a really positive experience. And something I'll definitely take with me for a while is just, like, keeping a cool head and just knowing you have, like, really smart, talented folks with you working on it and that you can get through it. And just, like, doing some, I mean, we relied on what we did best, which was, like, design thinking, using design exercise to think about, like, how we might re-organize the company, or what other services we might try launching, or how might we re-package, you know, larger services into smaller more palatable services when people have, like, kind of tighter purse strings. So, that was, like, a great educational experience, and I think something we just continue to do now: be open to change, be open to changing how we package services, what clients we go after, and coming at it with, like, an agile, experimental mindset and try to find out what works. VICTORIA: I really appreciate that. And it aligns now with the new service we've developed around you and the marketing that you provide. And I'm curious because I've had founders come up to me who say they need help with marketing or they need to, like, figure out their marketing plans. So, say you've met a founder who has this question, like, what questions do you ask them to kind of narrow down what it is they really need and really want to get out of a marketing plan? LINDSEY: I've been thinking about this a lot recently. And, like, obviously, I see other marketing leaders in the market. Marketers like to talk about what they do on LinkedIn [laughs], so I get to...I read a lot about different people's approaches to this. And some people kind of go in and are like, okay, this is what you need. This is how we're going to do it, and they start executing on it. And I really do take a very collaborative approach with founders. I think they're, especially in early stage, they're your most important asset in a way, and a lot of their intuition around the market and the business, you know, it's gotten them to where they're at. And so, I think starting from the point of, like, taking what they view as priorities or challenges, and then helping them better explore them or understand them with my own marketing experience and expertise, to
Last summer, Tailwind UI moved from selling individual content packages and upsells to a one-time purchase, lifetime access pricing model. Since then, the business has doubled. Having seen this in action, Adam recently convinced his friends Sam and Ryan to try lifetime pricing for their product Build UI, and the results are starting to come in. In this episode, Adam and Ben dive deep into the world of lifetime pricing, why it's not something to be afraid of, and how it can be an absolute game-changer for the right type of business.Discuss this episode on Twitter →Timestamps(00:00) - Intro (00:14) - Why are we talking about this? (03:28) - Moving from package pricing to lifetime all-access pricing for Tailwind UI (06:03) - What about when you run out of new customers? (10:17) - "Everything You've Learned at MicroConf is Wrong" by Chad DeShon (13:33) - The myth of starting from zero every month (16:04) - Would Tailwind UI work as a subscription model? (18:09) - Characteristics of a lifetime-suitable product (20:50) - Subscription LTV vs. lifetime pricing (22:47) - Subscription friction and the death of the impulse purchase (25:42) - The brutality of churn in content businesses (27:21) - Why your lifetime price can actually be higher than your subscription LTV (29:01) - Ben's experience running Upcase at thoughtbot (32:42) - The hidden costs of the content treadmill (36:20) - Hitting a subscription plateau with Upcase (38:34) - Cookie Clicker game — how to make perceived value go up over time (42:31) - Why aspirational, impulsive purchases are more likely with lifetime deals (45:22) - Pricing decisions aren't forever (49:13) - Turning Build UI from a grind into an instant success by flipping the switch on pricing (54:17) - Using lifetime pricing to buy yourself flexibility and time to focus LinksAdam on TwitterBen on TwitterTailwind UI all-accessEverything You've Learned at MicroConf is Wrong, Chad DeShon's lighting talk at MicroConf Growth 2018Build UI, Sam and Ryan's new UI training site that recently switched to lifetime pricing
It's Steph and Chris' last show. Steph found a game, and if you've been following the journey, all of the Test::Unit test files are now live in RSpec. JWTs really grind Chris' gears. They wrap up with things they've learned, takeaways they've had, and their proudest podcasting moments. They also thank all the folks who've helped make The Bike Shed happen. This episode is brought to you by Airbrake (https://airbrake.io/?utm_campaign=Q3_2022%3A%20Bike%20Shed%20Podcast%20Ad&utm_source=Bike%20Shed&utm_medium=website). Visit Frictionless error monitoring and performance insight for your app stack. Microservices (https://www.youtube.com/watch?v=y8OnoxKotPQ) Transcript: CHRIS: One more round of golden roads, our golden. So here we go. STEPH: Oh, one more round of golden roads. Okay, maybe that's going to get to me today. [laughs] CHRIS: [singing] Golden roads take me home to the place. STEPH: [singing] I belong. CHRIS: Yeah, there you go. Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm 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, at least one more time. So with that [chuckles] as an intro, Steph, what would you say is new in your world? STEPH: Hey, Chris. Well, today is the big day. It is the day that you and I are recording our final Bike Shed episode, which we have all the feels about, and we will definitely dive into. But to ignore some of that for now, I have another small fun update I can provide about a new game that I found. So one of the things that's new in my world is I started playing a new board game with Tim; it's called Ticket to Ride. Have you heard of that? CHRIS: I have. I don't know if I've played it. I feel like it's a particularly popular one now. But I don't know if I've ever had the pleasure. STEPH: It's a very cute game, so we have the smaller version of it. For anyone that's not familiar, it's essentially a map. And then there's a bunch of spots where you can build trains and connect them, and then you get tickets. So your goal is that you're going to connect one location to another location. And then you get points and yada yada, but it's so much fun and especially the two-player version. It's like this perfect 20, maybe 30-minute game. I'll be honest; I'm not really a board game person. I always enjoy it. Once I get into it, then I'm like, this is great. I don't know why I was resistant to this. But every time someone's like, "Do you want to play a board game?" I'm like, "Not really." [laughs] I first have to get into it. But I have really enjoyed Ticket to Ride. That's been a really fun game to play. And it's been a nice way to, like, even during the day, we'll break for lunch and squeeze in a game. CHRIS: Well, I love good two-player games. They're hard to find. But when you find a good one, and it's got that easy pickup and play...I believe I'm going to now purchase this. And thank you for the tip. STEPH: Yeah, this is definitely one of those where it's easy to pick up, and then you can get the expanded board. So there's a two-player version, but then yeah, you can get one that's a map of the U.S. or a map of Europe. And I think it accommodates up to five players as the maximum, so not a huge group but definitely more than two. On a slightly more technical note, I have something that I'm very excited to share. It is a journey that you have been on with me, that everybody listening has been on this journey with me. And I'm very excited. I see you nodding your head, so I'm guessing that you're going to know where I'm headed with this. But I'm very excited to announce that all of the Test::Unit test files now live in RSpec. So that is a big win. I'm very, very excited for that to be a previous state of life and not an ongoing state of life. Because I have certainly developed too much niche knowledge around migrating these tests, and that became apparent to me when I was pairing with another developer that works with the client because they had offered...they had some time. They're like, "Hey, do you want help migrating a test file?" And I was like, "Sure." I was like, "But this is wonky enough, like, we should pair and work on this together because I just know some ins and outs. And I don't want you to have to learn a lot of the hard lessons that I've learned." And the test that we happened to pick up was very gnarly. It had a lot of mystery guests. And we spent, I think it was a good two hours. And we only migrated one of the tests, so not even a full file but one of the tests. And at the end of it, I was like, I know way too much about some of the oddities and quirkiness of this. And we got through it, but we decided that wasn't a good use of their time for them to go at this alone. So that's why I'm extra excited and relieved because I didn't want this task to carry on to someone else. So, hooray, we did it. CHRIS: Hooray. Just in time. You're Indiana Jones grabbing your hat right as you roll out and off to [laughs] be away from the project for a bit. So you stuck the landing. Well done, Steph. STEPH: Thank you. Thank you. So that's some great news. And then also, everything else in life is pretty much focused around getting ready for maternity leave. That's about to happen soon, and I am so ready. I have thoroughly enjoyed a lot of the things that I'm doing, [laughs] but goodness, being pregnant is hard. And I am very much ready for that leave. So also, a lot of the things that I'm doing right now are very focused on making sure everything's transitioned and communicated and that I just feel really good about that day of departure. That covers all the newness in my world other than the big thing that we're just not talking about yet. How about you? What's new in your world? CHRIS: Well, continuing to skirt the bigger topic that we will certainly get to in the episode, what is new in my world? I'm actually quite excited workwise right now. We have a much larger body of work that finally we got the clarity. All the pieces fell into place, and now we're sort of everybody rowing in the same direction. There's interesting, I think, really impactful code that we're writing for Sagewell right now. So that's really fantastic. We've got the whole team back together on the engineering side. And so we're, I think, in the strongest and most interesting point that I have experienced thus far. So that's all really fantastic. On a slight technical deep dive, you know what really grinds my gears? It's JWTs. JSON Web Tokens and I have never gotten along. It's never been a match made in heaven. And we have a webhook that comes from Plaid. Plaid is a vendor for connecting bank accounts and whatnot. And they have webhooks like many people do. So they can inform us when things change, lovely feature of how we build web apps these days. But often, there's a signature that says, "This is definitively from us, and you can trust us." And usually, it's some calculated signature, HMAC, or something like that. For some reason, Plaid's uses JWTs, and more than that, they use JWKs. So there's JWT which is the signature. That JWT itself is signed with a JWK. You have to fetch the JWK from their server based on the key ID in the header of the JWT. But how do you know if you can trust the JWT before you've gotten the JWK? All of this broke in a recent upgrade. We went from Heroku-20 to Heroku-22 to the new platform with Heroku, which bumped us to OpenSSL 3.0, and it turns out JWT doesn't work with it. And so that's sad. It's a no. It's going to be a no. It turns out the way that OpenSSL 3.0 works is incompatible with some of the code paths in JWT. And so I was like, wait, we just can't do this? And it's low-level cryptographic primitive stuff that I'm not comfortable messing around with. I'm not going to hop in there and roll up my sleeves. And even just getting to the point that I understood what was broken about this took like an hour and a half just to sort of like, wait, which is okay...so the JWT signs and encodes. And this will be a theme that we come back to later, but I think web development should be simpler. I think we should strive for simplicity. And this is a perfect example where I'm guessing Plaid uses JWTs and that approach to communicating security things often, but I've not seen it used much for signing webhooks. And, oof, it led to a complicated day. And it's unfixable now as far as I can tell. There is a commit on the JWT Ruby repo as of five days ago, but it doesn't build in our system. And it's not released. And it's just a mess. So yeah, engineering is complicated. I'm both wildly excited about what we're doing at Sagewell, and then today was this local minimum of like, oh, JWTs again. Again, we find ourselves battling. And you won today, but hopefully not for too long. STEPH: Oof, how did this manifest that you first noticed? So is it because a webhook suddenly stopped working, and that was like the error that rose up, and that's what helped you dive into it? CHRIS: Yeah, we have a little bit of code in the controller for where Plaid events come in. We calculate and verify the signature of the webhook to make sure that it's valid, and we reject it otherwise. And we alert ourselves via Sentry, and then we also have a Datadog scan that can show what's the status code of the response. Because these are incoming HTTP payloads or requests, and so we can see there were 200 up until this magical day when suddenly everything changed. And that was when we switched Heroku stacks. And then we can see it also in Sentry. So we're able to look at it, and we're like, why are none of the Plaid webhooks able to verify the signature anymore? That seems weird. And so then Datadog confirmed that it consistently was broken from this point in time. And then we were able to track that back. It was also pretty easy to guess because the error was "pkeys are immutable in OpenSSL 3.0," and that was the data. And I was like, oh, cool, that sounds fun. Let me go figure out what that means. STEPH: [laughs] Well, it's a nice use of Datadog. I remember in the past you were talking about adding it. And I was excited because I've never been at that point where a team has just introduced it; either a team doesn't have it, and they wish they had more insights, or they have it and don't use it. And nobody ever checks the board. So that's a nice anecdote for Datadog helping you out. Yeah, I'm not envious of your situation, friend. CHRIS: I do love the cup half full take [laughs] that you have on the overall situation, but that's nice how Datadog worked out for you. And you know what? It was. Thank you, Steph, for once again being that voice of positivity. STEPH: I appreciate that you enjoy it because there are times that when someone points it out to me that I do that, I have to be like, "I'm sorry, I'm not trying to be toxic positivity over here. [chuckles] That's just how my brain works." CHRIS: Oh, you are definitively not toxic positivity. That's a different thing. Because you ended with but also, I feel bad for you, and I'm glad that I'm not in your shoes. So you are the right level of positivity. I don't think I could have talked to you for three and a half years as co-host on a podcast if I didn't appreciate the level of positivity or the general approach that you bring to thinking about stuff. STEPH: Okay. Well, to borrow a phrase from Matt Sumner, who has been a guest on the show, cool, cool, cool, cool. I'm glad my positivity has been well calibrated. And I was about to say I'm interested to hear how this turns out for the team. [laughs] But we're in an awkward spot where I mean, you and I, we can still totally chat. But listeners won't get to hear the rest of that particular saga. I mean, you can share. I mean, you do you. I'm setting all sorts of boundaries for you right now. Okay. And now I'm just rambling, and I'm getting weird with it. Because the truth is that, you know, we won't be back. And this is our final episode together. So I think let's just go ahead and rip off the Band-Aid. Let's dive into it. Let's talk about it. Given that it's our last episode that we are recording, we thought of a couple of things that we'd like to talk about. You brought up a great idea that I'm excited to dive into. Do you want to lead us in? CHRIS: Sure. Well, if we go back all the way to Episode 172, that is the first episode that you came on as a guest. I actually continue to really love the title of that episode, which is What I Believe About Software. And it both captured that conversation really well, but also, more generally, it's actually become the tagline of the show when we do our little introduction. What do we believe about building great software? Et cetera. And I think that's been the throughline of the conversations that we've had is what remains true. What are the themes? Not necessarily the specific technologies, although we certainly talk about that. But what do we believe about building great software? And so today, I thought it would be fun for us to talk about what do we still believe about building great software? It's roughly three and a half years or so that we've been doing this. What's still true? STEPH: Oh, well, I have the first unequivocal one, the thing that I still believe about building great software, and that's you should hire thoughtbot. That's definitely the way to go. We'll help you get it done, not that I'm biased in any way. CHRIS: No. I'd say collectively between us; there's zero bias with regard to thoughtbot or any other web development shop out there. But thoughtbot is the best. STEPH: All right, perfect. So we've got the first one, the clutch one of hire thoughtbot. And then I also really like this topic. And I still think back to that first episode that I recorded with you and how much fun that was and how that really got me to start thinking about this. Because it was something that, at the time, I didn't really reflect on a lot in terms of what does it take to build great software? I was often just doing the day-to-day actions but then not really going high-level think about it. So I'm excited this is one of the topics that we're revisiting. So for the next one, this one is, I don't know, maybe it's a little cutesy, but I was trying to think of an alliteration that I enjoyed. And so this one is be an assumption assassin. So what assumptions are you making? And then how can you validate or disprove them? And that is something that I find myself doing constantly. And it always yields better work, better questions, better software, better code, better code reviews. And that's my first one is be an assumption assassin and identify what assumptions you have. And I had a really good example come up today while I was having a conversation with Joël about something that I was looking to merge. But I was a little hesitant about it because there are some oddities that I won't dig in too deeply. But essentially, there's a test that I migrated that highlights an existing concern in the code. And I was like, should I go ahead and merge this test that documents it, or should I wait to fix that concern and address it? And he brought up a good point. And he's like, "Well, we're assuming it's a bug and an issue, but it may not actually be depending on how the software is being used." And so then he was encouraging me to reevaluate that assumption that I had where I'm like, oh, this is definitely a problem to, like, I don't know, is it a problem? Let's ask somebody. CHRIS: First off, I love that as a theme, as one of the things that you still believe about software. Second, I believe you correctly said that you were looking for an alliteration, but my brain heard acronym. STEPH: [laughs] CHRIS: And so then I was like, B-A-A-A. Is it BAAA? What are you going for there? Oh, you just wanted a bunch of As. Okay, I got it now. Secondly or thirdly, I think I'm on my third now. Apparently, within Sagewell team culture, one of the things that I'm most known for is... there are two phrases: one is just to name it, and the other is to be clear. And these are the two things that I do apparently constantly so much that it's become a meme within the team. It's just like, okay, everybody's been talking. But I just want to make sure we're on the same page here. So just to be clear, or just to name it, here's what I'm seeing. But I agree; I think taking those things...what are the implicit bits? What are the assumptions? And making them more explicit. Our job as developers is just to yell at computers all the time and make them try and do human stuff. And there's so much room for lossy conversions at every point in that conversation chain. And so yeah, being very clear, getting rid of assumptions, love it. It's all great stuff. Actually, in a very related note, the first on my list is that code is for humans to read. This is one of the things that I believe most deeply and most impacts the way that I write software. Any given piece of functionality that we want to author in our code feels like 10, 20, 50, frankly, almost infinite different versions of the code that would produce nearly identical functionality. So at the end of the day, the actual symbols and strings of text that we bring together to write the code is all about other humans, other people on your team, you five months from now, you a week from now, frankly, or me. I'm going to say me, me a week from now. I want to do future me and everyone else on the team a solid and spend that extra 10% of okay, I have something that works now, but let me try and push it around and try and massage it into a shape that is a little more representative of how we're actually thinking about the code, how we talk about it as an organization. Is that the word that we use to describe that domain concept? Maybe we could change that just a little bit. Can I push more of this into the private API? What actually needs to be known here? And I think that's where I'm happiest is in those moments because that's where all of the parts of the job come together, the bit where I trick a computer into doing what I want and simultaneously making it so that that code is revisitable, clear, expressive, all of those things. So yeah, code is for humans. And that's true across every language, and framework, and domain that I have worked in. And I've only believed it more and more so over time. So yeah, that's mine. STEPH: Yeah, I love that one. That's one of the things that comes to mind when people talk about disliking code reviews. And I can imagine there are a number of reasons that people may have had a poor experience with a code review process. But at the end of the day, if you're not getting that feedback or validation from fellow humans, then how do you know that you've been successful, that you've written something that other people can follow up on? Which goes back to the assumptions in terms of like, you're assuming that you have written something that your future self or that other people are going to be able to read and maintain down the road. So yeah, I love that one. One of the other things that I still hold really true to building great software is prioritize early and often. So always be checking in to understand with your users, with your tech concerns, with data that you may have, new insights, and then just confirm that yes, you and the team are constantly working on the thing that has been prioritized and that is the most important. And also, be ready to let go. That can be really hard. I have definitely had those moments in my career where I've spent two weeks working really hard on something. And then we've realized that the thing that we were pursuing isn't that valuable, or it's something that users don't need or actually want. And so it was better to let go of it than to pursue it and ship it anyways. So that's one of my other mantras that I have adopted now is prioritize, prioritize, prioritize. CHRIS: Unsurprisingly, I agree wholeheartedly with all of that. We're still searching for that thing, that core thing that we disagree on other than Pop-Tarts and IPAs. But I don't know that today is the episode that we're actually going to find that. But yeah, prioritizing is such a critical activity. And it is this interesting collaboration point. It gets different groups together. It's this trade-off. It's this balance. And it's a way to focus on and make explicit the choices that we're making. And we're always making choices. We're always making trade-offs. And so being more explicit, being more connected and collaborative around those I believe in so, so, so much. So love that that was something on your list. Let's see, next up on my list is reduce complexity, just sort of as an adage, just always be reducing complexity. It is amazing to me in my time, particularly as a consultant, but even now, this is something that I hold very true is just it's so easy to grow a system in anticipation of future complexity or imagine that the performance concerns that we're going to run into will be so large that we must switch from Postgres and a nice, simple atomic database into a sharded, clustered Kafka queue adventure. And there are absolutely cases that make sense for that sort of thing. But at a minimum, I beg of you, anyone starting a new system, don't start with microservices. Don't start with an event queue-based system. These are wildly complex versions of what often can be done with so much simpler of an application. And this scales through to everything. What's the complexity of an API? Do we need caching in that API layer? Or can we just be a little bit inefficient for a little while and avoid the complexity and the overhead of caching? Turns out caching is a tricky thing to get right, just as an aside. And so the idea of like, oh, let's just sprinkle in a little bit of caching. It'll be easy, and then we'll get better performance, like, yeah, but did you get it right? Or did you introduce a subtle bug into your program that's going to be really hard to debug later? Because do you cache in development? Well, maybe, I'm not sure, could be. So over time, this is something that I've sort of always felt, but I've only ratcheted it up. It's only something that I've come to believe in more and to hold more firmly to. I think earlier in my career, it was something that I felt, but I would more easily be swayed by aspirational ideas of the staggering amounts of traffic that we would be getting soon or the nine different ways that the data model will expand. And so, we should code the current version in anticipation of that. And I have become somewhat the old man on his lawn yelling at the clouds like, "Nah, we don't need it yet. We can grow to that." And there's a certain category of things that are useful to try and get out in front of and don't introduce additional complexity, but they're a tiny, tiny list. And so, for most things, my stance is what's the simplest thing that we can get away with right now, that still provides a meaningful experience to our users, that doesn't compromise on security or robustness or correctness but just solves the problem we have right now? And over and over and over again, that has served me incredibly well. So yeah, keep that complexity at bay. STEPH: That is one that I've definitely struggled with. And frankly, it works in my favor, that idea of keeping things simple. Because I'm terrible when it comes to predicting the future or trying to build things in a way that I just don't have enough information to really drive the architecture or the application that I'm building. So anytime I'm trying to then stretch and reach for the future in those ways unless I really have a concrete understanding of I am building for these particular scenarios, it's really hard to do. So I very much like keeping it simple and not optimizing before you need to. And it reminds me of I think it's Mark Twain, who has a quote, "Worrying is like paying a debt that you don't owe." And that's something that comes to mind for me when also writing code and building features and software is that I tend to be someone who will worry about stuff. And I'm like, oh, is this going to be easy to extend? Is it going to be what it needs to be six months from now if we need to add more features to this and build on top of it? And I have to remind myself it's like, well, let's just wait. Let's wait till we get there and we know more. One of my other ideas that couples nicely with the one that you just shared in regards to keeping things simple and then waiting for those needs to arise is that mistakes are going to happen. They are a part of the process. As we are learning and growing and we're stretching our skills and trying things out, things are going to go wrong. We're going to introduce bugs. And to take those opportunities, that's when we start to use that feedback to then improve things like observability, like capturing logs, and how we handle error reporting or having a plan for emergencies. So maybe that's the part of worrying that can pay off is thinking through, all right, if something does break, or if something gets shipped that shouldn't, then what is our plan in how we handle that? How do we roll back? Or how do we get things back to a stable build? CHRIS: It's funny. I was actually visiting with a friend this past weekend, and we were chatting more generally about life things but the idea of worrying and anticipation and trying to prepare for every bad outcome. And there's the adage of an ounce of prevention is worth a pound of cure. But increasingly, both in life, depending on the context, and in code, I've found that I've shifted to the opposite of it's impossible to stop everything. There are going to be bugs that are going to get out there. There are going to be places where we code things incorrectly. And I would rather...I still want to try as hard as I can to get things right, to be clear. I'm not giving up on trying. But I'm all the more focused on how do we know and how do we recover when those things happen? So it's interesting that you just described exactly that, which, again, is a very human life conversation, and yet it applies to the code. STEPH: I love that rephrasing of it. Instead of the mistakes are going to happen, it's, like, how do we know, and how do we recover? I think that's perfect. I've also found that by answering the how do we know and how do we recover, that really helps you build trust with clients as well. Because again, things are going to happen, things are going to break. And the more prepared you are for that and then the better plan that you have, and then they can watch how you execute that plan, and it's going to establish a lot of deep trust with other engineers and also the team that you're working with, that you have been thoughtful and that you have ideas on how are we going to address this? Instead of waiting for that moment to happen. That's going to happen too. You're going to make decisions in the heat of the moment. But I have found that to be a really useful way to establish yourself with a team in terms of I care about this team and these processes and this application. So how do we handle the bad times, not just the good times? I do want to circle back because you alluded to the fact that you and I, we've tried to find things that we disagree on. And so far, Pop-Tarts and beer have been the two things that we disagree on. But I do have a question for you that maybe I will disagree with you on. But I need to know some more about it first. You have alluded to there's the Brussels snack, (Oh, I'm going to get this wrong.) Brussels sprout snack hour or working lunch, something combination of those words. [laughs] And it's the working lunch that has stuck out to me, and I've wanted to ask you about it. So here I am. I'm asking you about it. What's a working lunch? What's the Brussels snack happy hour, snackariffic working lunch look like? CHRIS: This is fantastic. I love that you waited until the last episode that this was rolling around in the back of your head. And you're like, are you making the team work through lunch? And now, on this final episode, we get to address the controversy that has been brewing in the back of your head. Spoiler alert, no, this is just ridiculous nomenclature. These are two meetings that we have that are more like, let's get the dev team together and talk about stuff that's in our platform sort of developer experience. Or stuff in observability often is talked about in this context because it doesn't quite impact users, but it's how we think about the work. And so there are two different meetings that alternate every other week. So every Friday afternoon, we do this, but it's one of two meetings depending on the day. So there's a crispy Brussels snack hour that was the first one that was named, which was named purely for nonsense reasons because we don't have anything else that's named nonsensically in our organization. And so I was like, oh when we name this meeting, we should make it nonsense because we don't have any other...We don't have, you know, an SOA microservices fleet with Barbie doll and Galactus and all of the other wonderful names. Those are references to the greatest video ever about microservices; if you've not seen it, that will be in the show notes. It's required reading. But anyway, we don't have that. And so we thought, let's be funny with the name of this. So the crispy Brussels snack hour is one, and the crispy Brussels we wanted something that was...the first one is a planning meeting. The second is like, let's actually sort of ensemble program. Let's get the four of us together, and we'll work on some of the stuff that we're talking about here but as a group. And so I wanted the idea of we're working, and so I was like, oh, this will be the crispy Brussels work lunch. But it's purely a name. It's the same time slot. It's 3:00 o'clock on a Friday afternoon. [laughs] So it is not at all us working through lunch. I don't think we should work through lunch. I'm concerned that you thought that for a while, and you were just like, I'm a little worried, but I'm not going to bring it up. But I'm glad we got to cover this before we wrapped up this whole Bike Shed co-hosting adventure together. STEPH: I feel relieved and also a little robbed of an opportunity for us to have something that we disagree on because I thought this might be a thing. [laughs] CHRIS: We can continue searching for that thing. But maybe it's okay that we agreed on most stuff for the run [laughs] of this fun, little show that we did together. STEPH: Yeah, that's gone on quite a time. We've got like three years together that we have managed to really only find two, I mean, very important of course, two things. But yeah, it's been pretty limited to those two areas. And each time that you'd mentioned the work lunch, I was like, huh, I need to ask about that because I have feelings about it. But then, you always would dive into very interesting stories of things that came out of it, and I quickly forgot about it. So this feels good. This feels like very good important closure. I'm glad that this finally surfaced. But circling back, since I took us on a detour for a little bit, what are some other things that you still hold deeply about building great software? CHRIS: I've really got one last thing on the list. It's interesting, there's not a ton technically in this list, which I think represents broadly how I feel about software, and I think how you feel about software. It's like, it's actually mostly about how the people interact at the end of the day. And you can program in any language or framework, and you can get the job done. We certainly have our preferences and things that we enjoy. But the last one really rounds us out, which is think about the users. I always want to be anchoring the conversations that we're having, the approach that we're taking to building the software in what do the users think? Who are our users? What do we know about them? What do they care about? How are they using this technology? How is it impacting their lives? We've talked a number of times about potentially actually watching the sales demo as an engineering team, trying to understand what's the messaging that we're putting out into the world for this piece of software that we're building? Or write along with customer support and understand what are the pain points that people are hitting? And really, like, real humans, what are they experiencing? Potentially with a name attached. And that just changes the way that you think about the software. There's also even the lower-level version of it. As we're building classes or modules, what are the public facets of that, and what are the private API? What's the stuff that we're hiding away? And what's the shape that we are exposing to the outside world for varying definitions of outside? And how can we just bring in a little bit of empathy to try and think about, again, in the case of like the API for a class, it's probably you on the other side of it, but it's future you in a slightly different mindset with a little bit less information and context on the current problem that you're working on. And so, how can we make things easier for ourselves in the code, for our users at the end of the day? How can we deliver real value that is not mired in the minutiae of technical complexity and whatnot but really is trying to help people live better lives? That's a little too fancy as I say it out loud. But it is kind of the core of what I believe, so I'm not going to take it back. STEPH: I love how you've expanded users where more traditionally, it's people that are then using the software. But then you've expanded it to include developers because that is something that is often on my mind and something that I just agree with wholeheartedly in terms of when you're writing software; as you mentioned before, software is for people. And so we want to include others. And it does improve people's lives. People show up to work every day, and if you've been thoughtful if your past you has been thoughtful, it's either going to give you your future self a better day, or it's going to give other people a better day. So I think that's a very fair statement, improving lives by being thoughtful in regards to focusing on the users, people consuming software, and working in the codebase. CHRIS: I know we've talked about this before, but I was having a conversation with one of the developers on the team at Sagewell just last week, and they were mentioning how they really loved working on admin features. And I was like, oh, that's interesting. Let's talk more about that. And it was really it's that same thing that I think you and I have discussed of like there's that immediacy. There's that connection. These are actually colleagues, but you can build software to make their day better. You can understand in detail what the pain points are. What's the workflow that as you watch it, you're like, oh, I could put a button up in the corner of the screen that would automate almost all of this and your day would be that much faster? Oh, let me do that. That's exciting. And so I love that as another variation of it, like, yeah, there's for other developers. There's also for the admin team or other users in the organization of the software. There are so many different versions of users, but I think I think we build a better thing if we think about them more. STEPH: I have definitely worked with teams where I can tell that certain people are demoralized, and it comes down to they feel frustrated and often disconnected from the people that they are building for. And so then you really feel isolated. I'm pushing code around, but I don't really see the benefit or the purpose of it. And I think that's very hard for developers who typically want to build something that's going to be useful and not feel like it's just going to be thrown away. So connecting your team to those users, I certainly understand. Getting to build something for your colleagues and then they get to say how much they like it is an incredible, rewarding experience. You also touched on something that I really appreciate, where you highlighted that a lot of the technical decisions that we make are important, but they're not at the center of the things that we believe when it comes to building great software. And that's something that I will often reflect on. Like, as we were thinking through these particular ideas that we still hold true today, how mine are more people and process-focused and rarely deep in the technical weeds. And there are times that I think, well, shouldn't there be something that's more technical, something that's very concrete? Yes, you should build your code this way or build your application or use a specific technology. But after all the projects and teams that I've been a part of, that's just usually not the most important part. And so I appreciate that you highlighted that because sometimes I have to remind myself that, yes, those things can be challenging, but it's often with people and process. That's where the heart of great software lies. CHRIS: That's a fantastic phrase, I think, that really encapsulates all of the conversations that we're having here. MID-ROLL AD: Debugging errors can be a developer's worst nightmare...but it doesn't have to be. Airbrake is an award-winning error monitoring, performance, and deployment tracking tool created by developers for developers that can actually help you cut your debugging time in half. So why do developers love Airbrake? Well, it has all of the information that web developers need to monitor their application - including error management, performance insights, and deploy tracking! Airbrake's debugging tool catches all your project errors, intelligently groups them, and points you to the issue in the code so you can quickly fix the bug before customers are impacted. In addition to stellar error monitoring, Airbrake's lightweight APM enables developers to track the performance and availability of their application through metrics like HTTP requests, response times, error occurrences, and user satisfaction. Finally, Airbrake Deploy Tracking helps developers track trends, fix bad deploys, and improve code quality. Since 2008, Airbrake has been a staple in the Ruby community and has grown to cover all major programming languages. Airbrake seamlessly integrates with your favorite apps and includes modern features like single sign-on and SDK-based installation. From testing to production, Airbrake notifiers have your back. Your time is valuable, so why waste it combing through logs, waiting for user reports, or retrofitting other tools to monitor your application? You literally have nothing to lose. So head on over to airbrake.io/try/bikeshed to create your FREE developer account today! CHRIS: Actually shifting gears a little bit, so we've just talked about what we still believe about building great software. I'm intrigued. We've been chatting for a number of years here on this microphone, these microphones. We have separate ones because we're in different states. But I'm interested; what have we changed our minds about? What have you changed your mind about, Steph? I got a couple of ideas, but I'm intrigued to hear yours. STEPH: Nothing. I've never been wrong. I've stuck to everything that I've ever thought. CHRIS: That must be boring. STEPH: [laughs] Yeah, that's totally not true there. There are definitely things that I've changed my mind about. One of the things that I've changed my mind about is that people who know the most will ask the fewest questions. That's something that I used to consider the trademark of someone who is a more experienced senior developer in terms of you really know what you're doing. And so you typically don't ask for help or need help very often. And so, I'm going way back in terms of things that I have changed my mind about. But I have definitely changed my mind where people who know the most are actually the ones that do a really great job of constantly asking questions and asking for feedback. And I think that is still a misconception that people still carry forward. The idea that if you're asking a lot of questions or asking for help that you are not as skilled in your work, and I view it as quite the opposite, that you are very good at what you do and that you know precisely the value of your time. And then also reaching out to others for help, and then also just getting validation on things that you may have concerns around. So that's one I've changed my mind on is that I think the more experienced you are, the more questions you tend to ask. CHRIS: Oh, I love that one. It's a behavior that I know...I think we've talked about this before. But as consultants, we try and model it just the like; it's totally fine to ask questions. And because we often come in with less context, it makes sense for us to be asking questions, but I will definitely intentionally lean into it in those contexts to be like, everybody keeps throwing around this acronym. I don't actually know what that is. Let me raise my hand. And my favorite moment is when people disagree on what the acronym or what the particular word or what the particular project is. Like, I ask the question, and people are like, "Oh, it's this," and someone across the room is like, "Wait, that's what it means? I thought it was this totally other thing." I'm like, cool, glad that we sorted that out. Glad that we got that one up in the air. But I actually remember many, many, many years ago, at this point, there was a video series of...PeepCode was the company, and there was the Play by Play series. And so there were particular prominent developers, particularly in the Ruby community. And they would come and sort of be interviewed and pair program. And it was amazing getting to watch these big names that you had heard of, like Yehuda Katz is the one that stands out in my mind. He was one of the authors of merb, which was a framework that was merged with Rails, I want to say around the 3.0 time. And just an absolute, very big name in this world and someone that I looked up to and respected. And watching this video, they had to Google for particular API signatures and Rails methods. They were like, "Oh, how does that work? Is it link to and then you pass the name?" I forget what it was specifically. But it was just this very human normalizing moment of this person who has demonstrably done incredible work in our community and produced very complex software still needs to Google for the order of arguments to a particular method within Rails. I was like, oh, okay, that's good to know. And with complete humility in the moment, I was just like, yeah, this is normal. Like, it's impossible to hold all of that in your head. And seeing that early on shook me off the idea that that's the thing to do is just memorize everything. It's like no, no, get good at asking the questions. Get good at debugging. Get good, yeah, asking questions. It's a core skill rather than a thing that you grow out of. But I definitely shared early on I was like, not allowed to ask questions, that'll be scary. STEPH: I love that example. Because counterintuitively, to me, it demonstrates confidence when someone can say, "Oh, I don't remember how this works," or "Let me go look it up." And so I just very much appreciate when I see someone demonstrating that level of confidence of let's keep going. Let's keep making progress. I'm going to ask for help because that is totally fine, and we are in a safe space. Or I'm going to create a safe space for us to do that. One of my favorite versions of this where you shared like if you ask about an acronym and then people disagree, one of my favorite versions is to ask about a particular area of the codebase and be like, what would you say this code is doing here? What do you think users do here? Like, what is the purpose? What's the point of this? [chuckles] And then having people be able to say, "Oh, yeah, this definitively does this thing." Or people are like, "You know, I'm not sure. I don't even know if that code is getting run." That's one of my favorite outcomes of asking questions. How about you? What's something you've changed your mind about? CHRIS: I made a list of a couple of things like remote is on there. I didn't know if I'd like remote. I wanted to try it for a while. Tried it, turns out I like it a lot. It's complex. You got to manage it, whatever. But that I think everybody's talked about that a bunch. I think probably the most interesting one is deadlines. Initially, in my career, I didn't really feel anything about them. And then I experienced the badness of deadlines. Deadlines are bad. Deadlines are things that come down from on high and then you fail to hit them, and then you're sad. And maybe along the way, you're very stressed and work long hours to try and get there. But they're perhaps arbitrary. And what do they even mean? And also, we have this fixed scope, and they're just bad. And then there was a period of my time where, like, deadlines are bad. The only thing that we do is we show up, and we make the software as quickly as we can. But in reality, there are times that we need that constraint. And in fact, I have found a ton of value in deadlines when used intentionally. So we can draw a line in the sand, and we can say, at this point in time, we will have a version of the software. We have a marketing campaign that we need to align with this. So we got to have something at that point. And critically, if you're going to have a deadline, you've now fixed a point in time. You need to flex other things. And critically, I think the thing to flex is the scope. So we need to have team management. We have user accounts right now, but now we need to organize them into teams. That is like a category of functionality. It's not a singular feature. And so yeah, we can ship teams in the next quarter. What exactly that means is up in the air. And as long as we're able to have conversations essentially on a day-to-day at least weekly cadence as to what will make it in by that deadline and what won't, and we're able to have sometimes the hardest conversations but the very necessary conversations of the trade-offs that we have to make as we're building that software, then I find deadlines are absolutely fantastic tools for focusing and for actually reducing scope but in a really useful way. And getting something out there in the hands of users so that you start to get real feedback so that you start to learn, is this useful? What are the ways that people are using this? What should we lean into and do more of? What maybe should we roll back, actually? So yeah, deadlines. First, I didn't know them, then I feared them. Now I love them but only under the right circumstances. It's a double-edged sword, definitely. STEPH: I, too, have felt the terribleness of deadlines and railed against them pretty hard because I had gone through a negative experience with them but have also shifted my feelings about them where they can be incredibly useful. So I really liked that's one of the things that you've changed your mind about. It also reminds me of one of the other things...I'm going to circle back for a moment to one of the things that I believe about creating great software is to not wait for perfection, and deadlines are a really good tool that helps you not wait for perfection. Because I have also seen teams really struggle or sometimes fail because they waited until there was something perfect to present, and then you realize that you've built the wrong thing. So I do want to transition and talk a bit about the show because it's our last episode, and we should talk about it, and the fun adventures that we've had and some of the things that we've learned or things that we're feeling in the moment. So given that it's been a wonderful three years for me, it's been four years for you since you've been a host on the show. How are you feeling? CHRIS: I'm feeling a bunch of different things sort of all at once. I am definitely going to miss this immensely. Particularly, I loved when I started, and I got to interview a bunch of thoughtboters and other people from the community. But frankly, three-plus years of getting to chat with you has been just such a delight. There's been an ease to it. We kind of just show up and talk about what we're doing. And yet there are these themes that have run through it. And it has definitely helped me hone and shape my thinking and my ability to communicate about what I'm thinking. I've learned that you have a literal superpower to remember the last thing that you were talking about. Listeners, you may not know this, but we are not quite the put-together folks that we may sound like in these recordings. We have a wonderful editor, Mandy Moore, who makes us sound so much better than we are. But we'll often pause and stop and then discuss what we want to talk about next. And Steph always knows the exact phrase that she or I left off on. And it has been so valuable to the team. But really, it's been just such a pleasure getting to have these conversations. It's also been something that has just gently been in the back of my mind at all times. And so, I'm observing the work in any given week as I'm doing it. It's almost like meditation in a certain way, whereas I'm working on something, like, oh, this is actually really cool. I want to take a note about this and talk about it on The Bike Shed with Steph. And having this outlet, having this platform to be able to have those conversations and knowing that there are people out there is fantastic, although it's very weird because really, every one of these recordings is just you and I on a video call. And so there is an audience, I'm pretty sure. I think people listen to the show; I don't know, occasionally they write in, so it seems like they do. But at the end of the day, this really just feels like a conversation with a friend, and that has been so valuable to have. And yeah, I'm definitely going to miss that. It's been a wonderful run, you know, four years is a long time. It's about as long as I've done most things in my career. And so I'm very happy with what we have done here. And there's a trite saying that isn't...yeah, whatever; I'll just say it, which is, "Don't be sad that it's over. Be glad that it happened." And I guess I'm still going to be sad that it's over. But I am so glad that I got the opportunity to do this, that you joined in this adventure and that we got to chat each week. It's been really delightful. STEPH: I really liked how you refer to this as being a meditative state. And that is something that I have certainly picked up from you and thoroughly enjoyed that I have this space that I get to show up and bring these ideas and topics and then get to talk them out with you. And that has been such a nice way to either end the week or start a week. I mean, it doesn't matter. Anytime that we record, it's this very nice moment of the week where we get to come together and talk through some of the difficulties and share our stories. And that's been one of my favorite moments is because you and I get to show up and share everything that's going on. But then when someone writes into the show or if they send a tweet or something and they share their story or their version of something that happened, or if they said that we made them laugh, that was one of my favorite accomplishments is the idea that something that we have done was silly enough or fun enough that it has brought them joy and made them laugh. So I, too, I'm very, very much going to miss this. It has been a wonderful adventure. And I thank you for encouraging me to come on this adventure because I was quite nervous in the beginning. And this has definitely been an aspect of my life that started out as something that was very challenging and stretching my limits, and now it has become this very fun aspect and something that I get to show up and do and then get to share with everyone. And I do feel very proud of it, very much in part to Thom Obarski, who was our initial producer and helped us have that safe space to chat about things. And now Mandy, who keeps the show running smoothly and helps us sound our best week to week. So it's been a wonderful adventure. This is going to be hard to let go. And I think it's going to hit me most. Like, this was one of those things as we're talking about it, it's, like, I'll see you next week. This will be fine. But I think it's going to hit me when there's something that I want to talk about where I'm like, oh, this would be great to talk about, and I'll add it to The Bike Shed Trello board. And I'll be like, oh yeah, that's not a thing anymore, at least not quite in the same way that it was. CHRIS: So what I'm taking away from this is that you're immediately going to delete my phone number the minute we hang up this call and stop recording. [laughs] STEPH: Oh yeah. I preemptively deleted. So that's already done. Friendship is over at this point. CHRIS: That's smart. Yeah, because you might forget otherwise in the heat of the moment as we're wrapping this whole thing up. STEPH: [laughs] CHRIS: But actually, on that note, in a slightly more serious vein, again, there's this weird aspect where the audience is out there. But we're very sort of disconnected, particularly at the moment in time where we're recording. But it has been so wonderful getting various notes from listeners, listener questions, but also just commentary and the occasional thanks and focusing; oh, you pointed me in the direction, or you helped me think through a complicated piece of work or process a problem that we were having. And so that has been just so, so rewarding. And one of the facets of this that has been so interesting to me is being able to connect to people and basically put out there what we believe about software, and for the folks that resonate with it and be able to have that connection instantly. And meeting people, and they're like, "Oh, I've listened to The Bike Shed. I like all these things." I'm like, oh, cool, we get to skip way further into the conversation because I've already said a bunch, and you say you like that thing. So, cool, we're halfway through our introductory chat. And I know that we agree about a bunch of things, and that's really wonderful. And frankly, I'm going to miss that immensely. So for anyone out there who's found something valuable in this, who's enjoyed listening week to week, or perhaps even back to Upcase for things, I would love to hear from you. I'd love to connect to folks. Send me an email, Twitter. I'm on all the places. I'm Chris Toomey in various spots or ctoomey.com on the internet. Chris Toomey on GitHub. I'm findable, I think. Chris Toomey developer will probably get you there. But I would really love to hear from folks, to connect to folks, you know, someday down the road; I think I'll be hiring again. And that'll be fun. I would love to work with some of the folks that have listened to this show or meet you at a conference, or if I happen to be traveling to a city or you're traveling to Boston. Really for me, so much of what this show is about is connecting with people around how we think about building great software. And so, I would love to continue that forward into the future. So yeah, say hi, if you're interested. STEPH: I agree. That's been one of the most fun aspects of being co-host of the show. And I'll be honest, you are welcome to contact me, but I am going to be off-grid for probably six months. [laughs] So just know that there will be a bit of a delay before you hear back from me. But I would definitely love to hear from you. I also want to say a very heartfelt thanks to a couple of people, just folks that have made this journey incredible and have made it so much fun. One, in particular, is everyone at thoughtbot for their continuous stream of knowledge. I mean, frankly, my software opinions wouldn't be half as interesting if it wasn't for everyone at thoughtbot constantly sharing their knowledge and being a source of inspiration. So I deeply appreciate everyone that has contributed to topics and ideas and just constantly churning out blog posts because those are phenomenal. And I also want to give a shout-out to my husband, Tim, because he has listened to The Bike Shed for many years and even helped out with a number of show notes when that was something that you and I used to do before Mandy made our life so much easier and took that over for us. And has intervened a number of times when Utah mid-recording would decide it's time to play. So I want to give a very special thank you to him because he has been a very big supporter of the show and frankly helped me manage through a lot of the recordings for when I had an 80-pound dog that was demanding my attention. CHRIS: I think continuing on the note of thanks; similarly, I'm so grateful to thoughtbot as an organization for everything that is represented in my career. It's a decade-plus that I have been following and then listening to the podcasts and then joining the organization, and then getting so many wonderful opportunities to learn about this thing called web development. And then, even after I left the organization, I was able to stay on here on The Bike Shed and hang out and still chat with you, Steph, which has been really wonderful. So thank you, thoughtbot, so much. Thank you to Joël Quenneville, who will be the continuing host of the show. This show is not going anywhere. And, Steph, you and I aren't really going anywhere, but we won't be around anymore. But we are leaving it in the very, very capable hands of Joël, and I'm super excited to hear the direction that he takes it and Joel's incredibly thoughtful and nuanced approach to thinking about programming and communicating. So I think that will be really wonderful. And lastly, I definitely want to thank Derek Prior and Sage Griffin, the two original hosts of this show, who really produced something wonderful, and for many years, I think it was about four years that they hosted together. I was an avid listener despite actually working at the company the whole time and really loved the thing that they produced and was so grateful that they entrusted me with continuing it forward. And hopefully myself and then with the help of you along the way, we've...I think we've done an okay job, but now it is time to pass the torch or the green lantern. That's the adage I've been going with. Gotta pass the lantern, pass the mantle on to the next one. So, Joël, it's going to be in your hands now. STEPH: Yeah, I'm so looking forward to future episodes with Joël Quenneville. They are going to be fabulous. So I've been thinking in terms of this being our finale episode and then a fun ending for it, so there's a thing called the 21-gun salute, which is the military honor that's performed by firing cannons or artillery. Not to be confused with the three-volley salute, which I definitely confused earlier that is reserved and used at funerals, which this is not. So using the 21-gun salute, I was like, hmm, it is The Bike Shed, and we have this cute ring ring that goes. So I think for our finale, we should have a 21-bell salute as we exit the shed and right off into the sunset. CHRIS: I love it. I couldn't imagine a more perfect send-off. So with that, what do you think? Should we wrap up? STEPH: Yes, but I have one more silly thing to add. I've thought of a new software idiom that I'm excited about. And so, this may be my final send-off into glory that I'd like to share with you. And I think that we should make like a shard and split. CHRIS: [laughs] I so appreciate that in this moment, this final moment that we have together, you choose to go with a punny joke. It is so on brand for the show. It is absolutely perfect. And I think with that note, 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 on iTunes, as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey. STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. ALL: Byeeeeeeeeee!!!!!!!! ANNOUNCER: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.
Chris is back from vacation and gives hiring and onboarding updates. Steph has an update about the CI slowdown and scaling CI. They tackle a listener question regarding having some fear around potential merge conflicts. 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. Deckset (https://www.deckset.com/) parallel_tests (https://github.com/grosser/parallel_tests) paralleltests - important line that may alter the `groupby` strategy (https://github.com/grosser/parallel_tests/blob/9bc92338e2668ca4c2df81ba79a38759fcee2300/lib/parallel_tests/cli.rb#L305) KnapsackPro (https://knapsackpro.com/) rspec-queue (https://github.com/conversation/rspec-queue) Vim Conflicted Overview (https://github.com/christoomey/vim-conflicted#overview) Mastering Git Course on Upcase (https://thoughtbot.com/upcase/mastering-git) Git Object Model (https://thoughtbot.com/upcase/videos/git-object-model) Git Object Model Operations (https://thoughtbot.com/upcase/videos/git-object-model-operations) The Opportunity Will Find You (https://thoughtbot.com/blog/the-opportunity-will-find-you) This episode is brought to you by Studio 3T (https://studio3t.com/free). Try Studio 3T's full suite of features for 30 days, no payment details needed. Become a Sponsor (https://thoughtbot.com/sponsorship) of The Bike Shed! Transcript: CHRIS: Golden roads are golden. 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. Oh, I also have a new intro that I want to try out. This is thanks to Irmela from Twitter, where it's good morning and hooray; today is Bike Shed day. They technically said Tuesday, but we don't record on Tuesdays. So today is Bike Shed day, so happy Bike Shed day. And hey, Chris, what's new in your world? CHRIS: What is new in my world? Yeah, I loved when I saw that tweet come out. It really warmed my heart. So Tuesday, in theory, is Bike Shed day, but for you and I, Friday is Bike Shed day. It's confusing breaking the fourth wall, as I so often do. But yeah, what's new in my world? I'm back from vacation, which is the thing that I did. For listeners, well, I have been absent the previous week related to vacation and all those sorts of things. But I did what we're going to describe as a not smart thing. It wasn't intentional. The world just kind of conspired in this way. But I had two separate vacation islands that existed in my mind, and then they both kind of congealed, but as they did that, they moved towards each other, but they didn't connect. And so what I ended up with was two weeks back to back where I was out on Thursday and Friday of one week, and then I was back for Monday and Tuesday. And then I was out for Wednesday, Thursday, Friday of the following week. Protip: that's a terrible idea. It's just not enough time to sort of catch up. The whole of it was like the ramp-up to vacation and then the noise of vacation, then getting back and being like, oh, there are so many emails. Let me try and catch up on them. But also, on the very positive side, we had a new hire join the team, and so most of my focus on the days that I was in the office was around getting that new person comfortable on the team, onboarding, spending as much time as possible with them. And so, all total, it was an adventure. And again, I would strongly recommend against this. The world just kind of conspired, and suddenly these three different forces in my life came together. And this was just the shape of things. But yeah, I went on vacation, and it was great. The vacation part was great. STEPH: I will take your advice. So next time I have like two segments of PTO, I'm just going to stitch them together and just go ahead and take that whole intermittent time off. CHRIS: That probably would have been better. Again, someone new joining the team, it was very important to me to get some time with them early on, and so I opted not to do that. But yeah, the attempt to catch up in between was a completely lost effort, I would say. But I think I'm mostly caught up now, having been back in the office for about a week, so yeah. But let's see, what else has been up in my world? It's actually been a while since you and I have chatted based on the various timing and schedules and the nonsense vacation schedule that I had that you so kindly accommodated across a couple of weeks. Let's see, hiring and onboarding; the hiring went really well. We talked about that a bunch of weeks back. But now we're in the onboarding phase. And so next week will be the first week that all four of us on the engineering team are in the office together for the full week. I'm super excited to experience that. We've had different portions of it, with me being on vacation and other folks being on vacation. But now, for the first time, we're really going to feel what it's like as this team. And we're going to have our first retro as a group and all those sorts of things, so I'm very excited to do that. And thus far, all of the interactions that we've had have been really wonderful as a team. And so now it'll be the first time we're just bringing all of those various pieces together. STEPH: I just have to clarify; you said all of y'all in the office together. Do you still mean remotely? CHRIS: Oh, yes, yes, I just mean not on vacation, all present and accounted for on the internet. Remote is another interesting facet of what we're doing here and trying to figure out how to navigate that, particularly where there are some folks that are closer and can potentially get together in the city, that sort of thing, and then folks that are truly remote and making sure that we're...I'm very much of the opinion if we have anyone that's remote, we are remote team, and we must embrace async communication and really lean into that. And I think the benefits of async communication as its own consideration are so worth it. And it's one of those things that's hard to do. It requires careful, intentional thought. It requires more purposeful communication. But I think there are a lot of good things that fall out of that. It's similar to TDD in that way in my mind, like, it's not easy. It's actually quite difficult. But all the effort that I put into trying to learn how to do that has made me a better developer, I think, on all the various fronts. And I think similarly, async communication I believe in as a tool to force just better communication. And so I'm a big believer in it, and I've found a ton of benefit in remote that I'm also a big believer in that now. I, like everyone else, was forced into it as the world was, but I've really come to enjoy it a lot. And so yeah, so, no, not physically in the office, to answer your very short question with a long rambling aside. STEPH: [laughs] I like that comparison. I hadn't thought about it in that way but comparing that thoughtfulness and helpfulness of async communication and then also to TDD, where it's not easy, but the payoff is so worth it, the upfront cost of it. That is something that at thoughtbot, we've had conversations around where there are folks that really value...they want to be around people. They get energy from people, and so they want that option to be able to rent a WeWork space and maybe get together with a colleague once or twice a week, and that was supported by thoughtbot. But we also wanted to express well, if you are together, do treat everything still as a remote work environment. So let's say if you and your colleagues are on a project, but then there's a third person on that project that's remote, you still need to act like everything's remote to make sure that everyone else is still getting to participate and hear everything and be part of the conversation. So just keeping that in mind that yes, we want to support you doing your best work, and if that's around people, that's wonderful. But we are still remote-first, and communication needs to be in that fashion. Well, that's super exciting that you'll have all of the team together. That sounds like it will be wonderful to hear about and then also retros and meetings, and yeah, it sounds like you've got a fun week ahead. CHRIS: Indeed. I'm super excited to see what sort of new things come out of the new voices on the team and practices that each of the individuals have experienced at other companies that we can now fold together. The work that we've done so far has been very much inspired by thoughtbot ideas, and approaches, and workflows, and processes because that's what I brought to the table. But I'm super excited to bring in more voices and see what of that 100% stays on versus does anything change? Do we get entirely new things? So yeah, very excited about all of that. But to revisit a topic that we've talked about in the past, this week is catching up from vacation, so there's a certain amount that will constrain my work. But this was definitely another week of I did not do much coding. I'm trying to think if I did any coding this week. It's possible that the answer is no. The fact that I don't even know the answer to that is an interesting one. I still have in my mind the desire to get back to it, and I think I will. But there's so much other stuff to do. Recently, this week, there's been a lot of vendor selection and contract negotiation, which is an interesting facet of the work, but just trying to figure out, oh, we need platforms to do X, Y, and Z. And it turns out they're wildly costly and have long sales cycles. And how do you go through that, and how do you make sure that we're getting the right thing? And so that's been a big part of my work. Hiring and onboarding, again, has been a big part of it. There's also some amount of communicating back to the broader team - what are we doing? What is the product organization or the engineering team delivering? And so I'm okay at presentations, I think. I'm comfortable with giving presentations. The thing that I struggle with is finding the optimization point in preparation. I will, of my own accord, over-prepare. And that may sound a little bit like, oh, what's my greatest weakness? That I care too much. But I mean it sincerely as like, I would love to find that right amount of like, it's like an hour of preparation for a 15-minute presentation to the team. That's the right ratio. And I just hit that on the head, and it's great. But whenever I know that I need to give a larger presentation, it will distract me. And it's work that can expand to fill whatever time you give it, and so trying to thread that needle is a tricky one for me. STEPH: Yeah, I'm with you. Presentations, for me, they're one of those things that it's very stressful, anxiety-inducing; all the prep feels distracting from some of the other work that I want to do. Or maybe I'm excited about the presentation, and that is the work that I want to do. But it's not until it's done that then I'm like, oh, that was fun. That went well. This was great. It's not until after that then I feel good about it. So the lead-up to it is very stressful. And so if you can optimize that to say, well, I know exactly what this group needs, where I can cut corners, where I have to go into details, that sounds incredibly valuable. I'm curious, so this is probably a bad idea, but it's the only way I really know how to find those boundaries is you got to experiment and tweak a little bit and let yourself fail a little bit or just be very explicit with folks about this is what the presentation is, if you expected something else, let me know. Or here's what I've got, have someone to bounce ideas off of. But there's such a nicety if you can find that I'm going to try failing just a little bit and get some feedback. Or maybe it's not failing at all, but you are testing that boundary to find out did this work, or should I put more effort into this? I'm curious, do you have thoughts on that? How you're going to find that right optimization level? CHRIS: Not as specific to truly honing in on whatever the correct number is. The thing that I've been doing is I...this will sound complicated, but I wait until the last minute but a specific version of the last minute. So at most, I start working on it an hour and a half before the meeting. And these are, again, not particularly large presentations, and it's a recurring sort of thing. So it's sort of engineering talking about the work that we've done recently and trying to find the right level of detail and whatnot, so giving myself a smaller time window. I think that's enough time to tell the story and to find a meaningful way to tell the story and grab the screenshots and all of that, but it's constrained so that I don't over-optimize, over-edit, overthink. I'm using Deckset, which is a presentation tool that starts from a Markdown file. So it's just a Markdown file that I'm editing. That's great; that works really well. I do not twiddle with fonts. There's one theme that I use. It is white background with black text. That's it. And I think I've given myself deep permission to be the CTO that has a white background with black text and no transitions. I don't even go into presentation mode for it. I'm literally showing the UI of Deckset, and then just hitting the arrow to move between them. But the Chrome and the drop-down menu at the top is still visible because I want to see people's faces as I'm presenting. And I haven't figured out how to do that correctly on my computer. So I'm just presenting the window of Deckset. And I'm like, I have given myself permission to do all of those things, and that has been super helpful, actually. So that's a version of me negotiating what this means. Where I do invest the effort is trying to enumerate all of the things and then understand what is the story that I'm telling around the things and how do I get the message right for the collective audience? So, for a developer team, I would say much more nuanced technical things, for marketing folks, it would be at this end of the spectrum. I do lean on the old idea of, like, let us talk about it in the mindset of the user, so it's very much user-centric, but then some of the things that we're doing are important but invisible to the users. They're part of how we broadly build the platform that we need to, but they're completely invisible to users. And so, how do I then tell that story still with ideally a user-centric point of view? So that's where I do invest the time, and I give myself complete freedom to just grab screenshots, put black text on a white background, and then talk over it. STEPH: I love it. Because you made this comparison earlier, so now I'm thinking of a comparison of like TDD-driven presentations where it's like, what's the end goal? What's the assertion? What's the outcome that I want? And then backfilling from there. Or, in your case, you're talking about what's the story that I need to tell? What's the takeaway that I want people to have? So then you start there, and then you figure out what's the supplemental information that you need to provide to then get there. And the fact that you don't twiddle with fonts and all that stuff, I think you're already really on your way [chuckles] in terms of finding that right optimization of I need to present a clear and helpful message but not sink too much time into this CHRIS: Black text on a white background is very clear. So... STEPH: [laughs] If there are any designers listening to this, they might just be cringing to this conversation right now. [laughs] CHRIS: I actually wonder about what the...I know that dark mode is a thing that lots of folks care about. I'm thinking about the accessibility affordance of it now. I'm actually thinking through it now that I said it somewhat flippantly. I actually don't know what I'm talking about, but it was easy, and it wasn't a choice that I allowed myself to think about. So there we are. Mid-roll Ad Hi, friends, and now a quick break to hear from today's sponsor, Scout APM. Scout APM is an application performance monitoring tool that's designed to help developers find and fix performance issues quickly. With an intuitive user interface, Scout will tie bottlenecks to source code so you can quickly pinpoint and resolve performance abnormalities like N+1 queries, slow database queries, and memory bloat. Scout also recently implemented external service monitoring, adding even more granularity when it comes to HTTP requests and API calls. So give Scout a try today with a free 14-day trial and experience first-hand why developers worldwide call Scout their best friend. And as an added bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. To learn more, visit scoutapm.com/bikeshed. That's scoutapm.com/bikeshed. STEPH: In my personal world, so Tim and I are moving. We're on the move. We are transitioning from South Carolina to North Carolina. So I think I may have shared a bit of this news, but Tim has acquired his first software developer job, which is just phenomenal. It is in North Carolina. He does need to be there in person for it. So we are currently selling our South Carolina house and then moving. It's not too far. It's like three and a half hours away to where we're moving in North Carolina because we're already pretty far in North and South Carolina. So yeah, there's always another box that needs to be packed. And there's always just something else that you forget, another thing that you want to take to Goodwill or try to give to a neighbor. It's a good way to purge. I will definitely say that every time you move, it's a good time to get rid of things. CHRIS: That is a very cup half-full point of view on it, but yeah, it feels true. STEPH: [laughs] It's true. I'm a very cup half-full person. For more technical news, for more client stuff that I've been working on, so I think the last time we chatted, I was sharing that we had this mysterious CI slowdown where we were going from CI builds taking around 25 minutes to spiking to 35, sometimes 45 minutes, and I have an update there. So we found out some really great things, and we have gotten it back down to probably more about 23 minutes is where the CI is running currently. As for the actual who done it, like what caused this specific slowdown, we got to a point where we were like, we're doing so much investigative work to understand exactly what caused this that it felt less helpful because at the end of the day, we really just wanted to address the issue. And so solving the mystery of exactly what caused this started to feel less and less meaningful because we're like, well, we want to improve this anyways. So even if we found that one line or something that happened that caused this, we want a bigger solution to this type of problem because then this could happen again like, someone else maybe adds one line or something happens, and things get thrown off balance, and then suddenly, we have a slowdown, and that just takes too long to investigate. So I don't have a concrete who done it answer for the slowdown. But we've learned a couple of things; one of the things that we learned is we're using parallel_tests to then split our tests across all of the CPUs that are then running the RSpec test. And we realized that we weren't actually splitting tests based on runtime data. So there are a couple of ways that paralleltests will let you divvy up your test, and two of those ways one is file size. So you can split the files based on the size of the file, or you can use info from the runtime log. So then paralleltests can be a little bit more intelligent about like, well, I know how long these files take, so I'm going to split it based on that versus just the size of the file. And we realized that we were defaulting and using the file size instead of the runtime even though we all thought we were using runtime. And the reason for this took a bit of source code diving because looking at the README for paralleltests; it looked like as long as we're passing in a file to the runtime log path, then paralleltests is going to use that runtime data. But then there's some sneaky-sneaky in there that I'll actually link to in the show notes in case anybody's interested. But if you are setting a particular flag and don't pass in another flag, then paralleltests is going to be like, cool, I'm going to portion out your test based on file size instead of the runtime. So we fixed that, or we updated that, and that has had a significant improvement for the test being split out more evenly. So we didn't have a CPU that was taking 25 minutes while the next CPU was only taking like 17 minutes. And paralleltests also provides some really helpful data that because we have that runtime log file, we could tell how long each CPU is running and how they're getting split. So the past couple of weeks, it's heavy measure, measure, measure, take all the data, create lots of graphs, understand what's happening, and then look for ways to then fix it. So figuring out how these files or how the tests were being distributed across, we had a number of graphs that were just showing us what's actually happening. So then we could track the improvement, so that was really nice. It was the measure twice and change something once [laughs], and then we got to see the benefit from it. For scaling the CI, so we are looking on adding more machines to then process tests. That has been really interesting because we're at the point where we are adding more machines, but if we add more machines, we're not going to speed up how quickly our CI processes everything. Because we are splitting tests based on file size and not by examples, we're always going to have this effect of a tentpole. So if we have a file that takes 10 minutes, that's the fastest we're ever going to get. So Joël and I are in discussions right now of where we still really want to understand what's the fastest we can achieve just by adding another machine or two versus are we at the point that, okay, scaling horizontally and adding more machines has been helpful, but we have reached the breaking point where we actually need to divvy out the tests at a smaller scale and have a queue approach? So then that way, we can really harness the power of then we don't have one file that takes 10 minutes, and we don't have to care either. So if somebody adds a test to a file and suddenly a file goes from 12 minutes to like...well, hopefully, they added more than one test. [laughs] But let's say it goes from 10 minutes to 15 minutes; we don't want to have to manage that and understand that there's a tentpole. We just want to be able to divvy out all the examples and then have a queue approach. That's probably going to be MVP two of this, but we're still waiting that out. But it's just been really interesting to realize that scaling horizontally really only takes you so far. Like, we've added one machine, maybe one more, so then we'll have three total. And then it's like, okay, that's great, but now we need to actually address this other bigger problem. CHRIS: I know we've talked about this in previous episodes, but I'm super interested to hear as you progress into the queue approach because that's something that's been top of mind for me for a while. I don't know if we've talked about it before specifically, but Knapsack Pro is the one thing that I'm available as a service that does this. Do you have other tools that you're looking at for that, or is this still in the exploratory phase? STEPH: Knapsack is still a top contender. There's also RSpec Queue; that's another one that we have in mind. Unfortunately, I really wish paralleltests let us do this, but paralleltests just doesn't quite offer that feature. And someone in the team, I think, even reached out to the maintainer of paralleltests, and they were like, "Yep, you're totally right. We're actually more focused in making sure that this works for everybody versus has specific features." And they gave a really nice thoughtful response, which we appreciated, so at least we could confirm that paralleltests won't do exactly the thing that we need. So yeah, RSpec Queue, Knapsack, I think those are the top two that I'm familiar with. CHRIS: Gotcha. I don't know if I've seen RSpec Queue before. I'm intrigued. So actually, an interesting thing happened. While I was away on vacation, one of the folks who just joined the team as one of their first steps joining the team, noticed that our CircleCI config wasn't actually taking advantage of the parallelism that we had configured; that's on me. I turned on parallelism and then never did anything with it, which is a complete waste. And so I was super happy to come back and saw that CI, which had been creeping up to six or seven minutes, had suddenly dropped back down to two to three minutes sort of thing. I was like, this is amazing. But now I'm at the point where our RSpec suite is spreading across the different, I think, it's like four different cores that we have available, but it's not doing it as efficiently as we would like. So I'm like, oh, okay, can we dial it up to 11? But I'm intrigued; I've only looked very much in passing at RSpec Queue literally now that you've mentioned it. But Knapsack Pro exists as a different service. And so, as far as I understand, the agent that's running is going to communicate and say, "Give me another test. Give me another test." But there needs to be some external process running and managing that queue. Does RSpec Queue do that? Somebody owns the queue, right? Who owns it? Do you understand how that works? STEPH: So I was definitely familiar with this. If you'd asked me a couple of weeks ago, when I was diving heavily into the queue work before then, we transitioned more into focusing on then adding new machines; I was very up to speed on this. So I may get a couple of things wrong, but my understanding is that RSpec Queue, you're going to manage your own queue. So you bring in the gem and then use something like Redis, so then you are in charge of that. And with Knapsack, then you are using their service to manage that queue. And then they have found ways to optimize around what if you can't reach their API or something; their service is down? And making sure that that doesn't impact your CI so then you can't still run your test just because you can't reach their queue somewhere. So that's my current understanding, RSpec Queue you own it, Knapsack they're going to own it. CHRIS: Gotcha. That makes sense. That about maps to what I was expecting, and so I wonder if I could use RSpec Queue. Now I'm going to have to go research that. But it's always nice to have new things to look at on this to go at ludicrous speed. That's what I'm going for. I want to get to ludicrous speed for our CI. STEPH: I like that name. I haven't heard of that speed. I feel like I have. I feel like you've dropped that before, [laughs] like you've used that. CHRIS: I don't know; quite possibly, I have. It's a Spaceball's reference. It's a throwback to days of old. STEPH: Well, then we may be investigating RSpec Queue together. Because yeah, Joël's and I goal for this week has been very much to figure out what's our boundaries with TeamCity? What are our boundaries with horizontal scaling? And I think we're both getting to that conclusion of like, okay, this has been good, it's helpful, but we really need to look into the queue stuff if we really want to see significant progress. Also, some of the stuff we're doing because we're pushing on it, we are manually splitting files. So if there's a file that has created this tentpole that's taking 10 minutes, but we know ideally most of the other files only take six minutes, then we are splitting that file, so then we have two spec files that are associated with the same class. And then using that as a way to say, okay, what would this look like? Let's say if this were better balanced. And that's also been pushing us in the direction of like, okay, this is fun, this is informative, but it's not sustainable. We don't want to have to keep worrying about splitting these files and doing this manually and pushing us towards that queue-based approach. MIDROLL AD: And now a quick break to hear from today's sponsor, Studio 3T. When you're developing applications, it can often be a chore to work with your underlying data. Studio 3T equips you with a complete set of tools to work with MongoDB data. From building queries with drag and drop, to creating complex aggregation pipelines; Studio 3T makes it easy. And now, there's Studio 3T Free, a free edition of Studio 3T which delivers an essential core of tools. This means you can get started, for free, with Studio 3T Free and when you're ready, you can upgrade and enjoy even more features through Studio 3T Pro and Studio 3T Ultimate. The different editions unlock more tools and additional integrations with Mongo DB, SQL, Oracle and Sybase. You can start today by downloading Studio 3T Free, which also includes a 30 day free trial of all the features of Studio 3T Ultimate, so you can try out some of the enterprise features as well. No credit card required. To start your trial head to studio3t dot com forward slash free. That's studio dot com forward slash free. But shifting gears just a bit, we have a listener question. So this person wrote in, "I have listened and loved your podcast for many years dreaming of getting a job with people half as thoughtful and intentional as you, and finally it happened. I have my first junior dev job, and my co-workers and bosses are all super awesome. Up until now, I've been flying solo. And in my new job, I've been finding it very unsettling to resolve merge conflicts. As careful as I am to comb through the conflict and contact the other developer if needed, I feel like I am covering my eyes and crossing my fingers whenever I select the resolve conflict button. Is there some type of process or checklist I could rely on? Is it normal to have such a high fear factor with a merge conflict? Any advice or maybe just a bit of been there felt that way...?" All right. So one, that's fabulous, congratulations on the new job. That's very exciting. I think I've voiced this many times, getting your first junior dev job is so hard, and so I'm so excited when it works out for people, and they get there. And then, for the merge conflict, I have thoughts. Chris, do you want to start? Shall I start? How are you feeling? CHRIS: Why don't you start? Well, actually, I'm going to add some pre-commentary, and then I think you should lead into our actual answer. But first, I just want to say a deep thank you to this listener for sending in the question. Again, we really love getting these questions. And also, thank you for the very kind words. To be clear, listener, if you're going to send in a question, you don't have to say very kind words, but they are really wonderful to hear and especially to hear if we had any part in helping this person feel more comfortable getting into that first dev role and having an idea of what maybe a good version of that could look like. Additionally, I really love the shape of this question because it gets into the people stuff and the tech stuff, so I'm super excited about this question. Actually, both Steph you and I responded very quickly to this one. And so it really did catch our attention because I think it crosses that boundary in an interesting way that I think is sort of The Bike Shed space in the world. But to that end, you did reply first in our email chain. So I think you should start, and then I'll follow on after that. STEPH: I should also check with you. Wait, so you don't have a filter on your email that's like kind words only to The Bike Shed, and then you filter out anything that's negative? CHRIS: I have a sentiment analysis, and if it's even neutral, it gets sent straight to the trash, only purely positive. No, constructive feedback is welcome too. We would love to hear that. Well, love is a strong word. We would accept it into our inboxes and then deal with it, but yeah. STEPH: [laughs] It will be tolerated. Must require at least three hearts in all emails; just kidding. [laughs] CHRIS: Are you kidding? I'm counting them now, and I see a lot of hearts in our emails. [laughter] STEPH: Merge conflicts. So is it normal to have such a high fear factor with a merge conflict? I'm going to say absolutely. Resolving a merge conflict can be really tricky and confusing. And I think; frankly, it's something that comes with just time and practice where then you start to feel more confident. As you're resolving these, you're going to feel more comfortable with understanding what's in the branch and the code changes that you're pulling in versus something that you need to keep on your side. So I think over time, that fear will subside. But I do think it's totally normal for that to be a very scary thing that then takes practice to become accustomed to it. As for if there is some type of process or checklist, I don't know of a particular checklist, but I do have a couple of ideas. So one of the things that I do is I will often push my code to whatever management system I'm using. So if I'm using GitHub, then I'm going to push up my branch because then, at least that way, someone has a copy of my work. So if I do something and I completely botch it locally, I know I can always reset to whatever it is that I pushed up to GitHub, so then that way, I have more freedom to make mistakes and then reset from there. So that is one idea is just put it somewhere that you know is safe, so that way you now have this comfortable sandbox to then make mistakes. The other one is run the test. So hopefully, the application that you're working with has tests that you can trust; if not, that could be another conversation. But if they do have tests, then you can run those, and then hopefully, that would let you know that if you have left something in, like maybe you left a syntax error, or maybe you removed some code that you shouldn't have because you weren't sure, then those tests are going to fail, and they'll let you know that something went wrong. And you can run those while you're still in the middle of that merge conflict as long as you've addressed like...well, no, if you haven't addressed syntax errors, that's still a time that you can run it, and it's going to let you know that you haven't caught all of the issues yet. So you don't have to wait till you're done to then go ahead and run that. A couple of other ideas, practice. So go ahead and create your own merge conflicts on purpose. So this is something that I think is really helpful because it will teach you, one, what causes a merge conflict? Because now you have to figure out how to create one, and then it will help you become comfortable because you're in a completely safe place where you have made up the issue, and now you're having to resolve that, so it'll help you become more confident in reading that merge conflict message. And then last but certainly not least, grab a buddy so if you are just feeling super nervous. Anytime I'm doing something that I just feel a little nervous about, then I just ask someone like, "Hey, would you look over my shoulder? Would you pair with me while I do this?" And I have found that's incredibly helpful because it eases some of my fear. I've got someone else that is also looking through this with me. But I also find it really helpful because then it encourages that person to be like, hey, if they're ever in a spot that they need to pair, I want them to know that they can also reach out to me and have that same buddy system. I guess that's my checklist. That's the one I would create. How about you, Chris? What do you think? CHRIS: Well, first, I just want to say that basically everything you said I 100% agree with, and purposely I think was great that you actually replied to the email first and that you're saying those things first because I think everything that you said is true and is foundational. And it's sort of the approach that I would definitely recommend taking as well. My answer, then adding on to that, has to do with how I've approached learning about this space in my own career. To name it, to answer the core question, is it reasonable to be scared of this? Yes, Git is confusing. Git is deeply confusing. I absolutely love Git. I have spent a lot of time trying to understand it, and in understanding it, I've come to love it. But it's only through deep effort that I've gotten to that place. And actually, the interface, the way that we work with Git on a day-to-day basis, particularly the command line is rough. I'm going to say, what does Git checkout do? Well, it does just about everything, it turns out. That command just does all of the stuff, and that's too much. It's, frankly, the UI for Git, specifically the command-line user interface; the commands that we run to manipulate the Git history are not super intuitive. But it turns out if you pop open the hood, the object model underneath the core way that Git stores your code is actually very simple. I find it's very easy to understand, but I, unfortunately, have found that I can't understand it without dropping down to that level. And so, in my own adventures, I kind of went deep on this topic a couple of years ago, and I created a Vim plugin because obviously, that's the best way to encapsulate your knowledge about Git, and so I created a plugin called Vim Conflicted. I don't necessarily recommend the plugin. It's fine if you want to use it. I don't do a great job of maintaining my plugins at this point, to be honest. But there was a weekend where I was trying to understand the world of Git and merge conflicts in particular, and it was really sort of fighting me. And as I started to understand it better, there's a little diagram that I drew on the README that I think is probably the most interesting artifact from it. But it's this idea that there are actually four files, four versions of a given file involved in any merge conflict. And that realization shifted my thinking a good amount. And then as I started to think about that, I was like, oh, okay, and then I want to see this version of it, and this version of it, and this combination, and the diff between these two, and that was super helpful for me. More generally, I also made a course on Upcase about Git as I tried to understand it better. And there are two particular videos from the middle of the course named the Git Object Model and Object Model Operations. And again, those two videos deal with popping the hood on Git, looking inside it, and what actually is happening to your code as you perform different Git operations. One of the wonderful things about Git is it is immutable. So you're never going to destroy your Git history if you've committed. So one of the rules that I have is just always be committing, never worry about committing. If you've committed, you can always get back to that version. You would have to try very hard to destroy committed code in Git. It's the things that you do when you haven't yet committed the code that are dangerous. So commit the code, like you said, Steph, push that up to GitHub, so you have a backup of it. You will have a backup locally as well, and that's a thing that you can come to be more comfortable with. But then, from there, there's actually a lot of room to experiment and play around because there's a ton of safety in the way that Git stores the code. You do have to know how to get at it, and that's the unfortunate and tricky part. But I think, again, to sort of summarize, yes, this is confusing. Your feelings are absolutely valid and totally grounded, but it is also knowable, is what I would say. And so, hopefully, there are a couple of breadcrumbs that we've laid there in how you might go about learning about it. But yeah, find a buddy, watch a video or two, and give it a try. This is definitely a thing that you can get there but totally reasonable that your first approximation is this is confusing because it sure is. STEPH: I often forget that Git has that local copy of my code, so I'm so glad you mentioned that. And then yeah, I saw when you linked to Vim Conflicted. The diagrams are great. I had not seen these before. So yeah, I highly recommend folks take a look at those because I found those very valuable. CHRIS: In that case, it's a white background, but I allowed myself to use some colors in the little images to help differentiate the different pieces. And it's an animated diagram, so it's really a high bar for me. [laughs] STEPH: So now the question is, did you go too far? Have you over-optimized? [laughs] CHRIS: I'm going to be honest; it was a weird weekend. STEPH: [laughs] Well, I don't think you've over-optimized. I do think it's wonderful. And I think this is definitely a reference that I'll keep in mind for folks whenever they're learning about merge conflicts or just want to get more knowledgeable about them. I think these diagrams are fabulous. CHRIS: Well, thanks. Yeah, I hope...they frankly were a labor of love, and the course is three and a half hours of me rambling about Git, so hopefully, it's useful to folks. If anything, it was super useful to me because my understanding of Git was deeply crystallized in making that course. But I do hope that it's useful to other folks. And particularly those two videos that I highlighted, I think are the ones that have been most impactful for me in terms of how I think about working with Git and getting comfortable with it. STEPH: Do you still receive emails every now and then from people, or maybe they are tweets from people that are like, "Hey, I watched one of your videos and found it really helpful." I feel like I still see that every now and then where people are just commenting on like, they watched some of the content that you created for Upcase a while back, and I think that's really cool. I'm curious if you still see that. CHRIS: I do, yeah, from time to time. It is absolutely wonderful whenever I hear that. Again, listener, do not feel the need to send me anything, but it is nice when I get them. STEPH: It does seem like I'm fishing for compliments now. [laughs] CHRIS: It does seem like that. So I want to be clear that's not what's going on here. But it is nice because I do actually forget that they're out there. But a lot of the stuff that I produced for Upcase, in particular, I tried to do more timeless stuff, so like the Vim content was really about how Vim works in a deep way. And the tmux course and the Upcase course...or the tmux course, the Git course. I look back at them, and a couple of little syntactic things have changed. But I'm still like, yeah, I agree with me from six years ago or whatever it was. Oh, that's a weird number to say, and I think is honest. It's fine. I'll just be over here. [laughs] STEPH: [laughs] That's helpful to hear, though, because that's always one of my fears in creating content. It's like, I don't know, it's okay if it's more opinionated and I change my mind and disagree with my past self. But it's more like, yeah, keeping up with is this still accurate? Is this still reflective of the times? And then having to keep that stuff updated. Anywho, that's a whole big thing, content creation. CHRIS: Content creation, but there's a parallel to it that many folks will not be creating content, and I think that's a very fine and good way to go about progressing on the internet. But there's a parallel to it in learning that I think is useful. I, at this point, will typically lean in if there is something in the SQL layer that is fighting me. I have never found effort spent trying to better understand the structured query language to be wasted time. Similarly, Git is one of those tools that is just so core to the workflow that it felt very worth it to me to spend a little bit of extra time to get to a deeper level of comfort with it, and I have not regretted one minute of that. Vim and tmux are pretty similar because they're such core tools for me. But React, I would not call myself a deep expert of React. I follow some of the changes that are happening but not as deeply, and I'm not as worried about it. And if I'm like, I don't know how to do this thing, should I spend two hours learning about it or not? With frameworks and tools that have not been part of my toolset for as long, I will spend less time on them. And I think that the courses that I produced on Upcase mirror that. They're the things that I'm like; I feel very true about these things versus other stuff. Maybe it was in a weekly iteration episode or something like that. But that very much mirrors how I think about learning as well. What are the things that I'm going to continually invest in versus what are the things that I'll sort of keep an eye on from a distance but not necessarily invest as much time in? STEPH: There's a particular article that you're making me think of as we're talking about content creation and, as you mentioned, finding the things that you always find value in investing in. There's a wonderful blog post that was recently posted on the thoughtbot blog by Matheus Richard, and it's called The Opportunity Will Find You. And it made me think a lot about what you're talking about, find the things that you're excited about, find the things that you think are a good investment and just go ahead and lean into it. And it's okay if maybe that's not the thing that you're using currently at your work, but if it's something that gets you excited, then go ahead and pursue that. So in this article, for example, Matheus uses the example of learning Rust, and that's something that he's very excited about and wants to learn more about. And then there's another one where he started looking into crafting interpreters. And then that has actually led to then some fruitful work around creating custom RuboCops because then he had more knowledge around how the code is being interpreted so then he could write custom RuboCops. So yeah, plus-one to finding the things that give you energy and joy and leaning into that and investing in it. And if you share it with the world, that's fabulous, and if you don't, then keep it for yourself and enjoy it, whatever makes you happy. On that note, shall we wrap up? CHRIS: Let's wrap up. The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review on iTunes, as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey. STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. ALL: Byeeeeeeeee!!!! ANNOUNCER: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.
In this episode, Jake and Michael are joined by Jess Archer to talk more about Vim, covering motions, text objects, managing projects, working with tmux, and more.This episode is sponsored by Workvivo and Makeable.dk and was streamed live.Show links Mastering the Vim language The Vim learning curve is a myth Learn Vim on Upcase by thoughtbot The Art of Vim ThePrimeagen TJ DeVries Painting motion with the right brush repeat.vim surround.vim commentary.vim tmux-continuum tmux-resurrect zsh cdpath and autocompletion kitty vim-tmux-navigator vim-test
Chris is making hiring progress and loves asdf and M1 laptops. Steph is anticipating the arrival of one dongle to rule them all and talks about moving away from having a lot of Bluetooth connections. Two other big things on Steph's mind are education around factories because they're v important and shared examples and how they can be overused. She and Chris agree that it is better to tell stories in tests instead. 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. Services down? New Relic (https://newrelic.com/bikeshed) offers full stack visibility with 16 different monitoring products in a single platform. GitHub - asdf-vm/asdf: Extendable version manager with support for Ruby, Node.js, Elixir, Erlang & more (https://github.com/asdf-vm/asdf) Factories Should be the Bare Minimum (https://thoughtbot.com/blog/factories-should-be-the-bare-minimum) Mystery Guest (https://thoughtbot.com/blog/mystery-guest) GitHub - varvet/pundit: Minimal authorization through OO design and pure Ruby classes (https://github.com/varvet/pundit) Become a Sponsor (https://thoughtbot.com/sponsorship) of The Bike Shed! Transcript: STEPH: Hello and welcome to another episode of The Bike Shed. [laughs] CHRIS: Hello, and I'm singing, and I love singing. STEPH: It's Buddy the Elf; what's your favorite color? [laughter] For reals, here we go. Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Steph Viccari. CHRIS: And I'm Chris Toomey. STEPH: And together, we're here to share a bit of what we've learned along the way. So hey, Chris. What's new in your world? CHRIS: My world continues to be focused on hiring as a pretty core aspect of things. We have happily had one offer extended and accepted, so that's great. We've got a person who will be joining the team in a couple of weeks. That's very exciting. And we're continuing in conversations with some other folks. So I look forward to the place where I can be on the other side of this and have that team and be growing the team and not having to focus because hiring takes a lot of effort. It is something that I believe should be done as well as possible and intentionally as possible and then just outreach and all that. So yeah, I'll be fine with being on the other side of that. But it's going well, so that is nice. STEPH: That's awesome that you're making progress. Once you have hired your team, will you then add to the agenda to hire someone to help with hiring? CHRIS: I don't actually know if the organization, if the whole company has someone who's focused on hiring. I think that can make sense. Working through recruiters and things like that is something that I've seen in the past. I've seen it work for certain organizations. I've also been on the receiving end of plenty of obviously copy and pasted very generic "Hey, person, I saw that you do lots of Java and other enterprise code software. Would you like to come work with us?" I'm like, none of those are true, and I do not want to go work with you. But thanks, I still appreciate the outreach. [laughs] So I am intrigued to see how we think about it. More generally, this is something that you and I have talked about offline but the idea that you kind of always want to be hiring. We do have specific roles that we've identified that the budget has space for. But more generally, ideally, we're going to need to hire more people down the road, and that will happen at a particular point. But having those conversations, starting to talk to people, now planting the idea of like, hey, you're great, and I would love to work with you someday and just keeping those lines of communication open. Networking is perhaps what the people call it. I don't know; I've never felt super comfortable with that word, but I think it's that and being friendly and staying connected with people whose work I respect and would love to work with more. So that's part of what I will come out of this with is yeah, let's always be hiring in a certain sense. STEPH: I'm glad you expanded on it because I was just thinking I have specific ideas as to what always be hiring means to me and what those activities would include. So I was curious what it means to you. And I agree, I think it's a lot of networking. It's a lot of taking chats and social chats with folks and just talking about the company and finding out where they're at. And then one day, if it works out that then they want to make a shift, then you've already got that relationship that started, and they're already potentially interested in your team. I guess some of the other big stuff that comes to mind, too, is like thoughtbot we have the blog. I feel like that's always really helpful too. Like when you help somebody, when you publish information that then helps them in their career, I feel like that will then draw people towards you as well. CHRIS: Yeah, the thoughtbot blog and basically everything that thoughtbot does, the podcast here, or Upcase, or all those things were so incredibly helpful in the hiring. But I also know they're hard to spin up, is what I would say. The thoughtbot blog has I don't even know how many hundreds of thousands of hours maybe. It's weird to try and put a number to it. But I've written a handful of posts for it, and I'm not great at writing them. They take me way longer than they should, but they took many hours. And then I had wonderful peer review by other developers at thoughtbot. And so, the amount of effort that goes into the thoughtbot blog absolutely produces wonderful benefits. But it's not free by any means, and similarly, the podcasts or Upcase or any of those sort of things. Similarly, the one that's actually most interesting that I see a lot of organizations go for initially and then often walk back is open source. Like, oh, we have this internal library that we built to do something. What we'll do is we'll just package it up and share it with the world, and then it'll be great. And the maintenance burden and support necessity of an open-source project is so high. I've actually historically gotten into the mode of suggesting...when I was working with clients, they would start to mention this and be like, "Oh yeah, we think we'll open source this thing, and it'll be great." I'm like, "Are you sure, though? Do you definitely want to?" There's definitely a difference between open sourcing and just putting an idea out there is one thing that I would say. Can you just write a blog post that has code snippets but not reusable code that you have to maintain that people, unfortunately, I think unfairly expect responsiveness and maintenance over time? And what if you stopped using that technology? What if you stop using this thing, but your name is still attached to it? And people have expectations of what that looks like. Or people come in and say, "Hey, this is great, but I want to change it in this way." And you're like, "Yeah, but that actually doesn't work for us. That's not how we use it. But we would be on the hook to maintain that code if we accept your pull request." And so, as wonderful as open source is, I tend to be on the more conservative end of the spectrum of like, are you definitely sure you want to open source this? Is there another way that you can share this with the world? Can it be a conference talk, or a blog post, or something like that? But it is an interesting one. STEPH: Yeah, I've been a part of several teams that have started with that; let's start an engineering blog. And their hearts are totally in the right place, and I understand why they want to do it. But like you just said, there's a cost to that. And if you don't have something like thoughtbot has like an investment day or a time for engineers to then be able to contribute to that blog, then either they're just not because they're not going to have their downtime to be able to do that. And it is hard to write and publish and be happy with what you're going to publish with the world. I really like what you're talking about in terms of the maintenance burden because I can't remember if it was an Upcase conversation or if there was something...but I was early on at thoughtbot and had a similar thought of why can't we just open source it? Why can't we make it public? And there was a very big thoughtful discussion around well, we have to have all these considerations in place. Who's going to maintain it? Just like FactoryBot is a really big internal project at thoughtbot. And there's typically a rotation of folks who will then take ownership and then onboard other people who are interested in it and curate the issues. And it's very important work, but you have to allocate time for it. All of that to say, I totally agree. There's a big burden that goes with it. CHRIS: Yeah, it's interesting that this has been an evolving thought in my head, and it makes me sad is another thing I'll say about it. I wish it were easier to just put code out there in the world and have the expectations properly calibrated for like, hey, I did this thing. Here's a code sample. It worked for me. Actually, I found dropping something in a Gist...a Gist just has a point-in-time connotation to it that I like. Like, if I see a code sample in a Gist, I'm like, I have no expectation that that person is going to do anything or respond to anything I have to say. But this is great because I now have this sample code that helps me get a little bit further. And I may have to vendor that code or take it on myself, and I now own it. It's not this person's responsibility. But the minute you have a repo with a README that says stuff and like, here are the installation instructions, the expectations just flip in a way that I don't think is...at least I become cautious around. And that does make me sad, though. STEPH: Yeah, it feels like you went from offering an example to I'm offering a product. And so then as soon as people feel like, oh, you're giving me something as a product that you maintain, then I'm going to have higher expectations of it should work how I expected it to work. I'm going to ask questions. And yeah, you make a lot of good points. CHRIS: Would you like to pay me $0 for me to build software for you? That sounds fun. STEPH: [laughs] CHRIS: And open source is such a wonderful thing. And so I'm interested in...like, I follow a lot of folks who are in the open-source world and have found ways to make it make sense financially or otherwise or organizationally. Open Collective and things like that is one option or OpenCore and then paid pro models and things like that like Sidekiq as an example. Sidekiq just celebrated ten years with some wild numbers in terms of the revenue, and it's like, yeah, that's fantastic. This is a cornerstone piece of software in the Ruby and Rails community. And also, Mike Perham had a great outcome from it. I think that's a win. So maybe blogging, maybe, but not sure. Probably not open source is my suggestion, at least for me. But one thing that I am interested in that hasn't been an option in my mind for a long time, but I'd love to get back to is conferences and going there, especially with a small team from an organization. The three developers we go, and we hang out at a conference and the company has a space there. And there's room to have conversations and meet people. That is one that I would love to continue in a way of making sure that our name is in people's minds as a place that they could work in this world. It is interesting, though, that it gets scoped a little bit like we are definitely a Rails shop. But that's not all that we are, or that's not the complete totality of our technical identity, so it becomes interesting. But I think it's probably the most representative. And I definitely see the Ruby and Rails community is having a good product-centric mindset that is definitely the sort of thing that I want in the teams that I'm building. STEPH: Yeah, I think that's an awesome idea because it's a way that you could focus on creating content. It'll likely have a big impact. But then you can also replay that content, but it's not the commitment of a blog or a commitment of open source. CHRIS: But yeah, so hiring has been, I would say, most of what I've been doing. One other thing that was fun this week, so I have my new laptop that I've had now for a couple of months, I'd say. And just this week, we had a very frustrating issue where Heroku stopped deploying our application. Just one day, it was like, nah, it doesn't work anymore. And I was like, well, that's less cool than I want it to be. And so one of the developers on the team dug into it, and it turned out Node-sass was the answer, which we're not even using is extra unpleasant. It's just part of Sprockets and Webpack or something like that. There's some downstream dependency sequence. We're using Tailwind and PostCSS. So we don't even need Node-sass. I think maybe PostCSS does. But anyway, turns out Heroku had switched to using version 16 of Node just without telling us. We were previously on 14, and then Node-sass didn't build on that. There was just this weird dependency chain that stopped working one day. And we weren't pinning the Node version within our application. So one of the developers figured this out, pinned us back to version 14 something of Node, and that was fine. But then my computer got confused because the versions were out of sync. Anyway, asdf is great. That's the first thing I'm going to say. So I use asdf to manage the versions of Ruby, and Node, and Yarn, and Elm, and basically everything else that I use. And I love that it's all under one hood, so asdf, wonderful. Also, my laptop, wonderful. I really love the M1 fancy laptop. But what was fun was I had to install the new Node version. And this was the first time in the three months I've had this computer that I've heard the fans come on. Finally, I asked it to do something hard enough that it was like, whoa, whoa, whoa, I'm going to need some backup here. And so the fans finally kicked in. So I don't know what's going on installing Node, but good for everyone involved, [laughter] impressive to make such aggressive use of all of the hardware in my computer. STEPH: Yeah, I love asdf. I miss it right now because I'm on my client machine, and we're not using asdf. Instead, we are using Chruby, C-H Ruby to manage Ruby versions. asdf is awesome. That's fun. It's the first time that the fans kicked on. I'm intrigued with my machine. I haven't really paid attention to it when the fans kick on except the one time where I had like a Ruby process that was running away, and I had to figure out what was going on there. Because then all the CPU was just being dedicated to Ruby even when I wasn't using Ruby. But since then, I haven't heard the fans. It's been very, very quiet. It's lovely. I like when it's quiet. CHRIS: Oh, it's been great. It was interesting because it was this weird noise that I'd forgotten about. STEPH: [laughs] CHRIS: My previous computer was so old that this was happening regularly whenever my backup process would run. Apparently, that is a very computationally intensive activity. So I would hear the fans kick in, immediately go find the backup process and say pause for 60 minutes or whatever it was. Just like, leave me alone. Stop it. The computer is getting too hot. You need to calm down. But now, with the new computer, there was nothing I could do to make it happen. And then finally it happened, and I was like, oh yeah, I guess this computer has fans. That's neat. But yeah, so things that are great, asdf and the M1 laptops. STEPH: Nice. Yeah, you're one of the few individuals I know that's using one of the M1 chip. So it's been reassuring to hear how well it's going because I did not opt in to that new-new. I opted in to the give me something stable and steady that I know so that way I don't have to fuss with it because I can then fuss with all the other things that I need to fuss about. CHRIS: So much fussing to do. STEPH: Lots of fussing. Fussing and cussing is what I do over here. CHRIS: [laughs] Mid-roll ad Hey, friends, let's take a quick break to hear from today's sponsor, New Relic. All right, so you've probably experienced this before where you're just starting to fall asleep, and it's a calm, code-free peaceful sleep, and then you're jolted awake by an emergency page. It's your night on call, and something is wrong. But I have some good news because you have New Relic, which means you can quickly run down the incident checklist and find that problem. So let's see, our real user monitoring metrics look good. And that's where New Relic measures the speed and performance of your end-users as they navigate the site. But it looks like there's an error in application performance monitoring. If we click on the error, we can find the deployment marker where it all began, roll back the change, and, ooh, problem is solved. We can go back to bed, back to sleep, and back to happy. That's the power of combining 16 different monitoring products into one platform. You can pinpoint issues down to the line of code so you know exactly why the problem happened and can resolve it quickly. That's why more than 14,000 other companies, including GitHub and Epic Games, use New Relic to improve their software. So you know that next late-night call is just waiting to happen, so get New Relic before it does. And you can get access to the whole New Relic platform and 100 gigabytes of data free forever. No credit card required. Sign up at newrelic.com/bikeshed. That's New Relic N-E-W-R-E-L-I-C .com/bikeshed, newrelic.com/bikeshed. CHRIS: Well, speaking of, what have you been fussing and cussing about this week, Steph? STEPH: So this is more in the pranting area, which is our portmanteau for praise and rant, where I'm super excited. I have a delivery coming from Amazon today. So I'm that person that keeps checking and waiting for it to show up. But I'm finally going to have one dongle to rule them all. I have a very messy approach right now [laughs] where I have all the dongles and have to plug everything in. And you know what? Normally it's fine. It's fine because I do it once, and I don't have to mess with it that much. But because I now have my thoughtbot laptop and I have a client laptop, and I needed to be able to switch back and forth, it is just too much. And I was realizing how many dongles I'm having to use. So I have one dongle to rule them all. It's showing up today. It's a very exciting day. CHRIS: I'm very excited for you. I recently made a similar switch when I got this new laptop. I was like, you know what? I'm going to look into it because power can come over USB-C and whatnot. And I was like, all right, it's finally time. I want to be able to just click in. And it's one of those things that feels trivial, or at least in my mind, I'm like, this doesn't feel like it'll make that big of a difference. But it makes it so much easier to disconnect my laptop, go somewhere else, and then come back. And I noticed myself doing that more, which I think is a positive thing. Otherwise, I'm just anchored to my desk. I'm like, I don't want to unplug everything and then have to replug it. That's like a whole thing. But now that it's not, I am more mobile, more flexible in where I'm working from, and I found benefits from that. So I'm a fan. I'm very happy that this is going to show up for you [laughs] and really change the way you're working. STEPH: Well, I've started moving away from a lot of Bluetooth connections as well because my keyboard will support Bluetooth, my headphones support Bluetooth. And I liked the idea of being wireless. But then, especially from switching laptops back and forth and then having to reconnect and all of it, it was just too tedious to go back and forth. And yeah, I'm with you where I didn't want to have to leave my desk and unplug everything and then bring it back where I'm playing, you know, like the game Operation where you had to reach in and then you had to grab different little bones? If you don't know the game Operation, that sounds really weird. But it felt like a game of Operation where then I was having to find all the dongles and connect them and plug them all in. And yeah, so it's going to be wonderful. CHRIS: Even knowing the game Operation, that still sounds kind of weird. STEPH: [laughs] CHRIS: But I really love that there are people out there listening that are like, what are they talking about? STEPH: What weird childhood did you have? CHRIS: Yeah, I'm definitely Team Wired-Almost-Everything. The only thing that I have that's wireless is my headphones. And it only works kind of, and I have to trick them sometimes. And the worst thing is occasionally my computer will have control, whatever, they're connected. So I'm listening to music on my computer and then suddenly, my phone will just steal it. It's like, what are you doing? No. Or, randomly, my headphones will be sitting away from me, and they'll just connect. And I'll be in the middle of a call on something else. Like, I'm here talking to you, and suddenly my headphones are like, hey, we wanted to join the party. It's like no, absolutely not, [laughs] not at this moment, under no circumstances. So I don't really believe in Bluetooth as a technology. I'm very much a fan, particularly with things like keyboards and whatnot. Bluetooth I've yet to be convinced that it is a sound technology. STEPH: I have the headphones where they try to be very smart, and they are pretty smart where they will block out sound. But then, if I am talking, then it will put me in more of an auditory space where then I can more easily hear, and it won't filter out sound as aggressively. But I've noticed a problem. And it's when I'm watching anything that's funny that then I'm laughing. So every time I laugh, my headphones think I'm talking to someone, and then it will switch over to where it's trying to let me hear more sounds out in the universe. And then it kicks back on because it's like, okay, she's done talking. It's a very jarring experience. [laughs] And I haven't figured out how to turn that setting off. It's like, oh, I just can't watch funny stuff with my headphones right now, which is also problematic with pairing because I tend to laugh a lot with pairing. It's a thing. I'm working on it. The struggles of Shteph. CHRIS: Well, at a minimum, it sounds like your dongle life is going to be improving very soon, and that's exciting. STEPH: Dongle life, it'll be single dongle life. That's it. [singing] All the single dongles, all the single dongles. Put your adapters up. [laughter] On a different note, talking about some of the work that I've been doing this past week with Joël Quenneville on our client work, is that we have been looking for ways that we still want to build up CI time. We've talked about the fact that we're working on some of that horizontal scaling. And I don't have an update there. But the other update I have is where we want to be very strategic about where we invest our time because improving the test is not trivial work. A lot of the low-hanging fruit has already been done, so triaging a flaky test can be very difficult, and it can take us a while. So we just want to make sure and verify that before we invest a lot of time into a portion of the test that then we know what the outcome is going to be. Are we improving developers' lives by this much? And how do we measure that? Are we reducing the CI build time, and how do we know that? And one of the areas that I really wanted to focus on is FactoryBot because there are a lot of factories. The factories tend to do a ton. So they are calling out to the database and building a lot of associations. And that's something that the team knows about as well is that there are just so many SQL queries that get executed in tests. And it would be great if we could reduce the number of SQL queries that are going out. And FactoryBot includes some ActiveSupport notifications, which means you can subscribe to factories being run which then gives you access to details like which factories are being used? What build strategy is used? Are you calling build build_stubbed or create? And the factory's execution time. So then the idea of this is that if we can harness a lot of the data that we can collect from FactoryBot, then can we ask questions around what's our slowest factory? How long does it take, and how many places is it being called? Because then ideally, we can calculate to say, okay, if this factory takes this long and it's used in this number of places, then we can have a formula to figure out how many minutes of our test suite is spent just on executing that factory. And then if we can reduce the time of that factory, let's say by half, then we know how much time we're shaving off of our CI build. And then we have this more concrete verified okay; this is worth our investment. We want to pursue this, even if the factory may take us a full day to improve because it does so much. And it's just gnarly. So it's going to take some time to really refactor it into a more simplified state. So, in theory, this sounds really, really great, and it was a lot of thanks to Josh Clayton, who was the one that advocated saying that we could use the ActiveSupport notifications to find a lot of this data. And so Josh and I paired on this for a bit to look into can we answer some of those other questions as well? And we were testing it on a small side project that he had, which was great because the other codebase is very big, and feedback is just a lot slower. So we wanted to first prototype it and have a proof of concept in a very quick space and just to be able to look through the data and make sure the assumptions that we had and the value would be there. So we applied that first, and that was going really well. And then Joël Quenneville took that strategy and then applied it to all the specs in the spec models directory and ran it for the much larger client codebase and got some really great results. And we also used a low fidelity approach where we wanted to be able to see which factories were the most popular. So how often are they getting called? And the average execution time. So that way, we could then quickly look at this scatter plot, and then we could see, okay, who's in the far upper right quadrant? Because those are the factories that are causing the most pain. But we started looking into a graphing library and what are we going to pull in. And Josh had the great idea. He's like, "I wonder if Google Sheets has a scatter plot. Can we export this to CSV data and then copy it from the terminal and import it into Google Sheets?" And it turns out that you can. So then we grabbed it and put it in Google Sheets and then just converted it into a scatter plot, which was really nice because then we didn't have to incorporate any chart library or any graphics or anything. We could just plop it into Google Sheets and then easily share it. So we now have this list thanks to Joël because he ran it through the spec models directory of all the factories that are getting called. And it's really interesting. And there's one, in particular, that is high on the list. And it was actually one of the first ones that we worked with when we were troubleshooting a test that took us a while when we first joined the project. And the average time for this factory is four seconds, and it gets called over 500 times. It's like 527 times. So then if we multiply that, so if we say, all right, it takes about 4 seconds times 527 and then divide it for 60 for minutes, that's 35 minutes, 35 minutes for that factory. Now, granted, these are getting parallelized across different processes. But still, if you divide that up across four processes, that's a non-trivial amount of time. So I think this is going to be really helpful and really interesting data that we can then use to drive our decisions to say, okay, we want to take this factory and let's say even if we can cut it into half, let's say if we bring it from 4 seconds to 2 seconds, it'll go from 35 minutes to 17 and a half. CHRIS: Oh wow, I love the methodical approach. I love that actually having a number you're like; this is how much pain or the cost of this right now. And so we've identified that this is this high-level thing. I love the intentional starting with, like, let's measure it. Let's understand where the most bang for the buck is. In particular, the graph that you're describing reminds me of one I haven't actually worked with it much. But Code Climate has a graph that they use, which is it's churn versus complexity. So it's like, you may have a very complex piece of your code, but someone wrote it once, and it just sits in the corner. And you know what? It quietly does its job. And yes, it's very complex, but nobody needs to touch it. So it's not a big deal. And then you have stuff that changes constantly, but it's super simple, so that's fine too. Your UsersController is probably going to change a bunch; that's fine. But the stuff that is constantly changing and very complex that's the magic quadrant that, like, pay a lot of attention to that. And similarly, which are the ones that are being used a lot and take a while? That's the magic quadrant. I'm intrigued now. I want to search for more magic quadrants that deserve attention. But for now, that sounds like a lot of fun. So now, what's the approach that you're going to take? I imagine you need to alias that factory and have it exist because some tests will rely on certain details of it. This is my guess. So let me see if this is the way that you're thinking about it, alias the factory, so you have a representation that does all the stuff that the current one does. But then you have a new one that is much more pared down. And then, on a test by test basis, you start switching it over and trying to move things to the lower weight, the slimmer version of the factory. But I would think you would want to do a gradual process if there are 520-ish usages. Because otherwise, just changing that factory out from under all the tests, I imagine you'd break some tests if you just were like, what if it did less? STEPH: Yeah, I like that idea of the incremental approach. And that all sounds great, especially the alias because you're right; we want to change it incrementally and not all of them at once. But then essentially implement, one, because I want to see what does the pared-down factory look like? What is the basic factory that we can get away with? And then how long does it take for that factory to execute? Because then that will help confirm, can we really get it down to two seconds? Or is this just a factory that's always going to take three and a half seconds, and then it's not really that much of a payoff? Maybe we should look for a different factory to investigate. And then also understanding from the test are people reaching for this factory all the time because it builds up the world and all of these tests need the full world? Or are people just reaching for this because it does the one or two things that they need, and we can get away with a much slimmer factory? So right now, it's in the space of understanding why are people reaching for this? What are the tests they actually need? And yeah, how can we do it incrementally? At one point, we may even be able to try to programmatically switch it out. Maybe we just find 50 tests that are using this once we have the slimmed-down version and we replace...50 is probably too big. But if we replace X number of tests with this factory, how many of them fail? Maybe 10% of them passed. Cool, let's just take those 10% as a win and issue those as a PR. So that could be a strategy as well just to find if there's any that are super easy to change. All we had to do is literally change the name of the factory. The other big part that's on my mind is education around factories. I think a lot of people on the team understand that factories are very important. They can be very helpful. They can also be very cumbersome. But it feels like a good opportunity to say, "Hey, we are specifically working on these factories. Here's the reasoning that led us to work on these factories. When you're in the space of factories, please be mindful about what are you reaching for? Is there a slimmed-down factory that you can reach for? Maybe you can implement your own slimmed-down factory if one doesn't already exist." So I like the idea of coupling it with also just broader awareness because we are but two people. So I would love for more people to be part of the changes. CHRIS: Unsurprisingly, there are some wonderful blog posts on the thoughtbot blog that speak to this topic. One that I'm a fan of is Factories Should be the Bare Minimum. This was written by Matt Sumner. And it describes basically that idea of factories shouldn't build the worlds. They should give you the pieces that you can use to build the world but not build the world entirely. And so I'm a big believer in that, having your factories be as minimal as possible. They should be valid, but that's about it. And then I will often reach for extracted helper methods and keeping those as locally scoped as possible often in the spec file, or if not, maybe they're sharing spec support. But being intentional with where we reach for them and not having everyone use the same thing that just slowly gets added to. And it's like, do I actually need everything that's in there? The other thing that's interesting is the idea of having a factory that does a ton is, in my mind, sort of in direct contradiction to what I believe factories exist for which is when I think of factories, they're useful to fill in the rest of the details such that you don't have mystery guests in your test. But you can explicitly say build me a user who has an email that looks like this because, in this test, I care about the email, but I don't care about the rest of the details. I don't care about their name. I don't care about their password, or the roles, or any of the other details. Just let the factory deal with that because it's not important to the test. But I want to make sure that the relevant detail is present and specified within the spec. If you have a factory that builds everything in the world, that's like build a user and then grabs the first action from the project that that user has, because I know that they do because they use the big factory, that is just in direct contradiction to what we want factories to do. We want tests to tell their story. We want to avoid mystery guests. Factories are a great way to do that while still remaining concise. But if your factories just build the world, then there are some mystery guests in the world, I can assure you. STEPH: Yeah, I agree where factories have served as an abstraction for what I think is important to the test. But then there becomes this moment of where someone thinks, well, I need to build up these records, but I don't really need to reference them directly. I just have some coupled code that's going to rely on these. And so I don't explicitly need them, but they need to be there. So I'm going to extract it away, and a factory feels like a good place for me to extract that too. And I would take the very hard opposite approach where if you have coupled code and you have these dependencies that aren't necessarily explicitly used in the test, but they are required for the test, I'd rather see a painful test setup than have all of that extracted away from me. Because then if I do need to triage or troubleshoot that test, it's going to take a lot of just mental overhead to work through what do I actually need here and why? So I'd rather see that painful test set up then have it moved somewhere else. But I think a lot of people take the opposite approach of where if I abstracted away, my test looks prettier. And I'm like, yeah, but maybe to you in the moment, but it's going to cause me a lot of pain further down the road when I have to work with this. So show me all the crap that you had to do upfront. Just let me know. [laughs] I'd rather the test be honest with me. And then it's a really nice jumping-off point because you can see a test that does all of this. And instead of blaming the test and thinking it's the test's fault, you recognize this test has a lot of complicated setup, and it's probably because of the code and how the code was written. And we should look at refactoring the code, not at how can we make our tests look prettier? CHRIS: Unsurprisingly, I agree with 100% of that. Someday we'll find things other than Pop-Tarts and IPAs that we disagree on. But today is not that day. [laughs] Once again, today is not that day. Mid-roll Ad Hi, friends. And now a quick break to hear from today's sponsor, Scout APM. Scout APM is an application performance monitoring tool that's designed to help developers find and fix performance issues quickly. With an intuitive interface, Scout will tie bottlenecks to source code, so you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, and memory bloat. Scout also recently implemented external service monitoring, adding even more granularity when it comes to HTTP requests and API calls. So give Scout a try today with a free 14-day trial and experience first-hand why developers worldwide call Scout their best friend. And as an added bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. To learn more, visit scoutapm.com/bikeshed. That's scoutapm.com/bikeshed. STEPH: Well, here's one more that maybe you'll agree with, maybe you won't. We'll see. I'll try not to lead you in either direction, but shared examples. If I'm going to rant for a little bit, shared examples are in that space of where they just get used so heavily, and they abstract away important information about the test. And it makes the test so succinct that I don't actually know what the test is doing. And I've seen a number of places where a shared example has been extracted, and it is only used within that test file once, maybe twice. And I'm just like, friends, too much abstraction. Please keep it close. [laughs] We don't need to move it away. We want our test to be friendly and just full of context, which is what I mean when I say friendly. I want full of context is what I'm looking for, well-named variables. And I won't be able to read the test and see what's happening. So my little complaint for today would also be about shared examples and how they can be overused. And they do have a really neat purpose. They can be helpful for if you're testing maybe a controller action and you want to say you're extracting that authentication, making sure that a controller always has authentication and then that is getting included. Sure, that feels very helpful. But that's really one of the few cases I can think of where a shared example comes into play. And if you are testing code over and over throughout different parts of your codebase, there's probably a part of your codebase there that needs to then be pulled out into a class and test that class in isolation. And then you don't need to retest it throughout all of your other classes. Have I already ranted about shared examples? I can't recall at this point if I have or not. [laughs] CHRIS: I don't think we have talked about shared examples before. And I appreciate you not leading the witness here. But I think I'm in agreement with you, particularly the way you refined it there at the end because that controller example is the one rare case where I might reach for it. But in general, I think this is one of those things that I saw early on in my career. I was like, oh, cool; this is a way to clean stuff up and DRY and all those wonderful things. And then I've definitely felt the pain of just overuse of shared examples and ways to pull details out of tests. But it's like, I want to see the details. And I think broadly, that's the theme that you and I are very aligned on is like, no, no, no, tell me the story in tests. I am much less interested in having these concise tests that have a single line, and it's like, expect foo to have bar. And it's like, why? Because...oh, there's a let and then a subject, and it's a shared...oh okay. Now that I can put it together, I can tell the story, but I cannot look at this test and see a story. I want to see a story, friends. So yes, I'm totally in alignment, especially with the slight caveat at the end of like, there are cases where it's useful. Similarly, I've used let. I definitely have not even that long ago. And I stand by the usage, but it was very rare. It's very rare, and it is something that I'll look at and be like, am I sure? Definitely, is this the right thing, or did I do something wrong? Because if I find myself leaning towards let, it's like there's something that I don't think is important to the story of this test that still needs to happen. Why is that? What's going on here? Something feels off about that. And similarly, with the shared examples, it's like, is there not a different way to extract this such that I can test it in a way that I have confidence in, and then we're good? I occasionally will talk myself into using shared examples or something like it where I'm like, oh, but it's really important that everything in the app has that authentication layer put in. And so, I should definitely have this very easily reusable test that can ensure that I have it. But there's a tautology there of well, if I write the test, then I'm definitely thinking about the implementation. But if I forget the implementation, I might also forget the test. And so, it actually doesn't provide any real safety. And in those cases, that's a rare case where I would reach for some weird metaprogramming thing that's like, controllers must do the thing. And we say that in application control and then everything inherited from that will raise if it doesn't implement the authentication layer. Something like weird code that says, "You shall not pass. You must, in fact, implement the authentication layer." Rather than saying, "Oh, we'll just make it really easy to test it so that we always test and, therefore, always use the necessary authentication layer." But yeah, that's a hard one to describe in the radio. So I don't know if that came through clearly. But that's sort of my headspace on this. STEPH: Yeah, and all of that makes sense. I'm trying to think of a good example. And it's been a while since I've used Pundit, but I feel like Pundit may have a really good example of this where it's very easy to document to say, hey, all of these controllers need to make sure that they call out to this class or that there's authentication. I can't remember the exact code and how that works. But I feel like Pundit has a really good example of that behavior. CHRIS: I think they do. It's something where I think it's a configuration level thing, but you say, "Hey, Pundit, we should definitely authorize any access to models." And so Pundit then has a before action, or it's an around filter one of those. But it will raise an unauthorized error, I want to say. Like, you did not do the authorization dance in this. And that's a great example of like, I like that it is loud and annoying and in your face. And it is not possible for me to forget it because we configured it throughout all controllers. And so it's that sort of thing that I would probably reach for even though that code gets complicated and messy, and actions at a distance. But it's worth that trade-off in my mind to have, like, I don't want to forget to do the authorization stuff. Permissions matter. STEPH: That was a really nice pre-emptive approach as well. Because in most cases that we're describing, it's the I'm going to write a controller, and then I need to add this test to verify and prove that yes, I didn't forget the authentication stuff versus upfront, you're setting in a configuration to say, "Hey, please remind me to do the configuration or the authentication step that I don't miss this." So that's also a really, really nice approach. CHRIS: Yeah, the same version of me that's going to forget to write the test is going to forget to write the implementation. So I don't want to trust that version of me to save that version of me. I'm equally untrustworthy in those situations. STEPH: You want to trust the version of you that's going to get yelled at by the code if you don't do it. CHRIS: Yep, I'm going to trust the version of me that was like, I don't trust any future version of me. I will yell at myself if I have not done the necessary things. STEPH: [laughs] CHRIS: To be clear, this is like a life philosophy of mine. I don't try to remember things because I forget stuff a lot. It just happens. And so if I need to take something out the door with me, it goes in front of the door but extra critically, and this is the subtle line. Because plenty of people do that trick where you put a thing in front of the door because then you can't leave without it. There's no way to forget it. But by virtue of that, you cannot put something in front of the door until it is time to use it. Like, if ever you have to go and be like, oh, I don't need it now, though, so I'm going to move it out of the way, open the door, and then leave. No, no, no, because then you've broken the magic of the thing in front of the door must leave with you. So it's a very subtle line. I will play games with myself. I'll be like, I am forgetful. I will not remember this. I do not trust future me, so I'm going to play a trick on them. But you got to calibrate it just right. STEPH: That's really funny because I totally [laughs] didn't think about it until now how you described it. But I have definitely done that where I set a rule for myself, but then I'll break it. And then, of course, everything all of it collapses. There is a time when Tim, my husband, was going through a developer bootcamp. And as he was learning the whole world and everything that's out there, he would ask me all these questions. And he's like, "Do you know this?" And I'd be like, "No." He's like, "Do you know that?" I was like, "No." He was like, "I thought you knew this stuff." He's like, "I thought this was your job." And I was like, "Yeah, I'm really good at finding it and Googling it. But I work really hard to not store this in short-term memory because I'm filling it up with other stuff. So I work really hard to be able to find this stuff and track it and Google it." But now, there's a lot of stuff that I try very hard to not hold on to until I need it. But that was a funny moment where he seemed very upset that I didn't know stuff. And I was like, "Well, welcome to web development. There is too much to know. You're going to have to have a really good catalog system." CHRIS: Also, just so we're clear, it's going to change by next Thursday, so don't hang on to anything like it's just true forever. STEPH: [laughs] CHRIS: SQL will probably be around. That's about it. That's the one thing that I'm really confident in. STEPH: Yeah, that feels fair. Get really good at understanding HTTP forms, SQL, all that feels like some really good groundwork. CHRIS: There are some foundations. We should have a foundations episode where we talk about what we think the foundations are, the stuff that we bet won't be different in 10 years. But everything else is going to change by next Thursday, specifically. STEPH: Yeah, I like the idea of foundations. I'd be intrigued to see what we talk about and what happens there because I feel like that's going to be very representative of already what we talk about. We often will sprinkle in some new-new, especially thanks to a lot of the adventures that you go on. But I feel like a lot of the stuff that we talk about we always bring it back to the foundation because we do want the experiences that we're having to be applicable to everyone else as well. So yeah, that would be interesting to see what comes out of that. On that note, shall we wrap up? CHRIS: Let's wrap up. The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review on iTunes, as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey. STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. ALL: Byeeeeeeeee!!! ANNOUNCER: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.
Steph talks about winter storms and thoughts on name pronunciation features. Chris talks about writing a query to add a new display of data in an admin panel and making a guest appearance on the Svelte Radio Podcast. Finally, Chris decided that his productivity to-do list system was failing him. So he's on the search now for something new. He asks Steph what she uses and if she's happy with it. How do you, dear Listener, keep track of all your stuff in the world? 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. Upcase advanced Active Record (https://thoughtbot.com/upcase/advanced-activerecord-querying) Svelte Radio (https://www.svelteradio.com/episodes/chris-toomey-talks-svelte-rails-and-banking) Things (https://culturedcode.com/things/) Todoist (https://todoist.com/) MeetingBar (https://meetingbar.onrender.com/) SavvyCal (https://savvycal.com/) Become a Sponsor (https://thoughtbot.com/sponsorship) of The Bike Shed! Transcript: CHRIS: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey. STEPH: And I'm Steph Viccari. CHRIS: And together, we're here to share a bit of what we've learned along the way. So, Steph, what's new in your world? STEPH: Hey, Chris. We have Winter Storm Izzy headed our way. It's arriving in South Carolina early tomorrow morning. So that's kind of exciting just because it's South Carolina. We rarely see snow. In fact, I looked it up because I was curious because I've seen it every now and then. But I looked up the greatest cumulative snowfall in 1 season, and it was 19 inches in the winter of 1971. I was trying to add an old-timey voice there. I don't know if I was successful. CHRIS: Does 1971 deserve a full old-timey voice? STEPH: Apparently. CHRIS: I feel like people from 1971 would be like, "We were just people in the 70s." Like, what do you... STEPH: [laughs] CHRIS: Wait. Nineteen inches, is that what you said? STEPH: 19 inches. That was total for the season. CHRIS: Yeah, we can bang that out in an afternoon up here in the North. So yeah, okay. You were here for the terrible, terrible winter, right? STEPH: Oh, Snowmageddon? Yes. CHRIS: Yeah, that was something, oof. STEPH: I don't remember how many inches. Was it like 100 inches in a month or something wild like that? I've forgotten the facts. CHRIS: I, too forget the facts. I remember the anecdotal piece of data, the anecdata as it were where we shoveled our driveway, and then another storm came, we shoveled our driveway. And then finally, I was living in an apartment, and it was time to shovel the driveway again. But the pile of snow on the lawn was too big. So we had to shovel the pile of snow further up the lawn to make room for the snow that we were shoveling out of the driveway. But I also remember that being a really nice bonding moment, and I met more of the people living in the...it was a house that had been converted into six apartments. So I actually met some of the people from the house for the first time. And then we hung out a little bit more in the day. So I actually have weirdly fond memories of that time. But to be clear, that was too much snow. I will officially go on record saying too much snow. No, thank you again. STEPH: It was a lot of snow. I think it broke Boston for a while. I remember I don't think I went to...I worked remotely for two weeks because they were just like, "Yeah, don't even try to come into the office. Don't worry about it." So it felt like my first dabbling into understanding quarantine [laughs] except at least with less complicated reasons, just with lots of snow. We also went snowboarding in Charlestown, where we were living. And that was fun because there are some really great hills, and there was so much snow that that was delightful. But I'm not expecting Snowmageddon in South Carolina, although people may act like it and rush out and get their milk and bread. But hopefully, we'll get a couple of inches because that'll be lovely. I don't know that Utah has ever seen the snow. So this will be fun. CHRIS: Oh, that'll definitely be fun. I imagine you've got like even if you do get some amount of accumulation, a day later the sun will just be like, "I'm back. I got this," and clear it up, and you won't have any lingering. The year of Snowmageddon, if I remember correctly, the final pile of snow left in July, the shared one that the city had collected. So you'll probably do better than that turnaround time. [laughs] STEPH: Yeah, it's perfect. It's very ephemeral. It snows, it's beautiful. It's there for a couple of hours, and then poof, it's gone. And then you're back to probably 70-degree weather typically what's here, [laughs] which I have no complaints. There's a reason that I like living here. But in some other news, I have something that I'm really excited about that I want to share. So there's something that you and I work really hard to do correctly, and it's pronouncing someone's name. So whenever there is either a guest on the show, or we are referencing someone, we will often pause, and then we will look for videos. We'll look for an audio clip, something where that person says their name. And then we will do our best to then say it correctly. Although I probably put a Southern twang on a lot of people's names, so sorry about that. But that's really important to say someone's name correctly. And one of thoughtbot's projects is called Hub, which is something that we use internally for all of our project staffing and then also for profiles and team information; there's a new feature that Matheus Richard, another thoughtboter, implemented that I am just so excited about. And now that I have it, I just think I don't know how I lived without this. And I want it everywhere. So Matheus has added the feature where you can upload an audio file with your name pronunciation. So you can go to someone's profile, and you can click on the little audio button and hear them pronounce their name. And then a number of people have taken it a bit further where they will provide, say, the American or English pronunciation of their name. And then they will provide their specific pronunciation; maybe it's Greek, maybe it's Spanish, and it's just phenomenal. And I love it so much. And I can't wait for just more platforms to have something like this. So really big shout out to Matheus Richard for that phenomenal feature. CHRIS: Oh, that is awesome. Yeah, we definitely do pause pretty regularly to go scan through YouTube or try and find an example. And often, people just start into talks, or they'll only say their first name. We're like, oh, okay, keep searching, keep searching. We'll find it. And apologies to anyone whose name we still got wrong regardless of our efforts. But it's making this a paramount idea similar to people putting their pronouns in their name. Like, okay, this is a thing that we should get into the habit of because the easier we make this, the more common that we make this. And names absolutely matter, and getting the pronunciation right really matters. And especially if it can be an easier thing, that's really wonderful. I hope Twitter and other platforms just adopt this; just take this entirely and make it easy because it should be. STEPH: That's what I was thinking; if Twitter had this, and then I was thinking if Slack had this, that would be a wonderful place to be able to just see someone's profile because we can see lots of other helpful context about them. So yeah, it's wonderful. I want to hear more people how they pronounce their names. Because I'll always ask somebody, but it would just be really nice to then be able to revisit or check-in before you talk to that person, and then you can just say their name. That would be delightful. CHRIS: I do feel like creating it for my name would be interesting. I actually had someone this week say my name and then say, "Oh, is that how you pronounce it?" And I stopped for a minute, and I was like, "Yes. I'm really intrigued what other options you were considering, though. I would like to spend a minute and just...because I always thought there was really only the one approach, but I would love to know. Let's just explore the space here," but yes. STEPH: [laughs] You ask them, "What else you got? What other variations can I hear?" CHRIS: [laughs] I would like three variations on my desk by tomorrow so that I can understand what I'm missing out on, frankly. There's a theme or an idea that I've seen bouncing around on Twitter now of people saying, "Yeah, I really just want to apply, get hired, work for one day, make this one change to a platform, and immediately put in my resignation." And I could see this like, "All right, I'm just going to go. I'm going to get hired by Twitter. This is it. This is all I'm doing," which really trivializes the amount of effort that would go into it for a platform like Twitter. I can't even imagine what engineering looks like in Twitter and how all the pieces come together. I'm imagining some amount of microservices there, and that's just my guess. But yeah, that idea of just like, this is my drive-by feature. I show up; I work for a week, I quit. And there we go; now we have it. STEPH: Well, we are consultants. Maybe we'll get hired for all these different companies, and that will be our drive-by feature. We'll add it to their boards and be like, "Don't you want this? Don't you need this?" And then they'll say, "Yes." [chuckles] CHRIS: I am intrigued because I can't imagine this hasn't come up in conversations at Twitter. And so, what are the trade-off considerations that they're making, or what are the reasons not to do this? I don't have any good answers there. I'm just asking the question because, for an organization their size, someone must have had this idea. Yeah, I wonder. STEPH: Yeah, there's; also, I'm sure malicious things that then you have to consider as to then how people...because, at the end of the day, it's just an audio file. So it could be anything that you want it to be. So it starts to get complicated when you think about ways that people could abuse a feature. On that peppy note, what's going on in your world? CHRIS: I had a fun bit of coding that I got to do recently, which, more and more, my days don't involve as much coding. And so when I have a little bit of time, especially for a nice, self-contained little piece of code that I get to write, that's enjoyable. And so I was writing a query. I wanted to add a new display of data in our admin panel. And I was trying to write a query, and I got to build a nice query object in Ruby, which I always enjoy. That's not a real thing, just in case anyone's hearing that and thinking like, wait, what's a query object? Just a class that takes in a relation and returns relation but encapsulates more complex query logic. It's one of my favorite types of ways to extract logic from ActiveRecord models, that sort of thing. So I was building this query object, and specifically, what I wanted to do here is I'm going to simplify down the data model. And I'm going to say that we have users and reservations in the system. This may sound familiar to you, Steph, as your go-to example [laughs] from the past. We have users, and we have reservations in the system. So a user has many reservations. And reservations can be they have a timestamp or maybe an enum column. But basically, they have the idea of potentially being upcoming, so in the future. And so what I wanted to do was I wanted to find all users in the system who have less than two upcoming reservations. Now, the critical detail here is that zero is a number less than two. So I wanted to know any users that have no upcoming reservations or one upcoming reservation. Those were the two like, technically, that's it. But say it was even less than three, that's fine as well. But I need to account for zero. And so I rolled up my sleeves, started writing the query, and ActiveRecord has some really nice features for this where I can merge different scopes that are on the reservation.upcoming is a scope that I have on that model that determines if a reservation is upcoming because maybe there's more complex logic there. So that's encapsulated over there. But what I tried initially was users.leftjoinsreservations .groupbyusers.id havingcountofreservations. So that was what I got to. And thankfully, I wrote a bunch of tests for this, which is one of the wonderful things about extracting the query object. It was very easy to isolate this thing: write a bunch of tests that execute it with given data. And interestingly, I found that it worked properly for users with a bunch of upcoming reservations. They were not returned by the query objects which they shouldn't, and users with one upcoming reservation. But users with zero upcoming reservations were being filtered out. And that was a surprise. STEPH: Is it because the way you were joining and looking where the reservation had to match to a user, so you weren't getting where users didn't have a reservation? CHRIS: It was related to that. So there's a subtlety to LEFT JOINS. So a JOIN is going to say like, users and reservations. But in that case, if there is a user without reservations, I know they're going to be filtered out of this query. So it's like, oh, I know what to do. LEFT JOINS, I got this. So LEFT JOINS says, "Give me all of the users and then in the query space that I'm building up here, join them to their reservations." So even a user with no reservations is now part of the recordset that is being considered for this query. But when I added the filter of reservations.upcoming, I tried to merge that in using ActiveRecord's .merge syntax on a query or on a relation, as it were. That would not work because it turns out when you're using the LEFT JOINS...and as I'm saying this, I'm going to start saying, like, here's definitively what's true. I probably still don't entirely understand this, but trying to do the WHERE clause on the outer query did not work. And I had to move that filtering logic into the LEFT JOINS. So the definition of the JOINS was now I had to actually handwrite that portion of the SQL and say, LEFT OUTER JOIN users on and then, you know, the users.id=reservations.userid and reservations. whatever the logic there for an upcoming reservation. So reservations.completed is null or reservations.date>date.current or whatever logic there. But I had to include that logic in the definition of the LEFT OUTER JOIN, which is not a thing that I think I've done before. So it was part of the definition of the JOIN rather than part of the larger query that we were operating on. STEPH: Yeah, that's interesting. I don't think I would have caught that myself. And luckily, you had the test to then point out to you. CHRIS: Yeah, definitely the tests made me feel much more confident when I eventually narrowed down and started to understand it and was able to make the change in the code. I was also quite happy with the way I was able to structure it. So, suddenly, I had to handwrite a little bit of SQL. And what was nice is many, many, many years ago, I recorded a wonderful course on Upcase with Joe Ferris, CTO of thoughtbot, on Advanced ActiveRecord Querying. And I'm still years later digesting everything that Joe said in that course. It's really an amazing piece of content. But one of the things that I learned is Joe shows a bunch of examples throughout that course of ways that where you need to, you can drop down to raw SQL within an ActiveRecord relation. But you don't need to completely throw it out and write the entire query by hand. You can just say, in this case, all I had to handwrite was the JOINS logic for that LEFT JOINS. But the rest of it was still using normal ActiveRecord query logic. And the .having was scoped on its own, and all of those sort of things. So it was a nice balance of still staying mostly within the ActiveRecord query Builder syntax and then dropping down to a lower level where I needed it. STEPH: I love that you mentioned that video because I have seen it, and it is so good. In fact, I now want to go back and rewatch it since you've mentioned it just because I remember I always learn something every time that I do watch it. On a side note, the way that you represented and described query objects was so lovely. I know you, and I have talked about query objects before because we adore them. But I feel like you just gave a really good mini class and overview of like, this is what a query object is, and this is what it does. And this is why they're great because you can test them. CHRIS: Cool. I'm going to be honest; I have no idea what I said. But I'm glad it was good. [laughs] STEPH: It was. It was really good. If anyone has questions about query objects, that'll be a good reference. CHRIS: Well, thank you so much for the kind words there. And for the ActiveRecord querying trail, really, I was just along for the ride on that one, to be clear. I did write a bunch of notes after the fact, which I've found incredibly useful because the videos are great. But having the notes to be able to reference...past me spent a lot of time trying really hard to understand what Joe had said so that I could write it down. And I'm very glad that I invested that time and effort so that I can revisit it more easily. But yeah, that was just a fun little bit of code that I got to write and a new thing that I've learned in the world of SQL, which is one of those topics that every little investment of effort I find to be really valuable. The more comfortable I feel, the more that I can express in SQL. It's one of those investments that I'm like, yep, glad I did that. Whereas there are other things like, yeah, I learned years ago how to do X. I've completely forgotten it. It's gone from my head. I'm never going to use it again, or the world has changed. But SQL is one of those topics where I appreciate all of the investment I've put in and always find it valuable to invest a bit more in my knowledge there. STEPH: Yeah, absolutely same. Just to troll Regexs for a little bit, they're powerful, but they're the thing that I will never commit to learning. I refuse to do it. [laughs] I will always look it up when I need to. But Postgres or SQL, on the other hand, is always incredibly valuable. And I'm always happy to learn something new and invest in that area of my skills. CHRIS: Yep, SQL and Postgres are great things. But let's see. In other news, actually, I had the pleasure of joining the Svelte Radio Podcast for an episode this week. They invited me on as a guest. And we got to chat about Svelte, and then I accidentally took the conversation in the direction of inertia as I always do. And then I talked a little bit more about Sagewell, the company that I'm building, and all sorts of things in the world. But that was really fun, and I really enjoyed that. And I believe it will be live by the time this episode goes live. So we will certainly include a link to that episode in our show notes here. STEPH: That's awesome. I haven't listened to the Svelte Podcast before. So I'm excited to hear your episode and all the good things that you said on it. I'm also just less familiar with them. Who runs the Svelte Podcast, and what's the name of the show? CHRIS: The show is called Svelte Radio. It's hosted by Antony, Shawn, and Kevin, who are three Svelters from the community. Svelte is a really interesting group where the Svelte society is, as far as I can tell, a community organization that is seemingly well-supported by the core team and embraced as the natural center point of the community. And then Svelte Radio is an extension of that. And it's a wonderful podcast. Each week, they talk about various things. So there are news episodes, and then they have guests on from time to time. Recently, having Rich Harris on to talk about the future of Svelte, Rich Harris being the creator of Svelte. Interestingly, if you search for Svelte Radio, they are the second Google result because the first Google result is the tutorial docs on how to use Svelte with radio buttons. But then the second one is Svelte Radio, the podcast, [laughs], which is an interesting thing. Good on Svelte's documentation for having such strong SEO. STEPH: I was just thinking there's something delightful about that where the first hit is for documentation that's a very helpful; here's how you use this. That's kind of lovely. Well, that's really cool. I'm really looking forward to hearing more about Svelte and listening to you be on the show. CHRIS: Yeah, they actually had some very kind things to say about The Bike Shed and, frankly, you as well and our co-hosting that we do here. So that was always nice to hear. STEPH: That's very kind of them. And it never fails to amaze me how nice podcasters are. Everyone that I've met in this community that's a fellow podcaster they're just all such wonderful, nice, kind people, and I just appreciate the heck out of them. CHRIS: Yeah, podcasts are great. The internet is doing its job; that's my strong belief there. But let's see. In other news, I actually have more of a question here, sort of a question and an observation. My work has started to take a slightly different shape than it has historically. Often, I'm a developer working on a team, picking up something off the top of the Trello board or whatever we're using for project management, working on that thing, pushing it through to acceptance. But all of the work or the vast majority of the work is encapsulated in this one shared planning context. But now, enough of my work is starting to spill out in different directions. Like right now, I'm pushing on hiring. That's a task that largely lives with me that doesn't live on the shared Trello board. Certainly, the rest of the team will be involved at some point. But for now, there's that that's really mine. And there are other pieces of work that are starting to take that shape. So I recognize, or at least I decided that my productivity to-do lists system was failing me. So I'm on the search now for something new, but I'm intrigued. What do you use? Are you happy with what you have for to-do lists? How do you keep track of stuff in the world? STEPH: Oh goodness. I'm now going to overanalyze everything that I do and how I keep track of the things that I do. [chuckles] So currently, I have two things that I used to track, and that is...okay, I'm going to expand. I have three to-do lists that I use to track. [laughs] Todoist is where I add most things of where whatever I just think of, and I want to capture it Todoist is usually where it goes. Because then it's very easy for me to then go back to that list and prioritize or just simply delete stuff. If I haven't gotten to it in a while, I'm like, fine, let it go. Move on. And then the other place I've started using just because it's been helpful in terms of linking to stuff is Basecamp. So we use Basecamp at thoughtbot, and we use it for a number of internal projects. But I have created my own project thanks to some advice from Mike Burns, a fellow thoughtboter, because he created his own and uses that to manage a lot of his to-dos and tasks that he has. And then that way, it's already one-stop shopping since you're in Basecamp a lot throughout the day or at least where you're going to visit some of the tasks that you need to work on. So that has been helpful just because it's very simple and easy to reference. And then calendar, I just live by my calendar. So if something is of the utmost importance...I realize I'm going in this in terms of order of importance. If something is critical, it's on my calendar. That's where it goes. Because I know I have not only put it somewhere that I am guaranteed to see it, but I have carved out time for it too. That's my three-tier system. [laughs] CHRIS: I like it. That sounds great, not overly complicated but plenty going on there. And it sounds like it's working for you, sounds like you're happy with that. STEPH: It has worked really well. I'm still evaluating the Basecamp, but so far, it has been helpful. It does help me separate between fun to-do items which go in Todoist and maybe just some other work stuff. But if it's really work-focused, then it's going in Basecamp right now. So there's a little helpful separation there between what's going on in my life versus then things I need to prioritize for work. What are the things that you're currently using, and where are you feeling they're falling down or not being as helpful as you'd like them to be? CHRIS: My current exploration, I'm starting to look for a new to-do list-type things. Specifically, I've been using Trello for a long time for probably a couple of years now. And that was a purposeful choice to move away from some of the more structured systems because I found they weren't providing as much value. I was constantly bouncing between different clients and moving into different systems. And so much of the work was centrally organized there that the little bit of stuff that I had personally to keep track of was easy enough to manage within a Trello board. And then slowly, my Trello board morphed into like 10 Trello boards for different topics. So I have one that's like this is research. These are things that I want to look into. And so I can have sort of a structure and prioritization within that context in my world. And then there's one for fitness and one for cooking. I'm trying to think which else...experiments, as I'm thinking about I want to try this new thing in the world. I have a board for that. So I have a bunch of those that allow me to keep things that aren't as actionable, that are more sort of explorations. But then they each have their own structure. And that I found to be really useful and I think I'll hold on to. But my core to-do board has started failing me, has started being just not quite enough. And then, more so, I wanted a distinct thing for work for a professional context. So I was like, all right, let me go back to the drawing board and see what's out there. And I did a quick scan of Todoist and Things, respectively. And I've settled on Things for right now. It just matches a little bit more to my mental model. Todoist really pushes on the idea of due dates or dates as a singular idea associated with most things. Almost everything should have a date. And I kind of philosophically disagree with that. Whereas Things has this interesting idea of there is the idea of a due date, but it's de-emphasized in their UI because not everything has a due date; most things don't. But Things has a separate idea of a scheduled date or an intent date. Like yeah, I think I'll work on that on Wednesday. It's not due on Wednesday; that's just when I want to work on it. It can have a separate due date. Like, maybe it's due Friday. STEPH: Is the name of the application that you're saying is it Things? Is that the name of it? CHRIS: Yeah, it is. STEPH: I haven't heard this one. You kept saying Things. I was like, wait, is he being vague? But I realized you're being specific. [laughs] CHRIS: It's one of the few things that...yeah, one of the few things that I think is not great about Things. It's from a company Cultured Code, and the application is called Things. And that is all I will say on that topic. Different names maybe would have been better, but they seem to have carved out enough of an attention space. Enough people know of it that if you search for Things and to-do list, it will very quickly pop up. But yeah, that's a pretty ambiguous name. They maybe could have done a different one there. But the design of the application is really nice. It's on my desktop. And now I have it on my phone as well, and they sync between them and all the stuff. So there's never going to be a perfect system. I'm certain of that. I've at least talked myself out of trying to build my own because, man, have I fallen into that trap before. Oh goodness, so many times. STEPH: I'm very proud of you. CHRIS: Thank you. I'm trying. STEPH: But yeah, it'll be interesting to see how it evolves. I continue to struggle with there are these things that come to mind, and I want to capture them during the day. But some of them are just stories I'm telling myself, which would probably be best captured in a journal tool. And then there are notes that I might want to keep on remote work and how people think about that. And so I'm starting to think about Obsidian or a note-taking system for that. And then I've got this Trello board concoction. And now I've got a to-do...and suddenly I'm like, well, that's too many things. And so I'm trying to not overthink it. I'm trying to not underthink it. I'm trying to just find that perfect amount of thinking. That's what I'm aiming for. I'm not sure I'm going to hit it directly, [laughs], but that's what I'm aiming for. 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: Some of the topics that you mentioned earlier did stand out to me when you're talking about recipes and working out some other topics. Those are things for me that I often just put in notes. So I liked the word that you used for stories that you're telling yourself or things that you're interested in. Is that something that...I don't put it in Todoist or put it somewhere because I don't really have an action item. It's more like, yeah, this recipe looks awesome and one day...so I'm going to stash it somewhere so I can find it. I'm currently using Notion. I used Bear before. It is beautiful. I really liked Bear, but I needed a little bit more structure, and Notion gave me that structure. And so I will just dump it in Notion. And then it's very searchable, so I can always find whatever recipe or whatever thought that was as long as I try to add buzzwords to my own notes. Like, what would have Stephanie searched for looking for this? So I will try to include some of those words just so I can easily find it. CHRIS: I love you're defining yourself as a Stephanie. For a random Stephanie walking through the woods, what search terms? How can I SEO arbitrage a Stephanie? STEPH: What would she look for? CHRIS: Who knows? STEPH: That Stephanie, she's sneaky. You never know. CHRIS: You never can tell. Obsidian is the one that I'm looking at now. But I'm currently using Apple Notes. And it's really nice to be able to search directly into a note very quickly. I have that both via Alfred and then on my phone. And I'm finding a lot of utility in that, particularly for notes, for things I want to talk to someone about. But now there are seven different things, and how are they connected? And where is something? And to the question of where would a future Christopher look for this, let's make sure I put it in that place. But I don't know what that dude's going to be up to. He's a weird guy. He might look in a completely random place. So I'm trying to outsmart him, and oof, good luck, me. STEPH: [laughs] I have heard of Obsidian, but I don't recall much about it. So I'd have to look into it. I do feel your pain around Todoist and where it really encourages you to set a date. Because there are often things where I'm like, I saw something I want to read. And I know there are tons of tools. There are so many tools and videos and things that people could watch if they really want to invest in this workflow. But right now, I've told myself no, and so I use Todoist. And I see something I want to read, and so I just link to it. And I don't have a particular date that I want to read it. I'm like, this looks cool, and so then I add it to a reading list. But that also, I guess, could be something for notes. More and more, I'm trying to shove things into notes, so it feels less like a task and more of a I'm curious, or I'm interested in things that have piqued my interest. Let me go back and look at that list to see if there's something I want to pull from today or I need inspiration. That's what my notes often are; they're typically inspiration for something that I have seen and really liked, or maybe it's a bug that I looked into, and I want to recall how that happened or what was the process. But yeah, my notes are typically a source of inspiration. So I try to dump most things in there. I don't know if that's particularly helpful for your task, though, because it sounds like you're looking for a way to manage the things that you actually need to do versus just capturing all of your thoughts. CHRIS: Honestly, part of it is having a good system for those like, oh, I'd like to read this sometime. Ideally, for me, that doesn't go into my whatever to-do list system. But if my brain doesn't trust that I'll ever read it or if I feel like I'm putting it into a black hole, then my brain is just like, hey, you should really read that thing. Are you thinking about that? You should think about that and just brings it up. And so having a system externalized that I trust such that then the to-do list can be as focused as possible. It's a sort of an arms race back and forth battle type thing of like, I've definitely done the loop of like, all right, I want to capture everything. I want to have perfect, lossless, productivity system, and that is not possible. And so then I overcorrect back the other way. I'm like, whatever, nothing matters. I'll just let everything fall away. And then I'm like, well, then my brain tries to remind me of stuff or tries to remember more. And there's a book, Getting Things Done, which is one of the more common things recommended in the productivity world. And that informs a bunch of my thinking around this, the idea of capturing everything that's in your head so that you can get it out of your head. And in the moment, be focused and in the moment and not having to try and remember. And so that's the ideal that I'm searching for. But it's difficult to build that and make that work. STEPH: It seems the answer is there's no perfect system. It's always finding what works for you. And I feel like it's always going to change from hopefully not month to month because that would be tedious. But it may change year to year depending on how you're prioritizing things and the types of things that you need to remember or that you need to accumulate somewhere. So I feel like it's always this evolving, iterative process of changing where we're storing this. But I feel like where you store the notes and inspiration, that's something that, ideally, you want to make sure that you can always continue to keep forward. So even if you do change systems, that's something that's usually on my mind. It's like, well, if I use this system to store all of my thoughts, what if I want to move to something else? How stuck am I to this particular platform? And can I still have ownership of the things that I have added here? But overall, yeah, I'd be intrigued to see what other people think if they have a particular system that works for them, or they have suggestions. But overall, it seems to be whatever caters best to your personality and your workflow. That's why there are so many of these. There are so many thoughts, so many videos, so many styles. CHRIS: Yeah, I think a critical part of what you just said that feels very true to me is this is something that will change over time as well. Life comes in seasons, and my work may look a certain way, or my life may look a certain way, and then next year, it may be wildly different. And so, finding something that is good enough for right now and then moving forward with that and being open to revisiting it. And yeah, that feels true. So I'm in an explore phase right now. I'll report back if I have any major breakthroughs. But yeah, we'll see how it goes. STEPH: I will say I think the main tool that I have really leaned into, while some of the others will change over time, is my calendar. There are certain things I've let go. My inbox is always going to be messy. My to-do list is always going to be messy. But my calendar that is where things really go to make sure that they happen. And I will even add tasks there as well. So I feel like the calendar will always stick with me because I can trust that as the one source of like, these are the things that have to happen. Everything else I can check for during that day or figure it out as I go. Or if something gets dropped or bounces to the next day, it's okay. CHRIS: Yeah, the calendar is definitely a core truth in my world. Whatever the calendar says, that is true. And I'm actually a...I hope I'm not annoying to anyone. But I'm very pointed in saying, "This recurring meeting that we have if we keep just canceling it the day before every time, let's get this off our calendars. Let's make sure our calendars are telling the truth because I trust that thing very much." And two apps that I'm using right now that I've found really useful in the calendar world are MeetingBar, which I've talked about before. But it's a little menu bar application that shows the next meeting that's upcoming. And then I can click on it and see the list of them and easily join any video call associated, just a nice thing to keep the next thing on my calendar very top of mind, super useful, really love that. That's just open source and easy to run with. The other that I've been spending more and more time with lately is SavvyCal. SavvyCal is similar to Calendly. It's a tool for sharing a link to allow someone to schedule something on your calendar. And, man, it is an impressive piece of technology. I've been leaning into some of the fancier features of it of late. And it has an amazing amount of control, and I think a really well-designed sort of information architecture as well. It took me a little while to figure out how to do everything I wanted to do in it. But I wanted to be able to define a calendar link thing that I could share with someone that really constraints in the way that I wanted. Like, oh, don't let them schedule tomorrow, and make sure there's this much buffer between meetings. And don't let this calendar link schedule too many things on my calendar because I need to control my day, and give me some focus blocks. And they're not actually on my calendar, but please recognize that. And it basically supports all of these different ways of thinking and does an incredible job with it. As an aside, SavvyCal is created by Derrick Reimer, who is the co-host of The Art of Product Podcast, which is co other hosted by Ben Orenstein, former thoughtboter, creator of Upcase, and a handful of other things. So small world and all of that. But yeah, really fantastic piece of technology that I've been loving lately. STEPH: That's really cool. I have not heard of SavvyCal. I've used Calendly and used that a fair amount. And that is so awesome where you can just send it to people, and they can pick time on a calendar and do all the features that you'd mentioned. So it's good to know that there's SavvyCal as well. Well, pivoting just a bit, we have a listener question that I'm really excited to dig into. This question comes from fellow thoughtboter, Steve Polito. And Steve writes in that, "Hey, Bike Shed, I've got a question for you. I find it difficult to know if there's an existing method in a large class or a class that includes many concerns. How can I avoid writing redundant methods when working on a large project?" And Steve provided a really nice just contrived example where he's defined a class user that inherits from ApplicationRecord. And then comments, "Lots of methods making it really hard to scan this giant class. And then there's a method called formatted name. So it takes first name, adds a space, and then adds the user's last name. And then there are a lot more methods in between. And then, way down, there's another method called full name that does the exact same thing. Just to provide a nice example of how can you find a method that has existing logic that you want and avoid implementing essentially the same method and the same class?" So as someone who has worked on some legacy systems this year, I feel that pain. I feel the pain of where you have a really giant class, and that class may also include other modules. So then you have your range of all the methods that you may be looking through gets really widened. And you are looking for particular logic that you feel like may exist in the system, but you really just don't know. So I don't know if I have a concrete method for how you can find duplicate logic and avoid writing that other method. But some of the things that I do is I will initially go to the test. So if there's some logic that I'm looking for and I think it's in this class or I have a suspicion, I will first look to see what has test coverage. And I find that is just easier to skim where I can find, and I'll use grep, and search and just look for anything. In this particular case, let's use first name as our example. So I'm looking for anything that's going to collaborate with first name. Some of the other things that I'll do is I'll try to think of a business case where that logic is used. So, where are we displaying the user's full name? And if I can go to that page and see what's already in use, that may give me a hint to do we already have this logic? Is there something there that I should reuse, or is it something new that I'm implementing? And then if I really want to get fancy about it, for some reason that I really want to see all the methods that are listed, but I'm trying to get rid of some of the noise in the file, then I could programmatically scan through all the available methods by doing something like class.instance methods and passing in false. So we don't include the methods that are from superclasses, which can be very helpful. So that way, you're just seeing what scoped to that class. But then, let's say if you do have a class that is inheriting from other modules, then you may want to include those methods in your search. So to get fancier, you could look at that class' ancestor chain and then collect the classes or models that are custom to your application, and then look at those instance methods. And then you could sort them alphabetically. But you're still really relying on is there a method name that looks very similar to what I would call this method? So I don't know that that's a really efficient way. But if I just feel like there's probably already something in this space and I'm just looking for a clue or some name that's going to hint that something already exists, that's one way I could do it. To throw another wrench in there, I just remembered there are also private methods, and private methods don't get returned from instance methods. I think it's private instance methods is a method that you'd have to call to then include those in your search results as well. So outside of some deeper static analysis, this seems like a hard problem. This seems like something that would be challenging to solve. And then I guess the other one is I ask a friend. So I will often lean on if there's someone else at the team that's been there longer than me is I will just ask in Slack and say, "Hey, I want to do a thing. I'm worried this already exists, or I think it already exists. Does anybody have any clues or ideas as to where this might live?" I know I just ran through a giant list of ideas there. But I'm really curious, what are your thoughts? If you have a messier codebase and you're worried that you are reimplementing logic that already exists, but you're trying to make sure you don't duplicate that logic, how do you avoid that? CHRIS: Well, the first thing I want to say is that I find it really interesting that I think you and I came at this from different directions. My answer, which I'll come to in a minute, is more of the I'm not actually sure that this is that easy to avoid, and maybe that's not the biggest problem in the world. And then I have some thoughts downstream from that. But the list that you just gave was fantastic. That was a tour de force of how to understand and explore a codebase and try and answer this very hard question of like, does this logic already exist somewhere else? So I basically just agree with everything you said. And again, I'm deeply impressed with the range of options that you offer there for trying to figure this out. That said, sometimes codebases just get really large. And this is going to happen. I think the specific mention of concerns as sort of a way that this problem can manifest feels true. Having the user object and being like, oh man, our user object is getting pretty big. Let's pull something out into a concern as just a way to clean it up. That actually adds a layer of indirection that makes it harder to understand the totality of what's going on in this thing. And so personally, I tend to avoid concerns for that reason or at least at the model layer, especially where it's just a we got 1,000 methods here. Let's pull 200 of them into a file and maybe group them somewhat logically. That tends to not solve the problem in my mind. I found that it just basically adds a layer of indirection without much additional value. I will say in this particular case, the thing that we're talking about presenting the full name or the formatted name feels almost like a presentational concern. So I might ask myself, is there a presenter object, something that wraps around a user and encapsulates this? And then we as a team know that that sort of presentational or formatting logic lives in the presentation format or layer. Maybe I'm not entirely convinced of that as an answer. But it's just sort of where can we find organizational lines to draw within our codebases? I talked about query objects earlier. That's one case of this is behavior that I'll often see in classes as, say, a scope or something like that that I will extract out into a query object because it allows me to encapsulate it and break it out a little bit more but still have most of the nice pieces that I would want. So are there different organizational patterns that are useful? I think it's very easy to start drawing arbitrary lines within our codebases and say, "These are services." And it's like, what does that mean? That doesn't mean anything. App Services, that's not a thing, so maybe don't do that. But maybe there are formatters, queries, commands, those feel like...or presenters, queries, commands. Maybe those are organizational structures that can be useful. But switching to the other side of it, the first thing that came to mind is like, this is going to happen. As a codebase grows, this is absolutely going to happen. And so I would ask rather than how can I, as the developer, avoid doing this in the first place...which I think is a good question to ask. And again, everything you listed, Steph, is great. And I think a wonderful list of ways that you can actually try to avoid this. But let's assume it is going to happen. So then, what do we do downstream from that? One answer that comes to mind is code review. Code review is not perfect. But this is the sort of thing that often in code review I will be like, oh, I actually wrote a method that's similar to this. Can you take a look at that and see can we use only one of these or something like that? So I've definitely seen code review be a line of defense on this front. But again, stuff is still going to sneak through. And someday, you'll find it down the road. And that's the point in time that I think is most interesting. When you find this, can you fix it easily? Do you have both process-wise and infrastructure-wise the ability to do a very small PR that just removes the duplicate method, removes the usage of it, and consolidates on the one? It's like, oh, I found it. Here's a 10-line PR that just removes that method, changes the usage. And now we're good. And that can go through code review and CI very quickly. And we have a team culture that allows us to make those tiny changes on the regular to get them out to production as quick as possible so that we know that this is a good code change, all of that. I found there are teams that I've worked on where that process is much slower. And therefore, I will try and roll a change like that up into a bigger PR because I know that's the only way that it's really going to get through. Versus I've been on teams that have very high throughput is probably the best way to describe it. And on those teams, I find that the codebase tends to be in a healthier shape because it just naturally falls out of having a system that allows us to make changes rapidly with high trust, get them out into the world, et cetera. STEPH: This is that bug or inconsistency that's going to show up where on one page you have the user's full name. And then on another page, you have the user's full name, but maybe the last name is not capitalized, or there's just something that's slightly different. And then that's when you realize that you have two implementations of essentially the same logic that have differed just enough. I like how you pointed out that this is one of those things that as a codebase grows, it's probably going to happen, and that's fine. It's one of those if you do have duplicate logic, over time, based on your team's processes, you'll be able to then identify when it does happen, and then look for those preventative patterns for then how you organize your code. How quickly can you make that change? Can you just issue a PR that then removes one of them? But then look for ways to say, how are we going to help our future selves recognize that if we're looking for a user's full name, where's a good place to look for that? And then what's a good domain space or naming that we can give to then help future searchers be able to find it? I also really like your code review example because it does feel like one of those things that, yes, we want to catch it if we can, and we can leverage the team. But then also, it's not the end of the world if some of these methods do get duplicated. There's one other thing that came to mind that it's not really going to help prevent duplicate methods, but it will help you identify unused code. So it's the Unused tooling that you can run on your codebase. And that's something that would be wonderful to run on your codebase every so often. So that way, if someone has added...let's say there was a method that was full name but is not in use. It didn't have test coverage; that's why you didn't find it initially. And so you've introduced your own formatted name. And then, if you run unused at some point, then you'll hopefully catch some of those duplicate methods as long as they're not both in use. CHRIS: I think one more thing that I didn't quite say in my earlier portion about this. But in order to do that, to use Unuse or to have these sort of small pull requests that are going through, you have to have test coverage that is sufficient that you are confident you're not going to break the app. Because the day that you do like, oh, there's a typo here; let me fix it real quick. Or there's this method I'm pretty sure it's not used; let me rip it out. And then you deploy to production, and suddenly the error system is blowing up because, in fact, it was used but sneakily in a way that you didn't think of, and your test coverage didn't catch that. Then you don't have trust in the system, and everything slows down as a result of that. And so I would argue for fixing the root problem there, which is the lack of test coverage rather than the symptom, which is, oh, I made this change, it broke something. Therefore, I won't make small changes anymore. STEPH: Definitely. Yeah, that's a great point. CHRIS: So yeah, I don't have any answer. [laughs] My answers are like, I don't know, it's going to happen, but there's a lot of stuff organizationally that we can do. And granted, you gave a wonderful list of ways to actually avoid this. So I think the combination of our answers really it's a nice spectrum of thoughts on this topic. STEPH: I agree. I feel like we covered a very nice range all the way from trying to identify and then how to prevent it or how to help future people be able to identify where that logic lives and find it more easily. Also, at the end of the day, I like the how big of a problem is this? And it is one of those sure; we want to avoid it. But I liked how you captured that at the beginning where you're like, it's okay. Like, this is going to happen but then have the processes around it to then avoid or be able to undo some of that duplicate work. But otherwise, if it happens, don't sweat it; just look for ways to then prevent it from happening in the future. On that note, shall we wrap up? CHRIS: Let's wrap up. The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review on iTunes, as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey. STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Byeeeeeeeeee!!! Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.
Steph gives an update about RSpec focus and how she often forgets to remove the focus feature from tests. She figured out two solutions: one using Rubocop, and the other from a Twitter user, suggesting using a GitHub gist. She also suggests that if you're one of those people who misses being in an office environment, you check out soundofcolleagues.com for ambient office noise selection. Chris has been struggling to actually do any coding and is adjusting to doing more product management and shares some strategies that have been helping him. They answer a listener question about dealing with large pull requests and how it's hard to recognize a good seam to break them up when you are in the thick of one. This episode is brought to you by ScoutAPM (https://scoutapm.com/bikeshed). Give Scout a try for free today and Scout will donate $5 to the open source project of your choice when you deploy. Twitter note re: rspec-retry (https://twitter.com/jasonrudolph/status/1458416077726158852) soundofcolleagues.com (https://soundofcolleagues.com) mailcheck (https://github.com/mailcheck/mailcheck) Inertia.js (https://inertiajs.com/) Svelte (https://svelte.dev/) devise (https://github.com/heartcombo/devise) clearance (https://github.com/thoughtbot/clearance) Become a Sponsor (https://thoughtbot.com/sponsorship) of The Bike Shed! Transcript: CHRIS: One day, I'll grow up. It's fine. I look forward to that day. But today, I don't think it's that day. Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey. STEPH: And I'm Steph Viccari. CHRIS: And together, we're here to share a bit of what we've learned along the way. So, Steph, what's new in your world? STEPH: Hey, Chris. Well, in some fun news, Utah started his professional training as of this morning, which I'm very excited about. Because we've been working with him to work on being good with walking on a leash, FYI, he's not, [laughs] and also being good about not jumping on people. And essentially, being a really good roommate. And he started training today, and we are using an e-collar, which initially I was really hesitant about because I don't want it to hurt him in any way. But now that I have felt the e-collar myself and we've had a first day with it, it's going super well. I'm very excited for where this is headed. CHRIS: That's very exciting. When does he start paying rent? STEPH: Ooh. I'll have to check with him, or I guess I have set those boundaries. That's my job. CHRIS: I just figured that's a core part of being a good roommate. But maybe we've got baby steps or doggy steps to get there. But that's exciting. I'm glad [laughs] that the first day of training is going well. STEPH: Yeah, it's going great. And the place that we're going to the trainer they have horses, and mules, and goats. And so now I have a very cute video of him trying to play with a goat, and the goat was having none of it. But it's still all very cute. In tech-related news, I have an update for when you and I were recently chatting about the RSpec focus and how I mentioned that I often forget to remove the focus feature from tests. And so then that goes up to a PR, and I have to rely on a kind human to let me know, and then I remove it. Or worst-case scenario, it gets merged into the main branch. And for anyone that's not on Twitter, I just wanted to share an update because I also shared something there. But the resolution for what I was looking for there's already a rule that's written into Rubocop, but it's specifically written in the Rubocop RSpec codebase. And with that rule, you can essentially just say, hey, let me know anytime that a test is using the focus metadata, and then make sure to let me know and fail. And then if you don't want to actually include all of Rubocop into your project because Rubocop is pretty opinionated, you can still add Rubocop to your project, but you can specifically add Rubocop RSpec, and then you can say, hey, all other rules disabled by default, but then you can enable that specific rule. So then, that way, you will catch all of your focus tests. There's also another approach that someone on Twitter shared with us recently from Marz Drel. And Marz shared specifically a really nice simple GitHub Gist that documents or exemplifies that you can add an environment variable that checks to say, hey, if we're in CI mode, then add a before hook. And then that before hook will look for any examples that are using that focus metadata, and then it's going to raise. And then if we're not in CI mode, then don't do anything, don't raise, and carry on. And that's just a really nice simple addition if someone didn't want to pull in Rubocop into their project. CHRIS: Both of those definitely sound like great options. I don't think we have Rubocop on the current project that I'm working on. But I think the RSpec focus thing, the metadata one, seems like it'll work great. More generally, I just want to thank folks out there who listen to the show and then write back in like, "Hey, this is probably what you want." There was a similar thread that someone shared around the RSpec::Retry stuff that I was talking about recently and the failure mode there and trying to get that into the Junit Reporter. And so they had some suggestions around that. Jason Rudolph on Twitter reached out, sharing just his initial exploration and thoughts on how it might be possible to extend the XML reports that are generated and capture a flaky test in that way. So that's really interesting. And again, just really love that folks are listening to the things that we say and then even adding on to them and continuing the conversation. So thanks to everybody for sharing those things. STEPH: Yeah, it's incredibly helpful. And then one other fun thing that I'd love to share, and I found this out from someone else at thoughtbot because they had shared it recently. But it's a neat website called soundofcolleagues.com. And I know you've got your laptop in front of you. So if you'll go visit it, it'll be neat to see as we're talking through it. For anyone else that wants to pull it up, too, we'll include a link in the show notes. But it's a neat project that someone started where you can bump up the sounds that you would normally hear in an office. So maybe you want to bump up background noise of people or an open window. There's one specifically for printers and a coffee machine, and keyboards are on there as well. [laughs] I have discovered I am partial open window and partial rain, although rain is just always my go-to. I like the sound of rain for when I'm working. CHRIS: Gentle rain is definitely nice white noise in general. I've seen this for coffee shops, but I haven't seen the particular one. Also, yes, I definitely know how to spell the word colleague on the first of three tries. Definitely didn't have to rely on Google for that one. But yeah, nice site there. I enjoy that. STEPH: I tried the keyboard option that's on there because I was like, oh yeah, I'm totally going to be into this. This is going to be my jam. I don't think it is because I realized that I'm very biased. I like the sound of my own keyboard. So I had to shush the other one and just listen to the rain and the open window. But that's some of the fun things that are going on in my world today. What's new in your world? CHRIS: I'm just now spending a moment with the keyboard sound. It's a very muted keyboard. I want a little more clackety. STEPH: A little more clackety? CHRIS: I was assuming it would be too much clackety, and that would be the problem. But it sounds more mushy. Maybe we can pipe in some of the sound here [laughs] at this point. Or we can link to these sounds, and everyone can dial up the keyboards to 100. But I, too, am partial to the sounds of my own keyboard. But what's new in my world? This past week and I think probably even a little bit more of the prior week, I've been noticing that I've been struggling to actually do any coding, which has been interesting to observe. And again, trying to observe it, not necessarily judge it, although if that's not the thing that we want to be doing, then try and improve that. But mostly trying to observe what's going on, what is taking my time. A lot of it is product management type work. So I am spending a good amount of time trying to gather the different voices and understand what is the work to be done, and then shape that into the backlog and make sure that that's clear and ready for the team to pick up. And then, thankfully, the other two developers that are working on the project are fantastically prolific. So they're often very quickly working through the work that has been set up in front of them. And so I'm trying to then be proactive and respond to the code. But there's almost a cycle to it where I'm just staying out in front of them, but they're catching up with everything that's going on. So it's something that I'm trying again to be intentional about, name, share some of that back up with the group. If there are things that I'm doing that I don't uniquely need to be doing, then let's share as much of that knowledge as possible. But one thing that I will say is the product management, shaping the backlog work is exhausting. I am astonished by just how drained I am at the end of the day. And I'm like, I don't even really feel like I did anything. I didn't write any code, but I am just completely spent. And there really is something to when the work is clear, just doing the work, I can actually find energizing. And it's fun, and I can get in flow state. And sometimes, I'll be drained in a certain way. But the work of taking a bunch of different slack threads, and communications, and meetings, and synthesizing that down, and then determining what the work needs to look like moving forward, and providing enough clarity but then not over constraining and not providing too much clarity. And there are so many micro-decisions that are being made in there. And I'm just spent at the end of the day, and I have so much...I've always had a lot of respect for product managers and folks that are existing in that interstitial space and trying to make sense of the noise, especially of a growing company, but all the more so this week as I've been feeling some of that myself. STEPH: I totally agree. I have felt that having a strong product manager really makes or breaks a project for me where even though having technical leadership is really nice, I'd prefer someone that's really strong at the product knowledge and then helping direct where the product is headed. That is incredibly helpful. Like you mentioned, the work is exhausting. There's someone that joined the thoughtbot team fairly recently, and I was chatting with them about what type of projects they would be interested in working on. And one of their responses was, "I'd love to work on a project with a strong product manager because I have been doing that a fair amount for recent years. And I would love to get back to just focusing on coding." And so I think they enjoyed some of the work, but they just recognize it's exhausting. And I'd really like to just get back to writing code for a while. CHRIS: Yeah, I'm definitely in that space. And I think there's a ton of value to spending a little bit of time, like having any developer at some point in their career spend a little bit of time managing the backlog, and you will learn a bunch from that. But I'm also in the space of I would love to just turn on some music and code for a while. That sounds fun. There's a lot of work to be done right now. I'd love to just be in there doing the work. But sometimes, out of necessity, the defining of the work is the thing that's important. And so, I think I've been correctly assessing the most important thing. And that that has consistently for a while now been the defining and responding to the work that's in process as opposed to doing it myself. But, man, I really hope I get to dive back into the code sometime and use my clackety keyboard to its fullest extent. STEPH: Have you found any particular strategies that really help you with the product management work? CHRIS: I will say that I think this is a competency. This is a skillset and a career path that...again, I've been at plenty of organizations that I don't think respected the role as much as it should be. But it's an incredibly hard role and multidisciplinary communication at the core of it. And so I don't think I'm great at it is the thing that I'll say. So everything that follows is just to be clear; I'm not saying that I'm great at this, but I have been doing some of it. So here are some thoughts that I have. I think a lot of it is in reaction to where I felt like the work was clear. So I have a sense of what it looks like when I can go to the backlog, trust that it is in a roughly solid priority order, pick up a piece of work and immediately go to work on it. And understand what are the end-user implications of this piece of work? Where would I start on it like, how technically? What's a rough approach that I would have? And getting that level of specificity just right. So it's not overconstrained, but it's not under constrained. So having experienced that on the developer side, I try and then use that to shape some of the guidance that I'm putting into, say, the Trello tickets that I'm writing up here. We recently introduced Trello epics, which is I want to say like an add-on. And that allows us just the tiniest bit of product management, like one level up. So instead of just having cards and a list that is like, here's the work to be done, we now have an epics list that is separate to it, and it links between a card and its associated epics. So it's like project and action within that project. And just that little touch of structure there has been really, really useful to help look at like, okay, what are the big pieces that we're trying to move? And then how do they break down into the smaller pieces? So a tiny, tiny bit of fanciness in our product management tool, not Jira-like not going in that direction yet for as long as I cannot. But that little bit of structure. And then thinking about what has been useful to me as I pick up tickets. And then, as always, trying to just always be cognizant of what is the user's experience here? What problem am I trying to solve for them? What is their experience going to be? How will they know how to work with this feature? And just always asking that and then framing the work to be done in the context of that. STEPH: I like how you're adamant about a little bit of fanciness but not all the way to Jira-like. I also like how you highlighted end-users. All of that, I think, is awesome when developers are able to expand their role to experience all the other facets of building software. CHRIS: Yeah, definitely. I think that whole list of all of the different facets of where our work interacts with different groups. The more empathy or, the more experience that you can have there, the better that you'll be able to understand how to communicate there, how to express things in terms, et cetera, et cetera. So a huge fan of all of those ideas. I am ready to just get back in the code for a few minutes, though. But for now, for as long as necessary, I'll do some of this work. But I am trying to find my way to other things. In terms of actual feature work that we're working on, one of the things that we're doing right now is restructuring our onboarding. So when a user comes and signs up to the website and then subsequently has to fill out a handful of other forms, there's actually an external system that we've been working with that houses some of the core data of our application. And they have a hosted application form. So we can send the user over to them, and the user fills out the rest of the application on this other system's site. And then they get redirected back to us. And everything's got nice DNS entries for a particular subdomain and whatnot. So it looks roughly consistent. There's some branding. But it's still someone else's UI, essentially. And we were feeling enough pain from that experience. We were like; you know what? It's time. We're going to bring this back in-house. We're going to do all the forms ourselves. We're going to do a nice progressive little progress bar. You can see all the steps as you're going through onboarding. We're just going to own that more because that's a core part of the experience that we're building here. So biting the bullet, deciding to do that. But there's an interesting edge case that we run into, which is we are using Devise for authentication. Totally makes sense. We're in Rails context; there we go. It's the thing to use. But Devise exists in truly the Rails world. So like HTML ERB templates, the controllers have certain expectations as to what's going on. So thus far, we've just let that exist in that world and everything else we're building in Inertia and Svelte. But we're just now starting to feel enough of the pain, and that Devise exists in this other context. And for a while, we just kept saying, "You know what? It's not worth the effort to port it over. It's fine." Because we're using Tailwind, we have a consistent design language that we can use across them. That said, the components are drifting a little bit. And it's like, oh, this one's got a rounded corner like this, and that one's got this color. And we don't have the disabled style. But it is nice that it's not completely distinct. But we have finally decided it is time. We need to port this thing over because we feel like the onboarding and authentication type flows; they're actually a big part of the user experience or at least the first run user experience when someone's signing up to our site. So we want to own that a little bit more. One of the things that I ran into as I was trying to introduce Mailcheck, which is a library that I've talked about, I think in a previous episode...but basically, you can have it observe a field and if someone types in like, user@gmaip.com, you can like, did you mean gmail.com? And then go from there. And I think there's more subtlety. They can maybe even look up MX records and things like that. But basically validate an email address heuristically and offer the nice, very friendly to a user, "Hey, did you mean this instead?" So not a full validation that says, "No, you cannot put your email address," because maybe you have a weird one that sounds like Gmail but isn't. But that's a little bit trickier to implement both on the Devise side and then in any other place that we have an email input. And so what we want to do is port over to Inertia and Svelte, and then everything's in our nice, happy context with all our components and all the other work that we're doing. And it really does just highlight how much I've come to enjoy working with Inertia and Svelte. They are fantastic technologies. And now I just want absolutely everything to be in them. So we're finally going to bite the bullet, and I think port those over a little bit after we get the current batch of work done. But soon, soon, that's the goal. STEPH: I'm having a bit of déjà vu where I feel like there was a project that you were working on that was using Devise, and then removing Devise and replacing it with something else was a challenge. Does that ring a bell? CHRIS: Yes, that is accurate. So I had a project that I worked on where we had both Devise and Clearance was actually what was going on. There were basically two different applications that existed; one was using Clearance, the later one used Devise. But then we folded those two applications back together. And by virtue of that, I tried to unify the authentication schemes, and it was like, nope, not going to happen. And then we didn't. STEPH: And then we didn't. [laughs] I like that ending. CHRIS: Well, sometimes you don't. [laughs] STEPH: Yeah, I love that ending because it reflects reality. Sometimes that just happens. In fact, I'm going to segue for just a moment because you're reminding me that there's something I don't think I've shared with you yet. On my previous project, there was a particular feature. It was a big feature that someone had picked up and worked on. And at one point, we were essentially playing hot potato with this feature because we hadn't gotten it to the point that it was merged. There was too much that was happening in that pull request, although then we ended up merging it. But then we found lots of bugs. And it was just one of those features that we couldn't really get across the finish line. There was always something else that was wrong with it or needed to be done or needed to be considered. And we'd reach that point where Chad Pytel, who is on the project, was like, "We're either going to finish this, or we're going to throw it away." And I felt a little guilty saying this, and I was like, "I vote we throw it away. I have lots of concerns about this. We are essentially reimplementing another complex workflow. But now, we are implementing it pretty differently in another portion of the application. It's going to be hard to manage. The cost of adding this and maintaining this is a really high concern." And so he talked with the rest of the team and came back, and he's like, "Yep, we're going to throw it away." And so then he issued a PR, and we removed it. And it was one of those moments of like; this isn't great because then we have invested hours into this, and now we are taking it away. But it also felt really good that that's always an option. And that was the better option because it was either we're going to continue sinking more time into this, or we can stop it now. And then we can move on to more important work. CHRIS: Sunk costs and all that. STEPH: Yeah. I feel like it's so rare when that really happens because then we just feel dedicated to like, well, we're going to make this valuable to somebody. We're going to keep this. And in this case, we just threw it away. It's very nice. CHRIS: There's a similar anecdote that I remember. Actually, I think it's happened more than once. But very particularly, we were working on a system. And this was with our friend, Matt Sumner, a friend of the show, as well been on a few times. And Matt was working on the project. And we got to a point where we had two competing implementations of a given workflow, and we were opting to go with the new one. But there were folks that were saying, "Let's keep the code around for the old one." And Matt was like, "Absolutely not. If we do that, we might go...no, this will be bad. Then we have to maintain that code. We need to burn the ships," as he said. And he actually named the pull request burn the ships where he just removed all the code. And I was like, I like your style, man. You made a decision here. We collectively made a decision. And then this is a classic Matt Sumner move. But he did the thing that we said we were going to do. And he just held that line. And I really appreciated it. And it's a voice that I have in the back of my head often now, which is just like, no, burn the ships. If we need it, it'll be in Git history. We can recover it. But it's going to need to be handled in the interim. We don't want to have to support that code right now and for however long until we actually decide to remove it from the codebase. So let's get rid of it. And if we really need it, well, then we'll resurrect it, but for now, burn the ships. And I like that. STEPH: I like that too. I think it's one of those areas where it takes experience to feel that pain too. If you're pretty new to writing code, you're going to think, well, we can keep it around. There's no harm. And so it often has to be that sage, that person who's been around long enough and felt some pain from making that decision in prior centuries or years. And he's like, "No, we're not going to do this." The WE collective of developers who have experienced the pain from this understand that that's not a good choice. And so we're going to burn the ships instead. But it is one of those that if you're newer, you won't think that way. And I think that's totally reasonable that you wouldn't think that immediately. CHRIS: I think that tacit knowledge that oh, I've gone through this before, and I've experienced the pain, and now let me tell you about that. And let me try and share that with you because there's always the cost-benefit trade-off. Because if that code stays in the codebase, then we know it works because we've kept it around for that whole time. And so there's a nicety to that, but there's a cost, that maintenance cost. And being able to express that well and being able to say, "I've been here, and let me tell you a tale," but do it in a way that doesn't sound overly condescending or explainy or things like that. I think that's a very subtle skill and a very important one, and frankly, really hard one to get right. I'm not sure I always hit the mark on that where I'm just like, "No, can't do it. It's bad." I think it's very easy to end up in a space where you're just like, "No, it's bad." And they're like, "But why?" And you're like, "Because it's bad. Trust me." It's like, well, I feel like you do need to be able to explain the stories, the experiences that you've had in the past, the anecdotes that you've heard, the blog posts that you've read that have really informed your thinking. But I think that is a big part of what it means to continue on in this profession and be able to do the work and make those subtle trade-offs, and the it depends because, at the end of the day, it all depends. STEPH: Or you just issue a pull request and title it burn the ships. [laughs] CHRIS: Burn the ships. Indeed, that is, in fact an option. And actually, while we're on the topic of pull requests, this might be a perfect segue into a listener question that we have. Mid-roll Ad And now a quick break to hear from today's sponsor, Scout APM. Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more. Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform. See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed. CHRIS: As always, thanks to everyone who sends in listener questions. We so appreciate getting them. They help direct the conversation and give us something to chat about. So this question comes in from Bryan Robles. And Bryan writes in about large pull requests. And Bryan writes in with, "My toxic trait is large pull requests. Any tips on when you get into a place where you're fixing or refactoring something, and it ends up cascading to many more changes than you want it to? I sometimes can go back and break it up. But it's hard to recognize a good seam when you're in the thick of it." So, Steph, what do you think? Large pull requests and finding yourself in them after [laughs] certain amounts of time. STEPH: Yeah, speaking of that knowledge that often comes from experience, this is something that I'm certainly always striving to get better at. I think it does take practice. There are some things that I do that I can share. And I categorize them really into a before, and I guess midway. So there's the before I set sail and set off to deeper waters list that I will think through as I'm starting a new task, and then there's the I'm lost at sea. And then, I need to figure out how I'm going to organize this change. So in the first category, when I'm first starting off a task, I consider what sort of changes need to be made, and are there any obvious roadblocks? So an obvious roadblock may be changing or updating a model that has one relationship, and I need to change it to has many relationships. Or perhaps there's a part of the application that is untested. And before I make any changes, I need to document that existing behavior. And that really falls neatly within Kent Beck's advice where he said, "First make the change easy (warning: this might be hard) and then make the easy change." So I try to think upfront what are some of the small, incremental changes that I can make first that will then make the final change easy? And then I separate that mentally into PRs. Or I may separate it into tickets, whatever is going to help me stay organized and communicate how I'm breaking up that work. And then the other thing that I'll do is I'll consider what's my MVP? So what's my minimum viable pull request? What set of changes include just enough changes to be helpful to users or to other developers? Which, by the way, is also a helpful mindset to have when you're breaking down work into tickets. So, as an example, let's say that I need to fix some bad data that's causing a site to error. So my first step could be to write a task to fix the bad data. And then, step two, prevent bad data from being created. And then probably step three, I need to rerun the task to fix data that was created during step two. But I can think through each of those steps and separate them into different pull requests. And then there may also be the question of well, how small is too small? Like you're saying, what's a minimum viable pull request? How do I know if I am not delivering value? And that one gets a little trickier and vague. But ultimately, I will think, does it pass CI? Is this change deployable? And then I do have to define what value I'm delivering. And I think that's a common area that folks struggle because we'll think of delivering value as delivering a whole new feature or adding complete test coverage for an untested interface. But delivering value doesn't have to represent that end goal. It may be that you added one test for an untested interface. And that's still delivering really great value to your team, same for delivering a feature to a user. You may be able to speak with that wonderful product manager and find what's the smallest bit of value that you can deliver instead of the whole feature set? I think the smallest PR I can think of that I've issued is either fixing a typo or removing a focus metadata from an RSpec test. So that's my starting point. That's the before I set sail. Those are some of the things I think about. I have more for the I'm lost at sea. But what are your thoughts? CHRIS: First, that was a great summary that you gave. So I totally agree with everything that you just said. I think part of the question I would have...So Bryan wrote this in and described this as his toxic trait. So he's identifying this as something that seemingly consistently plagues him. So I would ask, is there a way that you can introduce something? Like, are there natural breaks in your day? And can you ask the question at those breaks? Like, hey, I've been working on a thing for a little while. Is there a version that I could...like, could I close off a body of work at this moment? When you break for lunch, if you go grab coffee in the morning, when you're leaving at the end of the day, use those natural breakpoints. I'm not sure exactly what you mean when you say large pull requests. But if those are spanning multiple days, in my mind, if anything starts to span more than a day, I will start to ask that question to myself. And that's a reflex that I built up over time by feeling the pain of large pull requests and putting it up, and feeling apologetic. And then having my colleagues gently, professionally kindly ask me to break it down into smaller pieces. And me saying, "I really don't want it. All right, fine, fine, fine, I'll do it." And then I do it. And it's one of those things that I never want to do in the first place, but I'm always happy to have done after the fact. But it is work. And so, if I can get better at pulling that thinking and pulling that question earlier in the process, that I think is really useful. Similarly, I will try to, again, as friendly as I can; if I notice someone mentioning the same body of work at stand up for a few days, I might gently ask, "Hey, is there a way that we can find a shippable version of a portion of that of a subset? Can we put it up behind a feature flag and get something out there just to try and keep the PR small, et cetera?" And so gently nudge in that direction. And then I think the other side of that is being very okay with one character PRs. Like, that's it. We changed one character. It turns out we need to pluralize that word, or we need one-line changes are great. That's fine. And more pull requests, in my mind, are better than fewer, larger pull requests. And so really embracing that and having that be part of the core conversation and demonstrating that throughout the team is a way to share this idea. So that's perhaps more in the process or person point of view on this as opposed to the technical, but that's part of the consideration that I would have. I am interested, and I'll bounce back to, Steph, what you were saying of now that you're out at sea, what do you do? STEPH: So I need to react positively to some of the things that you just said because you made me think of two things. One of them is I've never had someone say, "Hey, Steph, that PR is too small. Could you add some more changes to it? Could you do some more work?" I have had people say, "Hey, that PR was hard to review." But even then, sometimes getting that feedback from folks is hard because nobody really wants to say, "I had a hard time reviewing your PR." That's something that, over time, you may become really comfortable saying to someone. But I think initially, people don't want to say, "Hey, that was hard to review," or "There were a lot of changes in that. Would you break it down?" Because that's a lot of complex emotions and discussion to have there. But yeah, I just figured I'd share that I have never had someone complain that a PR is too small, and I've issued a single character change. And then I love, love how much you asked the question of what's the problem we're trying to solve? And so there's this ambiguous idea of a large PR. But what does that mean? What are the pain points? What are we actually looking to change about our behavior? And then how is that going to impact or benefit the team or benefit ourselves? And so, going back to the question of how do we measure this? How do I know I'm starting to break up my changes in a helpful way? We may need to circle back to that because I don't have answers to it. But I just really like asking that question. As for the I'm lost at sea part, or maybe you're not lost at sea, but you've caught too many fish, and the fish warden is going to fuss at you if you bring too many fish back to dock. I don't think this is a real nautical example. But here we are. CHRIS: Was that the fish warden? STEPH: Yeah, the fish warden. You know, the fish warden. [laughs] CHRIS: Sure, I do, yeah. Yeah, I know about that, well-versed in fish law. STEPH: [laughs] Got to know your fish law. If we're going to talk about pull requests, you got to introduce fish law. But I'm actually going to quote Joël Quenneville, a fellow thoughtboter, because they shared a thoughtful thread on Twitter that talks a lot about breaking up your changes and how to break up your pull requests and your commits. And I'll be sure to include a link in the show notes because it's really worth reading as there's a lot of knowledge in that thread. But one of the things that Joël says is get comfortable with Git, and it makes a world of difference. In particular, you want to get really good at git add --patch, git reset, and git rebase interactive. And that is so true for me. Once I have gotten really good at using those commands, then I feel like I can break up anything. Because often when I am helping someone break something up, it's often they want to, but they're like, "I don't know how. And this is going to take so much of my time. It doesn't feel efficient and the right thing to do." And they're probably right. If you don't know how to break it up, then it may take you too long. And maybe it's not worth it at that point. But if you can ask a friend, and they can help walk you through this process, or if you can learn on your own, that's going to be a game-changer because you will start to think about how can I separate these commits? And I can reorder them, and then issue separate PRs, or just keep them in separate commits, whatever process you're looking to improve. In fact, there's a really great course on Upcase called Mastering Git written by someone who is co-host of this podcast. And it has a lot of great videos and tutorials that will help you get really good at these Git commands and then will help you split up your commits. CHRIS: Oh yeah, I did do that. Warning: it's like three and a half hours long. But it is broken up into, I believe, 10 or 11 videos. So you can find just the ones that you want. There's a couple in the middle that I think are particularly useful talking about the object model of Git. Git is weird, unfortunately. And so I spent a bunch of time in that course. Also, thank you for the kind words, Steph. [laughs] But I spent a bunch of time in that course trying to make Git less weird or understandable. If you look under the hood, it starts to make more sense. But if you really want to get comfortable with manipulating Git history, which I think is a really useful skill for this conversation that we're having, that's the only way I found to do it, just memorizing the steps. It's always going to feel a little bit foreign. But once you understand the stuff under the hood, that's a really useful thing for being able to manipulate and tease apart a pull request and break it into different things, and port things from one branch to another, and all those fun activities. Yeah, man, that was a bunch of years ago too. I wonder what I look like in it. Huh. STEPH: I really liked that episode, the one you just mentioned, the Git Object Model. Now that you've mentioned it, I remember watching it, and it's very interesting. So yeah, thank you for making all this helpful content for folks. There's also a blog post that we can include in the show notes as well that is a really nice overview of using git interactive, and rebase, and squash and amend those types of behaviors as well. So will be sure to include both so folks can check those out. And then to round things out, one of the other things that I will do is I will ask a friend. I will ask someone for help. So we've talked about some of these behaviors, or some of these processes that we have are really built up from experience and practice. And you can watch a lot of helpful content, and you can read blog posts. But sometimes, it really just takes time to get good at it. I know, as I'd mentioned earlier, I am always still looking to improve this particular skill because I think it's so valuable. And one of the ways I do that is I will just phone a friend. And I'll say, "Hey, can we chat for a bit? I would like to show you my changes. I want to hear from you if you see something in here that's valuable that you think can be shipped independently, so that way we can get it delivered faster." Or it may be a change that's just like a test improvement or something. And we can go ahead and get that immediately released to the team, and it will benefit them. Or you may want to do this at the start of a ticket. If I am new to a project or when I am new to a project, I will often ask someone to break down a ticket with me if I'm feeling a little bit uncertain. Or just say, "Hey, do you see any clean lines of division here? I feel like there's a lot in this ticket. You're more familiar with the codebase. What would you ship? How would you ship this incrementally?" and have someone else walk through the process with you. CHRIS: Yep, the phone a friend and/or, as always, pairing is a wonderful tool in these sorts of situations. The one other thing that comes to mind for me is part of the question was about sometimes it's difficult to find a clear parting line within a larger body of work, within a larger change. And that can definitely be true. I think there are certain standouts of like is this a refactoring that can be shipped separately? Is this a test change that would be useful on its own? Is there a model change that we could break out and have just that go out? So there's a bunch of mechanical questions that we can ask and say; here's categories of things that might fit that bill. But to flip this to the other side, the question was asked by Bryan very much as an I struggle with this thing. This is my toxic trait is the phrase that he used, which I thought was really interesting. And that can be true. This can be something that if you're consistently and uniquely within the team producing these giant PRs and then folks find that difficult to review, then I think that is absolutely something to work on. But if this is something that is happening between members like, other members of the team are also finding that they keep ending up with PRs that are bigger than they expected and taking longer and harder to review, there is a question of is the codebase actually in a shape that makes it harder to do small changes? There's the phrase shotgun surgery, which refers to a codebase that is so entangled and coupled that any change requires modifying ten files just to make one small alteration. And I think that's a worthwhile question to step back and ask, actually, is it not me? Is it actually the codebase? It could be both certainly. But there is a version of your codebase is coupled in a way that means that any even small, tiny change requires touching so many different places in the code. And if that's true, that's at least worth naming and worth highlighting and maybe talking about in retro and saying, hey, this feels like it's true. So maybe we start to get intentional about refactoring, and breaking out, and starting to add those dividing lines within the code such that hopefully, down the road, small changes can, in fact, be small changes. So that is the one last thing that I would consider here. Also, anecdotally, this is just a thing that came to mind. As I've worked with strongly-typed languages, systems that have a compiler, and have a type system, and the ability for the compiler to keep an eye on the whole codebase, I've noticed that it's very easy to do this sort of thing where I just start with one small data model change, and then the compiler is like, oh, you got to go fix it here, and here, and here, and here. And I found that because the compiler is your friend and will just point you to all the places you need to make the change, it is very easy to just keep going because some of that mechanical work is happening on your behalf. And it's a wonderful facet of typed languages and of having a compiler and being able to have that conversation with the compiler. But I found that for me, it is much easier to end up in this mode where I'm like, oh no, this PR is way too large. When I'm working in a system that has types, that has a compiler, that frankly makes it a little bit easier to chase down all the places you need to make a change. So that's also a consideration. It's not necessarily a good or a bad thing, just something that I've observed that feels like it's adjacent to this conversation. But yeah, I think those are my thoughts. STEPH: Yeah, those are great points. I've certainly worked on projects where that felt very true where it's a small change, but it would cascade throughout the project. And all the changes were necessary. It wasn't something that I could split into smaller PRs. So checking if it is the codebase that's really making it hard to have small PRS is a really great idea. CHRIS: Who'd have thunk such a little question could get us rambling for so long? Oh, wait, I would have thunk that. STEPH: And so far, reflecting on the things that we've talked about so far, I think I've talked a good game of where I'm saying, "Oh, I identify the seams upfront, and then I organize and create different tickets." And that is very much not the case. That's the really ideal outcome. But often, I am in the thick of things where like you just said...and it's this moment of, oh, I've done a lot in this PR. And how can I break this up? And that does take time. And it becomes a conversation of trade-off, which is why those Git skills really come in handy because then it will lower the cost of then splitting things out for others. But for people that are struggling with creating smaller PRs, I do think it's very fair to ask your team for help. I think it's also fair that if you issued a large pull request and folks have already reviewed it, and it's gotten approved, and someone makes a comment like, "Oh, this would be great as two PRs instead of one," to say, "Awesome, thank you for letting me know. I will take that forward with me, but I'm not going to do it for this PR." I wouldn't recommend making that a habit. But just know that that is something that you can say to someone to say, "I think this one is good to go at this point. But I will keep that in mind for future PRs. And I may even reach out to you for help if I feel like I'm having trouble splitting up a PR." And bring that person into your progress and use them as an accountability buddy. They can be someone that helps you down that path towards smaller PRs. CHRIS: Yeah, I definitely agree with that, although it becomes a very subtle line. Saying, "Thank you, but no thank you," in a pull request or to feedback is delicate. It's difficult. That's a whole thing. But I agree there have been times where I have either been the one making that decision or suggesting that or being like, "We probably should have broken this up. But we're far enough along now. Let's get this merged. And then we'll iterate on it after the fact." One last thing, actually. I thought I was done, but I have one more thing, which is I feel like there's a strong parallel between test-driven development and this question in that, often, I hear folks saying, "I don't know how to write tests upfront. I don't know how to do that. I know after the fact I can write tests, and I can add them after." And that can definitely be true. It can become more obvious after you've written the code how you could then write a test that would constrain that behavior that would interact with the system. But I think the useful thing that you can do there is take a moment and pause there and say, "Okay, now that I have written the test, what would it look like if I had written this in the first place?" Or if you really want to go for it, throw away the code, try again. Start with the test first and then rebuild it. That's maybe a little much. But that thing of taking these moments of maybe you don't know upfront how to break the work into smaller pieces, but then you get to the end, and you have that conversation with someone. And they highlight where some parting lines would be, or you figure it out after the fact. Stay there in that moment. Meditate on it a bit and try and internalize that knowledge because that's how moving forward, you might know how to do this in the future. So take those moments, whether it be with TDD or with pull requests, or breaking up a ticket into smaller tickets, anything like that. And spend a moment there and try and internalize that knowledge so that you have it proactively moving forward. STEPH: You know how Slack has status? I really like the idea of there being a status that's meditating on...and you can fill it in. And the example that you just provided, meditating on splitting up a pull request or meditating on how to write a test first, [laughs] I think that would be delightful. CHRIS: I, too, think that would be delightful. But with that long, adventurous answer to what seemed like a simple question, and they always do, but here we are, shall we wrap up? STEPH: Let's wrap up. CHRIS: The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes, as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Byeeeeeeeeeee! Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.
On this episode, Chris talks about testing external services and dissects a tweet on refinements for Result. Steph talks about thoughbot's recent improvement to their feature flag system. Links: refinements For Result (https://twitter.com/alassek/status/1430683412264857600) Faking External Services in Tests with Adapters by German Velasco (https://thoughtbot.com/blog/faking-external-services-in-tests-with-adapters) Testing Interaction with 3rd-party APIs (https://thoughtbot.com/upcase/videos/testing-interaction-with-3rd-party-apis) Transcript: CHRIS: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey. STEPH: And I'm Steph Viccari. CHRIS: And together, we're here to share a bit of what we've learned along the way. So, Steph, what's new with you? STEPH: Hey, Chris. Well, today is Summit Day at thoughtbot, and it's the day where all the bots gather, and we hang out, and we chat, and we play games. And it's a lot of fun. We're actually taking more of a respite this year just because life has been taxing. And so we decided to give people more of the day off. So we still had some fun events, but most of it is everybody gets a chill day. Do something that brings you joy is the theme of the day. But we had Lightning Talks, which is my favorite thing that we do on Summit Day because I realize that I just work with the coolest people, and they have such interesting things to talk about. And we had such a variety of topics. So one of them, Alex Chen taught us acronyms in K-pop. And Sam Kapila, our resident foodie, taught us about a variety of spices. And one of my favorite talks was by Akshith Yellapragada, and it's the top 10 best limo entrances by The Bachelor, and it was phenomenal. And I really want to share some stuff that I learned with you. CHRIS: The Bachelor like the TV show? STEPH: Yeah, like the TV show. Are you familiar with it? Have you seen it before? CHRIS: I am familiar with it. I know it exists. I know that there's a spinoff, The Bachelorette. And I believe we have now exhausted my information on the matter. STEPH: [laughs] That's fair. For anyone that hasn't seen the show, the show revolves around a single person. For the bachelor, it's a single bachelor who dates a number of people over several weeks, and then they narrow down the people. There are elimination rounds, and the whole goal is for them to find their true love. So each week, someone is eliminated, and I think the show ends with a marriage proposal. So it's a wild show. It's something. [chuckles] And in Akshith's talk, I learned some really fun terminology. The first one is the Crown, and this is actually an important building block because we're going to get to the rest of the terminology that uses this word, so we got to start here. So the first one is the Crown, and this is the person that everyone's competing for. So they're the star of the show. They're the one that everybody is hoping to fall in love with or will fall in love with them so they get a marriage proposal. So then the other stuff that I've learned is all about the entrance because again, we're talking about the top 10 best entrances. And one of them is the sidecar entrance. So this is where the player, because yes, this is totally a game, has someone assist them in meeting the crown. So it could be like a family member, maybe it's like your grandma. And then there's TOT, T-O-T, which is short for Trick Or Treat. And this person exits the limo wearing a costume. So it's someone wearing a shark costume. There was someone wearing a sloth costume where they really dedicated to the role, and they climbed a tree and hung from a branch. I don't know for how long but for long enough to really vibe with the role. And then there's the Kringle, and this person brings a prop or a present to the Crown. And there's the Grandy, and this player arrives in something other than a limo. So the example that Akshith provided is someone arrived in a motorized cupcake. CHRIS: Was the cupcake edible? STEPH: I don't think so, fair question. [laughs] CHRIS: So really just like a go-kart that looked like a cupcake, not really a motorized cupcake, if I'm going to meet pedantic about the thing, [chuckles] which I think is my job. STEPH: Yes, it is a motorized non-edible cupcake, but that seems like something a next player should do. They should really up the game, and they should bring an edible motorized cupcake. CHRIS: Yeah, because you get the visual novelty, but then you layer on top of it that it's actually something that you can now eat, and it's a double win. STEPH: Ooh, and then you're a Grandy, and you're a Kringle because you arrived in something other than a limo, and it's a present. CHRIS: I love how you have so deeply internalized this now that you're like, ooh, okay. I can remix here. I'm going to bring together the pieces. Yeah, all right. Yeah, this all makes sense. STEPH: Yeah, it was a lot of fun. Those are most of my notes for today. I have some tech stuff too, but this felt like the most important thing to start the show with. CHRIS: We use the phrase tech talk and nonsense to describe the show often, but I think nonsense and tech talk is the correct orientation. STEPH: [chuckles] CHRIS: Correct in terms of importance and chronological order, and whatnot. But yeah. STEPH: I love that we start with a bit of nonsense. So I do have some tech stuff. But first, before I share any of that, what's going on in your world? CHRIS: I'm sure there's plenty of nonsense in my world, but at the top of my list is some tech stuff. So someone on Twitter, Adam Lassek, reached out and he suggested related to the conversation and the back and forth that I've been having with myself around some of the data structures within the app that I'm building…So I've talked about the dry-monads result object, and there's this success and failure. And I wanted to introduce this new method called bimap, but I wanted to do it in a reasonable way. So I wrapped, and then I wrapped, and I wrapped things. As an aside, former colleague and friend of the show, Joel Oliveira, sent a wonderful tweet which was a reference to the SNL video where they make a taco and put it inside of a pizza and put it inside of a bag. And that was his joke about it, which I really liked. That was an excellent reference. But in this case, Adam Lassek reached out and suggested if I'm that squeamish about monkey patching, which I am, have I considered refinements? And so he sent an image of a code sample, which is so kind of him to send that much detail over, but it was interesting because I know of refinements in Ruby. I know of that as an alternative to monkey patching, a more refined way, but a safer way, a more controlled way to alter code, but I've not actually used them. STEPH: I'm not familiar with refinements. What is that? CHRIS: Refinements are a way...so similar to monkey patching, where you say like, I'm going to reopen this class or this module and define a new method or redefine a method or do something like that, a refinement is a way to do that in a scoped manner. So I'll be honest, I'm not super familiar with them. I think I came into Ruby at a time where the community was moving away from monkey patching. And the dogmatic swing of the pendulum was like, that's a bad thing to do. And so even the refinements were introduced, as far as I understand it, to be a more controlled way to do it. So it's not just like, hey, cool. This module is redefined now in your app in a magical way that's really hard to figure out and hard for folks to debug refinements. You have to explicitly opt into within a certain lexical scope. I'll be honest; I know that at the headline level. I don't actually know the ramifications or where and when you can use them and how you can. But I know that that was the idea is refinements are a way to do monkey patching but in a more controlled, more understandable manner, and so the code sample that Adam shared does that. And it's very interesting. As I'm looking at it, I'm like, okay, that's cool because I think it'll be a little bit safer. But at the end of the day, my concern wasn't safety in this case because I was introducing a method that would be new, that would be additive to the API of this module that I'm working with, and so that I think of as a relatively safe operation. My hesitation was more around how does someone figure it out if they're working with this? And particularly, the name of the method that I was introducing was bimap so, B-I-M-A-P. And if someone sees that in our codebase and is like, "Bimap, where is this coming from?" Well, this is one of those dry-monad result objects. And they go to the code, and they try and look it up in the docs, and they're just not going to find anything. And I can imagine losing a lot of time to try and chase that down. There are ways to figure it out. There's the method in Ruby, which is a wonderful trick for chasing things down. Or if you grep the codebase, you'd find it. But I think I'm possibly over-indexed on worrying about that lost time, that moment. But I've lost that time so many times in my life where I'm like, I can't grep for this. I can't Google for this. And so I have so strongly moved in the direction of being like, everything should be grepable, everything should be googleable. Those are the two of the things that I believe about software. I think I believe a bunch of stuff. STEPH: I think we have a full episode that talks about what we believe in software. CHRIS: I believe we do. STEPH: Cool. Thanks. Yeah, I have not heard of refinements. That sounds really interesting. I really like that bit about everything should be grepable, and everything should be googleable, googling everything. I kind of agree with that one. We live in a world where we're always doing bespoke things so that one feels a little bit harder that we're always going to be able to Google it. But then that encourages people to constantly publish the bespoke work that they're doing so then others can benefit from that work. But the grepable, I absolutely agree with that one. It's so frustrating where I see a method, but I cannot find its definition. And then having the ways to figure out where that method is defined to then find its definition is crucial. CHRIS: Yeah, it's interesting. I definitely feel that way very strongly. And it's in such stark contrast to Rails. Rails is like, hey, don't worry. There's going to be a lot of methods. You don't need to worry about where they come from, or why they exist, or what they are, or what they do. Well, probably what they do. But all of the magic inflections on database tables,, and suddenly you have methods named after every column. That's both very magical and hard to grep for or impossible to grep for, but it also leaks the entire structure of your database into your application in a way that I've always felt a little bit complicated about. And so explicitness, grepability, those are things that I care about. There's another one, delegates in Rails, that I sometimes pause around using especially when it's like delegates 19 methods to user prefix user. And so you end up with methods that are like username. And that's a delegation to the user object to get the name method off of it, but it creates the method user_name. And you're never going to be able to grep for that. And it saves like a little bit of code, definitely, but it saves this very obvious, very knowable code. So this one I actually shy away from using delegates in most cases, and I'll just write out the methods manually because sometimes I like to hear the clackety of my keyboard. There's a reason I have a clackety keyboard. STEPH: You want to get your money's worth. You want to clackety as much as possible. Yeah, I'm also not a fan of delegates. This may be a lie, but I don't know that I've actually ever used it. I've worked with it, but I can't think of a time that I've implemented delegates. Maybe that's a lie, but I'm going to say it anyways because that feels true, at least in the last couple of years. CHRIS: I feel like that could be true for the last couple of years. I would be surprised if you have never even added to a delegates line. Because that's the thing, you can just keep shoveling stuff into them as well. So I would put money on you having used it at some point and then just forgotten about it. But who knows, maybe not. STEPH: This is where we play two truths and a lie and that one's my lie. [laughs] Yeah, that's also fair about adding to it because if that's already defined and it's easier to add to it, I don't know. Who knows what past Stephanie has done, probably some wild stuff. CHRIS: It's unknowable at this point. It's lost to the sands of time. But looping back to the core thing of this refinement and the module, I think I'm leaning in the direction of doing that and unwinding my wrapping and wrapping layer thing. Because obviously, as I talked about...I think it was the previous episode or maybe two episodes ago. There was conceptual complexity to the additional wrapping layer. Even as I was fully in the context of working on that, I was still getting myself confused in either triple wrapping or then unwrapping too much or whatever. And these are the concerns with this type of code. So moving away from that feels better, having just a single layer of context wrapping around a given value. And then the other thing it's actually just a lot less code, and it's less prone to error, I think. That's my hope. I have to look into exactly how refinements get used, but I noticed in a couple of places that sometimes we were wrapping with this local value object that gave us the bimap method, and sometimes we were forgetting to. And so, I could see that being a very subtle, easy way to introduce failures into the app that would be hard to catch just by looking at it. So I think having a more global refinement...although I think that's sort of a contradiction, a global refinement because I think refinements are meant to be local. But anyway, I'm going to look into it because it's a much more concise code sample than what I have. Yeah, I'm going to poke at that a little bit. But it was an interesting exploration of some different things. And then it forced me to consider why am I so resistant to monkey patching at this point, especially in this particular case where I think it's okay-ish? STEPH: That's a good question. Do you have any insights? I am also resistant to monkey patching. I feel that pain and also that timidness of diving into that space. But I'm curious, have you figured out any other reasons that you really prefer to avoid it? CHRIS: I think this one falls into that sort of...what's the word? Like tribal knowledge of we've been burned by it in the past and therefore we build almost a...religious is too strong of a word but that sort of cultural belief. This is a thing that we do not do because of the bad things that we've experienced in the past. And there are a lot of things that fall into that experiential negative space. So with monkey patching, things that I know we can run into is if I introduced this bimap method, but I introduce it subtly differently than the library will eventually, then they could eventually introduce it themselves. And suddenly, I have this fork of my code expects it to work this way, but you've now implemented it that way. I no longer can upgrade. This is a critical piece of infrastructure in my app. I've just painted myself into a corner by doing this. Whereas if I do this wrapping layer, that's my code. I own that. It's not going to be a problem in that same way. There's also the subtlety, the grepability that sort of thing is a concern in my mind. Like, is this our code? Is this their code? Is this an engine? Being able to find code within a codebase, I think, is a critical thing. And so that's a part of the hesitation. I also know longer ago prototypes...I want to say Prototype JS was the name of the project, but it was one that was just like, yeah, JavaScript doesn't have enough stuff in the standard library. So we're just going to override everything and add all of these wonderful methods sort of in the way that Active Support does, which is an interesting comparison. But the JavaScript community definitely moved away from Prototype. And now JavaScript is a language or the standard runtime that's available in most JavaScript engines. It has a lot of the methods, but there are conflicts, and stuff gets weird, and it's all complicated. But again, as I thought of it, Active Support is a complete contradiction to everything I'm saying. Active Support just adds whatever to anything, 2.days.ago. Why does the number 2 have a days method? Because it's great, that's why. But I'm just a walking contradiction, I guess. STEPH: Everything you said really resonates with me. And I'm just trying to reason with myself like yes, Active Support uses a lot of this, a lot of metaprogramming, and adds everything it wants to. So why does that feel okay? And I wonder if it comes down to one is more almost like an agreed standard. It's built by a team, and it's maintained by a team, and then it's used by a large number of people, and then you get that feedback. Or maybe it's not even just a team, but it's a larger community versus if it's internal to your software team, maybe that doesn't feel like a big enough group or if it just needs...Rails is also documented. So maybe that's part of it, too, is if you are going to dive into that space, it's easy to discover, and it's well-documented as if you are building an open-source project that other people are going to use. Like, you designed for the intent of people to use this pattern that you've introduced, then perhaps that's when it starts to feel okay. , But the experiences I have had is where people basically will add some dynamic programming or monkey patch an existing feature. And then that's very hard to find and has surprising results, or it gets outdated. So I guess it comes down to who are you designing for? Are you designing for more of an open-source community, or you're at least designing for the people behind you that are going to be using this? Or is this a one-off adventure that you have chosen for yourself and future developers to discover? [chuckles] CHRIS: Yeah, I think that's a good summary, although I'm open to the fact that I exist in a state of contradiction. I'm also fine with that, to be clear. [chuckles] But I think what you said is true, and I think there is subtlety and nuance and reasons that it's okay in one context and less okay in others. And that idea of just like, I don't know, this is one of those things that I got in my head that I've done the thinking a long time ago to decide this is a thing I don't do. So now, in order to override that, I would have to do so much thinking. I would have to be like, all right, well, my brain tells me, no, but I'm going to go reread everything about monkey patching right now to convince myself that it's okay or to fully get the context and the subtlety and the nuance. And so sometimes we have to rely on that heuristic knowledge of monkey patching, nope, don't do that. That's not a thing, but other stuff is fine. And well, Active Support is fine because it's Rails. But it is interesting to observe contradictions and be like, huh, look at me go. All right. Well, moving on. STEPH: It's our lizard brain that's saying, "Hey, there's danger here." [laughs] CHRIS: Exactly. STEPH: I rather like living in a world of contradictions, or at least I find it that I'm drawn to them. And maybe that's also one of the things that I really like about consulting is because then I join all these different teams, and I hear all these different opinions. So as I'm forming these opinions around something like tests are great, I really like tests, and then someone's like, "I really hate tests." I'm like, "Cool. Let's talk. I want to understand why you don't like this thing that I think is wonderful because then I'm really interested." So I find that I'm often really drawn to contradictions as I like hearing opinions that are very different than mine and finding out why people have a different opinion than mine. CHRIS: Yeah, the world is full of contradictions. So it's, I think, at least a useful way to exist in the world, to be open to them and to enjoy exploring them. But yeah, I'll update in future weeks if I do end up going the refinements route. I'll let you know if anything interesting falls out of that. And now we're going to take a quick break to tell you about today's sponsor, Orbit. Orbit is mission control for community builders. Orbit offers data analytics, reporting, and insights across all the places your community exists in a single location. Orbit's origins are in the open-source and developer relations communities. And that continues today with an active open source culture in an accessible and documented API. With thousands of communities currently relying on Orbit, they are rapidly growing their engineering team. The company is entirely remote-first with team members around the world. You can work from home, from an Orbit outpost in San Francisco or Paris, or find yourself a coworking spot in your city The tech stack of the main orbit app is Ruby on Rails with JavaScript on the front end. If you're looking for your next role with an empathetic product-driven team that prides itself on work-life balance, professional development, and giving back to the larger community, then consider checking out the Orbit careers page for more information. Bonus points if working in a Ruby codebase with a Ruby-oriented team gives you a lot of joy. Find out more at orbit.love/weloveruby. STEPH: So we made a recent improvement to our feature flag system, which I'm really excited about, that we have found a way to improve that workflow because it felt really great that we're...well, okay, I should say that with a caveat. It felt really great that we're using feature flags to ensure that the main branch is always in a deployable state. But it did not feel great around how tedious it was becoming to add all of the feature flags specifically because each time we're adding a feature flag, we're having to add a migration. So we're having to run a migration, add the feature flag column, and then we can interact with that feature flag. And that part's okay. It was more removing that feature flag once we're done with it, that that part was starting to feel tedious because then that's becoming a two-deploy process. So one change is to remove the code that's relying on that feature flag. And then the second deploy was to actually drop that column because we wanted it to be safe to make sure that the code wasn't trying to reference a database column that didn't exist anymore, which is what happened at one point at first when we weren't doing the two-deploy process. So the improvement that Chris White came up with is where we're now using a Postgres JSONB column. And it's here that we actually have a feature flag YAML file. And we can have the name of the feature flag. We have a description of the purpose of the feature flag. And we have an enabled property on there, so then we can turn it on and off. The benefit of this is now we don't have to do that two-deploy process. And we also don't have to run a migration for when we're adding a new feature flag. So we can add it to the feature flag file, we can load it in, and then we can set that property to say, "Yes, this is enabled," or "No, it's not." And that has just simplified our feature flag process. One tricky bit that I believe the team ran into is around enabling this with Active Admin because Active Admin was just relying on those database columns to then turn something on or off. But then we've added some methods that work well with Active Admin that then say, "Read from here when you're checking to see if something is enabled," or "Look at this list to see which feature flags can be turned on and off." So it's been a really nice improvement, and everybody on the team seems to be in favor of the ways that we've improved this. So it's been really nice. So I wanted to come back and bring an update on how we've simplified our feature flag system. CHRIS: That definitely sounds like a nice improvement, the ability to just more regularly iterate around that or taking away the pain, any pain associated with using feature flags. Because they are such a nice thing to have, but there's that overhead. Then you start to have that voice in your head that's like, do I really need a feature flag for this? Could I just sneak this one in? And we always regret that. I had a similar thing this week where I wrote some code. I didn't quite write as many tests as I should have. And it was wildly broken, just like all of the connection points through everything were broken. But then it pushed me in an interesting direction where I was like, well, what I'm going to do is write an integrated test. It was basically an event coming in from a webhook that then enqueued a job, which did a thing, which then spit out an email. But it was broken at like three layers, and I was very embarrassed, if we're being honest. But, I don't know, I was just having a low energy afternoon, and I did not write the test, which I know I'm supposed to do. So similarly, any pain that we can take out of these things that we're supposed to do, any way that we can pave the happy path, I'm all about those. I'm intrigued because I think we've talked about this before, but it sounds like you guys have a very home-grown feature flag system. Is that true? STEPH: We do. CHRIS: Is there something about it that makes it unique to your situation, or was it just like that's what happened? Someone early on was like, "We need feature flags. I can just do the simplest thing that works," and then that's where you're at now or? STEPH: You're asking a very good question. And I'm trying to recall what led us to the state that we're in because I feel like we had this same discussion several episodes back when we were introducing the home-grown feature flag system. And I was like, there are reasons, but I didn't really dive into those reasons because it felt very custom to the application. But now I've forgotten what those reasons were. So I think you ask a great question where it'd be worth revisiting to confirm that yes, there's a reason for this home-grown version versus using something like Flipper. CHRIS: I'm glad I'm at least consistent over time in the questions that I ask and the heuristics that I have. This does feel like one of those things. It's not quite like crypto where I'd be like, we can never write our own crypto. But a feature flag system, I would be really intrigued if there are things that they are just workflows or functionality that you really need that are not supported by any of the existing solutions that are out there. I think audit trails is an interesting one. I think Flipper has a hosted product at this point that does that, but the local version wouldn't necessarily. So maybe that's a thing that you want to get. Again, I'd just be really interested. It sounds like the current state of the world that you have is enabled or disabled; just broadly, that's it. Those are the two states for any given flag. Is that true? STEPH: It is. There's nothing complex with the flags in that nature. And then we use naming to indicate if something is more for beta, so if it's a change that we're making to the codebase, but it's a feature flag that we plan on removing, versus maybe it's a feature flag for enterprise customers. CHRIS: Oh, interesting. I wouldn't think of using a feature flag in that context where it's going to be like a persistent, long-lived; this is conditional logic around some state or some property of the viewer. I think of feature flags as a way to gate code conditionally based on a point in time. And the reason I asked about the enabled-disabled basically like the Boolean state for your flags is when I've worked with feature flags in the past, I've liked having the ability to say, for this user or these users, or this group of users, which we've named this is our beta list…and it's the ten people that just really love the product and are happy to bump into some rough edges. And so we'll put things on for them first or even like percentages, so roll it out to 10% and then 50% and so on. And I think the larger an application and user base gets, the more that sort of thing starts to feel right. STEPH: Yeah, we certainly have some complexity around where each customer can really specify which features that they want. And then the features also differ a bit for each customer. So we are in a world where we're pretty customized or configurable for different customers. And whether that's something that we could simplify, that would certainly be a good question or something to pursue. But part of this also feels like our decision may have been based around what the system was already doing, and we're looking for ways to make slow improvements versus trying to redesign the whole thing. Because initially, the way we were customizing all of these different features for customers was in a YAML file. And that part was painful because then, anytime we wanted to make a change, it required a deploy. So the introduction of feature flags is really to get away from having to deploy to then make a small change like that. But now that we're in the space that we can easily configure that change and do that on the fly and not have to issue a deploy, I think we're now in a good space to reassess. And the team may have some really good answers. Perhaps I'm just not recalling as to why we've chosen the more home-grown feature flags. But yeah, I'll visit that topic and report back. Because I've been coasting along on our new system and enjoying it, but you're asking some really good questions. CHRIS: I mean, as an aside, if you're coasting along and really enjoying it, then maybe you don't need to ask any questions. It's still interesting. I would be intrigued to know. But if it's not causing you any pain, then you probably shouldn't change it. Because frankly, changing out the feature flag system is going to be non-trivial, I'm pretty sure. You could feature flag the feature flag system, and then you can transition from one to the other. You need a third feature flag system for that. But anyway, I digress. [chuckles] STEPH: You referenced crypto earlier. So I think I like the feature flag, the feature flag system. We should have some crypto flags in there somewhere. I think that's a thing too. But I think the main goal if I'm looking into changing it would be, circling back to what we were talking about earlier, is discoverability, so having a home-grown feature flag system. How easy is it for…if nobody was around on the team and there was someone new working with it, how easy would it be for them to turn something on or off? And if that's easy, then that's great. Then I think we've got a great home-grown system. If that's challenging, then I definitely think it's worth reassessing. And now a quick break to hear from today's sponsor, Scout APM. Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more. Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform. See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed. CHRIS: One of the things that's been interesting working lately in the app that I'm building is thinking about testing. We have a number of interactions with third-party services. Frankly, a lot of the app is that at this point. We have a handful of different external data providers systems that we're interacting with, webhooks and flows and things like that. And so we had to make that decision that you always have to make in these sorts of situations which is, how are we going to test this? And there's a wonderful blog post on the thoughtbot blog called Faking External Services in Tests with Adapters. It's by the one and only German Velasco. And it is a beautiful summary of the different approaches that you can take, but it really dials into one, which is the adapter pattern. There's also a weekly iteration episode on Upcase with Joël Quenneville, which discusses a little bit more of an exploration of the different options. There are sort of a handful of different options that we can consider your whereas the blog post by German talks specifically about the adapters approach. But to talk about them briefly, there's one where you can go all the way outside your app, spin up a fake service. Typically, we would do this with Capybara Discoball, which is a wonderfully named project. But it allows you to spin up a little Sinatra app type thing such that your web application is still making quote, unquote "real HTTP requests." This external service is going to catch that and respond with whatever canned data or structured responses that you want. But you still have the ability in that to, say, tell it to create data beforehand or be in a certain state or respond with certain data or have any stateful persistence. So if you create a record in that external system, and then later you query for it, that system can do that. But it has the complexities of now, your test suite is running different systems. And do you have thread-safety or all that kind of stuff? So that's a particularly complex end of the spectrum. At the lowest end would be stubbing and mocking. You just take whatever external clients you have, and you're mocking the API calls in them. That's the lowest end. And that's the one, especially for feature specs, those I try and avoid. Then there's a middle ground of like WebMock or VCR, those sort of things where you're saying whenever you see an HTTP request that looks like this, respond in this way. You record the cassettes, all that kind of stuff. And then there's the one that we've settled on, which is the adapters. So the client that we've introduced in our local codebase to interact with any of these third-party systems internally has a class attribute, a cattr_accessor in the Rails parlance, I believe. And that allows us to switch out the backend. And so we have a real HTTP backend, and that's the one that actually runs in production and a test in-memory backend. And that in-memory backend can implement whatever logic. We're ending up with one of them almost recreating this external service, sort of re-coding some of their inconsistencies or oddities but also features and whatnot. But it feels like it has struck just the right balance, and it allows our feature specs to be very rich, very real. We start up the world, and we say, "Hey, external service be in this state." And then I'm going to go visit the page. I'm going to see the data. But we are almost making real HTTP requests. It's very close. It's always an interesting choice to make here. I'm very happy with the one that we've made, but it's still not perfect. There are always going to be trade-offs between the different options here. But it's always interesting revisiting this and being like, which one am I going to choose today? STEPH: I feel like my natural progression when testing external services; I always start with WebMock, and then I progress to using adapters. And then from there, I go to actually replacing the HTTP service that is receiving and then returning a response, like you mentioned to Capybara Discoball earlier. So I can certainly see what you like about the adapter pattern. You mentioned that you're coding some of the inconsistencies. That feels very real. I'm curious if you have an example of how you've had to manage that recently. CHRIS: A specific example would be the external API responds with certain error codes or error structures. So it's an error. It has a status of a number and then a reason, or sometimes instead of a key that is reason; it's the message. So it's like, oh, okay, I see that in this endpoint, you respond with reason, and then this endpoint you respond with message. So now, do I encode that into my fake? I guess I do. So my adapter now implements things like that. There are cases where it's inconsistency where I'm like, well, this is the way they behave. So I would like our test suite to exist in the context of that because then our app is getting exercise in a real way. But in some cases, it's like little bits of logic validation that an external system might do if that's an important part of the flow. The app that we're building has a lot of forms and a lot of data validation and things like that. And so, we want to make sure that we have robust handling around that robust messaging to the user so that it's very clear what they need to do and how they need to respond to things. And so putting in little bits of that like, oh, that's how you format a phone number, okay, cool. Our fake will also format phone numbers in that way, things like that. STEPH: Every time the topic of testing external services comes up, I really, really want VCR to be the answer. I really like the idea of being able to validate that...because you'd mentioned that we're programming the expected return from this other service. And it's very easy to get out of sync with those actual responses. And then we don't really have a great way to stay up to date other than we wait for production or staging environment to fail. And then we realize something has changed, and we have to go and update either our mock or our adapter. And maybe that doesn't happen often if you're working with an external service that is very good about broadcasting when they have a breaking change. But if you're working with a less stable endpoint, then I always want VCR to really work. But it's just one of those areas where I'm like, yes, that's the thing that I want. I want this idea where I can rerun my tests in a way that they actually hit that service and record the response. But then I have felt pain [chuckles] from working with VCR and how it's configured, and how people have used it. It's one of those where I don't blame the library. I like the library. But the way people have implemented it and test I have felt a lot of pain from that. CHRIS: Yeah, I definitely agree with that. It feels like it's nice if you can push the mocking all the way out to that layer. Because like right now, our codebase has code in it that is subtly changing the behavior for a test, and I don't like that. It's only the swapping out of the adapter, so it's a very minimal thing. And we try and push all logic away from that such that the test adapter is as similar as possible to the real production situation. But it's enough difference that I agree I would like if VCR would just like, I catch the HTTP requests, and I respond with the same thing and sometimes we can pass through. I do think one of the fundamental limitations, or at least very hard to get right things, would be sequential requests. So I post to this endpoint in the external service, which creates some data. And then later, when I make a GET request to their endpoint, I should get back that data that I just created. That's, I guess, doable because you can have sequential requests, have cassettes that are first this request, then that request, then that request. And it knows that, like scope them to a given spec. But that feels extra difficult. And it does, again to your comment, the maintainers of that project do a wonderful job, but it's a really hard target to hit. STEPH: Well, and one of the other hard requirements with using a tool like VCR is then that external service really needs that sandbox staging environment that you can use. So that way you can create this data, you can rerun your test. So they're actually going to hit this real environment. They're going to create this data and that not have any harmful effects. And then you can record fetching that data. So it requires a lot of pieces to fall into place for it to work well. But then I was just thinking as you're talking about adapters, I'm like, yeah, I love the adapter pattern. I've really enjoyed that one for testing as well. But then I immediately start to think, oh, well, what happens when it gets out of sync, and how do we know that it got out of sync? And I don't have a great answer to that. CHRIS: Production blows up, obviously. STEPH: Production blows up, and then we go update our adapter. That's very calm. [laughs] CHRIS: It would be great if CI could more proactively catch that or...yeah, I agree. I would love if VCR would work because that facet of it is so attractive. But [chuckles] I've never gotten to walk exclusively the happy path with VCR. So here we are. This is a classic case of here's four options as to how we can think about this hard and important thing that we do in our codebases, and they all have trade-offs much like everything else in software. STEPH: I'm going to add this to my developer bucket list to live in a world where I can easily validate if an external API has changed or not and then also have tests that know when something has broken before production does. CHRIS: Ooph, dare to dream. I like it. STEPH: I'm a dreamer. CHRIS: I want to live in that world. Well, with that wonderful dream to take us out, should we wrap up? STEPH: Let's wrap up. The show notes for this episode can be found at bikeshed.fm. CHRIS: This show is produced and edited by Mandy Moore. STEPH: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or a review in iTunes as it helps other people find the show. CHRIS: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed on Twitter. And I'm @christoomey. STEPH: And I'm @SViccari. CHRIS: Or you can email us at hosts@bikeshed.fm. STEPH: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Byeeeeeeeee. Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.
This is the sweeps week episode, the epic crossover episode, the mega episode! We have a very special episode as Chris, and Steph teamed up with the hosts of three other podcasts to bring you one giant, mega Ruby episode! In this episode, you'll hear from the hosts of Remote Ruby, Rails with Jason, and Brittany Martin, the host of the Ruby on Rails podcast. They cover the origins of their shows, their experiences as hosts, and why podcasting is so important in keeping the Ruby community thriving. Remote Ruby (https://remoteruby.transistor.fm/) Rails with Jason (https://www.codewithjason.com/rails-with-jason-podcast/) Ruby on Rails podcast (https://5by5.tv/rubyonrails) *Transcript: * STEPH: Hello and welcome to another episode of the Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. This week we have a very special episode as Chris, and I teamed up with the hosts of three other podcasts to bring you one giant, mega Ruby episode! In this episode, you'll hear from the hosts of Remote Ruby, Rails with Jason, and Brittany Martin, the host of the Ruby on Rails podcast. This episode was so much fun to record, and we have Brittany Martin to thank as she organized and moderated this special event. So without further ado, here is the mega Ruby episode. BRITTANY: Welcome, everyone. We have a whopping seven podcast hosts recording today. So, listeners, you are in for a treat. This is the sweeps week episode, the epic crossover episode, the mega episode. We're going to need our editor to insert some epic sound effects right here. Announcer: The mega episode. BRITTANY: So let's go ahead and introduce the crew today. I am Brittany Martin from the Ruby on Rails Podcast. CHRIS OLIVER: I'm Chris Oliver from Remote Ruby. JASON CHARNES: I am Jason Charnes, also from Remote Ruby. ANDREW: I am Andrew Mason, also from Remote Ruby. STEPH: And I'm Stephanie Viccari from The Bike Shed. CHRIS TOOMEY: I'm Chris Toomey from The Bike Shed. JASON SWETT: And I'm Jason Swett from Rails with Jason BRITTANY: Today, we're going to cover the origins of our shows, our experiences as hosts, and why podcasting is so important in keeping the Ruby community thriving. Now I know personally, I really enjoy the origin story behind Remote Ruby. So, Chris Oliver, could you kick us off with that? CHRIS OLIVER: Yeah, we can go back maybe to the first time that Jason and I met, which was Jason emailed me out of the blue and was like, "Hey, are you going to be at RailsConf?" And I wasn't planning on it, but it was over in Kansas City, like four hours away from me. I was like, "No, I'm not going, but I'll meet you." So we went and drove over there and met and have been friends ever since. And Jason had the idea of doing an online meetup. And I'll let him explain where that started and turned into the Remote Ruby Podcast. JASON CHARNES: I thought it would be a good idea. There weren't any online meetups. This was pre even the idea of shutting down the world for a pandemic. And maybe I was just too soon because I got Chris to speak at the first one, and we had 40, 50 people. I spoke at the next one, and there were 20. And by the third one, there were five of us. So it wasn't really a super sustainable thing for me to do. So Chris and I got together and said, "What if we tried podcasting?" Chris, you hadn't really done your own podcast at that point, had you? CHRIS OLIVER: No, I don't think so. And you and I were just having calls every week or whatever just to hang out and chat. And we were like, why don't we just record that and publish that as a podcast? And here we are. JASON CHARNES: Yeah. So we've been doing that. I think we started in 2018, so yeah, three years in June, and somehow people still keep listening to us talk but probably because we brought along our friend, Andrew. ANDREW: Wow. Okay. No, that's not true. But yes, I was a guest on Remote Ruby before I joined as a host. And not to get into the details, but I was on another podcast, and something went down, and I no longer was on that podcast anymore. And Chris and Jason were like, "Do you want to come hang out with us?" And I was like, [chuckles] "Absolutely." So I started doing that, and at the same time, I also started The Ruby Blend with Nate Hopkins and Ron Cooke. And so we were doing that for a while until that had to tragically shut down. But I'm still here with Jason and Chris. I guess I should also mention that Jason Swett gave me my start in podcasting a month or two after I started full-time as a Rails developer on a now archived show called The Ruby Testing Podcast. BRITTANY: Which is the perfect segue because Jason Swett was also my first opportunity to guest on a podcast. So I was already hosting, but I hadn't guested, which is kind of the opposite order. So, Jason, do you want to tell the origin of where Rails with Jason came from? JASON SWETT: Sure. I'd been involved with podcasting since around 2016. I somehow ended up on the Ruby Rogues Podcast and was on there for maybe a year or so. And then, somehow, I got the idea that I could start my own podcast. And as an experiment, I started a podcast that I called The Ruby Testing Podcast, which I figured was sufficiently narrow that I could get some traction. And to my surprise, guests actually said yes to coming on the show. And also, to my surprise, people actually listened to the podcast. That gave me some confidence. So maybe a year later, I broadened, and I changed from The Ruby Testing Podcast to just Rails with Jason. And I have been doing that for something like two years. BRITTANY: That's fantastic. I want to move to probably our most experienced podcast veteran, and that would be Chris Toomey. When I was learning how to code, I was listening to Giant Robots and then was excited for the transition that The Bike Shed took. Chris, I would love to hear the story of what it was like taking over a really popular podcast and really maintaining the drive behind it. CHRIS TOOMEY: So, as you mentioned, I had done a little bit of podcasting. It was about a six-month run where I was a co-host on Giant Robots, which was the original podcast of thoughtbot. And that was more in the business and sort of how do we build a software company? So at that point, I was running Upcase, which was the subscription learning platform that thoughtbot had. So I was talking about the inner details of the business, and the marketing tests, and A/B tests and things like that that I was doing. And every week, I was sharing my MRR rather transparently in that thoughtbot way that we do. I did that for, like I said, about six months and then took a while off. And in the background, thoughtbot had started up a new podcast called The Bike Shed, and that started October 31st of 2014. So The Bike Shed has been going for a long time now, and that was hosted by Derek Pryor and Sage Griffin. And they ran that for a number of years. I think it was about four years that the two of them worked collectively on that. But at some point, they both moved on from thoughtbot, and there was an opportunity for new hosts to step in. So I took over in August of 2018. So I've been doing this now for about three years. And so, for that first year, I took the opportunity to do a tour around thoughtbot and talk with many different individuals from the company and a handful of people external to thoughtbot. But I knew that there were so many great voices and ideas and points of view within thoughtbot that I really wanted to spend some time getting to know more of them personally and then sharing that as much as I could with the existing audience that The Bike Shed had. But secretly, all along, I was looking for a person to hang out with all the more so, and Steph was the person that was a perfect choice for that. And so, for the past two years, Steph and I have been chatting. And I will send it over to Steph to share a little bit of her point of view on that transition. But from my point of view, it's been fantastic. STEPH: I still remember exactly when we had the conversation. You were running The Bike Shed and doing an incredible job of just having weekly guests. And then you'd reached out to me and said, "Hey, would you be interested in doing an episode?" And I thought, "No, absolutely not. I can't podcast. I can't begin to do this." So you continued to convince me. And finally, you said something that resonated where you were like, "Well, we can just show up and record, and we don't have to publish. We can just see how it goes." I was like, that's a perfect safety net. I'm into that. So I showed up, and I think the first episode that you and I recorded ended up being titled What I Believe About Software. And it was a lot of fun. I realized I have a lot of things to say. And after that, I think it was another month or so. You continued interviewing more guests, but then you reached out to me and asked me if I wanted to be a co-host. And at that point, I was super jazzed about it, and it's been wonderful. It's been a roller coaster. I have learned a ton. BRITTANY: I'm kind of seeing a pattern here where over the last three years, it seems like Remote Ruby came into place, Bike Shed transitioned. That's when I took over as host of the 5by5 Ruby on Rails Podcast. We're going to call it the golden era of the Ruby Podcasts. But for me, I probably have the longest-running podcast. It was started back in 2009 on the 5by5 Network, but it's gone through many different hosts. And so, I took over roughly about three and a half years ago as the main host from Kyle Daigle. And then, just a couple of weeks ago, as I announced on my podcast, we took the podcast independent. We are now just The Ruby on Rails Podcast. And I'm starting to change the model where I'm bringing in more co-hosts. So that way, I can get those regular updates that I really appreciate on all these podcasts we have featured on the show today. I am curious. I want to talk about how we put together the episodes and plan out how everything's going to go down. I know for me, I'm currently a mix of interviews and co-host episodes. So I'd love to hear from Andrew. How do you plan out what Remote Ruby is going to be week to week? ANDREW: This is an easy question because we don't at all. We don't plan. We do have some guests that come on, and sometimes, they may get their Zoom link the day of; who's to say? But we really don't have a plan. We don't talk about what we're going to talk about beforehand. We all just kind of show up, and I think we have that kind of relationship and flow where it always just works. JASON CHARNES: And I think part of that came from actually how Chris and I started the show because we were trying to make it as low stress as possible because we knew if we put a lot of pressure on it, we would stop doing it. Our first episodes were YouTube live links that we just shared out. And then in our next episodes, we were like, oh, we should start using some software to do this. And then eventually, we got an editor, but that same core of let's just keep it fun for better or for worse, I think, also affects our planning. BRITTANY: I've been lucky in the sense that I have guests sit on all three of the episodes. And I do want to give a compliment to The Bike Shed because it is very well run and very well planned. So I want to kick it over to Steph as to how putting together a Bike Shed episode looks. STEPH: Oh, thank you. That's wonderful to hear, by the way. That's wonderful feedback. So we predominantly use Trello to organize our thoughts. So we will have...and as we're capturing community questions that are coming in, so we will capture those on the board. And then, we will have a ticket that represents a particular episode. Usually, on the day of, we'll share some thoughts about, hey, these are the broad topics I'm interested in. And there's usually some hot takes in there, which is fun because the other person doesn't know exactly what's coming, and we can have real honest conversations on the mic. And then, every so often, we'll grab a beer, and we'll go through that list. And we'll chat through what sparks joy. What do we want to talk about? What would we like to respond to? And that's pretty much how we organize everything that we discuss. Chris, is there anything I've left out that you want to add? CHRIS TOOMEY: I think that mostly covers it. We do occasionally have interviews just as a way to keep some variety and different things going on, but primarily it's the sort of what's new in your world? And I find that those episodes are the ones that I think are the most fun to record for Steph and I when it really feels like a sincere conversation. I've recently taken to a segment I call good idea, terrible idea where I'm like, "I'm actually considering this, Steph. What do you think?" And live on-air, I'm getting Steph's feedback, and generally, we're very aligned. But every once in a while, she's like, "That's a terrible idea. Don't do that." And I love those, and I love being able to share that because I think it's really easy to talk about, you know, here's a list of things that are true about software, but really, everything depends. And it's all the nuance. And so, being able to share some of our more pointed experiences and then share the conversation that we have over those is hopefully very valuable to the audience but definitely the thing that I enjoy the most. BRITTANY: So kicking it over to Jason Swett, I really enjoy the interviews that you do. I'm curious, how do you select guests? JASON SWETT: Well, thanks. Selecting guests is tough. I had Peter Cooper on the other day, and I was telling him that I feel like every guest that I get on the show is the last guest I'm ever going to be able to get on the show. But somehow, I keep finding more and more guests. Early on, it was relatively easy because I would just find book authors, or if somebody else does podcasting, then it's fairly obvious okay, you're the kind of person who does podcasts, so I'll invite you. But it's a little bit tough because I don't want to invite people who aren't into podcasting and would be really thrown, although sometimes that happens. But let's see, sometimes I send an email out to my email list, and I'm like, "Hey, I'm looking for guests for my show." Sometimes I just tweet that I'm looking for guests. And sometimes I get some really interesting guests from surprising places. But at least in the start, it was looking for those authors and podcasters and the people who are known in the Ruby community. BRITTANY: I know for me, I strive to have at least 50% of my interviews be with people who've never been on a podcast before. And so that usually involves the top of the episode they're dry heaving into a paper bag. And I'm explaining to them, don't worry, about halfway through the episode, you're not going to remember that you're recording anymore. It'll be fine. And you know what? It's always fine. And so, I do love hearing from a wide variety from the Ruby community just because it really proves just how big it is. So I'm curious, could you host the podcast that you are currently hosting now if you weren't actively working in Ruby? ANDREW: I could because Chris is the one that has all the clout. I could sit back and make dumb jokes and memes during it. And as long as Chris is there, I think we'll be good. JASON SWETT: Yeah, I think I could because a good majority of what we talk about on Rails with Jason actually has nothing to do with Rails, so that would probably actually work out. STEPH: I think yes is the answer. While a lot of our conversations do focus around Ruby and Rails, we often use a lot of other languages and tools, and those are a lot of fun to talk about. So I think I would just talk about whatever new tool or language that I'm using. So I think yes, it would just take a slightly different form but would still be at its core the same where we're still talking about our daily experiments and adventures in web development. BRITTANY: I agree with you, Steph. I will say that it seems like Chris Oliver and Chris Toomey have an endless well of things to talk about just based on what they do day-to-day. CHRIS TOOMEY: I try and go on adventures and then share as much as I can. But to resonate with what Steph was saying there, we try to make the show more generally about software, and it happens to be that it's grounded in Ruby on Rails because the vast majority of the work that we do is in that. And I just recently started a new project. I was given the choice of I could pick any technology I want, and it remains the technology that makes sense to me to be the foundation of an application that I want to maintain for years and years and years. So, on the one hand, I think I could definitely talk about software more generally. I think I'm doing that most of the time. But at the other end of the spectrum, but it's always going to be based on Ruby because I haven't found a thing elsewhere in the world that is better than that. CHRIS OLIVER: I completely agree with that. I probably have a little bit of a unique thing doing a screencast every week. A lot of those are based on I'm building some project, and I need to build some random feature like Stripe Checkout. And that's a good one to do a screencast on and implement in the project. And then, we can also talk about the decisions along the way on the podcast, which is kind of nice. BRITTANY: Yeah, it feels like every week, Chris Oliver is like, yeah, I've created a new open-source library, and I'm fabulous. [laughs] Let me listen to this. CHRIS OLIVER: Too many of them. I'm currently rewriting a lot of the Pay gem. And it's just one of those things where you make a bunch of decisions. And then, if you make an open-source project, people use it in all these different ways that you didn't intend yourself, and so you want to support that. But then you need to rearchitect things in it. It is a lot of learning as you go, which is always a lot of fun. So those I think are really good topics to talk about when you're building something like that. I'm always amazed by how does the Rails core team make these decisions on what should be in the framework and what shouldn't? And what do they want to maintain, and how do they keep it flexible but yet have some sort of rule with how they allow things to be implemented and whatever? It is a very hard job to have. So I get my little taste of that with some open source but not on their level. BRITTANY: I always thought that you had a good contrast to Jason Charnes because Jason works at Podia. And while you do get to work on a lot of really cool technologies, I feel like the stakes are much higher. So you can't just rip out StimulusReflex and put in something else just because it sounds cool that week. And I love how you talk through the pluses and minuses to making a big change within the Podia codebase. JASON CHARNES: Yeah. I haven't really thought about that contrast before, but it's helpful for me even just to talk it out with two other people once a week, and luckily, pretty cool about me just coming on and talking about hey, these are the steps we took to get here. Yeah, it's a cool dynamic. BRITTANY: Steph, have you ever had a client from thoughtbot say, "Hey, were you talking about me?" whenever you're talking about your current client? STEPH: That is one of my fears at times that it will happen [chuckles] although we stay very positive on the show. That's something that's very important to us. There's enough negativity in the world. So we really want to focus on our positive experiences through the week. But there have been times where I'm speaking about some of the challenges or things that we are running into that yes, the engineering team is listening to the podcast, and they're like, "Oh, I heard you talk about this feature that we're working on or this particular challenge." And that's really cool because they get that behind-the-scenes peek to see how Chris and I are chatting about that. But yet they know enough, and they know which project that I'm on that they recognize exactly the technology and the feature that I'm trying to describe. So that has certainly happened, and it can be a lot of fun when it does. BRITTANY: Andrew, how have things changed for you now that you're not working at CodeFund, which was very much like an open-source thing? People could see what you were actively working on. And now you're working for a company where it's closed source. And so, you might not be able to reveal as much as what you're working on at any given point. ANDREW: It's different, but I don't think it's been an issue per se. I'm not like, oh crap, I let that slip, and I didn't mean to. That's not really an issue. I really cherish the time I had at CodeFund. When I think back on my experiences, that was my favorite time just because I was able to do that thing that a lot of people really want to do. I was working as an open-source developer. We were spiking StimulusReflex; that's when we were building up StimulusReflex and trying to build up the community. I joined Ruby. We started the Ruby Blend, and things were going good before a dramatic turn. But in terms of the closed and open source, it hasn't been that big of a shift just because instead of talking about what I'm doing at work, like, I still talk about it, but I speak about it in more general terms. But I also then kind of freed up to talk a lot more about the dumb crap I do on the nights and weekends. BRITTANY: So the majority of our podcasts either have the word Ruby or Rails in it, but I think we've all agreed that a lot of the topics that we're talking about are not specific to that community. But in a lot of ways, I feel that having podcasts in our community is how we're going to keep our community thriving. So I'm curious if anyone has any thoughts around...is there a way to market our podcasts so that other developers will listen to it? I get really excited when I get listener feedback saying, "Hey, I used to do Rails maybe ten years ago, but I've been listening to your podcast, and I really enjoy such and such episode." How can we make our podcasts accessible to the general software community as opposed to just Ruby? CHRIS TOOMEY: One thing that stands out to me about Ruby and Rails is because it's full-stack, because of its foundations, it tends to be holistically about web development. And so, whereas I look at React projects or other JavaScript or different things that are going on, I see a more narrow focus in those frameworks. And with Ruby and Rails, what I love about it is that it's really about building software. It's about building products that are valuable, that deliver value to end-users. And so that being the core of it, that's the story that constantly brings me back to Ruby and Rails. And it's the story that I want to keep telling as much as possible. And it's the thing that keeps me engaged with this community. And so, I think podcasts are a great way to continue to literally tell those sorts of stories and really celebrate that aspect of Ruby and Rails and why it remains such a productive way to build software. CHRIS OLIVER: I think related to that, one of the things that we should talk about more is the draw of Rails was look at what you can do with one person or two people. And I feel like we went down the JavaScript route, and now you need two teams of people, and you end up building bigger stuff. And Hotwire has kind of been like, hey, here's a reminder of what you can do with a very small team. And I think that resonates a lot with a lot of people building startups and trying to build side projects and everything. And that's one that is Rails-related. But there's a ton of people building Hotwire stuff in Laravel too. And they're all very similar. So I think at a certain point, yeah, we're talking about maybe Rails specifically, but you can apply all those things to different frameworks and just different tools. STEPH: I'd like to add on and extend that because I wholeheartedly agree with what both Chris Toomey and Chris Oliver just said. And in addition, a lot of the conversations that we have on The Bike Shed are focused on Ruby and Rails, but then we will extract that particular concept to the point that it really doesn't matter which language that you're using or which framework that you're using. We're talking more about the high level. What's your process? What are you thinking as you're going through and implementing this? And based on more of our recent conversations, you'd think we're more of a Postgres podcast, how much we hype up Postgres, and the things that we can do at the database layer. So I think there are a lot of ways that we can start with a foundation of this is how we're doing it with Ruby and Rails, but then talk about it at a higher level where then it's really applicable for everybody. JASON CHARNES: If talking about one technology defined your podcast, we might as well be a Laravel podcast because we talk about that framework more than we do Rails sometimes. [chuckles] BRITTANY: So that begs the question: is there room for more Ruby and Rails podcasts outside of who's currently on this call? JASON SWETT: I think so. And I mentioned that Peter Cooper was on our podcast a little bit ago. That's something he and I actually talked about in that episode. And I shared the anecdote about how in the new America's founding, Ben Franklin's brother or something like that wanted to start a newspaper. And somebody told him what a dumb idea that was because America already had a newspaper. And people might say, oh, there are already however many Rails podcasts. There are a small handful. But I think there could be ten more Rails podcasts or even more than that potentially because I think people have an appetite for help, and camaraderie, and stuff like that. And I don't think we've nearly bottomed out in terms of satisfying people's appetite for that stuff. JASON CHARNES: Yeah, I agree with that because a lot of times, when I listen to podcasts, the more you get to know someone, that connection becomes what it's about for me. So, yeah, there's plenty of room. I mean, brand it as Ruby and tell me about your life as a developer I'll listen. CHRIS TOOMEY: I'll also throw it out there that the way you framed the question is like, is there room for it? But one of the wonderful things about podcasting as a medium is it is distributed. It's not centralized. You can start up a podcast any day. And I will say, as someone who inherited a popular podcast or a sufficiently popular podcast and just got to run with that, it has been such a wonderful way to get my voice out there and provide opportunities that I want that for everyone. I want everyone to have this ability to speak about the way they think about software and then find like-minded people and be able to build even many communities within the larger community of Ruby on Rails. So beyond the question of, Is there room?” which I definitely think there is, I so wholeheartedly support anyone pursuing this for their own reason. ANDREW: Yeah, I think to bring it all the way back, one thing that Chris, Jason, and I care a lot about is Ruby as a community. The community aspects of Ruby are very important to us. And we're actively trying to build that up and bring in new people and bringing people onto their first podcast. We say it all the time, like, hey, if you want to come on the show, let us know. We've had a few people even, you know, recognition in jobs from that. So to us, that is the payoff of doing the show. Maybe our show is the first time someone learns about Rails. And that to me is the possibility in the future. It's like, how can we market our shows that markets Ruby as well so that this meme of Ruby being dead finally goes away because it's not. I think it's growing. And I think the more and more we push as people who are public figures in this space that we want to bring more people on, that this is a space for everyone, I think that's just kind of the ethos that all of us have, and I think that's great. BRITTANY: So I'm curious, on a lighter note, has anyone had the funny experience of realizing that you're not just podcasting into the ether and that what you're saying and what you're doing matters? For me, I have definitely been at conferences where people will run up and hug me just because they heard my voice, and they are like, "I didn't know what you looked like, but I have your voice memorized," and it just blew my mind. And I was like, "Thank you so much for being such a loyal listener." And it just proves that people are out there listening. ANDREW: I tend to talk very openly about mental health. And I very often fail in public and talk about it. And I've had a lot of people message me and email me over the past three or four years and be like, "Hey, thank you for talking about this thing that's not actually about Ruby. It's not actually about coding, but it's just about being a developer." And those are the emails that make me feel the best. Like, someone who's out there like, "Yeah, I also feel like this. Thank you for speaking about it." JASON SWETT: I had a surreal experience. I went to India in 2019 through RubyConf India. And this guy wanted to take a selfie with me because apparently, he considered me famous. So that was cool and pretty surprising because I definitely didn't consider myself famous. STEPH: My favorite has been when we receive listener questions because it lets us know that people are listening and engaged in the conversation, and I essentially feel like they're part of the conversation. They will write in to us and share anecdotes, or they'll share answers to some of the questions that Chris and I will pose on the show. But every now and then, we will also get an email from someone that says, "Hey, just thanks for doing the show. I listen, and it's great," and that's all they share. And that, to me, is just the most wonderful thing that I could receive. BRITTANY: Some of my favorite episodes from all of your shows is when we get an inside peek into what people are doing, like Andrew moving. Jason Charnes, you putting together a conference was actually some of my favorite episodes of yours, which was really early on, which proves that I'm a Remote Ruby OG. But I loved hearing the inside track as to what organizing a conference is because I think we need to get more content out there about how difficult but how rewarding it is. JASON CHARNES: Yeah, I hadn't really thought about...that was around those times we hadn't done... It feels like it's been ages since we did Southeast Ruby, but Chris and I actually podcasted from the last Southeast Ruby we did. We just met in a room and recorded. But when I started that conference, I didn't have a lot to go on. So I'm more than glad to share because the reason I started is there were no Ruby conferences around me, plus I'm an open book. So for better or for worse, maybe that's good podcast material. JASON SWETT: Side note, it's one of the most enjoyable conferences I've ever been to. JASON CHARNES: Thank you. BRITTANY: I completely agree. I miss the regional conferences. JASON CHARNES: We lucked out because we were already planning on skipping 2020 because we were tired, and then COVID hit. I just sat on the couch one night and looked at Shannon (she helps me put on the conference), and I was like, "Wow, that would have been terrible. That would have come out of our own bank account, all that loss if we would have already booked somewhere." So phew, when it chills out, we'll try it again. BRITTANY: So let's talk about legacies. I know that some of us have taken over from popular podcasts. Some of us have grown podcasts from the very beginning. So I'm curious, do you ever put any thought into the legacy of your podcast, whether or not you're going to stay with it to the end? Would you eventually pass it off? Do you think about whether or not it's your responsibility to the community to make sure that it keeps going? JASON SWETT: I, for one, plan to have my consciousness uploaded to a supercomputer upon my death so that the Rails with Jason Podcast can continue on indefinitely. JASON CHARNES: Did you recently watch Upload the TV show? JASON SWETT: No, I've never heard of it. JASON CHARNES: Oh, man. That's a whole nother conversation. BRITTANY: Consider that homework, Jason. JASON CHARNES: It's an interesting question because we started ours out of nothing. I wonder, is one of us going to get tired and just quit? I'd like to think that if one of us did, it would keep going because there are plenty of cool people who could hang out and talk Ruby on it. But it's interesting, something that's casually crossed my mind, but I think we're good. I think we're still doing it unless Chris and Andrew have a surprise for me today. ANDREW: Surprise! [chuckles] I've thought about it a few times, specifically because I'm the youngest member of Remote Ruby. What if Jason and Chris just left, and they were like, "Oh, it's all yours now." Could I keep running it by myself? I think honestly, the answer is I would probably still do it just to have an excuse to talk to someone. I enjoy it. It's almost like a hobby at this point. I don't feel any obligation to create it. To me, it's really like an excuse to hang out with two friends, and other good stuff comes from that. But at the end of the day, I cherish that time just us hanging out a lot. CHRIS OLIVER: Yeah. I think that's why we sometimes joke about it being a weekly therapy session where we are just hanging out and chatting about stuff. It's nice to be able to talk about programming things at a high level with people you don't work with that have totally different perspectives and stuff. So yeah, if Jason and Andrew dropped off, I would still try to have conversations with random people I know and keep it going just because it's enjoyable. I would hope that we would be able to keep it going and have other people on there. BRITTANY: I'd love to hear from someone from The Bike Shed. STEPH: I have thought about it. I've thought about it partially from the perspective that Chris Toomey brought up earlier in regards to being on a podcast is an incredible platform. You get to share your opinions, and people listen to you. And they know you, and it's really wonderful marketing. So I have thought about it from the perspective of I want other people to have access to this really wonderful podcast that we put on each week. So part of me is very aware of that and thinking about how more people can have similar exposures. So a sort of a similar event occurred when Chris was moving on from thoughtbot and pursuing other interests. And at that moment, I just thought, oh my goodness, Chris brought me on as co-host, and now I'm here alone, and I don't know what I'm going to do. And I just panicked. I truly don't think I even considered other options. I was like, well, okay, it's over now. This was fun. And then it turned out where Chris was going to stay with the show. So things have just gone on swimmingly, and it's been wonderful. But similar to what someone was saying earlier around when you start listening to a podcast, and you really develop that relationship and you go back to that podcast because you really enjoy hearing from those people and their adventures, it's very similar for me where The Bike Shed is very much the conversations and chats with Chris. So I think if we were to move on, it would be whenever Chris and I decided to move on and give the reins over to somebody else. I don't know if Chris fully agrees, so this will be interesting to find out. [chuckles] CHRIS TOOMEY: I agree with that. Honestly, I'm honored to have continued on in the podcast after having moved on from thoughtbot because, in a very real way, the show is thoughtbot's channel to talk about things. I was at thoughtbot for seven years. I think I live and breathe that truth. And to me, that's what maybe has made sense for me to continue on. But I really do feel a responsibility to keep the show in good shape so that someday someone else gets to inherit this thing because I was so happy to get handed it. It was such a wonderful thing. And it has been such a joy to do for these past three years. But at some point, I do presume that we will move on. And at that point, I do hope that other people pick up the mantle. And thankfully, thoughtbot as an organization, there is a group of individuals that I'm sure there will be someone wonderful that gets to step in, but I'm in no hurry to do that. And, Steph, I hope you're not either. So we'll continue the conversations for now, but I definitely do want to keep this thing alive if for no other reason than I got handed it. I don't feel like I could let it drop on the floor. That doesn't feel right. BRITTANY: Well, I think on that warm, fuzzy feeling, we should wrap up. So let's go through everybody and just tell the listeners where they can listen to your podcasts and follow you. I am Brittany Martin, @BrittJMartin on Twitter. And you can listen to the Ruby on Rails Podcast at therubyonrailspodcast.com. JASON CHARNES: So I'm Jason. We are Remote Ruby. I am @jmcharnes on Twitter. And I'll let the others tell you where you can find them. ANDREW: You can find me everywhere @andrewmcodes. And if you email me, there's a really good chance you're never going to see a response because my email is a disaster. Please don't email me, but you can contact me anywhere else. CHRIS OLIVER: I'm Chris Oliver, and you can find me on Twitter @excid3 or at Go Rails, and of course, gorails.com. And you can find the Remote Ruby podcast at remoteruby.com. CHRIS TOOMEY: I am @christoomey on Twitter. The Bike Shed is @bikeshed on Twitter. We are at bikeshed.fm for a URL. I'm pretty sure www works, but I'm going to go check that real quick after because I want to make sure that's true. And yeah, that's me. And I'll send it over to Steph for her part. STEPH: I am on Twitter @SViccari, and I post programming stuff, usually pictures of cute goats, cute dogs, that kind of content if you're into that. JASON SWETT: For me, if you want to find my podcast, it's Rails with Jason. And if you search for Rails with Jason anywhere, you should be able to find it. And then my website, if you're interested in my blog and all that stuff, is codewithjason.com. BRITTANY: Fantastic. Thank you, everyone, for being on this mega episode today. It was a lot of fun. We are going to be having a podcast panel at RubyConf; we're excited to announce and some of us will be present. So stay tuned for details around that. And if you enjoyed this mega episode and want to see more mega episodes, please let us know on Twitter. All: Bye. CHRIS: The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review on iTunes, as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us @bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey. STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Bye. Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.
Chris gives a DB sessions update and talks bifunctors & command objects. Steph shares the coolness of a gem she's been using called after_party, and excitedly gushes about her new laptop. (Chris is hoping to hold off on replacing his until the end of the year and then they can compare!) The two then answer a listener question on retrospectives and how they've seen productive ones run, while giving some of their own helpful opinions on dos and don'ts. They're talking to you, Grumpy Goose! dry-monads gem (https://github.com/dry-rb/dry-monads) attr_extras gem (https://github.com/barsoom/attr_extras) after_party gem (https://github.com/theSteveMitchell/after_party) What Went Well? - Bike Shed 123 (https://www.bikeshed.fm/132) What I Believe About Software - Bike Shed 172 (https://www.bikeshed.fm/172) Is Agile Over? - Bike Shed 299 (https://www.bikeshed.fm/299) Running a Retrospective - Upcase (https://thoughtbot.com/upcase/videos/running-a-retrospective) Transcript: STEPH: Cool. [laughter] CHRIS: Good. No, I like what you did there. STEPH: Yeah, I feel like we can get rambling on that one. CHRIS: It's been great. This is what the Bike Shed is at its best. It's the two of us just rambling and being like, well, what about this? And if it's this, then that, then these, and it depends. And it's complicated and it's nuanced. And what about the humans? That's the story of The Bike Shed right there. [laughs] STEPH: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Steph Viccari. CHRIS: And I'm CHRIS Toomey. STEPH: And together, we're here to share a bit of what we've learned along the way. Hey, Chris, how's your week? CHRIS: My week has been good. I have some updates actually on some topics from previous episodes. One of the things that I can update on is the discussion around the cookie versus the database store. So I had posed this as a thing that I was going to be doing in the app for a handful of reasons. Most notably, I wanted the ability to invalidate sessions from the server-side, wanted to have a little more control over that. And so that's a dream that the database-backed session store can do. Eventually, I have to make that actually work in the way that I want. But I was asking the question in that episode, which we can include a link to the specific episode, but I was asking the question of why don't we just do this all the time? The database-backed sessions seem better in all these ways. It's a lower overhead per request because you're just sending the session ID and the cookie instead of the whole payload of the session. You actually can have more data stored in it, a bunch of things that seemed really great. And then right after I introduced it, I figured out the thing. I figured out the secret. It's not a big issue, and we're going to stick with database session stores. But we have to be purposeful because it turns out they are essentially plain text in the database. And so if there's anything that you are putting into the session like say a social security number or an authentication token or other things which naturally I might have done if it was in a cookie that lives on the user's browser and never actually lives on the server, persists on the server, that seems fine to me. But now these things are getting stored in the database and that really changes the calculus, especially because if I'm not purposeful, they'll just stick around for forever. So social security is probably the most pointed example of this. If you happen to have a form in the app that accepts a social security number and you want that to persist through some number of other steps, not actually going to store the social security number in the database because that's a thing that I have actively chosen not to do. I need to send it off to some other system, but I do need to hold onto it for a few minutes. The session is a perfect place to put that unless the session gets stored in my database. STEPH: That's such a great point. I'm so glad you discovered that. And in our recent conversation, we were trying to think of the reasons why this isn't the default case. You may be headed in this direction, but this may also be timely, the fact that you're discovering this issue but also the fact that Rail 6.0 now has encrypted columns. Is that where you're headed with the fact that you can still keep session data in a database? CHRIS: That is a great question, and it is an intriguing option. But it's not the one that I'm going with here. I think broadly, my hope is to completely avoid ever persisting this data in the database, this truly sensitive user-specific PII or PCI or social security numbers or any of these other fancy acronyms that get collected together under the umbrella of I probably don't want that on my server. For those, I'm just opting to push them back into a cookie. So I'm using particularly a...In rails, it's fun because they have a fluent interface where you can just chain together things, so it's cookies.signed.encrypted.whatever, and then you go from there. But I'm using signed, encrypted cookie, which is essentially what the session store views; the cookie session store uses itself. So I'm basically reverting to the old session store behavior for specific values. So anything that is truly sensitive like that, I'm just saying, cool, that's actually just going to live in a cookie, and that will be it, but not leaning on the ability to encrypt the database sessions. There's just enough subtlety around that. There's so much volume of data if I do allow that sensitive data into the system that any failure, any exploit that happens, would be somewhat catastrophic. So, in my mind, this lowers the surface area and says, yeah, this data really never lives on the server. It comes with a request, and then it's gone after the fact. And that's the world I want to live in. STEPH: Yeah, that's super interesting. You're also raising questions for me that I hadn't considered when we originally had this conversation where there's necessity or that you're looking to store form data or sensitive data in that session as well. So that makes a lot of sense to me that for that type of behavior, we're going to separate that from the idea of authentication and the user session and still use encrypted cookies for those details. So it only stays with the user's browser, but then the actual authentication of a user that part could still live in the database. CHRIS: It is ending up being a weird Venn diagram of; this is data that I want to stick around but only sometimes and particular to the machine that the user is interacting with because the session is still associated with a cookie at the end of the day. So a user may have multiple sessions in the database-backed session version. It is somewhat interesting, and I'm going to see how it develops over time. But yeah, at a minimum, I have now found this edge case of like, ooh, okay, sensitive data, that's a thing, which is one of the reasons that I would reach for the session inherently. So it turns out, as always, it depends. Things are complicated. STEPH: It's a nice update. I like when we have closure to a question like that, especially so quickly. CHRIS: Love to provide that continuity. It's what I'm all about. But yeah, what's up in your world? STEPH: What's up in my world? I am excited that I have a new laptop. So I have been using a MacBook Pro for about the last...it's lasted me for a while. I think I've had it for a good four, four, and a half years, but that's on the fritz. The keyboard, in particular, the keys are popping off, and that's something that I could go get fixed. But I'm at the point that I need a new laptop. So I have a brand new shiny laptop. And I had the option to either go with a 16-inch MacBook Pro or to go with one of the new, fancy laptops that has the M1 chip. And I was torn for a little while because having the M1 chip sounds really cool and novel, and there's a lot of speed improvements that come with that. But I ended up going with just the 16-inch MacBook Pro; specifically, one, it's still very fast. It's very reliable. I can use this as my work machine and just know everything's going to work. That part feels really important to me. And then also the screen size is important. So any Mac laptop that is using the new M1 chip, I think they only go up to a 13-inch, right now, screen size. And I really want the 16-inch in case I am traveling, so I have that larger desktop. But I did do some research into the M1 just because I know about it. I know it's out there. I know it's hot. People are interested in it, but I didn't know a whole lot about it. So for anyone else that's like me and is curious about what the heck this M1 chip is, it's essentially Apple's foray into making their own processors. So traditionally, their machines have used Intel CPUs and third-party graphic processors, and other parts. And this introduction of the M1 chip really represents Apple's switch to having their own internal architecture rather than relying on those third-party parts. And it also means that all those features that were sourced from other parties like the CPU and its security are now being combined into a single chip, which has also led to some performance improvements. And while I was reading about the M1, there's a lot to go through, but the thing that stood out to me was this idea of Apple's Neural Engine. And I thought, well, that sounds super fancy. What is that? Are you familiar with Apple's Neural Engine? Have you read about that? CHRIS: I don't think I am. What all is that? STEPH: Yeah, good question. That was a question I was asking myself just recently. So essentially, their neural engine it's a microprocessor that specializes in the acceleration of machine learning algorithms. So it's really similar to how a GPU will focus on accelerating graphics rendering. And their neural engine or neural engines in general then focus on accelerating neural network operations. And the inclusion of a neural engine isn't something that's new because Apple introduced this into iPhones and iPads back in 2017 to support their features like Face ID and emoji, searching for photos with dog pictures. Siri speech recognition is also one that's using this engine and other machine learning tasks. But the sparkly stat that Apple is sharing with this new design is it's a 16-core design that can perform 11 trillion operations per second, which sounds very fancy, very fast. But it really got me thinking about how companies are working to improve, not just laptops but also our mobile devices to run machine learning software more efficiently, and then how that's just going to evolve and change all the different features that we use, and then how developers can integrate with this engine. I think currently, Apple hasn't shared much information about how this engine works, but I think they've exposed a few developer tools so people can still build features that will then use the power of this faster, improved neural engine. CHRIS: Oh, that's super interesting. I have still not really delved into machine learning or artificial intelligence, or any of that stuff in any real way. But it's one of those things like the number of mentions is ticking up. And at some point, I'm like; I probably have to pay attention to this, don't I? I'm still in the not paying attention to it camp. So if I'm understanding, though, you just described this wonderful feature, but you opted for the machine that does not have all the fancy stuff. You did not... STEPH: Exactly. [laughs] CHRIS: Okay, yeah. STEPH: Yes, it would have been nice. That would have been neat, but yeah, I needed a machine with a larger screen, all those good things. And that's still really fast, for the record. CHRIS: Oh yeah. I'm desperately hoping to make it to the end of this year. This is going to be a bit of a rumor mill here, but my understanding is the expectation is that Apple is going to release a 14-inch MacBook Pro with the M1 and the return of MagSafe, and the removal of the touch bar. And that sounds like my dream machine right there. I want that piece of hardware. I also seem to care a little bit less about the size of the laptop screen. I'm so often working at my desk with a large-format monitor that I'm connected to. And so, when I'm on the road, I want to optimize for portability when I'm traveling because I do it so rarely, and then I'm hopefully focusing on travel at that point. But we'll see if that remains true as the shape of my work changes and I start to not only work from home. And maybe I'll actually change my tune on that. But for now, that's my hope is to make it to that machine and then get one, and that it exists because right now, those are all rumors. STEPH: Well, I totally support this goal of yours. So that way, you can have that new-new, and then you can report back on what it's like, and then we can compare. Because I'll have the other version, the Intel CPU, and then you'll have the M1 chip, and we can see how our lives are different. CHRIS: You'll have the new, and I'll have the new-new, and that's how we'll categorize them. STEPH: [laughs] But yeah, I'm very much looking forward. Having a new laptop is always just such a fun feeling. It's just a clean space that I get to rebuild. It's like going through and prioritizing; what are the things that still spark joy? And then I get to only port over the stuff that I still really use all the time and want to keep. So I'm looking forward to getting it set up. CHRIS: I need to do that sometime soon. I'm like five years deep, at least on this machine. So I've been dragging along. Also, the hard drive is just completely full, and I regularly have to go through and delete things before we start recording because it turns out these audio recordings start as very large files. [chuckle] So it's almost a weekly thing where I'm just like, got to throw something out today. I don't know what. It's fine. I'm going to be fine. [laughter] I'm going to make it to the end of the year, and it's going to be great. STEPH: What else is going on in your world? CHRIS: Well, I wrote some fancy code, and I use fancy not necessarily as a good word. [chuckle] So I'm intrigued that the code could be described perhaps as clever or other words like that, which I think are very complicated words in the coding space. I tend to try and avoid this type of coding where I'm trying to introduce abstractions and clean things up, and remove duplication because I've been burned by that so many times in the past. But this time, I think maybe this time it'll work. So, in particular, there are two different areas of the application. There were two sets of refactorings, but they really went together. One is we have the idea of command objects within the application that we're working on. So there are a lot of cases where we need to save something to the database and then communicate something to an external API. And then presuming the results of that is a successful response from them, then unpack some data, make sure it's in the right shape, and then save something else to the database. And ideally, wrap that all in a transaction and keep everything together and then return some data at the end of it. So that whole sequential operation, I've been using dry-monads to model that. I've talked about this on a few previous episodes. I'm really enjoying it. The more I lean into it, the more I find that it is just a really great way to wrap up that very procedural code. But ideally, do it in almost a functional way so that we've got these sequential operations that feed into each other. There's the railway-oriented programming stuff, which is associated with this idea. But there is a lot of boilerplate to these objects. So the way we've defined them is they have a class method called run that takes whatever the arguments are, and then it needs to pass those arguments into the initialize and then call run on the instance. So in order to define one of these objects, what we had been doing was def self.run and then all the arguments. And then inside of the body of that, it's new, and then pass forward all the arguments .run, and then define initialize to capture all of those and set all the instance variables, and then define the run method, which actually does stuff. Also need to define an Adder reader for all of those instance variables, which is a thing that I enjoy doing. So that's the interface I want, or that's the way that I want this class to work. I know other folks in the Ruby world feel differently. But that's the shape of the thing that I want, but that's a lot. And there's also I regularly would find myself forgetting to duplicate something that we put into the class method run interface into the initialize method. And it was just like, this is all just wiring up and plumbing. There's also the binding of the dry-monads do notation for the run method as well as the inclusion of the results type within dry-monads. Type is a strong word, but that gives us the success or the failure objects that we can create. So ideally, all of these command objects either return a success object or return a failure object. It's one of the two. And that's one of the things that I really like about them. But yeah, so much plumbing. So we define a base command, and the base command has the self.run method, the class method, and that method is defined very abstractly. So it's just args * keyword args. So we're capturing all of the arguments and then forwarding them on to new. So that way, I don't have to think about that interface. It basically just says, "Give me anything, and I'll forward it onto new." And the new or initialize is in charge of actually defining things. It also includes the result type. It includes the macro annotation for the run method, which is how dry-monads does its magic, that actually I had to include inline within the self.run, just because of the sequence of definition and the metaprogramming that's going on there. As I said, that sentence terrifies me a little bit, but hopefully, no one ever needs to look at this magic base class [chuckles] and figure anything out. So that was one part of it. That cleaned a lot of things up, so that meant I didn't have to write a ton of the wiring up code. Then there was still the noise of actually defining all of the arguments to these classes. They often take a handful of arguments because that's their job is to grab a bunch of things and do some work with those things. So for that, I have brought Adder Extras, which is a gem that I've talked about probably in previous episodes, I think so. But this is the first time that I've really leaned into it and used it. And it gives some very high level what look like macros are just class methods. But the one that I'm using is Adder private initialize, and that you can then pass a variety of values too. And it will then say, okay, this method accepts a required keyword arg, a defaulted keyword arg, and a positional argument or something to that effect. But it's a very, very concise way to express that and then also get the private Adder readers, which again is the direction that I want to go with all of this. So that's a bunch of things that I have said. But all total, it cleaned up these command objects very nicely. And now, when you look at one of these command objects, all you see is the run method that does the work. And the plumbing and the wiring up behind the scenes should just happen. I am concerned about the day that someone forgets to inherit from the space command, and then it's like, why does nothing work? I thought command objects just worked in the system. But we're going to deal with that when we get there, which is hopefully a while down the road. STEPH: I like how you're pushing at the boundaries of our comfort zone. I say our comfort zone because I imagine we feel similar. CHRIS: It is. We definitely got a shared comfort zone. [laughter] STEPH: Yeah, we have a shared comfort zone with inheritance, but you're pushing at that boundary of that comfort with inheritance because it is something that can be so painful. But you've identified an area where inheritance feels useful. And then it also sounds like a very meaningful...you're introducing this pattern and then trying to make it easier for others to follow this pattern. So it's a very intentional design decision of where we want to group these behaviors together and then make it very easy for other developers to then pick up this pattern and run with it, and then also work with these classes. So I am intrigued to hear how it goes and how others feel about the pattern as well. I also wonder, this is one of those areas where it feels like this very intentional design decision. Is it something that you think in the base class would be worth highlighting? Like, hey, here are the things that we are using in this base class. This is the intention of this base class. I don't know if that's maybe a comment or if that's something that's documented in the README. I know; I see your eyebrows went up when I said comment. But it does feel like one of those areas where it's like, hey, we have introduced this new concept. We want you to follow along. Here are some helpful guidelines. CHRIS: Those were mostly joking eyebrow raises because I have thought of that. I haven't actually gone to that level. But in the back of my mind, there's this pattern that we have within this application. Ideally, we're going to lean into it more and more so that A, we have a clear way that we do things within the app but also make that as understandable and discoverable as possible. I'm not sure if a comment in the class is the right thing or...so I'm deferring what I want to do on that for now because right now, it's myself and one other developer. We sort of developed this in tandem. So we were working together on it. We would pair in a bunch of the features. And what we have now is the crystallization of what we found useful. And we're both very comfortable with it. So there isn't the need to explain it. I'm almost thinking about it as just-in-time educational content around this piece of our application. I don't actually trust that I would do a good job describing it in the abstract because I know it. Like, to me, this thing makes sense right now. But I've been on the other side of stuff where someone was like, "Hey, this totally makes sense." And I'm like, "I don't know any of the words you just said," and so I felt that pain being on the other side. You could say I'm just being lazy, but I do think this is a purposeful delaying of that where I want to wait until I actually have someone to teach this to. And at that moment, I want to see what that conversation looks like. And I'll try and explain it to the best of my ability, but I'm sure they're going to ask questions, and I'll be like, "Oh, wow. Yeah. I hadn't even thought of that. But now that you ask the question, totally let me explain this part that I was going to gloss over and forget to mention." And so, ideally, that is what will happen down the road. And then from that, hopefully, some artifact becomes clear, whether it's a documentation page in the repo or a comment in the class if it's simple enough or maybe even it's a recording of a pairing session. And that's the artifact that we keep around that explains this piece of the application. So I definitely think a version of that makes sense, but I am not doing it yet. STEPH: It's funny; you're saying so many good things that I agree with. I love the just-in-time education; that part is fun. And yeah, there's a part of me that definitely still leans into the idea because we've talked about this in the past too, where we write down, in the moment, the things. Having that context when we're implementing it is really important and helpful. So even if it's not this grand explanation…which I really like what you said around having someone to explain it to or have that conversation with so that way you're documenting the useful bits, that part I like very much, but capturing the intent as soon as the change was introduced. So even if it is a very high level like, hey, we are using dry-monads and Adder Extras, even if it's just links to those things, that's something that I think I would still favor just to go ahead and start surfacing this is a pattern. This is a choice. And then, as you continue to work with the pattern, if you change your mind, it's still very easy to scrap that documentation. So I think if it were me, I would still go ahead and document it. I think it's that piece about discoverability that's calling to me so strongly where that's where I want to then highlight the things that are in use. So even if there's not an explanation, people can find the resources very easily. Because you're right, you did say a lot of interesting bits in describing this pattern. And the fact that we're talking about it now also just deepens my suspicion that it would be nice to comment somewhere, and perhaps a repo is a perfect place for it and just get it out there, and then it can always be revisited later and improved. CHRIS: Okay. I like that you are keeping me honest on this because I do think there's a certain amount that I'm just being lazy here and not wanting to do that because it is actually really hard to try and document something like this. Like, what are the important pieces versus what are the extraneous details that people don't actually need? I do wonder, so the pull request that did this refactoring and introduced this base command object that does have the explanation captures the point in time and whatnot. And so I wonder, is there a version of tagging important pull requests that tell the story of the application? A lot of things are just going to be like; this is adding a feature. It's the same as the other 30 pull requests recently that added a new feature. But this one is special from an architecture perspective. And so let's tag this, let's add a label. I don't know what it is but something that allows for discoverability of the story of how this application became what it is today because anything else I worry will go out of date almost instantly. But this pull request is true fundamentally in that same way that we say commit messages should capture as much of that detail. So I did do that writing for the pull requests/the commit message. And I wonder if maybe that's the best artifact for this moment but then the question of surfacing it and making it discoverable because otherwise, it's just lost in the sea of other pull requests. So I don't know. But I do like the slight push back that you're giving me here of like, yeah, but what if you did something though? And I'm like, yeah, that's fair. I should probably do something. STEPH: Being able to pin those specific PRs that have significant architecture changes sounds really novel, but I'm going to take this opportunity for me to be lazy. And if I'm joining a project, I don't want to read through what has happened. I just want to know what's true now. And if I go back and look at those PRs, I won't know if all of that is still relevant and how it's changed. So it sounds neat from telling the story of how an application has evolved. I like that sort of developer lens, and what are the things that we have tried and then changed over the years? But from I am onboarding to this application, I just want to know what's true today? What are the things that you want me to follow? What are the patterns that are going to be really helpful for me to look at? And so then, I don't know if I would use it in that context. And this may be one of those areas where I'm feeling overly skittish in response to the number of things that you said and the use of inheritance. Because I have felt so much pain of where I'm going up the tree to figure out what the heck is happening in the world and then to understand all of those pieces, and then swimming all the way back down to the class that I'm actually working in. So it could just be past experiences that are now influencing how I want to document or work with inheritance. It probably is. [chuckles] That's probably a big factor of it. It doesn't mean I disagree with it because those painful experiences are meaningful. [chuckles] CHRIS: Yeah. I think the foundational thing...I tried to start this with the context of like; I did a thing. This is another example of good idea, terrible idea; my favorite segment on The Bike Shed. I stand by it. I think it was useful. It does use things that we have traditionally moved away from. I say we because, again, I think we have a shared approach to development at this point. But I think it's worth it. I hear everything that you're saying about the documentation, but I've been burned by that so many times where the documentation is like, here's what's true now. And you're like, no, there isn't even a class called that anymore, and no less does it work that way. And so, my inclination is not to go that way. The solution that I have in mind is when someone is onboarding into the application, I don't expect there to be documentation and other things that I can hand them so that they can run. I expect to sit down with them and work with them. I'm going to pair with people when they join a team for a long time. There's a period where that's true, I think, and then you get to a certain size of an organization, and you're onboarding enough people regularly enough that that's a thing that you should get better at. But for I think a surprisingly long time, my answer I'm more than happy for it to be, yeah, we're bringing someone new into the team. Let's sit down with them. Let's spend the time. Let's tell them what's true because I know currently, and I can give them an up-to-date version of that. And ideally, as part of that, then update the static documentation, the repo, the README, the other things based on the conversation that we have and recognize oh, that that link is very out of date. Let me change that one real quick. But I'm not expecting to have comprehensive documentation for that. I'm expecting to use real human interaction to fill that gap. STEPH: Yeah, I really like that you're also calling out how fallible documentation is and how it has misled us so many times. I also love what you highlighted where when somebody new is joining the team, we are more than often going to sit with them and then explore the app together. And it just made me revisit that phrase that you used earlier about the just-in-time education. Because for this command object, you may join the project and not need to interact with this design pattern for your first couple of weeks, first couple months, who knows? So then it comes back to the idea of how when someone is in the space of where using a command object feels like the right approach, then how do we introduce them to this pattern and then make sure that they have the tools that they need? And if someone is accessible to then sit down and go with them, that's great. But if someone is not accessible, then I still want them to have at least a few of the resources that they need to dive into some of the more complex things that are being included. So, yeah, it's a tricky one. I like this thought experiment. CHRIS: But yeah, overall, I'm happy with it for now. I'm hopeful it will work out for us moving forward, and I'm hopeful that it will also be a sufficiently discoverable or teachable thing within the application. But again, I will certainly report back and see how that one plays out for us. But yeah, that's what's up in my world. What else is going on in your world? STEPH: Something else that's up in my world is I have pulled in a tool that I've used in the past, and I really like it. So I'd really like to talk about it here for a bit because I just find it so useful. And now that I've added it to this new project, it's just really top of mind for me. So I found that when working on a project, there are often times where I want to run something right after a deploy has happened, and I want that to be automated. I can do it manually. I can hop in, but then perhaps if you're deploying across many environments or many systems, you don't want to have to do all that manual work, or you also just want the convenience of you can set it and forget it. And that way, you know something's going to happen. So perhaps it's something where you want to change some data, or if you want to enable a feature flag, then this is really helpful. So the gem I've been using for this is called afterparty, where you can write automated deploy tasks that essentially behave very similar to migrations. So you can write a Rake task. It has a timestamp. You can implement the logic that you want to be run right after your code has deployed, and then afterparty itself, we'll check the timestamp. It will see if it has been run. If it's already been run, it won't run it again. Or if you like, you can set it up so that way, you can tell after_party to say, "Hey, after every deploy, I want you to run this particular task," but it's such a nice improvement to the workflow. And the other thing that I really like about this that I feel is a bit contentious is separating changing data outside of migrations. So I am a big fan of migrations are focused on changing your schema itself. But if there's actual data that you need to change, I really like when that is separated outside of the migration. There are definitely times that I understand it's really nice to just do it all at once, and it's easier. But anytime it starts to get even a little complex, I immediately want to write tests for it. And I can't test my migration. But if I'm changing some meaningful data on production, I want tests to back it up to make sure that I'm scoping correctly, that the outcome is exactly what I expect. It also makes it easier for other people to review. And after_party gives me that functionality so then I can have my migration. But then I'm like, oh yeah, but I still want to automate changing this data because that's often one of the complaints that I hear from people when I do ask them to separate into a Rake task, changing the data. They're like, "But I don't want to have to then follow up and then run this task later." And I'm like, that's cool. Afterparty has you, and you can automate it and not worry about it. So afterparty has been one of my favorite gems to add to applications. CHRIS: That's interesting. There's a bunch of layers to everything that you just said. I think I've worked with after_party on a project. I think we were working together on that project, if I'm remembering correctly. I have no bad memories of it, which given the nature of the tool, makes me think it did its job very well because its whole point is just like, oh cool, now you can just do this thing, and you don't even really have to think about it. Because there are plenty of other times where I've had to orchestrate or do a deploy. And then I SSH tunnel into production, which is a bad idea, and then I'm running Rake tasks manually. And so, I think the fact that I don't have any pointed memories of this is a really good sign for a tool like this. So that's a weird vote in its corner for me. You did say something that was interesting that I want to poke at a tiny bit which was you can't test migrations, and I think that's true. Like, I don't know of any way. And it feels like a thing that is sort of fundamentally deeply true. But I do wonder, is there any gem out there? Has anyone done a weird science experiment to figure out like, I would actually really like to be able to test my migrations? So I think the idea of having to pull data change out of migrations for the reasons that you said totally makes sense. But there are often times where I want to convert from non-nullable to nullable. And in the process, I want to backfill with a given value or something to that effect. And I like to encapsulate that altogether such that if it fails or succeeds, it's transactionally consistent. And I do wonder, could I wrap a test around that? I don't know of a way, and I think it may actually be the Rails testing infrastructure is just like no, we prepare your schema for you in the background, so it's just up to date. And therefore, you don't even have a way to be in a state where the migration hasn't run. But it's an intriguing one. STEPH: Yeah, that's probably a hard absolute that I said where you can't test it, and I'm sure there is a way to test it. How friendly or how easy that is to do, I'm really not sure of. It also feels like one of those areas where it feels like I'm testing this other service that I should trust fully, so then I'm not necessarily testing the migration itself. I'm testing some logic that I've added inside of the migration where I'm changing some data. And the example that you provided is perfect because that's one of those that I'm inclined to include in a migration. It's more like where we want specific users who have this value or in this category. And then, we want to migrate them from this data to the other data. And when we start getting complicated in our migrations, that's when I'm like, this is a bit much, and I'd really like a test that documents that we're doing this correctly. That's where I get squeamish about having data changes in migrations. But you do raise a good point. I don't know; I've never tried to test one. I've just always reached for this other approach, but that is more the pain point of if I could test this data change inside of migration, then that would work for me. That would solve my problem. CHRIS: I wonder if an alternative approach would be to just introduce an object or a class that does this work. So like a command object as it were, to do a call back to earlier in the episode, that does that data transformation because it's exactly what you're describing, for this subset of users do this. But if they're in this state, then do these things and create two new records for any user like this. That sort of stuff is really complicated. Definitely want to have some tests around it. But you're talking about a gem that allows you to extract it into a Rake task-like situation. But I wonder, could we just have a class for that? And I used to be a big believer in your migration should live forever, and they should always be runnable from the beginning of time. I've given up on that belief. That's one of the things that I've been like; I don't know. It turns out I've never done that. It's not an important thing. Just DB schema load is going to be fine most of the time. It's great for the past ten migrations to be around just to tell a little bit of a story. But I'm not tied to migrations being runnable forever. So the idea of you introduce this class, it encapsulates that data transformation. You can test it because it's its own thing. It will still be run within the context of the transaction of the migration. And then you throw it away down the road along with the migration, and you do that migration roll-up thing. It's just a different thought there, although I do like the...well, I guess that would also run automatically, but that runs as part of the deploy as opposed to after the deploy, which is meaningfully different than what after_party does because there might be one of these migrations that takes a long, long time to run because you've got a ton of data. And you want to decouple it from the true deploy release sequence that happens and the time limits that are there. So I think I've now talked myself in three circles, and I'm going to stop. STEPH: I like how you highlighted that part where it does decouple you from the deploy process where it's still automated; it runs afterwards. But say if it's something that doesn't need to hold up the deploy, you don't need to wait for this data to be migrated before the deploy can go out. Then that's a nice separation because then it can happen afterwards. Or if you do need it to happen part of the deploy, yeah, there's lots of interesting bits there. I feel like you and I could talk about it for a while. But we have a listener question that I'm really excited for us to talk about. So I'm going to hard pivot over to our listener question. This question comes from Jonathan. And Jonathan wrote in, "Hey, gang, longtime listener, first-time emailer. I've heard you reference retrospectives a few times as part of your normal development practice. In my limited experience with them, I often find retrospectives don't feel productive because team members are reluctant to raise issues without seeming critical or blaming another team member. I would love to hear you describe how you typically run retrospectives to foster open discussion and make it a productive use of time. Bonus points," oh, I love bonus points "if either of you have experienced rescuing an existing team that was not having productive retrospectives. P.S. Thank you for ongoing participation in the Ruby and Rails communities. I look forward to seeing a new episode pop into my podcatcher each week." All right, retrospectives. I love this question because I've definitely been part of teams that are really struggling to have a productive retro. So I think it would be helpful, as Jonathan highlighted, to go ahead and share how thoughtbot runs a retro. And then I'd also love to touch on some of the areas where I have seen teams really struggle to have a productive retro. So with the thoughtbot format, there are really two questions that we focus on. The first question is, what went well? And this starts the meeting on a positive note, which can help people get engaged before then we move on to heavier topics like concerns and issues. When we run a retro, we ask each person these two questions. So that first question, we go around to the room, and we say, "Hey, what went well for your week or for your last two weeks?" And then we document all of those positive things that people say. The next question is, "What concerns do you have, or what are you worried about?"And the goal here is to highlight issues early, which then gives us the chance to address them as they come up rather than waiting till an issue has grown out of control. And it's usually during the concerns portion that I often see retrospectives fall apart. The reason for that is hearing someone describing a concern is often something that can stir up a lot of emotions. And I know for me, it certainly triggers my instinct to where I really want to dive into that issue, and then I want to solve it. But by reacting to a specific issue and then trying to solve that issue, I'm interrupting that retrospective flow to then focus on that issue. And we may not get to a bunch of other important issues that people had. So that's often where I see retrospectives fall apart. And the way to fix that is to then have the team consensus that hey, this is a space where everybody gets to air concern. We're going to go around the room, so everybody has a chance to speak. We're going to document it, but then we're going to move on and then come back to this later. So when do we talk about concerns? So once everybody's had a chance to share their concern and that's been documented, during that process, you're often upvoting other concerns. So someone may bring up a concern that I also have as well. So when it's my turn to speak, I'll say, "I'd like to plus-one that particular concern," and then maybe add my own or just plus-one some of the others. So then, by the time that everybody's had a chance to speak, you already have an idea on…whoever's taking notes or if it's being ideally shared so the whole team can see. You can already see the concerns that most of the team is identifying with or that are the more popular concerns. So then, as a team, you can say, "Hey, we're going to focus on the top two concerns because that's really the amount of time that we have," and that way, we're focusing on concerns that impact the majority of the team. So at that point, then we can start talking about those specific issues and how we'd like to address them. And then out of that conversation is then the next part of the retro format, our action items. And then action items are where we can capture the things that we would like to try during our next iteration of work until our next retro. This is our experiment area. So then we can say, "Yes, we'd like to try something different, or we'd really like to monitor how this goes." And then one other fun thing that I typically include in retros are housekeeping. So then we can talk about time off, team celebratory events, anything like that that's helpful to highlight to the team. That's a quick overview of how typically I myself run a retro. Chris, do you have anything you'd like to add or anything that I've missed? CHRIS: No. I think that that mirrors pretty well the best retros that I've been a part of. There are a couple of things that I think I would add or emphasize in that. So one is foundationally, with a retro, what are we doing? What's the goal? And the goal with a retro is to identify and evolve our process. So identify where there are any bottlenecks or things that aren't working, and then ideally change things over time. I've been on many teams where just the same issues get brought up over and over in retro, and nothing changes. And that will just completely deflate the team. And so, if that is happening, that's a fundamental thing that we need to fix. And I can totally understand folks being like, "Retro is awful. We just sit down and say the same things, and then nothing ever changes." If that's happening, we have to fix that at a more fundamental level. That is going to be more than a retro's worth of effort. But ideally, retro is now this structured space each week, each iteration, whatever it is where we are discussing what's going on and ideally, slowly, incrementally making the process slightly better. In my experience, it's something that I really love because I come to associate it with stuff is going to get better now. That's what retro means. If that's not the feeling you have, then I totally get why you wouldn't want retro. But I promise that that can be a reality. And then to touch on some of the particular procedural points, everything you said definitely maps. And I've found that structure works really well, but there's a lot of subtle things in that structure that I think are important to highlight. So one, going around the room and actually asking everyone individually for their thoughts, I find to be so useful because it's very easy for one or two more vocal individuals to just dominate the conversation. So particularly by starting with what went well and then also by actually going around the room and requesting "Everyone reply to this question please," even if it's just like, "Yeah, you know what? It just felt like a good week." That's an answer we'll accept but ideally, a little more structure or a little more meat to it. But I find that to be really important. Likewise, I have found that having a facilitator, so someone who is guiding the retro but not actually a part of it. They're not going to be saying what went well or what didn't go well. They are just directing the conversation and somewhat critical as you're going around and asking for concerns. They are the person whose job it is to prevent the team from starting to try and address the concern when it's first voiced. So ideally, we're just collecting the concerns. We're collecting the plus-ones so that we know which are the more prominent ones, and then we can focus on those. And I think that idea of the plus-oneing of concerns and then really focusing on the ones that have more folks that are concerned about it feels really critical in my mind. So ideally, we are a team. We're working as a team, and if one person has this gripe that they really feel deeply, but nobody else really cares about it; ideally, we find a way to help that person not feel that way. But that's not necessarily where the team collectively should put all of their energy. So yeah, that's a bunch of little pieces. Also, just as a note, we'll include these in the show notes, but there are a couple of previous episodes, so Episode 132: “What Went Well?” is a discussion between Derek and Sage, previous hosts of the show, talking about retros. Episode 172: “What I Believe About Software” was the first guest visit by a certain Steph Viccari. And so that is a wonderful episode in which we dug into retro because it's one of our favorite topics. Also, Episode 299: “Is Agile Over?” We definitely touched on...that was a pretty recent one, but we touched on retro. Then there's also a video on Upcase called “Running a Retrospective” that basically describes exactly this process and shows actually an example retro and running through it. So there are lots of other things that we can point out here. But again, I think fundamentally, what are we doing, and how are we doing it? If we can answer those questions well, retro is going to be great. If not, it's probably not going to be that great. STEPH: I appreciate you calling out all of those important nuances because those nuances are what lead to then a retro feeling more productive. And to address Jonathan's other question around if people are feeling timid to bring up an issue because they don't want to blame anyone, then I think to address that one; specifically, you have to come to retro with a WE mindset. And I think HBO accidentally sending a test email is a really good example of that. Because in the Twitter thread, a bunch of other I presume developers were commenting and responding in support of the person that sent that out to say, "Hey, you discovered a missing safety net in the system," or the fact that it was fairly easy to make this mistake and send it out. So if you come to retro with this mindset of if a mistake was made, how can we as a team improve this so then it's less easy to make that mistake? Then you won't have the sense of we're blaming this on one person, but instead, we as a team are responsible for helping each other out. CHRIS: It's interesting to have that conversation in the context of retro because I don't necessarily think of retro in exactly this way. But there is the idea of blameless postmortems, which come out of the Google Site Reliability Engineering; I think it's a book, maybe it's a website. We can include a link regardless. But that idea of blameless postmortems of collectively as a team, this thing made it out into the world, this bug, this problem. So we need to own that as a team, and we need to have a blameless conversation around that, just talking about what happened. And there are subtleties there. And that's a nuanced idea that needs to be evolved, but that is at least some writing that exists in the world that talks specifically to that part of it. That said, I wonder if a true postmortem, so a distinct meeting just dedicated to those more pointed issues, might be more relevant, and then retro is more of a shared overall conversation. But if there are smaller versions of that, then I think using that framing could be really helpful in retro. STEPH: Yeah, I think you said that perfectly where there needs to be team ownership over all of the issues that are being discussed. And I think there is one other very tricky area to navigate with having a productive retro. And I don't know of a better way to say this. But you have a grumpy goose on your team. You have someone who doesn't like retros, and they're going to be negative, and they're going to be vocal. And that is a hard one. I have been there before. And I often approach that situation by speaking with them specifically around what are your concerns with retro? Are you willing to at least buy-in and give this new format a chance? But you essentially need them to buy in or have leadership buy-in so then they know to follow suit as well that this is a team process that we're going to improve and work on together. And if you don't like it, then that's what retro is for. So how we can make this a better, more productive meeting? But just showing up and being grumpy isn't helpful. And then helping people who have been burned by retros overcome that negative reaction to retros is something that takes time. CHRIS: Oh yeah. The grumpy goose just affects everything on the team. But definitely retro is one where I've seen that particularly pointed. I think in those cases, the best luck I've ever had is to, like you said, have a separate conversation but have the conversation at a higher level. So the question isn't about do we have retro or do we have it in this shape? The question is, do we think we are operating at our best? Do we think everything is going perfectly? And almost never will the answer be "Yeah, this is great. We have no bugs. We're moving as fast as we possibly can. Everyone is happy. No one is burnt out." And so if we get to an agreement that is like, well, yeah, sure, there are things that we could improve, then I think that's a toehold that we can then build on and say, "Okay, so how do you want to go about that? I am fine to explore a different approach than retro as a meeting to continually improving and evolving our process. I'd love to know what thoughts you have, Mr. Goose." But if they don't have an alternative, retro is the most effective structure that I've found for this continuous feedback loop around the process. I'm very happy to find an alternative, but I critically think we need something like that. And so if they're going to be pushing back on retro specifically, then I'll bump up to the higher level and say, "Okay, how do you want to be improving our process? Let's try something else, but let's make sure we are asking the question of how do we improve our process and is that succeeding?" And also, stop being so grumpy. Come on, what are you doing? STEPH: [chuckles] I recognize that approach so much because then it really gets to the heart of the purpose of retro whether it's actually called retro or how we handle it is not significant, but the fact that we together as a team can get together and discuss how to improve. That's really the important thing that we're after. And retro just happens to be the format that I use and really enjoy. But like you said, it's always open to each team's interpretation. On that note, Jonathan, I hope this quick overview of the thoughtbot retro has been helpful. And we will also include some other links that also highlight how thoughtbot runs retros and some other discussions that we've had about retrospectives. But on that note, shall we wrap up? CHRIS: Let's wrap up. The show notes for this episode can be found at bikeshed.fm. STEPH: This show is produced and edited by Mandy Moore. CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review on iTunes, as it really helps other folks find the show. STEPH: If you have any feedback for this or any of our other episodes, you can reach us @_bikeshed or reach me on Twitter @SViccari. CHRIS: And I'm @christoomey. STEPH: Or you can reach us at hosts@bikeshed.fm via email. CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Bye. Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.
Let's talk about Agile! What is it, what do we like, we do we not like? In this episode, Steph and Chris discuss: Broadly, are they fans? What makes this practice work well? What makes this practice work poorly? And also, hit specific topics and practices like Scrum, Kanban, and Extreme Programming. Twitter Poll re: Gotime Podcast - Is Agile's Time Over? (https://twitter.com/gotimefm/status/1388126124299878412?s=21) The Mortifying Ordeal of Pairing All Day (https://www.simplermachines.com/the-mortifying-ordeal-of-pairing-all-day/) The Real Story Behind Story Points (https://thoughtbot.com/blog/the-real-story-behind-story-points) Agile Manifesto (https://agilemanifesto.org/) & Agile Manifesto -- Principles (https://agilemanifesto.org/principles.html) Extreme Programming Introduction (http://www.extremeprogramming.org/index.html) Extreme Programming Explained (https://www.amazon.com/Extreme-Programming-Explained-Embrace-Change/dp/0321278658/) Ron Jeffries - What is Extreme Programming (https://ronjeffries.com/xprog/what-is-extreme-programming/) Transcript: CHRIS: I feel like we should try a couple of different byes just so we have sort of a smorgasbord of options, and then we can pick the best one. STEPH: With countdowns, [laughter] because I do so well with countdowns. CHRIS: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey. STEPH: And I'm Steph Viccari. CHRIS: And together, we're here to share a bit of what we've learned along the way. So, Steph, I thought we would try maybe something a little bit different this week, a little bit more of a structured topic. In particular, I've been gathering little tidbits of information. I've been seeing conversations happen all around the topic of Agile, things that people like about Agile, things that people hate, mostly it's things that people hate about Agile. Lots of ire on the internet about Agile, but I think also some disagreement about what it actually means. And I think; generally, you and I are probably fans, so I want to talk about that. What parts do we like? What parts do we not like? What do we think Agile actually means or, at its best, maybe what it means? But yeah, let's start at the very top stuff. Steph, what do you think about Agile? STEPH: I am generally a fan. I'm with you. And yeah, the internet being full of more negative remarks and ire, that sounds very true. But generally, I am very much a fan of Agile, and the very broad scope of this is how we work, and this is how we plan our work, and this is how we collaborate as a team, and then how we reflect on the work that we have completed. I can also pick apart some of the things I don't like about Agile, but in the broad umbrella definition, I'm a big fan. I've enjoyed that approach. Granted, I've also only ever used Agile. I haven't written software using a Waterfall style, at least not purposefully. And then if I have encountered a team that was using more of a Waterfall style, then we changed it quickly. I really only have known the more Agile approach to writing software. CHRIS: I think that's largely true of me as well, where most of my work would fit somewhere under the umbrella of lowercase "a" agile, although I've tried variants of Scrum and Kanban and a bunch of other things that we'll probably chat about today. But I think in general, I find that things are most effective; things seem to move the most smoothly. And I think the software that we come out with is the best one. It's closest to those very simple ideals of Agile. And every layer of process that gets added on even though, like you, I've not done true Waterfall where it's like six months requirements gathering and then it gets handed off, and no one talks for a while. I've never done that. STEPH: I have to interject because I actually think you have in a previous life when you were an engineer. You have done the more Waterfall. Like, you have to plan very far in advance. CHRIS: I think this is one of those cases where people think "engineering" quote, unquote like mechanical engineering is one thing and it's actually...there is a little more structure, and there's a little more necessity of sequencing where you've got to figure out what you need to buy first because sometimes it takes a while to find the particular piece of metal that you need in the world. But it also has a lot of figuring out as you go and being like, well, we've got a bunch of stuff, and we're just going to figure it out. And also, this is something that as I was studying software while working as a mechanical engineer, I started to hear about this whole Agile thing, and I was like, huh, I wonder how I can bring more of that? Because I definitely saw cases where a more Waterfall-centric approach to engineering projects was leading to bad outcomes. It's like we decided upfront what we're going to do, and then we went away for six months, and we did it. And then we came back, and it turned out it was wrong. So that was solvable along the way. There were ways to build prototypes and things like that. So that is definitely a part of the mechanical engineering world. Although I think there are some true constraints, but I think there are also some occasionally self-imposed constraints, but again, I see sort of the same thing in software. Anytime that we can shorten feedback loops, that's what I like. And I think that for me, that's the core of Agile. Specifically, to come to the Agile Manifesto, to start at the very top, the thing that kicked it all off is a very simple document that the first line of it is "We prioritize individuals and interactions over processes and tools." It's like, yeah, that seems like a great thing, having more regular conversations about the things that we're building rather than having those initial conversations. And everybody goes away for a while and tries to build that thing, and then they come back, and hopefully, the thing that they've produced actually solves the problem. But I think almost always there are some deviations like, oh, actually, it would have been better if it was like this or now that we're actually trying it in the field, it's fundamentally different. So in that way, I think there's actually a lot of commonality between mechanical engineering and software development. STEPH: Okay, that makes sense. Yeah, I was thinking around the process of where you'd have to order stuff in advance versus for us; we can describe everything that we need as we need it unless we're having to procure some specific software or licensing. But otherwise, we don't have to wait on that shipment flow to then have our goods. And then, if we also mess something up, then we don't have to reorder more pieces. But I like how you started talking about that agile with lowercase "a" and then talking about the manifesto because I suspect most people are familiar with Agile, but it wouldn't hurt just to read off some of those top things about what Agile is so that way we're all on the same page together for this conversation. So you already covered the first one that talks about individuals and interactions over processes and tools, and then the others are working software over comprehensive documentation, customer collaboration over contract negotiation, and responding to change over following a plan. And that's it; those are the aspects of Agile. And so then, circling back to what you were saying earlier where people are having more criticisms around Agile, it sounds that it's less about Agile, and it's often more about the implementation of these ideas and then how you're approaching them. Because, boy, do we have several ways to implement Agile. We have Scrum; we have Kanban; there's Extreme Programming. Does that fall within the Agile umbrella? I think it does. CHRIS: I believe so. And I think a lot of the things that people take issue with particularly come from Scrum and Extreme Programming. We're taken to their extremes. Yeah, it's right there in the name, so you should probably know that it's going to be a little out there. But taken to the extreme and especially where it becomes rigid and dogmatic, then it becomes a problem. But again, so we listed out now the four items that are the core of the manifesto. There is a separate part of the manifesto, which is the principles, which digs in a little bit deeper, but it's still very much in that same ethos. But I do want to highlight because there's a subtext to the Agile Manifesto that I really love, which is given there are things on the left and then things on the right when the Agile Manifesto was presented. And so it's like we like individuals and interactions, that's the thing on the left, over processes and tools. And so the subtext below it is that is while there is value in the items on the right, we value the items on the left more. And that's one of the things that I love about the Agile Manifesto is it's not this very rigid thing that says, "This is good, and that is bad," it is a statement of a preference of well, yeah, it's definitely good to have comprehensive documentation. That's a really nice thing to have, but it's incredibly difficult. And if we have to choose, we're going to choose working software. We're going to prioritize that well before we have comprehensive documentation. So I really love the juxtaposition, and the emphasis on it's not that one is good and one is bad of these two things that we're comparing but that we have a preference, and that we want to orient our work around the items on the left rather than the items on the right, which I think the items on the right are more traditional or were more traditional to the Waterfall approach. STEPH: I like how you highlighted how those statements are presented to the reader. So then that way, as you mentioned, we still value what's on the right, but we favor more what's on the left. So one of the things that I saw recently was something that you shared with me in regards to where you're bringing up the idea of, like, hey, let's talk about Agile. And you shared with me a clip or a specific tweet that linked to a clip from the Go Time Podcast, which is a podcast that I hadn't listened to before. But I listened to that episode or at least part of it, and it's really delightful. I enjoyed listening to them very much. And they had Kris Brandow on the episode. And at the end of the episode...and they do something really fun where they ask the guests, "Do you have an unpopular opinion that you'd like to share?" And one thing that I like about their unpopular opinions is they often have polls afterwards, and they want to see was this truly an unpopular opinion? And if most people agree with you, then they actually consider it nope, he didn't win. I don't know if they use the word win if you didn't achieve the unpopular opinion. And in this instance, Kris shared the opinion that Agile is done and over with and that we should move on, which is a big thing to say. Everyone on the podcast reacted in a similar way that I would where it's like, well, how do we track things? And there are still things that we need to care about. But then also, there's a part of me that's just like, yes. I am not sure where Kris has heard it just yet when I heard that, but I'm already tuned in and very interested. And one of the things that Kris said that also really resonated with me is he mentioned that "I've never worked on a team where Scrum specifically like sprint and story points functions well," and I absolutely agree. There are parts of Scrum, we can get to the specifics that I think are fine that I've certainly used in the past and that have worked. Story points resonate deeply. I very much agree that story points are something that I do not enjoy using, and I do not find that they really lead to building software. There's even a blog post that I published along with Matt Sumner, a former thoughtboter and guest on this show, where we talk specifically about story points and some of the concerns and issues that we have with using story points. CHRIS: It was actually also the first episode where you came on as a guest to Bike Shed; that that was the topic that we dove into because it was so near and dear to our respective hearts. STEPH: That's right. I forgot about that. So yeah, story points are certainly up there on my don't list. I feel like we're doing a fashion do and don't, but we're doing the Agile do and don't list. [laughs] CHRIS: I kind of like that. Yeah, we should lean into that vibe. But yeah, continuing on with the poll there, it was interesting to see also, like you said, they tweeted out, and then there's the poll that comes after. And it was 64-ish percent of folks agreed that Agile's time is over and done with, and we need to move. Granted, it wasn't a huge sample size. It was like 85 people that took the poll but still, seeing both the statement and then also the general support from folks on the Twitter, it was interesting to see. So I do have the question of like, well, okay, if not, what else? And I share your sentiment of we should be able to ask questions and iterate. And nothing is so precious that it can't be replaced by something else that's better. So we always need to be trying to find the best ways to work. But again, I think there are still kernels of good stuff in the Agile. So I found this and I was like, oh, this is interesting. What's going on here? STEPH: So I'd love to dive into some of the specifics around Agile to understand what are the bits and pieces that work for you and the bits and pieces that don't. So if we are taking our Agile approach and reviewing the things that do and don't work and changing that process, what are the things that you would keep, and what are the things that you would throw out? CHRIS: Yeah, well, we can dig in, and we can bounce back and forth, I think, on this. But again, there are sort of a few different camps. So I collected together some of the lists of practices associated with some of the different approaches to Agile. So starting with Scrum, which I think perhaps is one of the most rigid, most structured, and perhaps most ire-deserving of the approaches to Agile, one of the first things is sprints or iterations, so the idea of starting...before you begin the work, you sit down, you define how much work you think you're going to take on. There's often an estimation process. Actually, we'll say that because that's maybe a separate idea, but even just broadly the idea of sprints and iterations, which often involve the idea of committing to a certain body of work. And that commitment is always handwavy and loose. No, no, no, we won't hold you to it, but then it's a constraint that's placed on the team. It's an expectation that's set, but it's wildly difficult to estimate software, as we all know. So sprints and iterations, personally, I am not a fan of. I really like a more continuous flow where we're constantly reprioritizing the work to be done. We're constantly measuring against what we built, what we think we need to get out there. How can we get something out in front of users as quickly as possible? But I've not found a ton of utility in the sprint or iteration workflow. But what do you think of that one? STEPH: Yeah, I'm generally not a fan of sprints, and it has taken me a while to get there. And I feel like I can admit that openly because it is something that I feel like when I first started doing software development, sprints were life. It was how you planned everything. It was how you committed to work. It's how you measured your work. It's how you then looked back to see what you could and couldn't accomplish in two weeks' time or maybe a week's time, depending on how long your sprint is. But over time, I have realized that I don't like the mentality of sprinting, and that may just be a nitpick on my part, but that is something that I don't enjoy because we write better software when we have breaks. And with the sprint methodology, there's really never that break unless you're going to plan that into your sprint. And then there's the idea of the upfront commitment, as you'd mentioned, it's one of those, don't worry, we're not going to hold you to this, but can we all commit to this work? And it's one of those you just feel compelled to say, "Yes," to the person who's asking because then you feel like a jerk if you push back and you say, "Well, actually, I don't know if I can, so I'm going to commit to way less." And then that's the approach that I started taking of, well, I don't know. So I'm going to always commit to a little bit because I'd rather overachieve and then deliver more than come in under because I could work really hard, but I've over-committed and then still feel like I didn't reach my goals, and that's a rough feeling. So I found that I was already lowering my commitment there. So then, it felt more appropriate to be in line with that sort of continuous workflow instead of trying to commit to all these features or all these tickets that needed to get done. I think those are the two areas for sprint where it doesn't align with me and where it can work for teams. But I feel like there's always that underlining unhappiness that a lot of us just don't want to talk about because we don't know what else to do other than to keep sprinting. CHRIS: Yeah, I think you said something about the specific, like nitpicking the word sprint, but I do think that's actually meaningful. It's The Bike Shed, after all; if we're not going to Bike Shed about some words, what are we doing here? But I do think that we're using that word...it's obviously the wrong word; this thing's a marathon. You can't have 26 2-week sprints back to back throughout a year. That's not going to work. That's not how humans work. But any amount that we let that thinking into our head, I think, is problematic. If I'm understanding correctly, it sounds like you've come to a place of comfort around committing to a smaller body of work and then ideally overdelivering. But in my experience, many developers, perhaps even most developers, don't feel comfortable. It's so difficult to say, "Yeah, I know that the login form should take a day. That's what I feel in my heart. But let's be honest, every other time we've done a form, it's taken a week. So I'm going to say a week." It's so hard to do that. And so I think continuously, we end up in a mode where we are failing to meet the collective commitment that we made, and that's demoralizing. That's going to constantly just be a drag on the team, even if they're fake, made-up deadlines that we're constantly setting, that we're constantly not hitting. Just doing that over and over, I think, is really detrimental to the morale of the team, to the cohesions, and the feelings of are we actually doing this work? So perhaps pedantic, but I definitely share all of that. STEPH: I do want to highlight, as I mentioned earlier, I'm feeling more comfortable that I can under commit and then I can overdeliver, and that is hard. That is something that still in the moment, even today, is very hard for me to do. And it's like how you said, in my heart, I feel like this should take a day, and the heart lies. But on top of that, it's often it's also my ego that's driving me all the time. And with that, it feels like a competitive environment to me where someone's saying, "Hey, can you get this done?" And in the moment, that brings out my more competitive side where I want to say, "Yes, I can get all this done, and I can deliver all the things." When, in truth, that's often not how it's going to work out. There is one thing I do like about sprints that I want to reflect on, or perhaps it's actually two. And one of them is that we are getting together every so often, and we're agreeing on the important work to be done. And I really like that planning process that is typically coupled with a sprint. So you get together, you review the work, you address any concerns or raise any concerns. And then you could say, "Yes, we all agree this feels like important work." And essentially, we're buying into the work that's getting done, and I really like that process. And then, as an extension of that, I really like how we often then pick themes. So as we are agreeing to the work, we're often grouping together work that makes sense where it's either the most cross-functional or collaborative. We're already going to be in that space together. We're aware of what everybody is working on. And those are the aspects that I really do like about sprint and some of the other styles, that more continuous workflow of where we're always pulling from a backlog. It feels more of a grab bag in terms of I don't really know what I'm going to get next. I don't know how this work has been reviewed or vetted. I haven't really gotten to talk to anybody, perhaps. I'm making some broad statements here. But I haven't really gotten to talk to anybody from the product side to understand this change. And I also don't really know what the rest of the team is working on, so I feel more disconnected from them. CHRIS: Yeah, I definitely share that, the planning or the meeting where we discuss the work that's coming up and shape it a little bit; I love that. Although it's interesting within the context of Scrum, I think like truly to the letter Scrum; my understanding is there are very discrete meetings, and they each have a distinct purpose. And so there's the sprint planning meeting, there's a backlog grooming, there's a sprint review and the sprint retrospective. And each of those are these four distinct meetings that are happening once every two weeks or so or whatever your sprint cadence happens to be. And the splitting of those becomes interesting. And some of the practices in there, I think, are...I think you and I share not being interested in doing them or not finding them to be super valuable. But I think broadly having some version of hey, let's sit down and talk about the work before we have to do the work, definitely a fan of that. For me, it often can be let's collapse four of those meetings into one sort of thing and maybe have it more regularly or something to that effect. But actually, we'll touch on the rest of those. But if you're good with bouncing from sprint/iteration, I think we've covered that topic well. Let's move on to one that I think we can do pretty quickly because I'm pretty sure I know how we feel, but sprint planning/planning poker/estimation. How do you feel about this one, Steph? STEPH: We grouped a couple of things in there. There's sprint planning, and then there's sprint poker, and those are different to me. CHRIS: Yeah. So let's go specific to the planning poker as the most pointed version of it but also generally estimation and sizing of stories. STEPH: Nope. Throw it out. I don't know how to play poker. Let's just get rid of it. [laughs] I was never a good poker player. CHRIS: Playing poker can be fun, but planning poker...Well, so actually, to ask a slightly different question, I think in the past we've talked about keeping aspects of it, definitely not keeping the let's figure it out, let's hash it out. Let's get down to an exact point value, and then we know we can have 34 story points a week, and that's what we're going to do. But the version of using planning poker, using this numerical communication tool to see if we're aligned, that one I think we've talked about liking that. I have enjoyed that, but under the strict guidelines that we throw the numbers out. The numbers are only a communication tool. They get thrown out after the fact. We do not commit to a set amount of work or anything like that. We just use it to say, "I think it's an eight. I think it's a one. Oh, we should talk," just for that. That's when it's useful. STEPH: I agree. Yeah, in my previous answer I was being flippant about it, but I do agree very much where I don't like the specificity of where you're trying to plan exactly what numbers are these. But I do find it very helpful for the reasons that you just said where the team agrees with the estimation around how long they expect something to take. Because then that is really great where you have someone who's never touched the codebase, and they're like, "I think it's a five or whatever system we're using here." It's an elephant...whatever scale you're using. And then someone else is like, "Well, I think it's a doughnut size." I'm making up silly stuff because it's more fun for me. And then those two people can talk and reconcile. So I do like discussing the estimation of work for that purpose but then not actually writing it down or maybe going with t-shirt sizes, something that's more simple, and then doesn't have anything with points, really. Anything with points can then be gamified and also brings out people's more competitive side. So, if you can make it something that's more fun, maybe around t-shirt sizes or a bunch of cute animals, various sizes, whatever works for your team. I'm trying to think of other fun measurements now [laughs] that we could use instead of t-shirt sizes. CHRIS: There are the sizes of bottles of wine as you go past. So there's a regular bottle of wine, and then there's a magnum. And then it gets to weird names like a Nebuchadnezzar and other things. These are big performative champagne bottles. So I think we should use that kind of sizing because I think they also have a geometric progression type thing, not quite Fibonacci but something like that. So I'm going to make that push for Nebuchadnezzar as being my go-to [chuckles] sizing in story points. STEPH: I have never heard of that, and I love it. That's great. CHRIS: Okay. We'll find a relevant link to the wine bottle sizing, and we'll put that into the show notes. We will also, of course, include a link to your wonderful blog post. What's the story with story points that you wrote with Matt Sumner? Because I think that really does dial into this topic really well. And again, coming back to that core idea around Agile, while we see value in the item on the...which side is it? While we see potential value in story points, I have worked with countless teams who desperately wanted to make this thing work. So it would be great if we could quantify the work and then numerically understand the work that we had ahead of us and sequence things and talk about deadlines and whatnot. Man, that would be amazing. I would really love to do that. So with every other developer and every manager of a team of developers in the world, I have not seen it done. I am still looking for that day. When that day shows up, then I think this will be a wonderful practice. But unfortunately, my experience has been that this doesn't work, and trying to do it causes more harm than good. STEPH: I agree that I certainly understand the reason that people want story points to work because it's very nice to then say, "We can calculate, and we can measure, and then we can have delivery dates." And that's really nice from a management perspective. But that does blend in nicely to the next topic, which I think fits nicely underneath the Agile umbrella, our daily syncs. Because that does bring us closer to that goal of where we can't give real valid updates on how something is going and provide a more real estimate as to when we think something is going to get delivered. That doesn't have the same effect of where we think we're able to plan and then promise delivery dates a week in advance because we're getting those updates in real-time, but they're going to be more reliable. And that is, we're so much more than where we try to over commit to work or if we try to say how much time something is going to take. And that is so much more valuable to have that reliable update and estimate versus trying to trick ourselves into thinking that we know when something is going to get delivered. CHRIS: Yeah, I think the daily sync or sometimes called the daily Scrum, or standup, or otherwise morning meeting often in the morning, this is one that I see lots of folks really hate, and I'm personally a big fan of. This is one that I would definitely hold onto. But I think you have to be very, very purposeful with how you structure it. It really should be as short as possible. And there's one particular thing that I see very regularly in teams, which is almost a performative version of what I did yesterday. It's trying to demonstrate to the team that yes, I, in fact, did work yesterday. I was a valuable team member. Please don't let me go from the team. And I think that's the sort of thing that we should try and just get rid of. There are definitely times where what you did yesterday is relevant to the team, or you worked on something, and now you have a bunch of questions, and bringing that to the team is useful. But that version of everyone needs to prove that they did work yesterday or...it's the sort of thing like if anyone says that sort of thing, then everyone else is like if you don't say what you did yesterday, then it sounds like you did nothing because everyone else is saying what they did. So you have to, I think, get a team buy-in to do this, say, "We're not going to talk about sort of bullet-list what we did yesterday. That's not going to get us anywhere as a team." But what's useful are those little magical moments of connection where I say, "Yep, I'm working on this. I'm going to implement it in this way." And someone's like, "Wait, wait, that way? Oh, we shouldn't implement it that way." And then ideally, what happens there is okay; let's connect after this meeting. You've now made this connection, but you don't need to hold up the rest of the meeting for that. You can just say, "Cool, this connection has been made. That's an incredibly valuable little point in time, but now let's continue on with the flow of the meeting," so that it keeps that rapid pace. And so times where you're blocked, times where you have questions, times where you're just describing what you think you're going to be working on. So if anyone's like, "Oh wait, no, we needed to stop that work because we actually made a decision yesterday that impacts whether or not we actually wanted to build that feature at all." If you can head off incorrect work at the pass, there's so much potential value in that meeting that it is interruptive. And it does take up some time, but I find that it is so, so worth it if you're able to really keep it focused, keep it concise, and keep that end goal of those little connections. When those happen, they're so valuable. So I think it's really worth the input. STEPH: I'm still smiling from where you said performative of what I did yesterday because that is something that took me a while to understand, one of the things that I did not like about the daily sync or daily meeting whenever your team gets together to talk about the work that's being done. And it was finally when I realized we're just going through a list of who has the longest list of the things that they accomplished yesterday. And again, it felt like it was bringing out more of that competitive mode in folks to talk about what they did, and it didn't feel very useful. Every now and then, maybe there was one thing that was interesting that someone did. But most of the time, it was always more helpful to hear what the person was working on that day for all the reasons that you just highlighted. There is one practical concern that I have with these types of meetings or with these types of events. And it's where you'd mentioned where if we can keep it concise…and someone brings something up, and it starts to devolve into a conversation right there. So then whoever was up next is now waiting while that conversation is happening. And that part gets awkward because then there's usually one person who is then willing or no one frankly is willing to then say, "Hey, so sorry to interrupt, but let's actually table this discussion and let everybody else go, and then we'll come back to this." And if you have people on the team that have been there for a long time with that culture, then that will just work because everyone will keep each other in check. But otherwise, if you're starting that new process, or if you start to notice there's always that one person who's doing that awkward thing of trying to then set that culture of this is how we do our daily chat, and these are the things that then we wait for later, it's really hard. And I say that because I have often been that person that's in that space where then I encourage people to table a conversation. And it always just feels awkward to interrupt someone and ask them to please wait until everybody else has gone. CHRIS: I share your hesitations around that, but it is very important. And it's that sort of ideally someone in a more senior position will model that behavior and model it in a positive, friendly way. Where I have done that often it's in the form of a question, so it's, "Actually, do you think maybe we could take this offline?" or something like that. Not a command, not taking over or shutting people down because it is somewhat interjective, and you're sort of correcting course. And so, being as friendly and empathetic in that moment as possible, but that's a hard note to strike. And again, if it's something that only one person is like the taskmaster, the Hermione Granger of the team who's trying to keep everyone focused and doing their homework sort of thing, nobody wants to be that. Well, Hermione did, but otherwise, nobody wants to be. STEPH: I love all the Harry Potter-themed references that have been coming through in the last couple of episodes. And I agree it is something that's hard to help teams course-correct, but it's important, and it's very much something worth doing. I just recognized that I think that's why these roles get implemented, why there's this concept of a Scrum Master, and then why we designate these tasks to specific people because then you have someone who can do it. And then when they do interject, it feels more appropriate because that is their role, and that's one of the things that they're supposed to do versus putting it more on the social pressure of whoever is comfortable speaking up to then course-correct. So I do understand where that implementation of Agile has then tried to create those roles, which I've been on teams that have a Scrum Master. And my experience is it's often been a very positive experience because the person that is in that role is often very kind and caring about that team. And so they are a wonderful person to work with, but it's also one of those...I've also been on teams without them, and things have been fine. So I have mixed feelings about that one. It's one of those; it feels like an extra heavy process, but I've also been on teams, and it worked. CHRIS: It's interesting the way you frame it, of the utility of that role. Like, having a role where we've now all bought into the idea that this person may take these actions say, "Hey, can we take that conversation offline?" and rather than one individual choosing to do that. I like that framing. I share what you're saying about the rest of the baggage that comes along with having this formal position, and often, that person is otherwise removed from the work. That can often be an aspect of Scrum. I think that gets complicated. But now I'm wondering can we make a software solution to do this? Because, of course, that's where my head goes. Can we have a standup bot that is listening and is like, "Hmm, it seems like you two people have been talking for the past two minutes. I'm just going to interject like my little bot self that I am and ask maybe take this conversation offline," in the way that we've sort of automated a lot of code formatting things, and that's been really wonderful, so that's not a part of PR review. Can we do the same for standup? I don't know. STEPH: I think all the award ceremonies have these where they start to play the music, and that's your cue to move off stage. CHRIS: Oh, I like it. STEPH: I think that's it. [laughs] So you cue the music whenever someone has been going for quite some time. On a slightly separate note but still related to this, some conversations that have been bubbling up around me have been related specifically to this idea around stepping in to say, "Hey, I'll take on that thing that you need a volunteer for," or "Hey, I will help the team stay on track," will often fall on people with a specific personality and then they will often be the one that continues to do that. And so they will end up taking on additional work or taking on additional roles just because they may be in a more empathetic spot where they feel that's the kind, helpful thing to do. And so, we've been looking for more ways to make sure that those tasks are being distributed evenly across the team. So we're not just waiting on someone to say, "Who would volunteer for this?" And then typically being the same handful of people that are always speaking up and then volunteering for it. And then trying to shift to more of a purposeful approach of having a queue of people and then cycling through that queue, and then if someone can't do it at a certain time, then we move on and then we just put them back in the queue. But this way, we don't have people that are typically just always taking on these responsibilities. And that's something that is a new consideration for me but one that I have found really helpful to be aware of and notice on your team who's the one that's always volunteering for these roles and checking in with them to see if they're comfortable with this, or if they're feeling compelled to volunteer for stuff because they may feel more inclined to speak up versus others are okay with staying quiet. But circling back to some of the Agile discussions earlier, you'd mentioned a handful of meetings and that you have some feelings about those meetings. What are those meetings that you have feelings about? CHRIS: Yes, the meetings. So again, this is somewhat contextual to Scrum, but the structure of Scrum has a handful of meetings that sort of define the sprint. So you have some at the beginning, the middle, and the end. So there's sprint planning, there's backlog grooming, there's sprint review, which typically includes a demo for stakeholders, and then there's sprint retrospective. And these, as far as I understand it, are four distinct meetings and are intended to be kept distinct so that their purpose stays purified in each of those meetings. And I think my feelings would be that again; I don't really find a ton of value in the sprint structure or in the two-week cadence or things like that. And so I think it can make sense in those contexts to be like, we need to make sure we have space for these things. But in a more continuous context, I think the backlog grooming or, more generally, let's talk about the work that's coming up. Let's make sure that we're all unified in how we're thinking about that work, what we think matters, what's prioritized. I think that is an incredibly valuable meeting. I think sprint review and specifically demo for stakeholders I'm really intrigued by that one. I don't know that I feel like that needs to be a distinct meeting. And in fact, more and more these days, almost every feature I deliver has either screenshots or a screen recording of what that workflow looks like. So we're continuously demonstrating to the stakeholders what does this look like now that it's a real thing? What does an end-user see? What's that experience like? And in retrospect, I think we'll probably spend a minute on that one. I like retros; some people hate retros. Yeah, let's loop back to that. But of those, what are your thoughts? What do you like? What do you not like about those meetings? STEPH: I think grooming is a very helpful meeting that can help a product manager and a technical team have discussions about the upcoming work. I don't necessarily think it needs to be the whole team. I think it can be a couple of engineers from the team; maybe those people rotate, maybe it's the team lead. And they get together with the product manager, and they essentially answer any technical questions about upcoming work. So then it can be refined. So then, as we get closer to that planning session, whatever we want to call it, then it feels more in a ready state for folks to react to and then have opinions on. So I do like grooming, but I wouldn't necessarily advocate that the whole team needs to be present for those. For a demo, I'm with you; it really depends. I've worked on projects where the stakeholders are less close to GitHub and Slack and areas that we could demo some of the work that's being done, and maybe they weren't poking around on staging as much. So it was really helpful to then have a more formal demo to then show them the work that's being done. And then I've also worked on plenty of teams where a demo was something that we used as a fun internal event where we have all these different teams, and we get together. And then we get to show off all the great work that we have done across all the different products. So then us, as fellow teammates, can then celebrate what the other teams are working on. Retros, you know I love retros. I think retros are a microcosm of your team's culture and process. And if your team is struggling to have a productive retro, your team is struggling. Because I think that is representative of your team's ability to get together, and reflect, share concerns, celebrate wins, agree on what's important, and run measured experiments. And if you're not having a retro, then I think you're not going to know how your team's doing until it's too late, and it's going to be harder to course-correct. CHRIS: #HottakeswithSteph. I like it. I like the intensity that you came in with there, but I know retro is near and dear to your heart. So I'm unsurprised that that is the line that you've drawn. I definitely share all of those feelings, particularly around retro, because I think much like the daily sync, I've seen many people who are just like, "This is a bad meeting. It's useless. Nothing ever happens. I don't like it." And I'm often surprised by that because I've found so much value in it. Retro similarly is this magical meeting that can just regularly change the course of how we're working as a team. But I also have come into plenty of teams where it definitely did not have that shape, where it was basically a place that everyone sits down, and somewhat downtrodden restates their list of grievances, their airing of grievances, and then nothing changes. And much like the sprint iteration thing where you're constantly missing the commitments, and that's just going to wear a team down. I think if you constantly have retro and nothing changes and it's that same list of concerns, then that is going to be bad, but that, like you said, is not the reason not to do it. [chuckles] Oh, we just keep saying the same things in retro, so I don't think it's even that valuable. I would say that maybe we should change the things. But I've definitely been on plenty of teams where retro was just so valuable. And it's definitely one where I feel like having a facilitator, having someone who is in that particular seat trying to guide the conversation without necessarily being in the conversation, can be incredibly valuable. There are also structures that I've seen work particularly well. We have a video on Upcase that we can link to. That's a format that I've found; it's a very lightweight format, but it basically involves getting everyone's input on a positive note, on a more critical note, and then revisiting and sort of sorting and waiting, and then digging into topics that need a little bit more focus. But I think a lot of different formats can work as long as retro is a way for people to sincerely meet up, safely talk about the things that they are feeling about the work, and then ideally, some change comes about as a result of that. You mentioned having measured experiments, and I love that as a framing or like something that retro can do for us. STEPH: I really do think that retros are so important because they're the health check of the team. As you'd mentioned, if people are having a very negative retro experience, which I understand, I've had very negative retro experiences as well, and I've walked away feeling like that was not a productive use of my time. But then that is our warning. That is our signal that's saying, "Something is not right, and something's not great, and we're not working together as we really want to be working together." And this retro is just that reminder that is right in our face, that is making this so uncomfortable and feel like a waste of our time because it is informing us that something needs to be improved upon. And we can feel like retros are not productive when we feel powerless to make that change. And that again is then another discussion to have with the team, to have with management, leadership, to talk about how do we get the power to then make the changes that we need to then have productive, happy retros? Because that's going to be a reflection that you have a happy, productive team. CHRIS: Love it, love the framing, love the symmetry there between team happiness and retro happiness. So to summarize, I think we've gone through most of Scrum now. So just to...correct me if I'm wrong on any of these, but I believe sprints and iterations, nah, we'll leave it. Planning poker, definitely not. That doesn't seem good, although maybe just to bring up conversations, but not as an artifact that we save in any way. And then otherwise, daily sync, we're fans. Retro, definitely fans. Sprint review, backlog grooming, some version of those, a lightweight version of a bunch of the meetings seems may be good, but a couple of things definitely are going to leave on the cutting-room floor. Does that sound about right to you for Scrum specifically? We've got other topics to cover. STEPH: Yep. All of that list sounds really good. CHRIS: All right. So we've now found our refined version of Scrum, re-Scrum as we'll call it. But now there's a couple of other pieces...So Scrum is very focused on the ceremonies and the team activities, but there's another facet of the Agile umbrella, which is Extreme Programming, which that's a book. I believe Extreme Programming Explained is the name of the book. And there are various different links that we'll include to point at those. But there are two particular practices that stand out that I have heard some people love, some people do not. So we'll go into both of them. The first is pair programming. What do you think, Steph? Do you like pair programming? STEPH: I do. I'm a huge fan. [laughs] Yes, I very much like pair programming, although it still has its limitations. I definitely want time on my own, and I can get exhausted from pair programming. It is a very vulnerable experience, too, where you have to share with someone: this is what I know, this is how I work, this is how I think. And I think that is incredibly challenging. I find that I am typically more productive when I'm pairing with someone or when I have the opportunity to pair with someone at least every couple of days. CHRIS: Yep. I'm definitely a huge fan of pairing. Although I think specifically to Extreme Programming, I think the idea is 100% pairing. I think you already spoke to this, but pairing is exhausting. And the idea of 100% pairing is I can't really even imagine that; even 50% pairing feels like an incredibly high bar to hold for any extended period of time. There's a recent article that was going around the mortifying ordeal of pairing all day, which spoke of one person's experiences getting deeply burnt out just going through that process. And so, as valuable as pairing is, it's definitely a tool to be used not all the time. That feels like a lot. STEPH: That's a lot of Stephanie singing because I tend to sing a lot whenever I'm stuck or thinking through things. So that's a lot of singing that I don't know if the world wants. CHRIS: I mean, based on all of the various Bike Shed intros that involve you singing, I think the world wants it. That's maybe one person's take. But definitely, something that you said of there's a vulnerability to it. And so many pairing sessions I've either been the one saying this or someone else that I was pairing with has said this to me, but they're like, "I swear I know how to type, just now that someone's looking, my hands don't work." It's like you're in a dream, and your legs don't work. You're like, I know how to run, I swear. But for some reason, my legs are made of jelly right now. Or you can't remember a particular method, or there's just something that happens, and so getting over that hump, getting comfortable with it, I think it is a skill and something to become accustomed to. And so, again, being conscious of that when you start doing it is super important. STEPH: I don't know if this is true because I only have access to people's thoughts when I'm pairing with them, and then they're sharing their thoughts with me. But I do feel like people tend to beat themselves up more when they have someone watching because then you feel the need to say, "Oh, I normally can type, but because someone's watching..." which is so true; that definitely happens. But those moments are some of those really great moments to then reflect on the fact that just because someone's watching us doesn't mean that then we suddenly need to beat ourselves up. And I don't know how philosophical that I want to get with this, but I feel like there are so many opportunities while pair programming to then encourage other people around us to be kind to themselves. That is one of the things that I have really benefited from pair programming is learning to be more kind to myself. And even if I don't know exactly what's happening or what I'm doing and I may not be as confident with someone else, I can still be positive and kind. Just because you're in a vulnerable space doesn't mean that you then need to be unkind to yourself. CHRIS: Yeah. I definitely agree with the idea of being kind to yourself also, where you can, be kind to someone else who you're pairing with, especially if they're finding that they're like, "Ah, suddenly my hands don't quite work." But I have pretty uniformly seen that a pairing session may start out that way. And then as everybody kind of just relaxes into it, suddenly you'll see someone just kind of flying around their editor. And you're like, wait, what just happened there? That was so fast. I don't even know. And so there's just this comfort level that sometimes it takes a little bit of time to ease into. But yeah, so pair programming, broadly yes. 100%, oh, that's going to be a no, no, thank you, not that. All right, so one other practice that comes from Extreme Programming, which is Test-Driven Development AKA TDD. What do you think about that one, Steph? STEPH: I feel like you're giving me lay-up questions here. For anyone that's familiar with us, [laughs] I feel like this is an easy one. Test-Driven Development is a thing. It's a thing that I enjoy. I don't always write tests first, though, so I don't always follow TDD, but I am definitely a fan of tests. So, I guess in that light, it's not so much that I adhere always to TDD. I don't feel the need that I have to write tests first, but I have found that with practice, that often helps me write code where I have tests then help me write out the logic for my code. So generally, yes, thumbs up on TDD, but I'm also not terribly strict about it where if you want to write some code first, write some code first. CHRIS: Yeah, I think I'm definitely in the mode where I like testing. I like Test-Driven Development. I can't always pull it off, frankly. It's hard. It is hard to know how to write a test in advance of the implementation that you're going to write such that the test will correctly constrain the system that you're about to write. That takes a couple of levels of knowledge that if I'm writing a Rail's controller action form sequence, I can probably TDD that because I've done it so many times. But if I'm doing something that's a little bit more new, novel, less familiar to me, then likely I won't be able to pull it off. TDD is like a fancy move that I don't always have available to me. But I consider that whenever I'm in that mode like that's not oh, it's fine to just write the thing before the test. Like, I want to be able to do TDD 100% of the time. I'm just not a good enough developer, frankly. And I don't know that I ever will be because I always want to be working a little bit past the edge of my comfort. So it's a delicate line of when I will not use TDD, but wherever I can, wherever I do have that level of knowledge of the system and the frameworks and whatnot built up, I find it is a vastly more effective way to work. It's not that I feel cool when I do it. It's like I feel much more effective. It helps me stay focused and on task and get the thing done. So it's very utilitarian in that way but also not something I can always pull off. STEPH: So, circling back to when we first started chatting, you were asking about Agile and then my thoughts about it. And having this conversation with you, I'm realizing, or I think I was already aware, but it's helping me re-solidify I'm very much a fan of Agile. There are specific implementations of Agile that I don't find enjoyable, and I don't find helpful to writing software, and I don't find helpful from the project management side either. But broadly speaking, I'm still very much a fan of the approach that we use generally for Agile, where we want to work in small deliverable increments, and then we also want to have the ability to change any moment what is the most important thing to work on? To me, that is the heart of following the Agile process. And I don't think that's going anywhere. Like, I don't think Agile's going to disappear. But I wouldn't be surprised if we see another implementation of an Agile variety of the things that you and I just shared and the things that we like. And so, I feel like most teams that I work with follow Agile within their own unique bespoke version. And we don't have to give it names because everybody's going to have their own custom version where they decide which process works for them and which one doesn't work for them. And that's what retros are for so then you can figure out which process works for you. CHRIS: Once more, Steph on the record about her love of retro. I think the core of Agile, the Manifesto, those core ideas about small iterations, delivering value, staying close to stakeholders, all of that feels deeply true to me. And I would be really surprised if a year from now or two years from now I was doing something that was wildly different from that. But then each of the layers of practices on top of that to varying degrees I like or don't like. And I wouldn't be surprised if aspects of that were swapped out down the road. But that core, that idea of this is how we think about building software. I like that thing; that seems like a good thing. So I'm going to hold on to Agile for a little bit longer personally. STEPH: Same. I still see Agile in my future. On that note, shall we wrap up? CHRIS: Let's wrap up. STEPH: Show notes for this episode can be found at bikeshed.fm. CHRIS: This show is produced and edited by Mandy Moore. STEPH: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or a review in iTunes as it helps other people find the show. CHRIS: If you have any feedback for this or any of our other episodes, you can reach us @_bikeshed on Twitter. And I'm @christoomey. STEPH: And I'm @SViccari. CHRIS: Or you can email us at hosts@bikeshed.fm. STEPH: Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Byeeeeeeee. Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.
After the last episode where database switching was discussed, a number of listeners reached out with thoughts. In particular, one listener gave a reproducible example of how to make things better. Chris talks about why he always moves errors to the left, and Steph gives a hot take where she admits that she is not a fan of hackathons and explains why. Steph and Chris also share exciting Bike Shed show news in that we now have transcripts for each episode, and tackle another listener question asking, "How do you properly implement a multi-step form in a boring Rails way?” Chris talks about his experiences with multi-step forms and gives his own hot take on refactoring: he doesn't until he feels pain! Database Switching in Dev Mode Gist (https://gist.github.com/danott/e698435bb4e1d34bc70853514ba681a7) In Relentless Pursuit of REST – Derek Prior (https://www.youtube.com/watch?v=HctYHe-YjnE) Transcript: CHRIS: Happy Friday or whatever day it happens to be in your future situation. STEPH: Happy day. [chuckles] CHRIS: Happy day or night. I'm sorry, I'm done. [laughter] STEPH: Shut up. [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, happy Friday. How's your week been? CHRIS: Happy Friday to you as well. My week's been good. It's been busy. I am taking next week off for a quick vacation. So it's that…I think I've talked about this every time before I go on a vacation on the podcast, that focusing lens that going on vacation gives you. I want to make sure everything's buttoned up and ready to hand off, and I'm not going to be blocking anyone. And so, I always like the clarity that that brings. Because a lot of times I can look at well, there are infinity things to do, how do I pick? And now I'm like, no, but really, if I'm going to be gone for a week, I must pick. And so yeah, I'm now very excited to lean into vacation mode and relax for a bit. STEPH: Yeah, that's awesome. I hear you. I always go into that same mode pre-vacation. CHRIS: But in tech news, after the most recent episode that was released where we talked about the database switching stuff, a number of listeners were very kind and reached out with some thoughts. In particular, Dan Ott is one listener who reached out not only with just some generic thoughts, but he also gave a reproducible example of how to make things slightly better. So the particular thing that a few folks honed in on was the idea that I was describing the feeling of in production; we can occasionally run into these ActiveRecord read-only errors, which is a case where you have a GET request that happens to try to create or update a record. And as a result, you're going to get this ActiveRecord read-only because you're using the follower database, which has a read-only connection. All of that is fine, but ideally, we would want to catch those before production. We want to catch them in development. And broadly, the issue that we have here is that in production, our system is running in a different way. It's running with two different database connections, one for read-only, one for writing, and that's different than in development, where we're running with a single connection. As an interesting thing, a lot of the stuff that I see on the internet is about using SQLite in development and then Postgres in production. And so that's an example of development production parity that we've really...I think thoughtbot is definitely a place that I internalize this very strongly. But you've got to have the same database, and especially because it's relatively straightforward to run Postgres locally, I'm always going to be running the same version of the database locally as in production. But in this case, I'm now getting this differentiation. And so what Dan and a handful of other folks highlighted was you can actually reproduce this functionality in development mode with a fun little trick where you end up creating a secondary connection to your development database, but you mark it as replica:true. And so, by doing that, Rails will establish a read-only connection. And then, all of the behavior that you configure for production can also be run in development. So now, as you're building out a new feature, and if you happen to implement a GET request that does some side effect in the database, that'll blow up in development as opposed to production, which is very exciting. STEPH: Yeah, that's awesome. I love that Dan reached out and shared this example with us. I actually haven't read through all of the details just yet. In fact, I just opened it up, and I started going through it, and there's a lot of really...it looks like a lot of great notes here and a really nice example that walks you through how to have that production parity locally. So this is really neat. I appreciate Dan sending this to us. CHRIS: Yeah, this is a wonderful little artifact actually that's interesting just in and of itself. We'll certainly include a link in the show notes to the gist that Dan shared. What's interesting...I think I knew of this, but I've never actually seen it before. This is a single-file Rails application, which is a very novel concept, but it's got a bundler/inline call at the very top. And then there's an inline gemfile block, and then a set of requires to pull in the relevant Rails stuff. And then it configures the database connection, configures a single controller or actually a handful of controllers, it looks like, and then it renders inline HTML. And so it has all of the pieces. And I didn't realize that at first, but then I pulled it down and I just ran it locally. So it's just Ruby and then the file that this just represents, and suddenly I had a reproducible Rails app. I believe this is used in reporting issues to Rails so you can get the minimum reproducible test case. And that's why this works is, I think, the Rails core team, over time, has pushed on any of the edges that wouldn't have worked and made it so that this is possible. But it's a really neat little thing where it's this self-contained example. And so running this file just via Ruby does all of this stuff, installs everything that's necessary. And then, you can click around in the very minimal HTML page that it provides and see the examples of the edges that it's hitting. And again, this is in development mode, so it's pushing on that. But yeah, it's both a really interesting tip as to how to work with this and a really interesting way to communicate that tip—so double points to Gryffindor, aka Dan Ott. STEPH: Double points to Gryffindor. I love it. CHRIS: I'm cool. [laughs] STEPH: That's very charming. [laughs] I've never seen anything like this either, in terms of one file that then can reproduce and run in a Rails app. Agreed, double points to Gryffindor, aka Dan. CHRIS: Aka Dan. STEPH: [chuckles] I hope Dan's a Harry Potter fan. CHRIS: I hope so. And I hope he's a Gryffindor, who knows? Maybe Ravenclaw. It's really up in the air. But the other thing that is interesting that I haven't yet figured out here is this works for development mode. I've tested it in development. It's great. I was able to remove the fix line that I had in my code where I had one of these breaking controller actions and run with this configuration in development mode. And then boom, it blew up in development, and I was like, yay, this is great. Move those errors to the left, as they say. But I realized there are some other edge cases, known ones actually. Another developer on the team mentioned something where he knows of a place that this is happening, but that code path isn't running right now just because it's a seasonal thing within the app. And I was like, oh, that's really interesting. I wish there were a way to test all the behavior. Oh, tests, that's what I need here. And so I tried to configure this in test mode, but I wasn't exactly clear on what was failing. But at a minimum, I know that the tests run in transaction, so I think that might make this more complicated because if you have two connections to the same database, but you have transactions, I feel like that might be conflating things, and it wouldn't necessarily map perfectly in. But if we could get that, that would be really great. Moving forward, any new development the development configuration will cover what I need. But retroactively, as I'm introducing the database switching to the application, it would be great if the test suite were a way to find these edge cases. So that's still an open question in my mind. But overall, the development fix is such a nice little addition to this world. And again, thank you so much to Dan for sending this in. STEPH: Yeah, I agree; having this in tests would be wonderful. I am intrigued not having read through the full example that's been provided. But I'm wondering if this is one of those we default to read-only mode, although that feels like too much because we're often creating data for each test. So maybe we default to...yeah, you have to have both because you have to have your test set up where you're going to write data. So you can't default to just being in read-only mode. But then say you want to run a controller action or something else in a read-only mode. So then you would have to change your database connection for that action, and that sounds complicated. You also said something else I'm intrigued by. You said, “Move errors to the left.” CHRIS: Yes. Now that you're asking me, I'm trying to remember the exact context. But it's the idea that there are different phases in your development and eventually getting to production life cycle, and so a bug that a user sees that's all the way to the right. That's as far along the development pipeline as it can be, and that's the worst case. You don't want a user to see a bug. So QA would be a step right before that. And if you can catch it in QA, you've moved it to the left, which is a good thing. But even better than that would be to catch it in your automated tests, and maybe even better than that would be static analysis that's running in your editor, and maybe even better than that is a type system or something like that. So the idea of moving to the left is to push those errors or when you're catching the errors closer to the point where you're actually introducing them. And that's just a general theme that I like or a Beyoncé song. STEPH: I was just going to say, all right, move over, Beyoncé. There's another phrase in town, moving to the left. [laughs] CHRIS: I'm really going for a lot of topical pop culture references today. That's what I'm about. STEPH: We've got Harry Potter, Beyoncé. We've got to pull out one more at some point. CHRIS: We'll see. I don't want to stretch myself too thin right before vacation. But yeah, thanks again to Dan and the handful of other folks that reached out either on Twitter or via email to point me in the right direction on the database switching stuff. At some point, I should definitely do a write-up on this because I've now collected together just about enough information that it feels like it's worthy of a blog post, or at least that's the story in the back of my head. I got to cross a certain threshold before I'm probably going to write a blog post. But yeah, that's a bit of what's up in my world. What's going on in your world? STEPH: I love it. You're saying write a blog post into the mic, so then that way you know it's going to encourage you to write it later. CHRIS: That's the trick right there. [chuckles] STEPH: Let's see, today's been a lovely day. It's been a lovely week in general. Today is especially lovely because it is thoughtbot's Summit, and Summit is where we all gather. We do this once a year. So the whole team, all of us across all of our...I was going to say offices but now just across all of our home offices. And we get together, and we have a day filled with events, and we usually have a wonderful team that helps organize a bunch of events that then we get together for. So a number of those fun events are like paired chats, which is one of my favorites because I often talk to people that I haven't talked to in a long time or perhaps people that I haven't even met yet that have just recently joined the company. We also have lightning talks, and I know I'm very biased, but I think we have some of the best lightning talks. They are just hilarious. So I love our lightning talks. We're also doing escape rooms. Oh, speaking of which, there's a Harry Potter-themed murder mystery that's happening. We have Nintendo Switch parties and a professional tarot card reading, which I've never done, but I'm actually doing that later today after we're done chatting. CHRIS: Wow, that is an adventurous day. And I like that it's fun, and it's connecting people and getting to know your teammates and all those nice things. STEPH: Very much. I also have a hot take. I don't know if I've shared this with you, so I'm going to share it here with you on the mic in regards to this. So previous years, for Summit, we used to have more coding projects, too. They were often opt-in, but that's something that happened. And specifically, we have Ralphapalooza, which is our hackathon. And it recently came up where a number of us were talking about Ralphapalooza, and I have come to the potentially contentious point of view that I don't like hackathons. I'm not a fan of them. CHRIS: Hot take. I like that you led in calling it a hot take, and then you provided said hot take, so I have to respond as if it's a very hot take. STEPH: That's true. Maybe it's not a hot take. Maybe people disagree. What do you think? Do you like hackathons? CHRIS: I have enjoyed them in the past. But I will say, particularly within the context of Summit or Ralphapalooza, I always felt a ton of pressure. It's so hard to right-size a project to that space, to that amount of time. You want to do something that's not trivial. You want to do something that at the end of it you're like, oh cool, I did that. Either it's like a novel thing that you're creating, or you're learning something new or whatever, but it's so hard to really do something meaningful in that amount of time. And often, people are shooting for the moon, and then they're just like, “Ah, so it's just a blank page right now. But behind the scenes, there's a machine learning algorithm that is generating the blank page. And we think with enough inputs to the model that it'll…” and it is actually super interesting work they did. But there's the wonderful pressure at the end to present, which I think is really useful. I like constraints. I like the presentations; they're always enjoyable, even in a case where it's like, this project did not go well, let's talk about that. That's even fun. But it really is so hard to get right. I've never gone to a hackathon outside of thoughtbot, so I can't speak to that, but I know that I have heard folks having a negative opinion of them. And I don't know that I'm quite at the hot take level that you are, but it's complicated, if nothing else. It's a lot of fun sometimes. I particularly remember the Elm project that you and I worked on. Well, we worked in the same group. We didn't actually work together, but same idea. That was a lot of fun. I liked that. STEPH: That's a good point. Even within the context of Ralphapalooza, our hackathons are more...I'm going to use the word sustainable because they're nine-to-five hackathons where we are showing up; we are putting in the work. There is pressure, and we do want to present. But it's not one of those stay up all night and completely leave your family for a day or two to hack on some code. [laughs] Sorry, I'm throwing some shade right now. But even with that sustainable approach, I've always felt so much pressure. I enjoyed that green space and then getting to collaborate with people I don't typically collaborate with, but it still felt like there was a lot of pressure there, especially that presentation mode always made me nervous. Even if it is welcoming to say, “Hey, this didn't go well,” that doesn't necessarily feel great to present unless you are comfortable presenting that scenario. And I also really look forward to these company events as a way to connect and have some downtime and to just relax because then the rest of our days are often more stressful. So I want more company time for me to connect with colleagues but then also feel relaxed. So I was always, in the beginning, I was like, yeah, Ralphapalooza, woo, let's go. And now I'm just like, nah, I'm good. I'd really just want a chill day with my colleagues. CHRIS: Is there an option to go for a walk with friends? Because if so, I will be taking door number two. STEPH: Cool. Well, I feel better having gotten that out into the ether now. But switching just a bit, there is something that I'm very excited about where we now have transcripts for each episode. This is something that you and I have been very excited about for a while and wanted to make happen but just weren't able to, but we now have them. And so people may have noticed them as we're adding them to the show notes. And I'm just so excited for a number of reasons, one, because there are a number of times that I have really wanted to search the shows or an episode for a particular topic and couldn't do so. So I'm just sitting there listening, trying to find a particular topic. There's also the fact that it will make the episodes more accessible. So for anyone that is hearing impaired or maybe if English isn't their first language, having it written down can make the episode more accessible. And there's the massive SEO boost that's always a win. And then I don't know if this is going to happen, but I'm excited that transcripts may help us repurpose content because there's a number of our topics that I would love to see turned into blog posts, and I think having the transcript will make that easier. CHRIS: Yeah. I'm equally super excited about the addition of transcripts, and across the line, SEO is cool, I think. Yeah, that sounds nice. Being able to reuse the content is very interesting to me because this is definitely my preferred medium. I find that I can just show up on the microphone, and it turns out I have opinions about a lot of stuff but trying to write a blog post is incredibly difficult for me. The small handful of good things that we might have collectively said over the years if we can turn those into more stuff that sounds great and honestly, just the ability to search for and find older episodes now based on like, I know we talked about inbox zero. I remember that was an episode, but I don't know which one, now that's searchable, and that's a thing that we can find. I actually still use the Upcase search for…I know I said something. I know there was a weekly iteration where I talked about some topic. And I built the search on Upcase for me as the primary user because one, I'm often referencing content on Upcase, and I want to be able to find it more easily, so I made the search. I also put a SQL injection vulnerability into the search in my first implementation so, go me. But then I got rid of it shortly after. STEPH: I love when people bring that energy of “I introduced this issue, go me,” because I find that very fun and also just very healthy in terms of we're going to make mistakes. And I have noticed a number of times at thoughtbot standup that whenever we make a mistake, or it's like, I accidentally sent out real emails on production for a job that I thought I was testing on staging. Sharing those mistakes in a very positive light is a very honest way to approach it. So I just had to comment on that because I'm a big fan of that. CHRIS: I'm glad you enjoyed my framing of it. I really enjoy that type of approach or way to communicate, although I think it is a delicate line. Like, I don't want to celebrate these sorts of things because an SQL injection vulnerability is a non-trivial thing. It shows up in tons of applications, and we need to take security seriously and all of that sort of stuff. But I think the version that I think is good for that type of thinking or communication is the psychological safety. If we're scared of admitting that we introduced a bug, that's bad. That's going to lead to worse outcomes longer term. And so having the shared communication style openness to like, yep, that happened yesterday. And there should be a certain amount of contrite in this where it's like, I feel bad that I did that. I even feel worse because when it happened, I recognized that it happened, and then I tried to exploit it in development mode to prove it to myself, and I couldn't exploit it. So I was like, I feel doubly bad as a programmer today. I both introduced a bug, and I'm not even smart enough to exploit it. But I know that an uber lead hacker out there could, and so I got to fix it. But that sort of story is part of the game. It's a delicate equilibrium, but having the ability to talk about that and having a group that can have a conversation, I do think that's very important. STEPH: Yeah, well said. I do think there's an important balance to strike there. Pivoting just a bit, we have a listener question, and this question comes from Benoit. Benoit wrote in to the show, “How do you properly implement a multi-step form in a boring Rails way?” I'm very interested in this question because I am working on a project that has a multi-step form. There are probably about maybe six, seven steps, and those steps can change based on different configurations. And our form is not implemented in a boring way at all. It's a very intricate, confusing design, I would say, which I think is fairly common when it comes to multi-step forms. I'm curious, what experience do you have with multi-step forms, and what's your general feeling with them? CHRIS: Well, I happen to be working on one right now. So generally, I don't have an oh, I got this, I know the answer. This is one of those that I'm like; I feel like each time I reinvent it a little bit. But the version that I'm working on right now is an onboarding flow. So we create a user record, which at this point I only have email associated with, and then from there, when a user lands, they need to provide a bunch of profile information, and it is a requirement. They have to fill it out. We need to have all of it before we can actually start doing the real stuff of the application. And so, the way that I've ended up modeling it is interesting. I'm going to use the word Interesting. I think I like it, but I'm not sure. So I have this model; let's call it a profile that we're going to associate with the user. And the profile has a bunch of fields: first name, last name, address, phone number, and a handful of other things. And again, I need to have these pieces of information. So I want those to be non-nullable columns. But as someone is walking through this form, I'm not going to have all the information. So there's going to be a progression. We'll get first name, then we get last name, and then we get the next piece of information. So I need a nullable storage, but I don't want to just put it into the session or something like that, which I think would be an option. So what I've done is I've introduced a secondary model. So this is a full ApplicationRecord database-backed model called partial profile. And it is almost identically the same interface as the profile, but each field is nullable. There's also a slight difference in that the profile field has an additional status column that talks about once we've gone through all of this, we can add some status and track other things. But yeah, that main difference of in the profile, everything is non-nullable, and the partial profile is nullable. So then there's a workflowy object, a command object, as I like to have in my systems these days that handles the once they've gathered all their information, turn the partial profile into a profile, send it out to an external system that does some verification and some other lookups and things like that. And then, based on the status of that, mark the status of the profile. But one of the things that I was able to do is make that transition from partial profile to full profile. I'm doing that within a transaction. So if at any point anything fails within all of this, I can roll the whole thing back, and I'll be back to only having the partial profile, which was a very important thing. I would not want to have a partial profile and a profile because that's a bad state. But a lot of this for me is about data modeling and wanting to tell truths with the database and constrain what are the valid states of my application? So one solution would be to just have a profile model that has nullable columns for all of these fields. But man, do I hate that answer. So I went what feels like an extreme take of having two fundamentally different models, but that's where it's actually working out well. I'm able to share validations across them. So as new data is added, I can conditionally validate as new things are shared, and I'm able to share that via concern in the two models. So it's progressively getting more constrained as I add data to this thing. And then, in the background, there is a single controller that skips through all of the steps and has an update action that just keeps pushing data into this partial profile until, eventually, it becomes a profile. So that's focused specifically on the data model stuff. I think there are other aspects of a more workflowy type thing in Rails, but that's our thing. What do you think, good idea, bad idea, terrible idea? STEPH: [chuckles] One, I love that you have this concrete example because I have some higher-level ideas around this particular question, but I didn't have a great example that I wanted to share. So I love that you have that, that we can talk through. I really, really like how you have found a way to represent the fact that each valid state of your application as you refer to it….so you have this concept of someone's going through the flow and their address can be nullable at this stage, but by the end of this flow, it shouldn't be nullable anymore. So you have that concept of a partial profile, and then it gets converted into a profile. I am intrigued by the fact that it's one controller because that is where I am feeling pain with the multi-step form that I'm working on where we have one very large controller that handles this entire...I'm going to call it a wizard since that's how it's referred to, and there are seven or eight different steps in this wizard. And the job of this controller is each time someone goes to a new step; this controller is trying to figure out okay; what step are you on based on the parameters that you have, based on some of the model attributes that are set? What step are you on, and what should we show you? And that has led to a very large method and then also complex, lots of conditional-based code. And instead, I would really like to flip that question around or essentially remove the what step am I on? And instead, ask what step is next? So instead, take the approach that each step of the form should have a one-to-one mapping to another controller. And that can get really hard because we're often conditioned to the idea that we should have a one-to-one correlation between each controller and an ActiveRecord model, but that's not necessarily what happens in our form. You have the concept of a partial profile versus being able to map to a full profile. So I am very much in favor of the idea of trying to map each step of the form to a controller. So that, to me, makes the code more boring. It makes it more understandable. I can see what's happening for each step. But then it's not boring in terms that it requires creativity to say, okay, I don't have a perfect ActiveRecord model that maps to this controller, but what resourceful controller can I make instead? What is the domain object that I can put here instead? Maybe it's an ActiveModel object instead. So that way, we can apply ActiveRecord-like behavior to plain old Ruby objects, or maybe it's using a form object. That way, we can still validate all the fields that the user is providing to us, but that doesn't necessarily map directly to a full profile just yet. So I really like all the things that you've said. But I am intrigued by the approach of using a single controller. How's that feeling so far? CHRIS: That part is actually feeling fine. So a couple of things you said in there stand out to me, one, where it's a very big controller. That is something that I would definitely avoid. And so, I have extracted other pieces. There is an object that I created, which at this point is just in-app models because I didn't know where else to put it, but it's called onboarding. And so the workflow that I'm trying to introduce, the resource maybe is what we would call it, is the idea of onboarding, but it's not an ActiveRecord level thing. At the ActiveRecord level, I have a profile and a partial profile, and then there's an account, and there's also a user. There are four different database level models that I want to think about. But fundamentally, from a user perspective, we're talking about onboarding. And so I have an object that is called onboarding, and it contains the logic around given the data that we have now, what step comes next? Is this a valid step? Should the user go back? Et cetera, et cetera. So that extraction is one piece that definitely makes sense. Also, thus far, mine is relatively straightforward in terms of I get data in, and I just need to update my partial profile record each time. So the update action is very straightforward. But I've done different versions of this where there are more complex things that happen. And so what I've done is basically make a splat route. So it's like onboarding/ and then the step name and that gets posted or gets put, I guess, along with everything else for the update. And so now the update says, “Well, if I'm updating for this, then handle it this way; otherwise, just update the profile record.” And so then I can extract maybe another command object that handles like, “Oh, when we're doing the address stuff, we actually have to do a little bit of a lookup and a cross-reference and some other things, but everything else is just throwing data into a database record.” And so that's another place where I would probably make an extraction, which is this specialized case of handling the update of the address is special. So I want to extract that, be able to test around that, et cetera. But fundamentally, the controller thing actually works out pretty well. The single controller with those sorts of extractions has worked out well for me. STEPH: Okay, cool. Yeah, I can see how depending on how complex your multi-step form is, having it all in one controller and then extracting those smaller objects to then handle each step makes a lot of sense and feels very friendly to read, and is very testable. For the form that I'm working in, there are enough steps and enough complexity. I'd really love to break it out. In fact, that's something that we're working on right now is taking each of those chunks, each state of the form, and introducing a controller for it. So let's say if you are filling out an appointment and we need to get your consent for something, then we actually have a consent controller that's going to handle that part, that portion of it. And I'd be intrigued for your form if things got complicated enough that it's the concept of onboarding or a wizard that leads us to having one controller because then we think of this one concept. But there are often four or five concepts that are then hiding within that general idea of an onboarding flow. So then maybe you get to the point that you have an onboarding address or something like that. So then you could break it out into something that still feels RESTful but then lets you have that very boring controller that does just enough and essentially behaves like a bi-directional linked list. So it knows, based on the route, it knows the step that it's on, and it knows where to go back, and then it knows the next step to go forward. And then that's all it's responsible for, so it doesn't have to also figure out what step am I currently on? CHRIS: I like the bi-directional link list, dropping knowledge bombs right there. STEPH: Pew-pew. CHRIS: It's interesting. I don't necessarily feel...right now; I don't feel that pressure. I feel fine with the shape of the singular controller. This is perhaps not necessarily even a good thing, but I think my bias is always to think a lot about the URL structure and really strongly embrace the user point of view. I'm going through the workflow. I don't care if I'm picking from a calendar and setting up a date versus filling in an address field or how you're storing those on the back end; that's your job, developer people. And I try as hard as I can to put myself in that mindset. And so the idea that there's this sequential thing that knows how to go back and forward and shows like, show which page we're on, that feels like it belongs in one controller in my mind, or I guess I'm fine with it being in one controller. And splitting it out feels almost more complicated in that I then need to share some of that logic across them, which is very doable by extracting some object that contains a logic of what goes back, what goes forward. But I think I like to align URL structure to how many controllers as opposed to anything else. And because I'm keeping a consistent URL structure where it's /onboarding/name /onboarding/address, and I'm stepping through in that way for all of those things, then it makes sense to me that those go to my onboardings controller. But I'm interested to see if I start to feel pain somewhere down the road because I expect this onboarding to get more complicated as time goes on. And will I bump my head on the ceiling? Probably. It seems likely. But for now, I'm liking it. STEPH: Yeah, it certainly makes sense. It's one of those areas that you want to start small and then build out as it feels reasonable. But in regard to the URLs, I'm with you, where I very much want there to be a clean, nice URL for the user to see. And then we handle out any of those details on the back end since that is our work to do. But I am still envisioning that there is a clean URL. So it may be you have an onboarding/address and then onboarding/consent, borrowing from my previous example, but then that maps to where you have an onboarding namespaced controller that is then for an address or for consent. So you don't necessarily have an object that's having to be passed along that stores the state and the next step that the person is on. But that way, you do definitively know from the route okay, I am on this step. And so then that's how you get away from that question of what step am I on? Because that's already given to us based on the URL and then the controller. So then you only have to care about validating the input that's provided on that page, but then also being able to calculate dynamically okay, if this person needs to go back, what's the previous step and if they go forward, what's the next step? CHRIS: What you're saying totally makes sense. And I'm now worried that I'm going to wake up a few days from now and look at my controllers and be like, I hate this. Why did I ever do this? I think the hesitation that I had, and this feels like a terrible reason, but in terms of what the config/routes.rb setup would be for this, it's namespace onboardings. And then within that, a bunch of singular routes and inside of that, inside that namespace, would be a bunch of singular resources so like, resource address, resource blah, blah. And I don't know why, but I don't like that. I don't like that. I don't like that. Now that I'm saying it out loud, I'm like, yeah, that actually would be a pretty clean mapping. And right now, I have implicitly what those available routes are but not explicitly. It also feels like there would be a real explosion of controllers there because there's a bunch of steps and growing in this controller or in this namespace. And they're all going to do the same thing, in my case at least, of just adding data in. But that's not a reason to not make...like, controllers are cheap; I should make controllers so, hmm. STEPH: Yeah. So I think that's the part in my mind that maps to the boring part is because we are creating controllers. There's maybe an explosion of them, and it's boring. Like, the controllers don't do very much. And then that feels a little bit wrong to us because we're like, okay, I created this controller, it does very little. So maybe I should actually group this logic somewhere else. But I think that is the heart of it and how you stay boring is where you have just that code be so simple that it almost feels wrong. CHRIS: That right there, that sound bite that we just had, that was a knowledge bomb drop, and I liked it. Now I've got to go back and refactor to the form that you're talking about because I am sold. STEPH: Oh, I'm glad you like it. I am intrigued if you do refactor then what that would look like and how it feels. But I also totally understand you're busy, so if you don't, that's cool too, no pressure. CHRIS: My honest answer is that I almost certainly won't refactor until I feel the pain. It's one of those things where like, okay, maybe I've now decided that this code is not the best, but the time to refactor it isn't when that code is just humming along working fine. It's a general thing that I think we share in terms of how we think about it. But the preemptive refactoring, I guess broadly speaking, I'm not a fan of preemptive factoring. I'm a fan of refactoring just in time or as we're feeling the pain, which is the counterpoint to that is let's not extract tech debt tickets because then they turn into preemptive refactoring again. It's like, ah, I'm not really feeling...I'm not in there right now. But the version of the code that I have now is probably fine. I don't think it's a problem although I am convinced now of the boring way. I want to go back to the boring way, but it will feel like it's worth changing down the road when I feel any pressure in that system or need to revisit it. So it's like that. That's how I think about that sort of thing. STEPH: Yeah, I wholeheartedly agree. It's one of those if you refactor...if this is a side project, if you want to refactor just for testing new software theories and then reflecting on what that new refactor looks like, that's awesome. In terms of any other refactors, then I wholeheartedly favor waiting until you feel that pain and it feels like the right thing to do; otherwise, it's unnecessary code turn. And while I strongly believe in experiments, I don't believe in putting teams through those personal experiments. CHRIS: More hot takes from Steph. I like it. STEPH: Circling back just a bit and talking about having one controller for each step of the form, that part I struggle with it frankly because it is hard to think about this is a concept, but what do I call this? Because it doesn't necessarily map to something necessarily in my database. There's a really great talk by Derek Prior that's called In Relentless Pursuit of REST, where Derek does a great job of providing some inspiration around how to create routes that don't necessarily feel like they could be RESTful, or maybe they're following that more RPC format. And he does a great job of then turning around and saying, “Well, this is how we could think about, or this is how we could shift our thinking in turning this into a more RESTful route.” So then it does map to something that's meaningful in our domain. Because we have thoughtfully, or likely very thoughtfully, grouped this form together in a meaningful way to the user. So then that's inspiration right there to give us a way to name this thing because we are showing it to the user in a meaningful way. So then that means we can also give it a meaningful name. That's all I got on multi-step forms. [laughs] CHRIS: That feels like it was a lot. We've covered data models. We've covered controller structures. We fundamentally reoriented my thinking on the matter. I feel like we covered it. STEPH: Yeah, I agree. Well, Benoit, thank you for sending in this question. I hope you found our discussion very helpful. And on that note, shall we wrap up? CHRIS: Let's wrap up STEPH: The show notes for this episode can be found at bikeshed.fm. CHRIS: This show is produced and edited by Mandy Moore. STEPH: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or review in iTunes as it helps other people find the show. CHRIS: If you have any feedback for this or any of our other episodes, you can reach us at @bikeshed on Twitter. And I'm @christoomey. STEPH: And I'm at @SViccari. CHRIS: Or you can email us at hosts@bikeshed.fm. Thanks so much for listening to The Bike Shed, and we'll see you next week. All: Byeeeee. 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 week's episode, Steph and Chris tackle a listener question around composition over inheritance, especially in the context of Rails which makes regular use of inheritance. Dependency injection, OOP vs FP, frameworks vs app code -- they hit it all! They also chat about burnout and how they've dealt with it, using jq to investigate differences between json responses, refactoring tests and using let, and Steph shares her recent learnings about graphviz. 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 ExpressVPN (https://www.expressvpn.com/BIKESHED) - Click through to get get an extra three months FREE on a one-year package! Getting Back to Work by Carl Reyes (https://thoughtbot.com/blog/authors/carl-reyes) "If you're feeling down lately, here's a quick test to figure out why" tweet (https://twitter.com/levelsio/status/1187045109063225345) jq (https://stedolan.github.io/jq/) (command-line JSON processor) lets not (https://thoughtbot.com/blog/lets-not) graphviz (https://graphviz.org/) Composition over Inheritance on Upcase (https://thoughtbot.com/upcase/videos/composition-over-inheritance) React hooks, composition (https://reactjs.org/docs/composition-vs-inheritance.html) Become a Sponsor (https://thoughtbot.com/sponsorship) of The Bike Shed!
This week, Jaclyn volunteers on a design sprint and prepares for PTO, while Kyle preps for a website redesign workshop. Also, collaboration vs customization in presentations, preparing a 2 day Pre-MVP workshop, approaches to editing, and balancing experimentation with expertise. The Code Cooperative (https://codecooperative.org/) Website Redesign Workshop (https://thoughtbot.com/events/website-redesign-workshop) Upcase (https://thoughtbot.com/upcase/) Become a Sponsor (https://thoughtbot.com/sponsorship) of Tentative!
On this week's episode, Steph is joined by thoughtbotter German Velasco. German and Steph chat about remote work and the rewards and challenges of their new(ish) roles as Development Team Leads. German also shares that he is writing a book! German shares his approach for defining a MVB (Minimum Viable Book), ideas for how to collect feedback, and plans for publishing. Lastly, they discuss a vim plugin that lives up to the hype. This episode is brought to you by Datadog (http://datadog.com/thebikeshed). Click through to get a free 14-day trial and a free Datadog t-shirt! To register for the free online workshop "How to Supercharge Your Rails App with a Code Audit", visit https://thoughtbot.com/events/code-audit-workshop. GitBook (https://www.gitbook.com/) Michael Hartl - The Ruby on Rails Tutorial (https://www.railstutorial.org/) Workshop - Being Human in the Absence of Humans (https://info.thoughtbot.com/remote-product-team-resources) Workshop - How to stay agile when building compliant health tech products (https://info.thoughtbot.com/building-compliant-health-tech-products-recording) vim-fugitive (https://github.com/tpope/vim-fugitive) Write good commit messages by blaming others (https://thoughtbot.com/blog/write-good-commit-messages-by-blaming-others) Upcase course featuring vim-fugitive (https://thoughtbot.com/upcase/videos/git-vim-and-git) More episodes with German: - 188: A Function by Any Other Name (https://www.bikeshed.fm/188) - 167: I Feel Like We Should've Solved This By Now (https://www.bikeshed.fm/167)
On this week's episode, Steph and Chris discuss what it really means to make a project "open source". Is it just about making the code publicly available, or should we be considering licenses and responsibility to update? They also discuss the need for breaks and structure now that everyone is working from home, revisit previous discussions around building functionality for admin users and the various admin systems out there, and they round out the conversation with a discussion around doubles vs spies in testing. Note - No snakes were harmed as Steph found them a new home
Geoff DiMasi, founder of Punk Ave. & Apostrophe, discusses his drive to build a CMS, balancing maintaining a service company while building a product (as well as the thought-process of spinning out a product into its own company), the Philadelphia tech-scene, and transitioning to a remote company.ApostropheCMSApostrophe Open SourceOpen Source at thoughtbotUpcaseObjectives and Key Results(OKR) SystemIndy Hall Coworking SpaceJAMstackHeadless CMSGeoff on TwitterSee open positions at thoughtbot!Become a Sponsor of Giant Robots!
On this week's episode, Chris and Steph discuss identifying refactoring opportunities by highlighting overly coupled code and Chris announces that he has advanced his vim setup into the 21st century by making the switch to Neovim. Types of CouplingHuskyConquer of Completion PluginDive Into Neovim on UpcaseMastering the Vim LanguageOnramp to VimPostgres Check Constraints
Derrick spent his birthday at the north shore of Lake Superior to disconnect and getaway. Yet, he found some time to brainstorm and problem solve for StaticKit. Ben’s back from Martha’s Vineyard, only to experience less positive updates for Tuple. For the first time, Tuple is shockingly “in the red” financially. So, he feels guilty about going away. Today’s Topics Include: Slow Growth: Substantially fewer Tuple trial signups than previous time periods Marketing and Sales Strategy: From being the new tool on the block to steady state where Ben has to earn new Tuple customers Bullseye Framework: Derrick re-read his go-to startup guide to select StaticKit’s repeatable traction channels Tuple’s Q4 objectives and key results (OKRs): Fill top of funnel to increase new email subscribers and trials to continue to grow Ben’s future plans to gather marketing and sales information/intelligence by advertising and appearing on dev-related podcasts Design Matters: Impacts people’s perception of product and builds trust Links and resources: Art of Product on Twitter (https://twitter.com/artofproductpod) Derrick Reimer (http://www.derrickreimer.com) Website Derrick Reimer on Twitter (https://twitter.com/derrickreimer) Ben Orenstein (http://www.benorenstein.com/) Website Ben Orenstein on Twitter (https://twitter.com/r00k?lang=en) Tuple (https://tuple.app/) Tuple’s Pair Programming Guide (https://tuple.app/pair-programming-guide) StaticKit (https://www.statickit.com/) Using Tailwind CSS with Next.js (https://statickit.com/guides/next-js-tailwind) Level (https://level.app/) Slack (https://slack.com/) Zoom (https://zoom.us/) Upcase by Thoughtbot (https://thoughtbot.com/upcase) Traction: A Startup Guide to Getting Customers by Gabriel Weinberg and Justin Mares (https://www.amazon.com/Traction-Startup-Guide-Getting-Customers/dp/0976339609) Ruby on Rails (https://rubyonrails.org) HubSpot (https://www.hubspot.com) Rob Walling (https://robwalling.com/) Drip (https://www.drip.com/) Adam Wathan (https://adamwathan.me/) Full Stack Radio (http://www.fullstackradio.com/) Syntax.fm (https://syntax.fm) Steve Schoger (https://www.steveschoger.com/) Elixir (https://elixir-lang.org) Recurly (https://recurly.com) Chargify (https://www.chargify.com)
Ben Orenstein first talked about being able to create products. We spoke about Ben's early programs and his attempt at studying in college. We then spoke about his second attempt at entering the IT industry, through the backdoor this time. Ben told us about his discovery of Ruby and joining Thoughbot. He told us about why sharing knowledge is important to him. We then touched on public speaking and the two podcasts he hosted during his career. We finally switched gears and talked about product development.Ben spent the last years working at Thoughtbot in Boston, where he and his colleagues obsessed about code quality and keeping shipping-speed high. You might remember Thoughtbot from the last episode with Saron Yitbarek. This is where Saron did her apprenticeship. There, Ben co-created the Upcase course, one of many products Ben has created. Ben is the author ofthe "Refactoring Rails" course, the "CodeQualityChallenge", "Trailmix" and "Briefs" products. He currently is building "Tuple", a tool for remote pair-programming. Thus it is not surprising to hear that he is also the host of "the Art of Product Podcast".Here are the links of the show:http://twitter.com/r00khttps://www.benorenstein.comhttps://tuple.apphttps://thoughtbot.comhttps://thoughtbot.com/upcaseSaron Yitbarek's #DevJourney Episodehttps://www.refactoringrails.iohttps://www.codequalitychallenge.comhttps://www.trailmix.lifehttps://www.briefs.fmhttp://artofproductpodcast.comCreditsMusic Aye by Yung Kartz is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 License.Your hostSoftware Developer‘s Journey is hosted and produced by Timothée (Tim) Bourguignon, a crazy frenchman living in Germany who dedicated his life to helping others learn & grow. More about him at timbourguignon.fr.Want to be next?Do you know anyone who should be on the podcast? Do you want to be next? Drop me a line: info@devjourney.info or via Twitter @timothep.Gift the podcast a ratingPlease do me and your fellow listeners a favor by spreading the good word about this podcast. And please leave a rating (excellent of course) on the major podcasting platforms, this is the best way to increase the visibility of the podcast:Apple PodcastsStitcherGoogle PlayThanks!Support the show (http://bit.ly/2yBfySB)
Ben had another good week. He signed up 25 new trials and about five conversions for Tuple. Are you one of the 500 chosen by Derrick to get access to Level? Be sure to check your Inbox on Monday for an email from him to find out. Also, Ben and Derrick welcome Adam Wathan as a co-host for this episode. Adam’s working on getting release 1.0 of Tailwind out the door with awesome documentation. Today’s Topics Include: Happiness vs. Harassment: Tuple’s paid trial process Will people pay for Level? Get free feedback first or make them pay upfront? Demo Option: Click around, view dummy posts to get sense of how Level works Refactoring UI: Could it be a perennial seller? How much should you share about your startup in your tweets? Focus on being best option; don’t brag about your success Trying to sell a theme via Tailwind; adding vs. creating new products Holy Grail of Software Business: Rob Walling’s stairstep approach to recurring revenue Growth rate required to stay alive? Keep product relevant to what market wants SaaS is definitely not all roses! Super Fast Email Services/Features: Snippets, Superhuman, Help Scout, and Shortcuts Links and resources: Adam Wathan on Twitter (https://twitter.com/adamwathan) Refactoring UI by Adam Wathan and Steve Schoger (https://refactoringui.com/) Steve Schoger (https://www.steveschoger.com/) Stripe (https://stripe.com/) Jason Cohen - Designing the Ideal Bootstrapped Business (https://vimeo.com/74338272) Perennial Seller: The Art of Making and Marketing Work that Lasts (https://www.amazon.com/Perennial-Seller-Making-Marketing-Lasts/dp/0143109014) MicroConf (https://www.microconf.com/) Tailwind CSS (https://tailwindcss.com/) Bootstrap (https://getbootstrap.com/) Justin Jackson Playing with Tailwind CSS (https://www.youtube.com/watch?v=TwUT0MmnrQw) Justin Jackson’s MegaMaker Club (https://megamaker.co/club/) Patreon (https://www.patreon.com/) Rob Walling’s Stairstep Approach to Bootstrapping (https://robwalling.com/2015/03/26/the-stairstep-approach-to-bootstrapping/) Upcase by Thoughtbot (https://thoughtbot.com/upcase) Paul Jarvis (https://pjrvs.com/) Heroku Dynos (https://www.heroku.com/dynos) Ruby on Rails (https://rubyonrails.org/) Elixir (https://elixir-lang.org/) Superhuman (https://superhuman.com/) Help Scout (https://www.helpscout.com/) Art of Product on Twitter (https://twitter.com/artofproductpod) Derrick Reimer (http://www.derrickreimer.com) Website Derrick Reimer on Twitter (https://twitter.com/derrickreimer) Ben Orenstein (http://www.benorenstein.com/) Website Ben Orenstein on Twitter (https://twitter.com/r00k?lang=en) Level (https://level.app/) Tuple (https://tuple.app/)
Sponsors Sentry use the code “devchat” for $100 credit Triplebyte CacheFly Panel Lucas Reis Justin Bennett Charles Max Wood Joined by special guests: Chris Toomey Episode Summary In this episode of React Round Up, Chris Toomey introduces himself, talks about his work and his podcast and moves on to explaining the differences between a React vs GraphQL centric application. Justin explains in detail how the Relay framework works, and Chris describes the scenarios where GraphQL stands out in the process of building an application and also throws some light on the benefits of choosing it over other APIs such as REST. The panel then discusses how GraphQL is advantageous in the documentation context since it has a good schema, and also in data modeling. Chris shares some past examples of creating React applications where GraphQL and Apollo made things much simpler, and also elaborates on the trade-offs and challenges associated with it. Links The Bike Shed Chris Toomey: React & GraphQL – Bringing Simplicity to Client-Side Development / React Boston 2018 Chris’s Twitter The Past, Present, and Future of GraphQL Native - Nick Schrock @ GraphQL Europe Picks Justin Bennett: Where art thou, my error? Auto by Intuit on GitHub Lucas Reis: MDX Deck library Code Surfer library Charles Max Wood: HubSpot Zapier Google Docs Chris Toomey: Tell me when it closes Quicklink Upcase
Sponsors Sentry use the code “devchat” for $100 credit Triplebyte CacheFly Panel Lucas Reis Justin Bennett Charles Max Wood Joined by special guests: Chris Toomey Episode Summary In this episode of React Round Up, Chris Toomey introduces himself, talks about his work and his podcast and moves on to explaining the differences between a React vs GraphQL centric application. Justin explains in detail how the Relay framework works, and Chris describes the scenarios where GraphQL stands out in the process of building an application and also throws some light on the benefits of choosing it over other APIs such as REST. The panel then discusses how GraphQL is advantageous in the documentation context since it has a good schema, and also in data modeling. Chris shares some past examples of creating React applications where GraphQL and Apollo made things much simpler, and also elaborates on the trade-offs and challenges associated with it. Links The Bike Shed Chris Toomey: React & GraphQL – Bringing Simplicity to Client-Side Development / React Boston 2018 Chris’s Twitter The Past, Present, and Future of GraphQL Native - Nick Schrock @ GraphQL Europe Picks Justin Bennett: Where art thou, my error? Auto by Intuit on GitHub Lucas Reis: MDX Deck library Code Surfer library Charles Max Wood: HubSpot Zapier Google Docs Chris Toomey: Tell me when it closes Quicklink Upcase
You've been coding for a little while. Maybe you just finished a bootcamp, maybe you're in your first job or your second. But at what point do you get to level up? And what does leveling up even look like for a developer? We talk to Ben Orenstein, one of the creators of Upcase, a learning platform designed specifically to "take the junior out of your title." He shares what technical topics you should learn when trying to level up, and what steps a newbie might take to start that leveling up process. We also feature our second installment of Tales from the Command Line, where Scott McCarty share stories on how he built up his confidence as a coder and how you can too. Show Links Digital Ocean (sponsor) MongoDB (sponsor) Heroku (sponsor) TwilioQuest (sponsor) Linux thoughtbot Do things that don't scale Vim Upcase Codeland Conf Codeland 2019
Panel: Eric Berry Charles Max Wood Nate Hopkins Special Guest: Paul Smith and Andrew Mason In this episode of Ruby Rogues, the panelists talk with Paul Smith and Andrew Mason! They discuss the platforms Lucky and Crystal. Other topics include: Ruby, Phoenix, Laravel Mix, Thoughtbot, Webpack, compilers, and much more! Check it out! Show Topics: 0:00 – Advertisement: Sentry.io 1:02 – Chuck: Welcome!! Eric Berry, Nate Hopkins, and myself are the panel - and our special guests are Paul Smith and Andrew Mason. Introduce yourself! 1:41 – Andrew / Guest: I have messed with every type of language, so there’s that! 1:55 – Paul / Guest: I have been here at my current company for 5 years and it’s a consultancy firm. I have been working on Crystal. 2:14 – Chuck: We are lucky to have you! Give people the elevator pitch for Lucky and Crystal? 2:33 – Guest: Let’s talk about Crystal and looks very similar to Ruby! It’s faster and it’s a compound language. It catches a fair amount of things at compile time. The other special features are... 4:17 – Guest mentions compilers. 4:23 – Chuck: Yeah we see this in the typescript. Is it language service – is that what it’s called? Pile and compile and all of this checking are a nice stage for it to run-through. Although the flipside is coding and to not worry about that – that’s nice! 4:56 – Guest: It has changed my approach for sure. 5:43 – Panel: How much slower are you? 5:54 – Guest: I am a lot faster in Crystal than I am in Ruby. 6:51 – Panel: Yeah you have to figure out where you want to save the time. 7:00 – Guest: Someone wrote a blog post and it said...the Rails service is like bolting a shelf on a wall and hoping to hit a stud and it’s not solid. But using Lucky it’s sold although it took a little longer. I think it can be true. You can do bad things with compilers, though. It depends on how you use it. 7:43 – Panelist asks a question. 7:53 – Guest: Every Friday is an investment day. Lucky is my “whatever I want thing.” I am technically getting paid to work on it. 8:33 – Panel: have you had to battle with the framework? 8:51 – Guest: Yes, even though Crystal looks like Ruby (at a high level) if you want to do it well you have to approach it in the Crystal-way. When I came to Crystal I came to it like Rails. The problem with that is I wanted to have type-saved parameters – you can’t do that in Crystal b/c...it doesn’t know when to have a parameter with... 10:48 – Panel: I have heard you talk about Crystal before on another podcast. You talked about templating and I am curious to hear about that. I have used Slim and others and now stick to ERB. 11:25 – Guest: Yes definitely. Let’s back up and talk about WHAT Lucky does! The guest talks about Rails, escaping, and more! 14:37 – Panel: So I imagine Rails partials are slow and expensive to render. I would imagine that this approach with Lucky... 15:00 – Guest: Yes exactly. It’s extremely fast! 15:20 – Panel: How is this for designers? 15:30 – Guest: Yes that was a concern of mine. With Lucky I tried to make it close to a regular HTML structure would look like! 16:32 – Panel: I spun up a Lucky app the other day. It looks like you are using... 16:50 – Guest: I have played around with a bunch of stuff. I landed on Laravel Mix. 18:27 – Panel: Yes webpack is a pain to set up and it’s hard to get it to working the way you want it to work. 18:47 – Guest: Yeah if you want React or whatever it will generate the configuration you need. I don’t like it b/c if you want to... 19:28 – Panel. 19:45 – Guest: I don’t want to maintain it. 19:54 – Panel: There is a Crystal community in Utah. I want to know – are you competing with Amber? Explain the difference between Lucky and Amber? 20:20 – Guest: Yes I did look at Amber but they are approaching it differently than us. The guest talks about the differences between Amber and Lucky. 21:54 – Guest (continues): With Lucky you will have to learn a little bit more but you get more of a pack! 23:23 – Panel: It sounds like Lucky is inspired by Elm – right? 23:32 – Guest: Yeah, I think so. The guest dives into this topic of Elm and Lucky! 24:35 – Panel: How much does the types feel like it’s getting in your way? How explicit is it? When I came to Ruby it was a breath of fresh air. I am a bit reluctant to go back to those days. 25:25 – Guest: I think Lucky does a happy medium. It doesn’t infer instant variables. I like the... 26:28 – Panel: I learned Java very early on in my computer science career. 27:00 – Guest. 27:10 – Panel: “Crystal...it’s not Java!” That should be your slogan! 27:20 – Fresh Books! 28:25 – Panel: A lot of people are moving to Elixir community. Do you see people moving from Ruby to Lucky and Crystal? How does Lucky compare to Phoenix? 28:55 – Guest: Good question! 29:10 – The guest talks about bamboo – see links below!! 29: 29 – Guest: Sure Ruby is fast but sometimes you spend more time on it then you would want to. 31:08 – Guest: Blessing and curse that Crystal looks so much like Ruby. That’s what I thought at first: why would I want to learn this if it’s so similar to Ruby. BUT there are so many benefits to Crystal vs. Ruby. 31:48 – Guest talks about Lucky catching the bugs. 32:00 – Panel: I wonder if that happened with Groovy and Rails? 32:21 – They go back-and-forth. 32:28 – Panel: Thoughtbot has always been on the forefront of Ruby. Can you talk about Thoughbot please? (See links below for Thoughtbot!) 33:15 – Guest: Great question. It’s hard to tell b/c there are different offices. I would say Ruby is our main thing. Ruby is the most mature thing that we use in-terms of web development. Guest: Actually – Rails is pretty nice! 34:54 – Panel: We went through the same thing with CodeFund! I wrote it initially in Python and then I wrote it in Elixir and it became so complex. Now we are moving everything back to Ruby and it’s been a fantastic decision. 36:30 – Chuck: You are talking about the sustainability of open source but there are benefits throughout the company right? There are tons of tangible benefits of doing it, especially when it’s your Friday schedule. You can level-up on things that could help you. I know a lot of companies cannot afford it if they are trying to hustle. 37:42 – Guest: It’s totally not charity through Thoughtbot. It’s a huge help for hiring new people. I know they are okay with letting me work on Lucky b/c it’s bringing on new developers and a good marketing tool, and finally recruiting! 39:07 – Chuck: Yeah, I have been talking about developer freedom and that’s what I am addressing through the DevRev show! It’s my new podcast show. We talk with Chris on Elixir Mix. It lends that credibility if they need to save our bacon. 40:02 – Panel: What’s your goal with Lucky? 40:11 – Guest: I would love to get it to the point where Thoughtbot could start a project and default to Lucky! Start a project and not resting every gem and be confident with launching it. 41:36 – Panelist asks a question. 41:45 – Guest: It’s not 1.0 and that means that the API will break with every release. I think that’s good to tweak stuff but that turns companies off, though. 42:40 – Chuck: Another thing that helps with adoption is Twitter used Rails to build their initial version. This blah, blah company uses important stuff and they are using Crystal and whatnot then that’s good! It sounds like you are waiting for social proof. 43:23 – Guest: Is the next Twitter going to even know about Crystal? 43:40 – Chuck: It literally only takes one enthusiast! 43:52 – Guest. 44:11 – Demo of Flickr Search is mentioned here! 45:13 – Panel: Is there something out there that you could POINT someone to? 45:27 – Guest: Not, yet. I built a small site with it! It is opensource and you can look at it. I want to show people a good example of what Lucky can do! 45:57 – Panel: You have very good docs and I am a visual learner. When I learned Rails I learned on my own and not through school. 46:20 – Panelist asks a question. 46:48 – Guest: What a huge advantage Lucky has through the Thoughtbot platform! Now that platform is kind of dried up. In terms of getting people excited it needs that killer app and they can see that it’s fast and killer! I think it takes a lot of time and finding time to do it so that’s tricky. It’s changing a lot when there is so much change. Getting Lucky to a 1.0 state so people can do videos and make apps. The hard part thing is that Lucky has to be 1.0 when Crystal is 1.0. The Lucky community is great b/c it’s encouraging and to respond in a very kind way. When you are starting something that’s new can be scary. We try to help out as much as we can and we are open and kind about it. 49:13 – Panel: “Paul is nice so Lucky is nice!” 49:19 – Guest: Everyone is super kind. It had to be short and simple. We in the dev community are very lucky – usually great pay/benefits and more w/o a college degree. What another field can you do that?! 51:00 – Panel: Great message and you need to push that! 51:10 – Panel: You were on a past podcast and you talked about how you are donating each month! Panel: Opensource maintainers are getting burned out and you want to support that. 51:40 – Guest: I think opensource sustainability what others need to do to make it sustainable. If you have the means to give we can be apart of that, too. It would be nice if companies did that. If it helps Crystal I am happy. 52:17 – Panel: I have a question about Crystal. 52:52 – Guest: Ruby right now you can do C sections right now. 53:01 – Panel. 53:10 – Guest: I don’t think so – it may but I would guess that you could do it but I don’t know how easy it would be. Note: Rust and C are mentioned. 53:37 – Panel comments. 53:46 – Guest: One thing I would say is to check-out the Lucky docs. We are happy to help! 54:10 – Panel: This is a favorite episode of mine! Both of today’s guests have been my favorite! 54:23 – Advertisement: Get A Coder Job! End – Cache Fly! Links: Get a Coder Job Course The DevRev Podcast Show DevChat TV Ruby Elixir Ruby on Rails Angular Cypress Vue React Jest.io Mocha.js Webpacker-Cli Amber Lucky The Lucky Philosophy The Bike Shed Thoughtbot CodeFund Lucky: Ruby on Rails to Lucky on Crystal... “Crystal is not Ruby Part 1” GitHub: Bamboo Ex_Machina Dialyxir Crystal Mastery Samsung T5 Carbon Copy Cloner iMazing Awesome-Lucky Paul Smith GitHub Sponsors: Sentry CacheFly Fresh Books Picks: Nate Samsung SSD Carbon Copy Cloner Application Eric iMazing HEIC Converter Charles Mastodon Andrew Upcase by Thoughtbot Awesome Lucky Paul Tailwind CSS Phoenix Live HTML Chris McCord Elixir Mix Episodes with Chris McCord
Panel: Eric Berry Charles Max Wood Nate Hopkins Special Guest: Paul Smith and Andrew Mason In this episode of Ruby Rogues, the panelists talk with Paul Smith and Andrew Mason! They discuss the platforms Lucky and Crystal. Other topics include: Ruby, Phoenix, Laravel Mix, Thoughtbot, Webpack, compilers, and much more! Check it out! Show Topics: 0:00 – Advertisement: Sentry.io 1:02 – Chuck: Welcome!! Eric Berry, Nate Hopkins, and myself are the panel - and our special guests are Paul Smith and Andrew Mason. Introduce yourself! 1:41 – Andrew / Guest: I have messed with every type of language, so there’s that! 1:55 – Paul / Guest: I have been here at my current company for 5 years and it’s a consultancy firm. I have been working on Crystal. 2:14 – Chuck: We are lucky to have you! Give people the elevator pitch for Lucky and Crystal? 2:33 – Guest: Let’s talk about Crystal and looks very similar to Ruby! It’s faster and it’s a compound language. It catches a fair amount of things at compile time. The other special features are... 4:17 – Guest mentions compilers. 4:23 – Chuck: Yeah we see this in the typescript. Is it language service – is that what it’s called? Pile and compile and all of this checking are a nice stage for it to run-through. Although the flipside is coding and to not worry about that – that’s nice! 4:56 – Guest: It has changed my approach for sure. 5:43 – Panel: How much slower are you? 5:54 – Guest: I am a lot faster in Crystal than I am in Ruby. 6:51 – Panel: Yeah you have to figure out where you want to save the time. 7:00 – Guest: Someone wrote a blog post and it said...the Rails service is like bolting a shelf on a wall and hoping to hit a stud and it’s not solid. But using Lucky it’s sold although it took a little longer. I think it can be true. You can do bad things with compilers, though. It depends on how you use it. 7:43 – Panelist asks a question. 7:53 – Guest: Every Friday is an investment day. Lucky is my “whatever I want thing.” I am technically getting paid to work on it. 8:33 – Panel: have you had to battle with the framework? 8:51 – Guest: Yes, even though Crystal looks like Ruby (at a high level) if you want to do it well you have to approach it in the Crystal-way. When I came to Crystal I came to it like Rails. The problem with that is I wanted to have type-saved parameters – you can’t do that in Crystal b/c...it doesn’t know when to have a parameter with... 10:48 – Panel: I have heard you talk about Crystal before on another podcast. You talked about templating and I am curious to hear about that. I have used Slim and others and now stick to ERB. 11:25 – Guest: Yes definitely. Let’s back up and talk about WHAT Lucky does! The guest talks about Rails, escaping, and more! 14:37 – Panel: So I imagine Rails partials are slow and expensive to render. I would imagine that this approach with Lucky... 15:00 – Guest: Yes exactly. It’s extremely fast! 15:20 – Panel: How is this for designers? 15:30 – Guest: Yes that was a concern of mine. With Lucky I tried to make it close to a regular HTML structure would look like! 16:32 – Panel: I spun up a Lucky app the other day. It looks like you are using... 16:50 – Guest: I have played around with a bunch of stuff. I landed on Laravel Mix. 18:27 – Panel: Yes webpack is a pain to set up and it’s hard to get it to working the way you want it to work. 18:47 – Guest: Yeah if you want React or whatever it will generate the configuration you need. I don’t like it b/c if you want to... 19:28 – Panel. 19:45 – Guest: I don’t want to maintain it. 19:54 – Panel: There is a Crystal community in Utah. I want to know – are you competing with Amber? Explain the difference between Lucky and Amber? 20:20 – Guest: Yes I did look at Amber but they are approaching it differently than us. The guest talks about the differences between Amber and Lucky. 21:54 – Guest (continues): With Lucky you will have to learn a little bit more but you get more of a pack! 23:23 – Panel: It sounds like Lucky is inspired by Elm – right? 23:32 – Guest: Yeah, I think so. The guest dives into this topic of Elm and Lucky! 24:35 – Panel: How much does the types feel like it’s getting in your way? How explicit is it? When I came to Ruby it was a breath of fresh air. I am a bit reluctant to go back to those days. 25:25 – Guest: I think Lucky does a happy medium. It doesn’t infer instant variables. I like the... 26:28 – Panel: I learned Java very early on in my computer science career. 27:00 – Guest. 27:10 – Panel: “Crystal...it’s not Java!” That should be your slogan! 27:20 – Fresh Books! 28:25 – Panel: A lot of people are moving to Elixir community. Do you see people moving from Ruby to Lucky and Crystal? How does Lucky compare to Phoenix? 28:55 – Guest: Good question! 29:10 – The guest talks about bamboo – see links below!! 29: 29 – Guest: Sure Ruby is fast but sometimes you spend more time on it then you would want to. 31:08 – Guest: Blessing and curse that Crystal looks so much like Ruby. That’s what I thought at first: why would I want to learn this if it’s so similar to Ruby. BUT there are so many benefits to Crystal vs. Ruby. 31:48 – Guest talks about Lucky catching the bugs. 32:00 – Panel: I wonder if that happened with Groovy and Rails? 32:21 – They go back-and-forth. 32:28 – Panel: Thoughtbot has always been on the forefront of Ruby. Can you talk about Thoughbot please? (See links below for Thoughtbot!) 33:15 – Guest: Great question. It’s hard to tell b/c there are different offices. I would say Ruby is our main thing. Ruby is the most mature thing that we use in-terms of web development. Guest: Actually – Rails is pretty nice! 34:54 – Panel: We went through the same thing with CodeFund! I wrote it initially in Python and then I wrote it in Elixir and it became so complex. Now we are moving everything back to Ruby and it’s been a fantastic decision. 36:30 – Chuck: You are talking about the sustainability of open source but there are benefits throughout the company right? There are tons of tangible benefits of doing it, especially when it’s your Friday schedule. You can level-up on things that could help you. I know a lot of companies cannot afford it if they are trying to hustle. 37:42 – Guest: It’s totally not charity through Thoughtbot. It’s a huge help for hiring new people. I know they are okay with letting me work on Lucky b/c it’s bringing on new developers and a good marketing tool, and finally recruiting! 39:07 – Chuck: Yeah, I have been talking about developer freedom and that’s what I am addressing through the DevRev show! It’s my new podcast show. We talk with Chris on Elixir Mix. It lends that credibility if they need to save our bacon. 40:02 – Panel: What’s your goal with Lucky? 40:11 – Guest: I would love to get it to the point where Thoughtbot could start a project and default to Lucky! Start a project and not resting every gem and be confident with launching it. 41:36 – Panelist asks a question. 41:45 – Guest: It’s not 1.0 and that means that the API will break with every release. I think that’s good to tweak stuff but that turns companies off, though. 42:40 – Chuck: Another thing that helps with adoption is Twitter used Rails to build their initial version. This blah, blah company uses important stuff and they are using Crystal and whatnot then that’s good! It sounds like you are waiting for social proof. 43:23 – Guest: Is the next Twitter going to even know about Crystal? 43:40 – Chuck: It literally only takes one enthusiast! 43:52 – Guest. 44:11 – Demo of Flickr Search is mentioned here! 45:13 – Panel: Is there something out there that you could POINT someone to? 45:27 – Guest: Not, yet. I built a small site with it! It is opensource and you can look at it. I want to show people a good example of what Lucky can do! 45:57 – Panel: You have very good docs and I am a visual learner. When I learned Rails I learned on my own and not through school. 46:20 – Panelist asks a question. 46:48 – Guest: What a huge advantage Lucky has through the Thoughtbot platform! Now that platform is kind of dried up. In terms of getting people excited it needs that killer app and they can see that it’s fast and killer! I think it takes a lot of time and finding time to do it so that’s tricky. It’s changing a lot when there is so much change. Getting Lucky to a 1.0 state so people can do videos and make apps. The hard part thing is that Lucky has to be 1.0 when Crystal is 1.0. The Lucky community is great b/c it’s encouraging and to respond in a very kind way. When you are starting something that’s new can be scary. We try to help out as much as we can and we are open and kind about it. 49:13 – Panel: “Paul is nice so Lucky is nice!” 49:19 – Guest: Everyone is super kind. It had to be short and simple. We in the dev community are very lucky – usually great pay/benefits and more w/o a college degree. What another field can you do that?! 51:00 – Panel: Great message and you need to push that! 51:10 – Panel: You were on a past podcast and you talked about how you are donating each month! Panel: Opensource maintainers are getting burned out and you want to support that. 51:40 – Guest: I think opensource sustainability what others need to do to make it sustainable. If you have the means to give we can be apart of that, too. It would be nice if companies did that. If it helps Crystal I am happy. 52:17 – Panel: I have a question about Crystal. 52:52 – Guest: Ruby right now you can do C sections right now. 53:01 – Panel. 53:10 – Guest: I don’t think so – it may but I would guess that you could do it but I don’t know how easy it would be. Note: Rust and C are mentioned. 53:37 – Panel comments. 53:46 – Guest: One thing I would say is to check-out the Lucky docs. We are happy to help! 54:10 – Panel: This is a favorite episode of mine! Both of today’s guests have been my favorite! 54:23 – Advertisement: Get A Coder Job! End – Cache Fly! Links: Get a Coder Job Course The DevRev Podcast Show DevChat TV Ruby Elixir Ruby on Rails Angular Cypress Vue React Jest.io Mocha.js Webpacker-Cli Amber Lucky The Lucky Philosophy The Bike Shed Thoughtbot CodeFund Lucky: Ruby on Rails to Lucky on Crystal... “Crystal is not Ruby Part 1” GitHub: Bamboo Ex_Machina Dialyxir Crystal Mastery Samsung T5 Carbon Copy Cloner iMazing Awesome-Lucky Paul Smith GitHub Sponsors: Sentry CacheFly Fresh Books Picks: Nate Samsung SSD Carbon Copy Cloner Application Eric iMazing HEIC Converter Charles Mastodon Andrew Upcase by Thoughtbot Awesome Lucky Paul Tailwind CSS Phoenix Live HTML Chris McCord Elixir Mix Episodes with Chris McCord
Panel: Eric Berry Charles Max Wood Nate Hopkins Special Guest: Paul Smith and Andrew Mason In this episode of Ruby Rogues, the panelists talk with Paul Smith and Andrew Mason! They discuss the platforms Lucky and Crystal. Other topics include: Ruby, Phoenix, Laravel Mix, Thoughtbot, Webpack, compilers, and much more! Check it out! Show Topics: 0:00 – Advertisement: Sentry.io 1:02 – Chuck: Welcome!! Eric Berry, Nate Hopkins, and myself are the panel - and our special guests are Paul Smith and Andrew Mason. Introduce yourself! 1:41 – Andrew / Guest: I have messed with every type of language, so there’s that! 1:55 – Paul / Guest: I have been here at my current company for 5 years and it’s a consultancy firm. I have been working on Crystal. 2:14 – Chuck: We are lucky to have you! Give people the elevator pitch for Lucky and Crystal? 2:33 – Guest: Let’s talk about Crystal and looks very similar to Ruby! It’s faster and it’s a compound language. It catches a fair amount of things at compile time. The other special features are... 4:17 – Guest mentions compilers. 4:23 – Chuck: Yeah we see this in the typescript. Is it language service – is that what it’s called? Pile and compile and all of this checking are a nice stage for it to run-through. Although the flipside is coding and to not worry about that – that’s nice! 4:56 – Guest: It has changed my approach for sure. 5:43 – Panel: How much slower are you? 5:54 – Guest: I am a lot faster in Crystal than I am in Ruby. 6:51 – Panel: Yeah you have to figure out where you want to save the time. 7:00 – Guest: Someone wrote a blog post and it said...the Rails service is like bolting a shelf on a wall and hoping to hit a stud and it’s not solid. But using Lucky it’s sold although it took a little longer. I think it can be true. You can do bad things with compilers, though. It depends on how you use it. 7:43 – Panelist asks a question. 7:53 – Guest: Every Friday is an investment day. Lucky is my “whatever I want thing.” I am technically getting paid to work on it. 8:33 – Panel: have you had to battle with the framework? 8:51 – Guest: Yes, even though Crystal looks like Ruby (at a high level) if you want to do it well you have to approach it in the Crystal-way. When I came to Crystal I came to it like Rails. The problem with that is I wanted to have type-saved parameters – you can’t do that in Crystal b/c...it doesn’t know when to have a parameter with... 10:48 – Panel: I have heard you talk about Crystal before on another podcast. You talked about templating and I am curious to hear about that. I have used Slim and others and now stick to ERB. 11:25 – Guest: Yes definitely. Let’s back up and talk about WHAT Lucky does! The guest talks about Rails, escaping, and more! 14:37 – Panel: So I imagine Rails partials are slow and expensive to render. I would imagine that this approach with Lucky... 15:00 – Guest: Yes exactly. It’s extremely fast! 15:20 – Panel: How is this for designers? 15:30 – Guest: Yes that was a concern of mine. With Lucky I tried to make it close to a regular HTML structure would look like! 16:32 – Panel: I spun up a Lucky app the other day. It looks like you are using... 16:50 – Guest: I have played around with a bunch of stuff. I landed on Laravel Mix. 18:27 – Panel: Yes webpack is a pain to set up and it’s hard to get it to working the way you want it to work. 18:47 – Guest: Yeah if you want React or whatever it will generate the configuration you need. I don’t like it b/c if you want to... 19:28 – Panel. 19:45 – Guest: I don’t want to maintain it. 19:54 – Panel: There is a Crystal community in Utah. I want to know – are you competing with Amber? Explain the difference between Lucky and Amber? 20:20 – Guest: Yes I did look at Amber but they are approaching it differently than us. The guest talks about the differences between Amber and Lucky. 21:54 – Guest (continues): With Lucky you will have to learn a little bit more but you get more of a pack! 23:23 – Panel: It sounds like Lucky is inspired by Elm – right? 23:32 – Guest: Yeah, I think so. The guest dives into this topic of Elm and Lucky! 24:35 – Panel: How much does the types feel like it’s getting in your way? How explicit is it? When I came to Ruby it was a breath of fresh air. I am a bit reluctant to go back to those days. 25:25 – Guest: I think Lucky does a happy medium. It doesn’t infer instant variables. I like the... 26:28 – Panel: I learned Java very early on in my computer science career. 27:00 – Guest. 27:10 – Panel: “Crystal...it’s not Java!” That should be your slogan! 27:20 – Fresh Books! 28:25 – Panel: A lot of people are moving to Elixir community. Do you see people moving from Ruby to Lucky and Crystal? How does Lucky compare to Phoenix? 28:55 – Guest: Good question! 29:10 – The guest talks about bamboo – see links below!! 29: 29 – Guest: Sure Ruby is fast but sometimes you spend more time on it then you would want to. 31:08 – Guest: Blessing and curse that Crystal looks so much like Ruby. That’s what I thought at first: why would I want to learn this if it’s so similar to Ruby. BUT there are so many benefits to Crystal vs. Ruby. 31:48 – Guest talks about Lucky catching the bugs. 32:00 – Panel: I wonder if that happened with Groovy and Rails? 32:21 – They go back-and-forth. 32:28 – Panel: Thoughtbot has always been on the forefront of Ruby. Can you talk about Thoughbot please? (See links below for Thoughtbot!) 33:15 – Guest: Great question. It’s hard to tell b/c there are different offices. I would say Ruby is our main thing. Ruby is the most mature thing that we use in-terms of web development. Guest: Actually – Rails is pretty nice! 34:54 – Panel: We went through the same thing with CodeFund! I wrote it initially in Python and then I wrote it in Elixir and it became so complex. Now we are moving everything back to Ruby and it’s been a fantastic decision. 36:30 – Chuck: You are talking about the sustainability of open source but there are benefits throughout the company right? There are tons of tangible benefits of doing it, especially when it’s your Friday schedule. You can level-up on things that could help you. I know a lot of companies cannot afford it if they are trying to hustle. 37:42 – Guest: It’s totally not charity through Thoughtbot. It’s a huge help for hiring new people. I know they are okay with letting me work on Lucky b/c it’s bringing on new developers and a good marketing tool, and finally recruiting! 39:07 – Chuck: Yeah, I have been talking about developer freedom and that’s what I am addressing through the DevRev show! It’s my new podcast show. We talk with Chris on Elixir Mix. It lends that credibility if they need to save our bacon. 40:02 – Panel: What’s your goal with Lucky? 40:11 – Guest: I would love to get it to the point where Thoughtbot could start a project and default to Lucky! Start a project and not resting every gem and be confident with launching it. 41:36 – Panelist asks a question. 41:45 – Guest: It’s not 1.0 and that means that the API will break with every release. I think that’s good to tweak stuff but that turns companies off, though. 42:40 – Chuck: Another thing that helps with adoption is Twitter used Rails to build their initial version. This blah, blah company uses important stuff and they are using Crystal and whatnot then that’s good! It sounds like you are waiting for social proof. 43:23 – Guest: Is the next Twitter going to even know about Crystal? 43:40 – Chuck: It literally only takes one enthusiast! 43:52 – Guest. 44:11 – Demo of Flickr Search is mentioned here! 45:13 – Panel: Is there something out there that you could POINT someone to? 45:27 – Guest: Not, yet. I built a small site with it! It is opensource and you can look at it. I want to show people a good example of what Lucky can do! 45:57 – Panel: You have very good docs and I am a visual learner. When I learned Rails I learned on my own and not through school. 46:20 – Panelist asks a question. 46:48 – Guest: What a huge advantage Lucky has through the Thoughtbot platform! Now that platform is kind of dried up. In terms of getting people excited it needs that killer app and they can see that it’s fast and killer! I think it takes a lot of time and finding time to do it so that’s tricky. It’s changing a lot when there is so much change. Getting Lucky to a 1.0 state so people can do videos and make apps. The hard part thing is that Lucky has to be 1.0 when Crystal is 1.0. The Lucky community is great b/c it’s encouraging and to respond in a very kind way. When you are starting something that’s new can be scary. We try to help out as much as we can and we are open and kind about it. 49:13 – Panel: “Paul is nice so Lucky is nice!” 49:19 – Guest: Everyone is super kind. It had to be short and simple. We in the dev community are very lucky – usually great pay/benefits and more w/o a college degree. What another field can you do that?! 51:00 – Panel: Great message and you need to push that! 51:10 – Panel: You were on a past podcast and you talked about how you are donating each month! Panel: Opensource maintainers are getting burned out and you want to support that. 51:40 – Guest: I think opensource sustainability what others need to do to make it sustainable. If you have the means to give we can be apart of that, too. It would be nice if companies did that. If it helps Crystal I am happy. 52:17 – Panel: I have a question about Crystal. 52:52 – Guest: Ruby right now you can do C sections right now. 53:01 – Panel. 53:10 – Guest: I don’t think so – it may but I would guess that you could do it but I don’t know how easy it would be. Note: Rust and C are mentioned. 53:37 – Panel comments. 53:46 – Guest: One thing I would say is to check-out the Lucky docs. We are happy to help! 54:10 – Panel: This is a favorite episode of mine! Both of today’s guests have been my favorite! 54:23 – Advertisement: Get A Coder Job! End – Cache Fly! Links: Get a Coder Job Course The DevRev Podcast Show DevChat TV Ruby Elixir Ruby on Rails Angular Cypress Vue React Jest.io Mocha.js Webpacker-Cli Amber Lucky The Lucky Philosophy The Bike Shed Thoughtbot CodeFund Lucky: Ruby on Rails to Lucky on Crystal... “Crystal is not Ruby Part 1” GitHub: Bamboo Ex_Machina Dialyxir Crystal Mastery Samsung T5 Carbon Copy Cloner iMazing Awesome-Lucky Paul Smith GitHub Sponsors: Sentry CacheFly Fresh Books Picks: Nate Samsung SSD Carbon Copy Cloner Application Eric iMazing HEIC Converter Charles Mastodon Andrew Upcase by Thoughtbot Awesome Lucky Paul Tailwind CSS Phoenix Live HTML Chris McCord Elixir Mix Episodes with Chris McCord
On this episode of the Bike Shed, Chris is joined by Christina Entcheva, developer from thoughtbot's New York studio who has been a product manager and designer previously in her career, but has since settled in to her role as a developer. Chris & Christina share a conversation ranging from their shared love of "boring Rails apps", Christina's recent work with headless CMSs like Contentful & Prismic, and a discussion around Rails performance. Throughout the conversation they touch on theme's of keeping a focus on user needs throughout the work of developing applications. Contentful Prismic Essential Scala book Nate Berkopec The Complete Guide to Rails Performance Mark/Compact GC in MRI - Aaron Patterson Benchmark module in Ruby Postgres Table Partitioning Getting Real book by Basecamp It Doesn't Have to Be Crazy at Work Upcase is now Free! Testing Interaction with 3rd-party APIs on Upcase Composition Over Inheritance on Upcase
The feeling of accomplishment you get from doing hard things has become Derrick’s way of living recently. Building a startup like Level is hard, but he feels good when he makes small wins. It’s rewarding when he makes progress. Ben is on a roll right now with Tuple. He’s making progress and getting stuff done. His Pairing Programming Guide is turning people into Tuple subscribers. Today’s Topics Include: Have people with high standards read and review your writing to get feedback Ben’s article, The Case for Pair Programming, was on the front page of Hacker News Ben’s marketing efforts for Tuple have increased its number of subscribers Derrick has a unique challenge of prioritization, so he set a deadline Derrick used Postgres to build a rudimentary search into Level By the end of October, Derrick should have people/teams to test and use Level Product Task List: After you launch, that’s not the end, it’s the beginning Balancing personal finances with no income; set the bar high, but don’t sell yourself short Links and resources: Derrick Reimer (http://www.derrickreimer.com) Website Derrick Reimer on Twitter (https://twitter.com/derrickreimer) Ben Orenstein (http://www.benorenstein.com/) Website Ben Orenstein on Twitter (https://twitter.com/r00k?lang=en) Level (https://level.app/) Tuple (https://tuple.app/) Tuple’s Pair Programming Guide (https://tuple.app/pair-programming-guide) The Case for Pair Programming (https://news.ycombinator.com/item?id=18230465) Upcase (https://thoughtbot.com/upcase) Indie Hackers (https://www.indiehackers.com)
Добрый день уважаемые слушатели. Представляем новый выпуск подкаста RWpod. В этом выпуске: Ruby Announcing: Our Online Learning Platform Upcase is Now Free!, Rails 5.2 disallows raw SQL in dangerous Active Record methods preventing SQL injections и A gem from Netflix the best serializer? Distributed cron for Rails apps with Sidekiq Scheduler, How to create a maintainable and scalable search for your Ruby on Rails app, ActiveSupport::StringInquirer magic и Spok is a tool for dealing with workdays and restdays in an easy way JavaScript The Ultimate Guide to Execution Contexts, Hoisting, Scopes, and Closures in JavaScript, Smart Bundling: How To Serve Legacy Code Only To Legacy Browsers и Searching and sorting text with diacritical marks in JavaScript Evergreen - a React UI Framework for building ambitious products on the web, Omi - Next Generation Web Framework in 4kb JavaScript, Graphpack - a minimalistic zero-config GraphQL server и Colorblindly - an extension that helps developers create websites for the people with colorblindness by allowing them to simulate the experience those users have on websites
In this special crossover episode, Chris is joined by Chad Pytel, Co-founder & CEO of thoughtbot and host of Giant Robots Smashing Into Other Giant Robots podcast, to discuss the content, history, and the process of making Upcase, thoughtbot's online learning platform, FREE. Giant Robots Podcast Upcase Test Driven Rails Mastering Git Fundamentals of TDD SOA on The Bike Shed Onramp to Vim thoughtbot Purpose Statement Chad on Twitter
In this special crossover episode, Chad is joined by Chris Toomey, Development Director at thoughtbot and host of The Bike Shed podcast, to discuss the content, history, and the process of making Upcase, thoughtbot's online learning platform, FREE. The Bike Shed Upcase Test Driven Rails Mastering Git Fundamentals of TDD SOA on The Bike Shed Onramp to Vim thoughtbot Purpose Statement Chris on Twitter See open positions at thoughtbot! Become a Sponsor of Giant Robots!
Chris & Derek discuss the world of services, exploring the various forms SOA can take, the oft stated benefits, and some of the pitfalls they commonly see in the wild. The discussion ranges from alternative architectures, guidelines for how to think about services within your platform, and even includes an anecdote about thoughtbot's foray into the world of SOA on Upcase. Things You Should Never Do, Part I The Entity Service Antipattern The Past, Present, and Future of GraphQL Native - Nick Schrock Netflix - Chaos Monkey Goodbye Microservices: From 100s of problem children to 1 superstar (Segment) Upcase
Jennifer Dary, founder of Plucky, discusses purpose, process, longevity, relationships, and trust by turning the tables and giving Chad a corporate counseling session. Plucky Hopscotch Design Festival Metis Upcase Joe Torre's Ground Rules for Winners 1:1 Starter Pack Jennifer on Twitter Become a Sponsor of Giant Robots!
Jaclyn and Kyle talk about ways to start a design career, as well as what happens when you're deep in the trenches building products. Headspace thoughtbot Jobs thoughtbot Purpose Beginning HTML5 and CSS3 for Dummies A Complete Guide to Flexbox | CSS Tricks Upcase Treehouse Optimizely thoughtbot Product Design Sprint jaclynperrone.com
Chad is joined by Code School & Envy Labs founder Gregg Pollack to discuss optimal work environments and building a company to support Open Source Projects. Gregg on Giant Robots Starter Studio Brené Brown The Human Element Code Pop Upcase Sell Your By-Products Dive into Neovim on Upcase Gregg's Blog Gregg on Twitter Panel Discussion: The Developer’s Path Become a Sponsor of Giant Robots!
On today’s episode we discuss Ben’s release of the first video in his Refactoring Rails course, on the benefits of following Rest in Rails applications. He goes over how he produced the video, sent it out and the feedback he got on his initial release. He now knows the rough format he wants to follow for the course, and he is still figuring out how many modules that would include. He is getting ready to release a final polished version, and has ordered some better audio recording equipment for future videos. His goal for next week is to release two more videos. Derrick has been shipping even more this week, and has seen a huge improvement in his workflow by reducing the notifications on GitHub. His team is adjusting to a more efficient way of working instead of push notifications. He shipped out a widget to embed sharable workflows within a website that includes affiliate links. He and his team have also been strategizing about their back-end infrastructure and scaling their Drip delivery system. Today’s Topics Include: Ben’s Refactoring Rails course first course video release and feedback The goals for the course format, length and possible supplementary materials The tools and skills included in the video course that could be expanded Releasing his video to a mailing list and ways to get more traffic Reflecting on doing the course solo and how he’s liking the co-working space Derrick’s improving work clarity by reducing GitHub notifications by unwatching of main drip repository Creating a new system for the team to be most productive Sharable workflows and the new embed widget Improving scale for Drip delivery system and looking for new infrastructure systems If you’re enjoying the show please give us your ratings and reviews in iTunes. Links and resources: RefactoringRails.io Working Effectively with Legacy Code by Michael Feathers Test-Driven Rails course on Upcase Spring Upcase courses Audio-Technica ATR2100 Drip Amazon DynamoDB SendGrid Amazon API Gateway How I Built This podcast by NPR
Ben outlines his next steps, reflects on his time at thoughtbot, and hands the proverbial podcast reins over to Chad. Ballroom Dancing Onboarding on Giant Robots The Art of Product Podcast Art of Vim Intro- Ben acting in a smoking jacket Upcase Refactoring From Good to Great "Blurred Lines"- Kyle Fiedler
Ben bids adieu to thoughtbot, and outlines his plans, hopes, and fears for the future. Upcase FormKeep How to negotiate the Long, Slow, SaaS Ramp of Death- Gail Goodman The Stairstep Approach to Bootstrapping- Rob Walling Natalie Nagele on Giant Robots Vim University
Derrick gets technical about Drip's performance optimization, and reflects on pre-conceived opinions in regards to tactical & strategic planning after receiving some constructive criticism. Upcase FormKeep Studio Pics New Relic
Ben and Derrick recount their experiences and lessons learned speaking at MicroConf. Upcase FormKeep MicroConf Hedonic Treadmill Thank you to our sponsor this week, FreshBooks
Ben is joined this week by Spencer Fry, founder of TypeFrag, Carbonmade, Uncover, and Coach, to discuss carryover lessons of successful startups. Upcase FormKeep TypeFrag Carbonmade Coach Why I Started Coach Being a Solo Founder Notation Capital Perseverance Pays Off Creativity, Inc. Spencer on Twitter Thank you to our sponsor this week, FreshBooks
As we prepare for MicroConf, Ben takes a new tact on his talk after giving an early demo, and Derrick recounts a positive pair-programming experience. Upcase FormKeep Screenhero Thank you to our sponsor this week, FreshBooks
On FormKeep, Ben implements custom redirects on form submissions and starts a test to remove up-front credit card collection, as well as discusses evaluation of feature requests. On Drip, Derrick walks through the app with new devs, considers on-boarding automation, and continues his refactoring project. Upcase FormKeep thoughtbot Laptop Setup Script Therapeutic Refactoring Rack::Attack Thank you to our sponsor this week, FreshBooks
Derrick welcomes new Javascript and Rails developers to Drip. Ben prepares a content deal and interviews a Content Manager for Upcase, discusses the benefits and methodology to Vim proficiency, works on an integration with Wistia, and ponders growing / selling apps. Upcase FormKeep How to Find Your Genius Zone- Laura Garnett Surviving Your First Week in Vim Wistia Startups For the Rest of Us What It's Like Buying a $128k Side Project Thank you to our sponsor this week, FreshBooks
As Ben and Derrick prepare their talks for MicroConf, Ben shares his tips and habits for talk preparation and public speaking. Upcase FormKeep Ben's Pre-Talk Checklist How to Talk to Developers Thank you to our sponsor this week, FreshBooks
Ben & Derrick reflect on the S3 outage and how it affected their services, and muse on managing user perceptions. Derrick submits a talk to MicroConf on what it means to be "customer driven", and begins a refactoring effort to rework Drip's integration system. On Upcase, Ben integrates a referral widget, and enables subscription pausing, while on FormKeep he fixes a trial plan selection bug. Upcase FormKeep AWS S3 Disruption Postmortem The Netflix Simian Army Chaos Monkey Octopus Gem MicroConf Referral SaaSquatch Thank you to our sponsor this week, FreshBooks