The Bike Shed

thoughtbot
undefined
Jun 13, 2023 • 34min

388: Empowering Other Departments Within a Company

Joël has a bike shorts update; Stephanie has a garden one. Often, power is centralized within the dev team. This is usually because they are the only ones able to execute. Sometimes this ends up interfering with team processes and workload. Joël is a fan of empowering other teams to do things themselves. Strangler Fig Pattern What Being a Staff Developer Means at Shopify by Rose Wiegley End-User Programming Transcript: STEPHANIE: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Stephanie Minn. JOËL: And I'm Joël Quenneville. And together, we're here to share a bit of what we've learned along the way. STEPHANIE: So, Joël, what's new in your world? JOËL: So, in a recent episode, I had mentioned that I was going to go on vacation on a bike trip and that I had purchased a pair of bike shorts to try out on that trip to see if that would help. And, wow, that was a great purchase. It literally saved my butt. STEPHANIE: That's awesome. I'm really glad that they worked out for you. JOËL: Still sore. This was a five-day biking trip. And I think day two was the worst, but after that, things got better. But the shorts definitely helped. STEPHANIE: I think my favorite part about us talking about biking and bike shorts is that we're finally living up to the name of our podcast. [laughs] Turns out that bikeshedding is actually even more, bikeshedding when it's about actual bike stuff. And a listener named James even wrote in with some pro tips about, you know, how to care for your bike shorts and, you know, have a comfortable biking experience. And gave some good tips for me on some longer rides to check out near me in Chicago. JOËL: So it sounds like there's some crossover between the software developer community and bike enthusiasts community who also tune into this podcast. STEPHANIE: I do think that we have gotten tweets before from, I think, like, the motorcycle Twitter tagging us @_bikeshed, perhaps maybe trying to tag a different account but, yeah, ended up in our Twitter inbox instead. JOËL: Now we just need some sweet, sweet bicycle sponsorships. So, Stephanie, what's been new in your world? STEPHANIE: I have a garden update. Last year, we purchased a small fig tree from the internet. It turns out that you can get little fruit trees delivered to your door. And this was, I think, around the fall, so it was getting a little cooler. And here in Chicago, we have to bring some of our plants inside to overwinter. And so we brought the fig indoors, and it's maybe, like, two or three feet tall. And, you know, over the few months, we were just, like, caring for it. And I was really excited to see that it had started fruiting several months ago. And I got to show it to all of my co-workers in a call. I, like, picked up this kind of large pot with our little fig tree, and I, like, held it really close to my camera and tried to point out the fruit to the other people on the call, which I realized was perhaps not a very effective way to show off my plants. Like, you could just take a picture and send it in Slack. And I was like, yes, I could have done that. But yesterday (Now our fig tree has been outside for a little while since it's warmer.) I noticed that they were ripe, and I got to harvest our figs and eat them, and they were delicious. And I got to update the team on my little fig adventure. And this time I did take pictures of the fruits and sent them in Slack instead of trying to bring this tree in from the outdoors. JOËL: That's exciting. Because I'm a fan of the design pattern, I have to ask, is this a strangler fig? STEPHANIE: It's not a strangler fig, though I have seen one in the wild on a trip to Florida. I saw a really big strangler fig, you know, completely, like, enveloping another tree, and that was really cool. If you ever get to see one in person, I think it's just, I don't know, just really amazing how nature works. JOËL: I did not realize they were wild in Florida, something to keep an eye out for next time I'm there. STEPHANIE: Definitely. So, in a recent retro on my client team, we were discussing the one-off requests our team has been getting from the folks over on the sales and client support side. Oftentimes, this involved running a script in our production console to fix some issue that a customer was experiencing. And we were talking about what we could do to make this process a little more automated, make it a little less time-consuming on our end. Even though it would just take a few minutes to run this script, we were seeing that we were getting this request repeatedly. I'm curious if you've kind of been in this situation before where dev work is required and kind of eating into time that we are trying to be delivering on other feature work for similar one-off requests or to support other folks at the company. JOËL: Yeah. I think it's a pretty common pattern that I've seen. And I think sometimes it can actually start from a healthy place. If you're taking very much of an MVP philosophy and you're building a small version of your product to start with, you're not going to have a whole suite of admin tools available. You might not even have any admin people. It might just be a founder and a technical co-founder. And so, for the first few hundred customers you have, maybe the way you make changes is by loading up the Rails production console and making a change. And that's good enough, but that doesn't scale. STEPHANIE: Yeah. You bring up a good point that I think one thing that we get to experience as consultants is seeing many different companies at different stages in their business. And I think I've seen this issue in many different iterations based on the size of the company, right? So you were saying for an MVP product, there's no admin support at all. Maybe you have a project that is now thinking of how to introduce a little bit of admin tooling and might reach for something lightweight like a gem. I've also seen custom admin dashboards, and that being its own namespace and having all of that feature set hand-rolled, and then maybe some other company might opt for a Software as a Service solution. JOËL: Yeah, there's a lot of different implementations that happen at various stages of companies. I think one thing that does seem to stay pretty constant, though, is oftentimes; other teams don't have the tools they need to make the changes they need to. So, if you have a customer service person and they're receiving a complaint or they're having to make a change, they're not always empowered to make the changes they need to. They need to talk to the dev team, who then need to make changes. And the dev team don't really want to spend their day doing admin work. They are incentivized to ship features. And so both sides are unhappy. And it kind of comes from a sort of fundamental, I think, over-empowering of the dev team and kind of a disempowering of some of the other departments within the company, if that makes sense. STEPHANIE: Yeah, that's interesting because I don't think it necessarily is intentional, the way that that happens, right? It's not like you start building a product, and you are saying, "Okay, we only want to give devs the power to change all of this stuff at the production level." It's just something inherent, I suppose, to the work that we do. And there's a lot of active effort that needs to be taken to spread some of that empowerment around. JOËL: Yeah, generally, it is not some sort of, like, nefarious corporate politics that's happening where the CTO is, like, hoarding all the power, or it's a turf war or anything like that. Like you said, it's kind of an emergent property. As developers, we're often used to being sort of ultra-empowered to do what needs to be done. In general, development teams are highly respected within companies, and so people listen to them. But also, in order to do their job, they need to have access to a lot of things. So you often have production access to all the things and the admin credentials. And if there's something that doesn't work, you write code, and you can change the sort of fundamental underlying platform that you're working with. And so you're generally empowered to make the changes you need to make your life better or if you're blocked on something. And that's not necessarily true for other departments who are working in the system that we're building. STEPHANIE: Yeah, it's kind of interesting the duality that you have identified where we do have all of this power or capability to change the system. But you had mentioned earlier that sometimes it actually gets in the way of our work, that it can be a drag to do if we have other competing priorities, and that those mundane tasks end up being something that we also don't enjoy doing. And so, like you're saying, like, no one is quite happy. I wonder at what point you, as a developer, having repeatedly been asked to do these kinds of tasks for other departments when you, would start advocating for building tooling. JOËL: I don't think there's a kind of a clear dividing line, like, oh, after three requests, you must build a dashboard. It's probably more about just general communication with the other teams. I like to think of it from kind of two perspectives. From the perspective of the developers, how can we keep them efficiently working on what they need to prioritize, which is typically new feature development? And then, from the perspective of other teams, how can they be empowered to do the work that you need to do without getting blocked? Because just like the dev team doesn't like to get blocked on all sorts of things, other teams don't like it either. And so, how can we make sure that other team members within the company are empowered to do their work as efficiently as possible? STEPHANIE: Yeah, that's interesting. I think as an IC, I've been in different positions, depending on the context of my work. There have been times when I've been happy to help with that kind of request, right? Because I know that I'm unblocking someone else. I'm facilitating their work. And they usually appreciate it too. And so maybe if that's still the case and that there's not necessarily any pain that comes with that being just the process that it is from both sides, like, that's perfectly fine. But then it's totally fair for, you know, either party, once they do feel like it's blocking other work, to start looking into maybe how much time you're spending on these one-off requests, especially if it's being spread around to other team members. You know how much effort you're making, but, like, a manager might actually be more aware of how it's affecting multiple folks on the team and wanting to figure out, like, how that sits in with the other priorities that the team is working on. JOËL: Yeah, I'm glad you mentioned talking to other people because I might be quite happy to say, "Oh, I'm going to go and, you know, go into the database and make a small change." But just because it's easy for me to do and I can take, you know, 10 minutes out of my day to do it, doesn't mean that that experience is good for, let's say, a customer service person who had to get blocked or had to ask someone else to help to move this ticket forward. When if it was something they could do themselves, that would have been a much better experience. So, even though it's a very fairly, you know, cheap request and because I don't get them a lot, I'm happy to do them, it's maybe not a good experience for my customer service colleague. So, like you said, it is important to get people's experiences on all sides. STEPHANIE: One thing that I have seen a lot is for these things to start as configuration in a YAML file that requires developers to change and then commit to the codebase whenever, you know, maybe it's, like, a list of products or a list of prices, something that is, you know, really the business domain. And yet we are hard coding it and, like, codifying it into our source control. JOËL: Oof, yes. I have been in those projects, yeah. Now, every time you want to make a change, a business person has to reach out to the dev team, and then you have to make a code change, and then you have to deploy it. And that just becomes a whole thing. And then they come back to you the next day and say, "Oh, actually, we talked about it, and we want it a little bit differently." And you have to go through that process again. STEPHANIE: I think we reach for that just because we think it's faster maybe to set up, you know, some kind of, like, lightweight configuration file, rather than if you're working in Rails, you know, setting up a whole MVC for whatever thing you're trying to configure. And I'm curious if you think that's true or not. JOËL: I think it depends. Sometimes it can be because this data feels very static, kind of hard-coded. And so it's not a thing you would necessarily want to have. In a database, it's more like a constant that you would have in your source control, except that then you find out that your constant is not quite as constant as you thought it was. And I think maybe that's okay. Writing software is all about kind of discovering the problem in the domain as it evolves and trying to not over-engineer things ahead of time. So, if we have a small set of values, maybe they're U.S. states that you deliver to or a small list of products or something that you feel is relatively hard coded, maybe it starts as a constant array hard coded into Ruby, maybe it is a YAML file that you load. Then, over time, there comes a point where you decide this should be a database table, and if it needs to be sort of pre-seeded, then there's a mechanism for that with database seeds in Rails. STEPHANIE: Yeah, that's fair. I find it so interesting because most of the time, I've not seen that transition happen, right? It almost feels like some form of the bystander effect where everyone is just, well, I'm adding just one more thing. So I don't want to make this really big change now. JOËL: And that's true for everything in code, right? You say, "Oh, this deeply nested condition, yeah, it should probably be restructured. But I'm just going to add, you know, an eighth nested level in there. And, like, eight is probably the limit, but mine is going to be the eighth, so it's going to be good." And then somebody comes in and says, "Well, you know, nine is not that bad, but the next person probably should refactor it." And then it's a mess. STEPHANIE: Yeah, it's kind of like the entropy of code, I suppose, [laughs] where, you know, we had said it requires a lot of active energy and effort to make those changes to support other folks in different departments of the company. And I think that's, like, one very common area that we see things starting as configuration but then end up being something that you are needing to support in changing. And I wonder if maybe that is a signal in itself, right? If you are getting this information from another team, like, someone external to the development team, I wonder if that's kind of a clue that this is something that should be reconsidered about whether you start with it being hard-coded. JOËL: That's an interesting thought. There's a sense in which I think these always come from places external to the development team because it's a form of kind of product research when you're trying to understand what the features need to be, what this needs to happen. Unless this hard-coded data is purely structural or internal values, but it rarely is. There probably is a broader discussion to be had about the use of any sort of hard-coded data in a configuration file in a Rails app versus just always starting with a database table. One thing that's nice about always having a database table is that if you ever need to connect it to other data in your system, now you can do things like table joins, where you can't join your users on some kind of YAML array, or you have to do some sort of Ruby Enumerable logic. You can't just do it in SQL. STEPHANIE: Yeah. This is a bit of a tangent, I think. But that reminds me of when I worked at a product company where we had a very robust data warehouse, and all of that information was available to teams on the marketing side and on the data science side. And I actually really liked that because they were able to, you know, construct their own dashboards and queries to get the things that they need. And I've certainly seen what you're saying, this pretty important business information being hard-coded, and that ends up being less accessible, right? And less insightful, really. One other area of this topic that I think I've also bumped into before is specifically a QA engineer or, like, a QA team and empowering them to be able to do their jobs. Oftentimes, I've noticed that QA environments are not as well-maintained as maybe they should be, where the data that's seeded or, you know, kind of overtime in this environment is a little wonky. I've also experienced, while working on a feature, kind of having to go back and forth between whoever is helping QA my work telling them, like, "Oh, this isn't finished yet. So, like, don't worry about this that you're testing," or, you know, "Actually, that does look wrong. But let me look into it over on this end." And I found it sometimes difficult to navigate because I want them to be more empowered to test their feature without that uncertainty over whether something is intentional or actually broken. JOËL: In this case, do you think it's more about communication between development and QA, clear acceptance criteria, or clear descriptions of what changes have been pushed up for review and what's not in scope? Is that where you're headed? STEPHANIE: I think that's a part of it. But I actually think there are more technical considerations, especially in terms of whether our environments all align in terms of the data we're expecting, right? Does our dev environment kind of look like our QA environment, which looks like our production environment? Because I've certainly been in projects where that's, like, all over the place, and that really messes up the different expectations we have. We all know the "Oh, it worked in my local" [laughs] response to when things come up in other environments that are unexpected. And I wonder if there is more attention that we should be having towards making sure that just because this environment is not the main one that we're working in as developers, that people who are having to use it have an equally good user experience. JOËL: I like that you brought up the term user experience because oftentimes, as developers, and just, I think, product teams in general, we're trying to make something good for the customers of the application. But there are a lot of other people that have to interact with it in sort of more ancillary roles; like you mentioned, it might be QA. It might be customer support. It might be business development. And they're not the customer. And so because of that, they're often kind of a second thought or even sort of no thought at all. And so they do their jobs as best they can with what they've got, and sometimes get really creative getting around some of the hurdles that are in place. But we can often, with very little effort because the bar is so low, make these people's lives a lot better by applying just a little bit of the same approach that we would use to make software great for a customer to use for teammates in these other roles. STEPHANIE: Yeah, absolutely. Especially because we have that line of communication open with them, and, like you said, they are also our users of our applications. And especially for QA folks, too, in some ways, they're the first line of defense of our users, right? They are a resource for us to know if the customers will eventually have a poor experience or not. And I was thinking about that back-and-forth communication I mentioned with QA, you know, trying to explain, like, oh, this isn't finished yet, so maybe, like, you should not expect this to happen. But, oftentimes, that perhaps is a signal that we haven't thought about the way that we're developing our feature to be able to be released to customers in a more incremental way. Or we might be hand-waving over something that ends up being a bug later on. JOËL: Definitely. For myself, I see that as a... code smell is maybe not the right term here, but maybe acceptance criteria smell. If I'm trying to write out some acceptance criteria, and I'm having to say, like, "Oh, but, like, ignore this, and, like, pretend this doesn't exist. All of these, like, weird edge cases and exceptions we're trying to put in, are oftentimes a sign that maybe the work was not scoped correctly. STEPHANIE: I'm curious, in your workflow, will you just make those improvements if you have the opportunity to? Or do you end up bringing that to the team or creating a ticket for it? How does that fit in when you identify areas that could be improved? JOËL: I think it depends on the team's current workload. Oftentimes, if it's just something small, it's something I can just slip into my day, and it makes somebody else's life easier, that's great. Otherwise, it can be a thing that needs to be brought up with the team in general. And then it's the thing that we prioritize, and we put it in the backlog because, like you said, the main users of our app are customers. But all of these other teammates are also users of our app in other ways, and so they need certain features to get their job done. And so it's worthwhile to, I think, at a product planning level, take those into account and prioritize them with the customer-facing things. And sometimes, because those other teams don't have as much of a voice at the table, it's up to us as developers because we sometimes have that direct communication where we're talking to them and sort of going back and forth about, "Oh, can you change this in the database for me?" or "Can you do this?" And it can be up to us to champion these other teammates' needs with the team and with the product organization in general. STEPHANIE: Yeah, I really like the way you put that. I think you used the word champion. And I've seen this also go the other direction, where we add more processes in place, where the direct communication that needs to be gatekept a little bit through a manager because the manager is trying to protect the time of the team. And that is one way to handle the issue of these requests taking too much of the team's time. But I think at some point, as an IC, you also have the agency to champion or advocate for how you use your own development time. And that reminds me of something I heard from Rose Wiegley over at Shopify about what it means to be, like, a staff or a senior developer, and that is sharing that I'm going to do this, and this is why. And that means that I won't have time to do this other thing that I may be committed to earlier. But you know, these are my reasons. And if anyone sees any problems with that, let me know. And I've been thinking about that a lot in terms of figuring out how to do the kind of work that I value. And for you and me, that does sometimes mean building those tools to empower people who aren't developers. But that is, yeah, just a way that we can assert a little bit of that agency rather than having to get the buy-in to even consider setting time aside for that work. JOËL: Yeah, I think some of the really fulfilling work that I've done has been just sometimes taking a morning and, quote, unquote, "pairing" with, like, a business development or a customer service person and just saying, "Hey, can I just sit with you while you process this kind of request or problem that you're trying to do?" And then just really seeing what they do and all the steps and being able to ask a lot of questions and kind of putting my product developer hat on. And because then I know, internally, all the things that are happening, I can quickly see, oh, okay, you're- having to do these, like, five steps to get around this really annoying thing that's just, like, a rough corner that we have that I can, like, just easily smooth the way, you know, with a 10-minute one-line fix. I'm going to go and do that, and, you know, by the afternoon, that's already done, and that's saved them so much time or so much annoyance because it's not always time. Sometimes it's just annoyance. And their life is better. And I put very little effort into it. Most of it is just taking the time just to talk to each other and to try to understand each other. So I think we brought up the idea in the beginning of trying to empower other teams to not sort of centralize all the ability to execute on change within the development team. And sometimes, you can go to fairly extreme lengths to that. One that I've seen is the idea of end-user programming or end-user development, where the using the software rather than the team developing it has some sort of way where they can sort of customize or build on, or sometimes even script or -code -their experience. Is that something you've ever had to deal with or interact with on a project? STEPHANIE: Yeah, it's really interesting that you brought that up because I had mentioned going with a SaaS solution earlier as something that I've seen before. And that reminds me of when I worked on a client project where we were using Freshsales to integrate with the business domain of the client. And this would eventually be the main software that the sales team would use. And the reason that we went with Freshsales was because it allowed for a lot of that custom configuration and workflows that they could create for themselves for their needs. Though ironically, as we were kind of butting up into the limitations of Freshsales and how it didn't necessarily work for the way we were representing our data, we kind of joked that we almost wished we had to build the tool from scratch ourselves. So I think there are trade-offs there, you know, folks had done a lot of research to figure out the right SaaS solution for this project that we were doing. And yet, you know, inevitably, like, there were some cons with the third-party and how we were able to integrate with it. And it was actually also replacing something that had been built in-house and had become difficult to maintain or something that the company decided that they didn't want to maintain anymore. So I hate to say it, but I really think it [laughs] depends. JOËL: And now you're getting into the classic build versus buy dilemma for chunks of your software. STEPHANIE: Yeah, absolutely. JOËL: I think a way that I've seen, and this happens in a kind of a smaller sense, is providing escape hatches for data. And so maybe you've got a couple of small dashboards, or you've got just a lot of things that happen in your system. And you don't have the development time, or you don't want to prioritize that time right now to build something custom for maybe your business development team. But you provide certain reports that can be exported as CSV or Excel, which then the business development team will load into Excel and do the work that they need. And now they're empowered to do what they want instead of having to ask for more information or just being limited to what was on that web UI. Similarly, sometimes, when you're able to Import a CSV, I've seen this happen a lot, where in software that's not built just right for a customer service team, they'll often export a CSV of data, put it into Excel, manipulate it the way they really want it to be, and then re-import it into the system. And so that can be a great way to temporarily empower people. I think it's also a product smell. Oftentimes, there's a fundamental flaw of the way that your product works because your team is trying to go around it. It's so bad. But as a shorter-term solution, that can be great. STEPHANIE: That makes me think that Excel is the real end-user programming software. JOËL: It really is. It really is. I do really like the idea of end-user Programming, though. And rather than developers or even product people having to decide how our software should work for our users, shifting that to the masses and letting them have all of that empowerment and agency that we're talking about. There's a technology research lab called Ink & Switch, and they build a lot of really cool end-user programming tools. I think I've seen some, like, note-taking software, that they've done, and just other research into why it's important and how it can impact users. And I have read a little bit of their work, and I think it's really cool. So I'll be sure to add that to our show notes. JOËL: I think even as developers, we like some of these ideas of end-user development. We have that a lot in our tooling. But then, even when we interact with other people's software that we don't own...because we're used to interacting with our own software, we own it. We can change anything we want. We've got complete freedom. But the moment we interact with somebody else's software and, of course, it doesn't work 100% the way we need it to, it is sometimes nice to have sort of ways to hook into it so that we can get the things we want and then maybe do some extra manipulation on our own. And APIs are often how we do that. And so the equivalent of providing an API for another developer, well, what is that for our other teams? STEPHANIE: Yeah, great questions to consider. JOËL: You know, it could be a CSV export. It could be maybe there's some easy way to connect to a Zapier plugin. And now, you know, they don't need to ask the dev team, "Oh, we want to receive this notification email internally when this event happens. They can just connect to a Zapier plugin and have it send an email or do something in Salesforce or all these other things that are helpful in their workflows but that we've not taken the time to build into the core software. And now they're empowered to do their work and not blocked on us. STEPHANIE: That's interesting because as you were talking about that, it made me think of development tooling that we get to integrate with and how those APIs are usually very flexible. And let us decide what we need and ask the API for that as opposed to it dictating it for us. And, you know, if that's something that we get to enjoy, then, yeah, we should certainly think about how you can spread that to others. JOËL: I love that. On that note, shall we wrap up? STEPHANIE: Let's wrap up. Show notes for this episode can be found at bikeshed.fm. JOËL: This show has been produced and edited by Mandy Moore. STEPHANIE: 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. It really helps other folks find the show. JOËL: If you have any feedback for this or any of our other episodes, you can reach us @_bikeshed, or you can reach me @joelquen on Twitter. STEPHANIE: Or reach both of us at hosts@bikeshed.fm via email. JOËL: Thanks so much for listening to The Bike Shed, and we'll see you next week. ALL: Byeeeeeeeee!!!!!!!! ANNOUNCER: This podcast is brought to you by thoughtbot, your expert strategy, design, development, and product management partner. We bring digital products from idea to success and teach you how because we care. Learn more at thoughtbot.com.Support The Bike Shed
undefined
Jun 6, 2023 • 31min

387: RubyKaigi 2023 with Mina Slater

Stephanie is joined by very special guest, fellow thoughtboter, Senior Developer, and marathon trainer Mina Slater. Mina and Stephanie had just been traveling together for two weeks, sponsored by WNB.rb for RubyKaigi in Matsumoto, Japan, and together, they recount their international adventure! RubyKaigi WNB.rb Understanding the Ruby Global VM Lock by observing it by Ivo Anjo gvl-tracing Justin Searls' RubyKaigi 2023 live coverage Prioritizing Learning episode Transcript: STEPHANIE: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Stephanie Minn and today. I'm joined by a very special guest, fellow thoughtboter Mina Slater. Mina, would you like to introduce yourself to our audience? MINA: Yeah. Hi, everyone. I am Mina. I am a Senior Developer on Mission Control, which is thoughtbot's DevOps and SRE team. STEPHANIE: So, Mina, what's new in your world? MINA: Well, I start marathon training this week. So I hope that this conversation goes well and lasts you for three months because you're probably not going to see or hear from me all summer. STEPHANIE: Yes. That sounds...it sounds hard, to be honest, marathon training in the summer. When I was doing a bit more running, I always thought I would wake up earlier than I did and, you know, beat the heat, and then I never would, and that really, like, was kind of rough. MINA: Yeah, actually, I was thinking about my plans for today. I didn't wake up early enough to run in the morning. And so I was calculating, like, okay, by midday, it's going to be too hot. So I'm going to have to wait until, like, 6:00 p.m. [laughs] STEPHANIE: Yeah, yeah. Or, if you're like me, there's a very real chance that you just skip it altogether. [laughter] MINA: Well, I have a deadline, so... [laughs] STEPHANIE: That's true. When is your marathon race? MINA: This is actually the first year I'm doing two in a calendar year. So I'm doing Berlin in September. And then, three weeks after that, I'm going to run one in Detroit. STEPHANIE: Nice. At least you'll be ready. You'll, like, have done it. I don't know; it kind of sounds maybe a bit more efficient that way. [laughs] MINA: Theoretically. But, you know, ask me in October. I'll let you know how it goes. STEPHANIE: That's true. You might have to come back on as a guest. [laughs] MINA: Just to talk about how it went. [laughs] STEPHANIE: Yeah, exactly. MINA: So that's what's new with me. What's new in your world, Steph? STEPHANIE: So, a while back on a previous Bike Shed episode, I talked about joining this client team and, in their daily team syncs, in addition to just sharing what we were up to and what we were working on, we would also answer the question what's something new to us. And that was a space for people to share things that they learned or even just, like, new things that they tried, like food, or activities, or whatnot. And I really enjoyed it as a way to get to know the team, especially when I was new to that client project. And recently, someone on the team ended up creating a random question generator. So now the question for the daily sync rotates. And I've been having a lot of fun with that. Some of the ones that I like are, what made you laugh recently? What's currently playing on your Spotify or YouTube? No cheating. MINA: [laughs] STEPHANIE: And then, yesterday, we had what's for dinner? As the question. And I really liked that one because it actually prompted me to [chuckles] think about what I was going to do for dinner as opposed to waiting till 5:00 p.m. and then stressing because I'm already hungry but don't have a plan [chuckles] for how I'm going to feed myself yet. So it ended up being nice because I, you know, kind of was inspired by what other people mentioned about their dinner plans and got my stuff together. MINA: That's shocking to me because we had just come off of two weeks of traveling together. And the one thing I learned about you is that you plan two meals ahead, but maybe that is travel stuff. STEPHANIE: I think that is extremely correct. Because when you're traveling, you're really excited about all the different things that you want to eat wherever you are. And so, yeah, we were definitely...at least I was planning for us, like, two or three meals [laughs] in advance. MINA: [laughs] STEPHANIE: But, when I'm at home, it is much harder to, I don't know, like, be motivated. And it just becomes, like, a daily chore. [laughs] So it's not as exciting. MINA: I think I'm the same way. I just had a whole bunch of family in town. And I was definitely planning dinner before we had breakfast because I'm like, oh, now I have to be responsible for all of these people. STEPHANIE: Yeah. I just mentioned the questions because I've been really having fun with them, and I feel a lot more connected to the team. Like, I just get to know them more as people and the things they're interested in, and what they do in their free time. So, yeah, highly recommend adding a fun question to your daily syncs. MINA: Yeah, we started doing that on Mission Control at our team sync meetings recently, too, where the first person...we actually have an order generator that somebody on the team wrote where it takes everyone's first and last name and scramble them and then randomizes the order. So you kind of have to figure out where in the queue you are and who's coming up next after you. But the first person that goes in the queue every day has to think of an icebreaker question. STEPHANIE: That's kind of a lot of pressure [laughs] for a daily meeting, especially if you're having to unscramble names and then also come up with the icebreaker question. I personally would be very stressed [laughs] by that. But I also can see that it's...I also think it's very fun, especially for a small team like yours. MINA: Yeah, yeah, just seven of us; we get to know really well what letters are in everyone's names. But I was first today, and I didn't have an icebreaker question ready. So I ended up just passing. So that's also an option. STEPHANIE: That's fair. Maybe I'll link you to our random question generator, so you can find some inspiration. [laughs] MINA: Yeah, it's a ChatGPT situation. STEPHANIE: So you mentioned that you and I had just been traveling together for two weeks. And that's because Mina and I were at RubyKaigi in Matsumoto, Japan, earlier this May. And that's the topic of today's episode: Our Experience at RubyKaigi. And the really cool thing that I wanted to mention was that this was all possible because Mina and I were sponsored by WNB.rb, which is a global community of women and non-binary people working in Ruby. And I've mentioned this group on the show before, but I wanted to plug it again because I think that this was something really special that we got to do. WNB runs a lot of initiatives, like, meetups and panels supporting people to speak at conferences and book clubs. And, you know, just many different programming events for supporting women and non-binary Rubyists in their career growth. And they are recently beginning a new initiative to sponsor folks to attend conferences. And Mina, you and I were the first people to get to try this out and go to an international conference. So that was really awesome. It was something that I don't think I would have done without the support from WNB. MINA: And you almost didn't do. I think there was a lot of convincing [chuckles] that went on at the beginning to kind of get you to, like, actually consider coming with me. STEPHANIE: It's true. It's true. I think you had DMed me, and you were, like, so, like, RubyKaigi, like, eyeball emoji. [laughs] I was, I think, hesitant because this was my first international conference. And so there was just a lot of, like, unknowns and uncertainty for me. And I think that's going to be part of what we talk about today. But is there anything that you want to say about WNB and how you felt about being offered this opportunity? MINA: Yeah. When Emily and Jemma, the founders of WNB, approached us with this opportunity and this offer, I think I was...taken aback is not really quite the right words but, like, surprised and honored, really, I think it's a better word. Like, I was very honored that they thought of us and kind of took the initiative to come to us with this offer. So I'm really grateful for this opportunity because going to RubyKaigi, I think it's always something that was on my radar. But I never thought that...well, not never. I thought that I had to go as a speaker, which would have been, like, a three to five-year goal. [laughs] But to be able to go as an attendee with the support of the group and also of thoughtbot was really nice. STEPHANIE: Yeah, absolutely. That investment in our professional development was really meaningful to me. So, like you, I'm very grateful. And if any of our listeners are interested in donating to WNB.rb and contributing to the community's ability to send folks to conferences, you can do so at wnb-rb.dev/donate. Or, if you work for a company that might be interested in sponsoring, you can reach out to them at organizers@wnb-rb.dev. MINA: I highly recommend doing that. STEPHANIE: So, one of the questions I wanted to ask you about in terms of your RubyKaigi experience was, like, how it lined up with your expectations and if it was different or similar to what you were expecting. MINA: Yeah, I have always heard that when people talk about RubyKaigi as a conference and about its contents, the word that everyone uses to describe it is technical. I have already had sort of a little bit of that expectation going in. But I think my interpretation of the word technical didn't really line up with how actually technical it was. And so that was one thing that was different than what I had expected. STEPHANIE: Could you elaborate on what was surprising about the way that it was technical? MINA: Yeah. I think that when I hear technical talks and having been to some Ruby and Rails confs here in the States, when I hear about technical talks, it's a lot more content about people using the technology, how they use Ruby to do certain things, or how they use Rails to achieve certain goals in their day-to-day work or side projects. But it seems at RubyKaigi; it is a lot more about the language itself, how Ruby does certain things, or how interpreters implement Ruby, the language itself. So I think it's much more lower-level than what I was expecting. STEPHANIE: Yeah, I agree. I think you and I have gone to many of Ruby Central conferences in the U.S., like RubyConf and RailsConf. So that was kind of my comparison as well is that was, you know, the experience that I was more familiar with. And then, going into this conference, I was very surprised that the themes of the talks were, like you said, very focused on the language itself, especially performance, tooling, the history and future of Ruby, which I thought was pretty neat. Ruby turns 30, I think, this year. And one thing that I noticed a lot was folks talking about using Ruby to reflect on itself and the possibilities of utilizing those capabilities to improve our experience as developers using the language. MINA: Yeah. I think one of the things I was really fascinated by is...you had mentioned the performance. There were several talks about collecting how Ruby performs at certain levels. And I thought that that was quite interesting and things I had never thought about before, and I'm hoping to think about in the future. [laughs] STEPHANIE: Yeah. One talk that I went to was Understanding the Ruby Global VM Lock by Ivo Anjo. And that was something that, you know, I had an awareness of that Ruby has this GVL and certain...I had, like, a very hand-wavy understanding about how, like, concurrency worked with Ruby because it hasn't been something that I've really needed to know too deeply in my day-to-day work. Like, I feel a little bit grateful not to have run into an issue where I had to, you know, dive deep into it because it was causing problems. [laughs] But attending that talk was really cool because I liked that the speaker did give, like, an overview for folks who might be less familiar but then was able to get really deep in terms of, like, what he was doing workwise with improving his performance by being able to observe how the lock was being used in different threads and, like, where it might be able to be improved. And he shared some of his open-source projects that I'll link in the show notes. But, yeah, that was just something that I was vaguely aware of and haven't yet, like, needed to know a lot about, but, you know, got to understand more by going to this conference. And I don't think I would have gotten that content otherwise. MINA: Yeah, I agree. The talk that you are referencing is one of my favorite as well. I think, like you, kind of this vague idea of there's things going on under the hood in Ruby is always there, but to get a peek behind the curtain a little bit was very enlightening. I wrote down one of the things that he said about how highly optimized Ruby code can still be impacted and be slow if you don't optimize GVL. And he also shared, I think, some strategies for profiling that layer in your product, if that is something you need, which I thought was really cool. STEPHANIE: Yeah. I think I had mentioned performance was a really big theme. But I didn't realize how many levers there were to pull in terms of the way Ruby is implemented or the way that we are able to use Ruby that can improve performance. And it's really cool to see so many people being experts at all of those different components or aspects of making Ruby fast. [laughs] MINA: Yeah. I think that part of the work that we do on Mission Control is monitoring performance and latency for our clients. And while I don't expect having to utilize some of the tools that I learned at RubyKaigi, I expect being aware of these things helping, I think, in the long run. STEPHANIE: Yeah, absolutely. Joël and I have talked on the show about this idea of, like, push versus pull learning. So push, being you consume content that may not be relevant to you right now but maybe will be in the future. And you can remember, like, oh, I watched a talk on this, or I read something about this, and then you can go refer back to it. As opposed to pull being, like, I have this thing that I don't understand, but I need to know right now, so I'm going to seek out resources about it. And I think we kind of landed on that both are important. But at Kaigi, especially, this was very much more push for me where there's a lot of things that I now have an awareness of. But it's a little different, I think, from my experience at Ruby Central conferences where I will look at the schedule, and I will see talks that I'm like, oh, like, that sounds like it will be really relevant to something I'm working through on my client project or, like, some kind of challenging consulting situation. And so the other thing that I noticed that was different was that a lot of the U.S. conferences are more, I think like business and team challenges-focused. So the talks kind of incorporate both a technical and socio-cultural aspect of the problems that they were solving. And I usually really like that because I find them very relatable to my day-to-day work. And that was something that was less common at Kaigi. MINA: Also, that I've never been to a conference that is more on the academic side of things. So I don't know if maybe that is more aligned with what Kaigi feels like. STEPHANIE: Yeah, that's true. I think there were a lot of talks from Ruby Committers who were just sharing, like, what they've been working on, like, what they've been thinking about in terms of future features for Ruby. And it was very much at the end of those talks, like, I'm open to feedback. Like, look out for this coming soon, or, like, help contribute to this effort. And so it was interesting because it was less, like, here are some lessons learned or, like, here are some takeaways, or, like, here's how we did this. And more like, hey, I'm, you know, in the middle of figuring this out, and I'm sharing with you where I'm at right now. But I guess that's kind of the beauty of the open-source community is that you can put out a call for help and contributions. MINA: Yeah, I think they call that peer review in the academic circles. STEPHANIE: [laughs] That's fair. MINA: [laughs] STEPHANIE: Was there anything else that you really enjoyed about the conference? MINA: I think that one of my favorite parts, and we've talked about this a little bit before, is after hours on the second day, we were able to connect with Emori House and have dinner with their members. Emori House is a group that supports female Kaigi attendees specifically. I think it's that they, as a group, rent out an establishment or a house or something, and they all stay together kind of to look out for each other as they attend this very, I think, male-dominated conference. STEPHANIE: Yeah. I loved that dinner with folks from Emori House too. I think the really cool thing to me is that it's just community and action, you know, like, someone wanted to go to this conference and make it easier for other women to go to this conference and decided to get lodging together and do that work of community building. And that social aspect of conferences we hadn't really talked about yet, but it's something that I really enjoy. And it's, like, one of the main reasons that I go to conferences besides learning. MINA: Yeah, I agree. At the Ruby Central conferences, one of my favorite parts is always the hallway track, where you randomly meet other attendees or connect with attendees that you already knew. And like I mentioned, this dinner with Emori House happened on the second night. And I think by midday second day; I was missing that a little bit. The setup for RubyKaigi, I noticed, does not make meeting people and organizing social events as easy as I had been used to, and part of that, I'm sure, is the language barrier. But some places where I had met a lot of the people that I call conference friends for Ruby Central conferences had been at the lunch table. And Kaigi sets up in a way where they send you out with food vouchers for local restaurants, which I thought was really cool. But it doesn't make meeting people and organizing groups to go out together with people you don't already know a little more difficult. So meeting Emori House on the second night was kind of exactly what I had been missing at the moment. STEPHANIE: Yeah, agreed. I also really thrive off of more smaller group interactions like organically, you know, bumping into people on the hallway track, ideally. I also noticed that, at Kaigi, a lot of the sponsors end up hosting parties and meetups after the conference in the evenings. And so that was a very interesting social difference, I think, where the sponsors had a lot more engagement in that sense. You and I didn't end up going to any of those drink-ups, are what they're called. But I think, similarly, if I were alone, I would be a little intimidated to go by myself. And it's kind of one of those things where it's like, oh, if I know someone, then we can go together. But, yeah, I certainly was also missing a bit of a more organic interaction with others. Though, I did meet a few Rubyists from just other places in East Asia, like Taiwan and China. And it was really cool to be in a place where people are thinking about Ruby differently than in the U.S. I noticed in Japan; there's a lot more energy and enthusiasm about it. And, yeah, just folks who are really passionate about making Ruby a long-lasting language, something that, you know, people will continue to want to work with. And I thought that was very uplifting because it's kind of different from what the current industry in the U.S. is looking like in terms of programming languages for the jobs available. MINA: It's really energizing, I think, to hear people be so enthusiastic about Ruby, especially, like you said, when people ask me what I do here, I say, "Developer," and they say, "Oh, what language do you work in?" I always have to be kind of like, "Have you heard of Ruby?" [laughs] And I think it helps that Ruby originated in Japan. They probably feel a little bit, like, not necessarily protective of it, but, like, this is our own, and we have to embrace it and make sure that it is future-facing, and going places, and it doesn't get stale. STEPHANIE: Right. And I think that's really cool, especially to, you know, be around and, like, have conversations about, like you said, it's very energizing. MINA: Yeah, like you mentioned, we did meet several other Rubyists from, like, East Asian countries, which doesn't necessarily always happen when you attend U.S.-based or even European-based conferences. I think that it is just not as...they have to travel from way farther away. So I think it's really cool to hear about RubyConf Taiwan coming up from one of the Rubyists from Taiwan, which is awesome. And it makes me kind of want to go. [laughs] STEPHANIE: Yeah, I didn't know that that existed either. And just realizing that there are Rubyists all over the world who want to share the love of the language is really cool. And I am definitely going to keep a lookout for other opportunities. Now that I've checked off my first international conference, you know, I have a lot more confidence about [laughs] doing it again in the future, which actually kind of leads me to my next question is, do you have any advice for someone who wants to go to Kaigi or wants to go to an international conference? MINA: Yeah, I think I have both. For international conferences in general, I thought that getting a buddy to go with you is really nice. Steph and I were able to...like, you and I were able to kind of support each other in different ways because I think we're both stressed [laughs] about international travel in different ways. So where you are stressed, I'm able to support, and where I'm stressed, you're able to support. So it was really nice and well-rounded experience because of that. And for RubyKaigi specifically, I would recommend checking out some of the previous year's talks before you actually get there and take a look at the schedule when it comes out. Because, like we said, the idea of, I think, technical when people use that word to describe the content at RubyKaigi is different than what most people would expect. And kind of having an idea of what you're getting into by looking at previous videos, I think, will be really helpful and get you in the right mindset to absorb some of the information and knowledge. STEPHANIE: Yeah, absolutely. I was just thinking about...I saw in Ruby Weekly this week Justin Searls had posted a very thorough live blogging of his experience at Kaigi that was much more in the weeds of, like, all of the content of the talks. And also had tips for how to brew coffee at a convenience store in Japan too. So I recommend checking that out if folks are curious about...especially this year before the videos of the talks are out. I think one thing that I would do differently next time if I were to attend Kaigi or attend a conference that supports multiple languages...so there were talks in Japanese and English, and the ones in Japanese were live interpreted. And you and I had attended, like, one or two, but it ended up being a little tough to follow because the slides were a little bit out of sync with the interpretation. I definitely would want to try again and invest a little more into attending talks in Japanese because I do think the content is still even different from what we might be seeing in English. And now that I know that it takes a lot of mental energy, just kind of perhaps loading up on those talks in the morning while I'm still, you know -- MINA: [laughs] STEPHANIE: Fresh-faced and coffee-driven. [laughs] Rather than saving it for the afternoon when it might be a little harder to really focus. MINA: I think my mental energy has a very specific sweet spot because definitely, like, late in the afternoon would not be good for that. But also, like, very early in the morning would also not be very good for that because my coffee hasn't kicked in yet. STEPHANIE: That's very real as well. MINA: Do you think that there is anything that the conference could have done to have made your experience a little tiny bit better? Is there any support that you could have gotten from someone else, be it the conference, or WNB, or thoughtbot, or other people that you had gone with that could have enhanced this experience? STEPHANIE: Hmm, that's an interesting question. I'm not really sure because I was experiencing so many new things -- MINA: [laughs] STEPHANIE: That that was kind of, like, what was top of mind for me was just getting around even just, like, looking at all the little sponsor booths because that was, like, novel for me to see, like, different companies that I've never heard of before that I think when I asked you about expectations earlier, like, I actually came in with not a lot of expectations because I really was just open to whatever it was going to be. And now that I've experienced it once, I think that I have a little more of an idea of what works for me, what I like, what I don't like. And so I think it really comes down to it being quite a personal experience and how you like to attend conferences and so -- MINA: For sure. STEPHANIE: At the end of the day, yeah, like, definitely recommend just going if that opportunity is available to you and determining for yourself how you want that experience to be. MINA: Certainly. I think just by being there you learn a lot about what you like in conferences and how we like to attend conferences. On a personal level, I'm also an organizer with Ruby Central with their scholarship committee. And that's somewhere where we take new Rubyists or first-time conference attendees and kind of lower the barrier for them to attend these conferences. And the important part I wanted to get to is setting them up with a mentor, somebody who has attended one of these conferences before that can kind of help them set goals and navigate. And I thought that someone like that would...at RubyKaigi, being both our first times, might be useful. STEPHANIE: Yeah, absolutely. I think that's totally fair. One thing I do really like about the Ruby Central conferences is the social support. And I think you had mentioned that maybe that was the piece that was a little bit missing for you at this conference. MINA: Yeah. I know that someone had asked early on, I think, like, the night before the conference officially kicked off, whether there is a Slack or Discord space for all conference attendees so that people can organize outings or meals. And that is definitely something that at least the Ruby Central conferences have, and I imagine other conferences do too, that was missing at Kaigi as well. STEPHANIE: I'm wondering if you would go to Kaigi again and maybe be that mentor for someone else. MINA: I think so. I think I had different feelings about it when we were just leaving the conference, kind of feeling like some of these things that I'm learning here or that I'm being made aware of rather at RubyKaigi will come up important in the future, but maybe not right away. So then I was kind of walking away with a sense of, like, oh, maybe this is a conference that is important, but I might deprioritize if other opportunities come up. But then I started to kind of, like, jot down some reflections and retroing with myself on this experience. And I thought what you mentioned about this being the sort of, like, the push learning opportunity is really nice because I went in there not knowing what I don't know. And I think I came out of it at least being a little bit aware of lots of things that I don't know. STEPHANIE: Yeah, yeah. Maybe, like, what I've come away with this conversation is that there is value in conferences being different from each other, like having more options. And, you know, one conference can't really be everything for everyone. And so, for you and I to have had such a very different experience at this particular conference than we normally do, that has value. It also can be something that you end up deciding, like, you're not into, and then you know. So, yeah, I guess that is kind of what I wanted to say about this very new experience. MINA: Yeah, having new experiences, I think, is the important part. It's the same idea as you want to get a diverse group of people in the room together, and you come out with better ideas or better products or whatever because you have other points of view. And I think that attending conferences, even if not around the world, that are different from each other either in academia or just kind of, like, branching out of Ruby Central conferences, too, is a really valuable experience. Maybe conferences in other languages or language-agnostic conferences. STEPHANIE: Yeah, well said. On that note, shall we wrap up? MINA: Let's do it. STEPHANIE: Show notes for this episode can be found at bikeshed.fm. JOËL: This show has been produced and edited by Mandy Moore. STEPHANIE: 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. It really helps other folks find the show. JOËL: If you have any feedback for this or any of our other episodes, you can reach us @_bikeshed, or you can reach me @joelquen on Twitter. STEPHANIE: Or reach both of us at hosts@bikeshed.fm via email. JOËL: Thanks so much for listening to The Bike Shed, and we'll see you next week. ALL: Byeeeeeeeeee!!!!!!!!!! ANNOUNCER: This podcast is brought to you by thoughtbot, your expert strategy, design, development, and product management partner. We bring digital products from idea to success and teach you how because we care. Learn more at thoughtbot.com.Support The Bike Shed
undefined
5 snips
May 31, 2023 • 41min

386: Value Objects Revisited: The `Tally` Edition

If you're in the market for bicycle shorts, Joël's got you. Stephanie just returned from RubyKaigi in Japan and shares details of her trip. Recently at thoughtbot, there have been conversations around an interesting data modeling exercise. Joël and Stephanie discuss the following: Value Objects vs. Hashes Doing Math on Compound Numbers Monoids and Folding Naming Concepts in Code This episode is brought to you by Airbrake. Visit Frictionless error monitoring and performance insight for your app stack. Ruby Kaigi Google Translate Lens Video on city parks Enumerable#tally Hash#merge Monoids Enumerable#all? Value of specialized vocabulary Gist with Joël’s code solution Transcript: STEPHANIE: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Stephanie Minn. JOËL: And I'm Joël Quenneville. And together, we're here to share a little bit of what we've learned along the way. STEPHANIE: So, Joël, what's new in your world? JOËL: I've made an unusual purchase this week. I went out and bought a pair of bicycle shorts. And, for those who are not aware, these are special shorts that have padding built into them. Typically, they're, like, skin-tight, but I got, I guess, what are called mountain biking shorts. So, they kind of look more like the cut of a normal short. But they've got this, like, built-in padding for biking. STEPHANIE: So. Just to confirm, you did get these shorts for biking purposes, right? JOËL: Yes. I purchased these shorts for biking purposes. STEPHANIE: Okay. [laughs] JOËL: And I got these because I was talking to a friend about this and mentioning that this was, like, probably the most ambitious cycling thing I've ever done in my life. And they recommended if you have not done bike shorts, you really should get them. They make a big difference. STEPHANIE: Wow. Okay, I have two thoughts here. First of all, you prefaced this saying that this was an unusual purchase. So I thought maybe that you bought these bike shorts for some other purpose. [laughs] But I am excited to talk about this because I've also been curious about trying bike shorts. I bike a lot in Chicago in the summer, and I've been doing, like, longer rides on the Lakefront trail. And one of my goals, actually, this summer is to do a bikepacking trip. But I have not been super comfortable on longer rides. And I was just thinking that this might be something really helpful to make them a little more enjoyable. JOËL: So, is the kind of biking that you're doing closer to what might be considered commuting? STEPHANIE: Yeah, mostly commuting. But also, just, like, going on long rides on the weekends, in addition to this, hopefully, forthcoming bikepacking trip up to a state park. So not too long, maybe, like, 60 miles, but definitely long enough to start getting a little uncomfy on your seat. JOËL: Yeah, is 60 miles, like, in one day? STEPHANIE: Yeah, exactly. JOËL: That's a lot. Yeah, the friend who recommended biking shorts to me told me that pretty much anything over maybe 10 miles is worth getting shorts. STEPHANIE: Wow, okay. I clearly have been suffering [laughs] for way too long, then. Tell me more about your cycling trip. JOËL: So this is a bikes plus beer trip. Basically, I plotted a bunch of breweries in Belgium on a map and constructed an itinerary that could hit a bunch of them while keeping fairly short rides between towns. And the goal is to do maybe 30-35 miles in a day. And so I'll be going probably, like, cycling in the morning, and then exploring and drinking in the afternoon and evening. STEPHANIE: That sounds amazing. That's really cool to do a little bit of a tour of the area and then also traveling by bike. JOËL: Yeah, I'm excited because other modes of transport really just give you the origin and the destination, whereas cycling, you kind of get all of the in-between places. You get a much better feel for the area that you're in. And you can make all these unexpected stops if you want. You can make detours. So I feel like you get the sort of being in the moment, being in the place effect that you would have as a pedestrian but with a much longer reign. STEPHANIE: Yeah, absolutely. That's exactly what I was going to say. I love cycling. And there's something really special about being able to be present in your surroundings and seeing people on the street or a cool building as you're going. But also going at a speed where it feels very fun and very freeing to just be cycling through a town and making stops when you want to, and traveling greater distances than you could be able to on foot. JOËL: So I just received these bike shorts yesterday in the mail. So today, at the end of the day, I'm going out for a bike ride, and I'm going to see if they perform as advertised. STEPHANIE: That's exciting. Keep us posted [laughs] on if you end up liking them or not. JOËL: Yeah, yeah. The next episode or two, I'll have to report bike shorts; yay or nay? STEPHANIE: Yeah, The Bike Shed will now become bike gear reviews. JOËL: The name will actually line up, then with what the people googling, it might think it actually is. Stephanie, what's new in your world? STEPHANIE: Speaking of vacation, I just got back from a two-and-a-half-week trip myself. I mentioned on the podcast a couple of episodes ago, I think, that I was traveling to Japan for RubyKaigi, an international Ruby Conference over in Japan. And then I spent another week in Taiwan, just on my own time. So, yeah, I had a really big, long trip, and it was really great. It was my first time going abroad in a really long time. It was my first time being somewhere where I didn't speak the language. So, in Japan...I don't speak any Japanese. And it was both challenging and also, like, not too bad. I found my way around through a lot of gesturing and smiling, and nodding. [laughs] And, hopefully, people were able to understand what I was trying to communicate. Also, pointing at menus, I highly recommend going to places that have pictures of the food, and then you can just point when you want to order. [laughs] JOËL: So, did you find that English was not particularly useful then in Japan as a tourist? STEPHANIE: Yeah, I would say so. The next thing was that most signs were translated. So we ended up taking public transportation a lot. And that was quite easy to navigate, especially since I have kind of navigated subways in other cities before, and reading the signs is no problem. But when you're trying to communicate with locals, that was a little harder. JOËL: Did you use any, like, apps on your phone or anything like that to help navigate kind of the different language? STEPHANIE: Yeah, the Google Translate Lens app. I can't remember exactly what it is. But this was my first time really using it. And I was really impressed by how it was able to translate things that you're using your camera to take pictures of, or just, like, having your camera view. I did feel a little silly, like, holding my phone up to everything and trying [laughs]...so I could understand what I was reading. But for menus that did not have pictures, that was my backup strategy. [laughs] JOËL: Did you ever have to have your phone translate something and then just show your phone to someone else? STEPHANIE: No, I didn't have to go that far. Though I do think that it has a feature where you can have someone speak into the phone, and it will translate that into your native language. And then you respond by speaking into it and then playing the sound for them, which, you know, I bet really works in a pinch. But I think that required a little more investment into the interaction [laughs] with the other person than I was ready for. Like I said, the gesturing served me quite well. JOËL: I got the experience of being on the other side of that a while back. So, here in Boston, I was just walking down the street, and someone stopped me and just holds up their phone. And they've typed something in Chinese on there. And they hit a button, and it comes in English. STEPHANIE: [laughs] JOËL: And they're asking for directions. And I think I typed a sentence back on their phone in English, and then they hit the translate button and got it back in Chinese. We went back and forth a few times. And eventually, I think he got what he wanted, and we went our separate ways. And I was kind of amazed that this whole interaction happened. STEPHANIE: Yeah, that's really cool. JOËL: Yeah, kudos to that person for having the courage to stop someone on the street when you don't speak their language. STEPHANIE: Yeah, absolutely. I think even when I was struggling to communicate with someone because of the language barrier, I could tell from their gesturing in return that we were, like, willing to help each other out. And that, like, there was still an ability to find some kind of connection, even though, you know, we didn't completely understand each other. And that was definitely one thing that I really enjoyed was being in a place with, you know, people different from me and having that exposure. It's been a really long time since I've got to experience that, and that was really valuable. JOËL: So, other than the conference, what would you say are some highlights of the trip for you, maybe one from Japan and one from Taiwan? STEPHANIE: So one of my favorite things about being in Tokyo was all the green space that was around. I ended up walking a lot just to explore the neighborhoods. And I always just stumbled across a local park or even a shrine that had really great nature around it, a lot of big trees. You know, some, like, water features, maybe like a pond, and a lot of really fun plants that I got to learn about. And, yeah, that was really nice, especially in such a dense urban area, like, coming across green space to just sit for a little while. And it was such a nice relief from the density and busyness of a big city. That was just one thing that I was really impressed by being in Japan. JOËL: That's really cool. I think that really speaks to the quality of their urban planning. I know that the stereotype of Tokyo that I have in my mind is that it's, like, you know, ultra-modern, ultra-urban, you know, it's the largest city in the world. So the idea that they've taken the time to set up all these little parks everywhere is really endearing. Particularly, I think the idea of smaller parks at the neighborhood level where you don't need, you know, something massive like, let's say, New York's Central Park, which is, you know, really cool. But having just a little green space in your neighborhood where you can, like, stop by, I think it's a wonderful upgrade to local people's quality of life. I was recently listening to a video on YouTube from a city planning channel talking about just all the thinking that goes behind city parks, and having them at different scales, and how that impacts the residents of different areas. So it's really cool to hear that Tokyo has done a great job with that. STEPHANIE: Yeah, absolutely. I think part of the joy of just stumbling upon it was that you know, even when I wasn't seeking it out, it would just come along during my walks. And, yeah, it really was very refreshing. JOËL: What about Taiwan? STEPHANIE: So, in Taiwan, what I really enjoyed about it it's a bit of a smaller island. And so you can actually get to a lot of places within a few days. And a lot of folks take day trips out to the coast from Taipei. And I was able to do a two-day trip to another county that had some hot springs, and I got to enjoy an outdoor hot springs in the rain. And that was really nice because it was, like, surrounded by trees. And it happened to be raining that morning, but, you know, we were all kind of already getting wet, so it didn't really matter. And it was just, like, this really serene and gorgeous experience being able to enjoy that. And I think that was another place where I was in a very urban area, and then being able to escape a little bit was really nice. JOËL: That sounds like a magical moment. Have you visited hot springs before, or was this your first time going to a hot spring? STEPHANIE: I have been to a few in the U.S. before. I like to take road trips to national parks. And there are some really great hot springs in the U.S. as well. And so this was kind of something that I really wanted to do somewhere else just to experience it elsewhere. And, yeah, I'm really glad to have checked that off my bucket list. JOËL: That's really cool. I've never been to a hot spring, and it sounds like a fun thing to do. So it's on my kind of greater bucket list. It's maybe not a top-five thing to do, but definitely, something I want to do one day. STEPHANIE: Cool. Love it. That was vacation talk from Joël and Stephanie. [laughs] 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 cut your debugging time in half. So why do developers love Airbrake? 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 of 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 helps 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 to include 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. Head on over to airbrake.io/try/bikeshed to create your FREE developer account today! JOËL: So recently at thoughtbot, we've been having conversations around this really interesting data modeling exercise, where let's say this is a company, and you want to purchase T-shirts for everyone at the company. You have already some T-shirts on hand because you've done this kind of thing before in a couple of different warehouses. And you need to know how many new T-shirts you need to order in order to have enough for everyone. So as long as you keep things simple, the math is pretty easy because you sum the number of people at your company, and then you sum the number of shirts across all of your warehouses, and that gives you the T-shirts that you need, the T-shirts that you have. You get the difference between those two numbers, and that tells you how many new T-shirts you need to order. Where things get more complicated is once you start introducing T-shirt sizes, and that's where the fun data modeling comes in. If everyone at your company has a T-shirt size that they want and then at your warehouses, you store...the object that represents a warehouse stores a hash of sizes and how many of each size you have. Now, how do you do all this, like, summing across things? And it's not really just a single number that you want. Now you need to know how many small, mediums, and larges. And, sometimes, you've got a hash. Sometimes you've got just symbols on a user, and you've got a sum across hashes. Maybe do some differences across hashes. And it gets kind of tricky to work with. So that's sort of the problem as it's initially presented. And we've been having a really interesting conversation around different ways to try to solve it in a way that's really kind of clean and nice. STEPHANIE: Yeah, that's interesting because what you described sounds like the first iteration of solving the problem is, oh, the warehouse stores this information as a hash. So maybe I will create a new hash for the counts of T-shirt sizes that I need and then do the comparison on those two hashes. It sounds like maybe there was some unwieldiness or maybe even some duplicated code there. Is that what you think you all were trying to solve by modeling this differently? JOËL: I think we kind of quickly hit some limitations with hashes. One thing that is fun before we start trying to combine a bunch of hashes is that some of the data exists as a hash on the warehouses. But to get the T-shirts that we need, all we have are an array of users and a size on all of them. And we can use this fun method from Enumerable called Tally to give us a kind of Tally hash that is just a mapping of size, two counts of that size in the array. And so that's a really fun method. You don't get to bring it out that often in Ruby. And it's nice because that hash format happens to match the same format as the hashes stored on the warehouse objects. STEPHANIE: Right. So now you're comparing apples to apples. But it sounds like maybe this hash representation does hold some kind of significance. JOËL: Yeah. I guess, for me, I tend to see anytime you're doing fancier operations on a hash more than just reading in and out; it probably wants to be some kind of value object. And, in this case, we kind of want to do math on hashes. I think the equation is kind of still the same thing. We're trying to get the difference between the two, between the want versus have, but you can't just subtract one hash from another directly. There's some things that you can do with the hash merge method that allows you to pass a custom block and do some things there. But we're going to have to do this sort of repeatedly. And now we're kind of leaking some of that knowledge a little bit. So it feels like something where you might want to actually name this concept and make it an object of its own that can then have its own kinds of domain operations as methods on it. STEPHANIE: Yeah, I like that a lot. Because even just as I was thinking about it when you are storing data like that in just a hash, what do you call it? Like, what do you name it? I think I've seen things like that named, like, T-shirt data, or, like, warehouse data, or warehouse T-shirt counts, or T-shirt counts. You know, that is when it starts to diverge, and you end up maybe seeing the same, like, data represented, but it being named different things in different parts of the code. And I, in experience, have found that very painful. JOËL: Yeah, because I guess you could have, like, T-shirts on hand from your warehouse; that's one hash. But the hash generated from the users might get called something like user preferences. And if you're reading through that code and you see a hash, and you're like, okay, do these two hashes that I'm looking at, maybe in a test, just kind of coincidentally have the same keys? Or are these kind of fundamentally the same thing? Or is the idea of, like, T-shirts on hand like a stock different from, like, a preference? And do they represent different things that just happen to be similar in this particular scenario? STEPHANIE: Right. And especially if then there are methods where you're passing that data structure that really represents the same thing. But you're passing it as arguments, and then, suddenly, one variable name, user preferences, or user T-shirt preferences becomes, you know, T-shirt count. That has been really confusing for me before. JOËL: One thing that does get, I think, clunky very quickly is that you have all of these warehouse objects that have that hash of, like, stock on hand on them. And what you really want is a kind of aggregate object that tells you not what's the stock on hand for one warehouse but across all warehouses. So you've got to go through, I guess, that array of warehouses and somehow kind of aggregate all of those hashes together. And because they're already tallies, you can't just do Enumerable Tally on it anymore. You've got to find some way to combine them together, and that gets tricky really quickly. STEPHANIE: Right. I can see they're starting to be, like, nested loops, especially if you're just working with primitives. JOËL: I think some initial implementations that we saw ended up doing either, like, some kind of reduce block or each_with_object, or something like that, which are, I think, fine solutions here. But what lives inside of those blocks is what gets complicated. And I don't know about you, but I feel like if I'm reading through some code and then all of a sudden I see a reduce block, and it's, like, ten lines of logic with maybe some, like, nested things, like, maybe some nested loops or some conditions inside of it, that's kind of intimidating. Reduce is not a super easy method to wrap your head around, especially when the block has got a lot of logic. STEPHANIE: Yeah, that's a really good point. It definitely gives me pause. And I have to, like, you know, commit to reading the method in its entirety to fully understand [laughs] what's going on. JOËL: Sometimes, like, really pause and, like, annotate with comments and all this stuff. STEPHANIE: So, what did you end up thinking about in terms of solving that problem of aggregating the sums of all the different T-shirt sizes for each warehouse? JOËL: So I think, for me, oftentimes, it's easier to make the problem a little bit smaller, solve that smaller problem, and then try to kind of scale up back up again and particularly when you're dealing with something like reducing or aggregating a large collection. Like, forget about dealing with a collection. Just how could I combine two items of this type? So if I had two of these hashes. And forget about fitting it for an array. But if I have two of these hashes, how could I combine them together? And you could do this with hash merge. I wanted to do things a little bit more encapsulated. And because I also knew that we're building some more logic around these, I actually wrote a custom object. I called it a tally, maybe inspired by that Enumerable method, and implemented an operator plus on this tally object. So a tally object can plus another tally object. And the response from that is you get a third tally object that's gone through all of the keys and summed them together. So it's kind of an aggregate sum. STEPHANIE: This is a cool example of a method that's a verb also representing a noun to name the return value, right? So the Tally method on Enumerable returns a hash, which we have been talking about for a while as, like, a data structure that's, you know, perfectly fine, but maybe we can leverage turning it into like you said, a value object to give it more meaning or to make it easier to work with. And it seems like the naming part just kind of fell into your lap. JOËL: Yeah, tally is interesting in that it is both a noun and a verb in English. I'm not sure what the grammatical term for that kind of word is. STEPHANIE: So, once you extracted this new class out, what insights or observations did you have about this problem? JOËL: What becomes really cool about this is that once you have a way of combining two objects together, reduce is a way to just kind of scale that up to an arbitrary number. And so, just like you can sum an array of numbers by reducing plus over the array. Because I have plus on my tally object, I can reduce plus operator over an array of tally objects. And they all just kind of sum together in a single tally that's the combination of all of them. So this is really cool. What used to be an intimidating reduce block, the intimidating logic gets moved into a plus method, which I think is much more approachable. Because I can go in the context of an object and say, okay, I've got this tally object, and I'm trying to add it to another tally object. And we're just going one key at a time, adding them together. Simple enough. And then in the place where we're reducing, all we're saying is list of tallies reduce plus. And I know that pattern already because I do it with integers to sum them together. And so now I've just got this really simple one-line in the scary part. And the actual complex logic is much more approachable. STEPHANIE: That is very cool. I found it really interesting that this came about because we were trying to do math on these two hashes. So it seems like, you know, a tally because it represents a score or, like, a number. Like, we were able to implement those plus operators and get to a simple solution because we're working with numbers. JOËL: Yeah, I think it might be fair to describe it as maybe a compound number is the term that I use. I don't know if that's mathematically correct. Oftentimes, when you're dealing with things that represent a number or something that's represented numerically but that might have more than one number involved in it. But you still want to do math with this kind of compound, multi-number value anyway. And one example that you might have is, let's say, a point in 2D space. You have an X coordinate and a Y coordinate. And you can do math on points. In fact, there's a whole field of math to deal with that kind of thing. That's an important thing that you have to do. You might want to be able to add or subtract points. You might want to do certain types of multiplication on them. And so just because something has more than one number associated to it doesn't mean that it can't be used for math. In fact, oftentimes, that's where the fancier math does come into play. But when we treat them as primitives, and we just have, let's say, our XY pair was a hash, or, like, a two-element array, then we lose the ability to do math nicely. If we create, let's say, a point class that has an X and Y, and then we define plus, we define minus, we define scalar and vector multiplication, things like that, now we can do all those operations. And we can treat it like math, even though it's not just a simple integer anymore. STEPHANIE: Yeah, I like that a lot because we do end up working with data, you know, maybe even from our database. But then, inevitably, we want to, like, learn something about it. And so I was thinking about how frequently I use GROUP BY in MySQL queries and how, oftentimes, I care about counts, or, like, number of records. And perhaps this is why we see, like, the hash primitive used so frequently in codebases that then become pretty complicated once we're trying to, like I mentioned, like, learn something about it or, like, compare things or whatever logic that we need to do. And transforming them into objects that then know how to do math on themselves [laughs] is very cool. JOËL: Hashes are interesting because they're pretty much just basic data structures. And I think, very often, they're sort of pre-objects. They're things that want to eventually become objects. And, oftentimes, what I find is that hashes get passed around a system. And various other classes or subsystems all have bits of logic that act on the hash because the hash can't own that. And so you end up with the logic around the concept of whatever the hash represents kind of scattered and maybe duplicated across three or four places in the application. And then, all of a sudden, if you give that a name, if you create a class for it, you can pull all of that logic into one place. And, all of a sudden, it probably cleans up all of the surrounding places because now they don't have to care about the implementation of exactly what operating on the hash is. But, also, it means that these operations generally have, like, nice domain names. And, in the case of a complex number, you might even have that represented through math operations, like, plus or minus. And that allows your code to read really nicely. STEPHANIE: Right. Which gets me thinking about how I mentioned, like, tally as a noun, and, you know, you implemented your custom class. But do you think there's any value in the idea of a tally being specifically like a hash-like thing with a number as the value for each key, like, that existing as a more general class for people to use? JOËL: Oh, that's interesting. So, in my personal implementation, I hard-coded values for small, medium, and large because those were the T-shirt sizes from the example. But you're talking about some sort of generic tally object that maybe would be a gem or something like that that people could use that represents counts of arbitrary things or multiple counts of arbitrary things that might then implement some common math operators so that you could add or subtract them. STEPHANIE: Yeah, exactly. Because I was just thinking, you know, like I mentioned, I often represent that when I count number of records in my database. Or even I can recall a problem that I encountered previously where I had to figure out the number of orders for an e-commerce store based on the location. And I held that in a hash data structure, but really, it's a tally. [laughs] And so, yeah, I think that maybe we've kind of stumbled across a very useful representation of very common problems. JOËL: Yeah, I can see there being use for a generic version of this. Maybe that's your chance to go out and create some open source, or maybe this already exists. We should maybe research that first. STEPHANIE: Yeah, if any one of our listeners know, [laughs] send us an email. JOËL: So something that was really interesting to me about all of these changes, introducing the value object, cleaning up the reduce, all that stuff, is that, in the end, once the...there was this object that represented the sort of aggregate compound value, the tally, then the equation stayed the same. And I can just slot in those variables as before. Whereas previously, when we switch from just a single count to this, like, we need to take into account sizes that, like, broke the initial implementation of the code. So it's funny how you sort of go from a simple implementation and then a new requirement, which breaks it. But then just changing the hash to be an object all of a sudden made the original code, which didn't really need to change; it just worked again. STEPHANIE: Hmm. That's really interesting because it makes me think about how maybe the primitives were perfectly fine, you know, in the first set of requirements, and not until, like, an additional complexity or something new emerged that we needed to reach for an object that could support the change. JOËL: Yeah. And I think I'd argue that if you're doing just raw T-shirt count, an integer is probably the right value to use there. But if you're doing counts broken out by T-shirt size, then having an object that's a single thing that responds to plus and minus so that you can use it in the same equation where you're saying sum up all of these things from the warehouse, and then do a difference with the T-shirts that we need that becomes really nice. STEPHANIE: Do you think there was some value in going through the hash implementation first, though, and then arriving at using a more custom object? I'm curious, kind of, like, what that journey was like. JOËL: It's hard to say. I would say maybe yes. But I could also see someone who's done this a lot, who's built the sort of heuristics, the instincts around this could immediately be like, oh, wait, we're trying to sum hashes here. Clearly, these need to be objects. Clearly, what we need is something that implements a plus operator that we can reduce. STEPHANIE: Yeah, I like that a lot. Because part of, you know, knowing what to reach for is having seen it enough times and seeing patterns, right? JOËL: This reminds me of a particular pattern that comes from the world of functional programming. It has a kind of scary-sounding name. It's monoid, not monad, monoid. And the idea in the context of Ruby is it's some kind of object that implements a plus method. So two of these objects can combine each other. And typically, you also have some sort of empty version of this object or some sort of, like, zero value. And there's a few rules that go around, like, kind of how this object has to behave. Like, you can't just put any implementation you want in that plus method. Certain requirements that have to be met for it to be considered, like, a valid plus method in this pattern. But if you do meet those requirements, then arrays of this type of object are just inherently reducible because you can just reduce plus over them. And so I think anytime you're trying to aggregate some sort of unwieldy data structure, that's probably a useful pattern to have because, you know, wait, as long as I have a way to combine two items together and potentially some way to generate an empty state, I can aggregate this whole list. STEPHANIE: I'm curious, does that also apply to non-numerical values? JOËL: Yes, any kind of aggregation combination, whatever. So maybe what you're doing is you're combining strings together. STEPHANIE: Got it. JOËL: String concatenation is a form of combination. And so you could be reducing some kind of concatenation over an array of strings, and you end up with one aggregate string that's the combination of all of them. Sometimes, though, you're not just taking values and putting them next to each other so that what you have is kind of all of them at the same time. You might instead do some kind of comparison. An example here might be Boolean values. You might say the way that I'm sort of, quote, unquote, "aggregating" two values, two Boolean values is with the operator AND. And so you have two Boolean values, and you get a new sort of combo value out of them, that is, are both of these values true? STEPHANIE: Whoa, that's blowing my mind right now. Because I had never thought of the, like, AND operator on Booleans, essentially aggregating them into a single true or false value. [laughs] JOËL: It's kind of weird, right? But I guess we do the same thing with numbers. One plus one doesn't give us 11 unless you're writing JavaScript. STEPHANIE: [laughs] JOËL: You know, we get a new number too, that is some sort of, like, combination of the two. So, similarly, it kind of makes sense that two Booleans might combine to create a new sort of third Boolean value. Where it gets really interesting, though, is that once you have this sort of combination, if you try to reduce AND over an array of Booleans, what you effectively have created is Ruby's Enumerable all method that checks to say, are all values in this array true? STEPHANIE: Interesting. But really, the way that's implemented is just, like, a definition of what aggregate means for Booleans, right? JOËL: Right. But it's taking that idea of aggregating two values and scaling it up to an array of many values. So we know Boolean AND. Another way to think about it is, are both of these values true? Is the question it's trying to answer. And then we're scaling that out to say, is both of these values true for everything? So are all of these values true? Because we're going from two to many. STEPHANIE: Cool. So maybe the takeaway for some of our listeners could be, like, next time they find themselves having to deal with a collection or an Enumerable and, you know, using a reduce or, like, trying to break it down to compare two of those elements first, and figuring out how they want that interaction to work. Does that sound right? JOËL: Yeah, absolutely. Once you have a way to combine two elements together, if you want to scale it up to n elements, you just plug it into reduce, and it does the rest of the work for you. My big takeaways from this exercise were one: the value of creating custom objects. Wrapping primitives like hashes in an object and adding a few domain methods on them made such a difference in my final implementation. Secondly, I think it's what you're saying, this whole thing about breaking down complex reduce problems by figuring out how to combine two items and then just using reduce to scale it to an array. And then, finally, I think this is a point that we've mentioned on this podcast before, the value of specific vocabulary - being able to name things and patterns. And so knowing some of the details of this monoid pattern and having a name for it means that now I start seeing it in places. And so the moment I see, oh, wait, we're aggregating values; we're combining two values together and then doing this in a reduce, immediately, my mind goes, wait, that feels like monoid. And then, I can explore that with my custom object to try to make the code better. STEPHANIE: Yeah. And even if you don't remember the monoid part specifically, the idea of Tally, like, that is something that I think is really cool and really applicable to a lot of codebases. JOËL: So, for those who are interested in more practically what this code looks like, I've put this all in a Gist, and I'll link to it in the show notes. This was a really fun exercise for me because I used sort of two development techniques to help sort of build this out. One, I went with a kind of literate programming approach, where I had just a Ruby file and would have put in some big comment blocks talking about what the setup was, what I was trying to do, and then describing how I'd like to use the code, and then try to write code that made that happen. And then, for the actual objects that I was using under the hood, I used TDD to test drive and build them out. So you've got all of that in the Gist. We've got the tests and that sort of literate programming script that almost reads like a mini blog post, except it's executable Ruby. So, if you're curious to see about that, the link is in the show notes. STEPHANIE: That's a very cool format. I'm excited to take a look. On that note, shall we wrap up? JOËL: Let's wrap up. STEPHANIE: Show notes for this episode can be found at bikeshed.fm. JOËL: This show has been produced and edited by Mandy Moore. STEPHANIE: 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. It really helps other folks find the show. JOËL: If you have any feedback for this or any of our other episodes, you can reach us @_bikeshed, or you can reach me @joelquen on Twitter. STEPHANIE: Or reach both of us at hosts@bikeshed.fm via email. JOËL: Thanks so much for listening to The Bike Shed, and we'll see you next week. ALL: Byeeeeeee!!!!!!! ANNOUNCER: This podcast is brought to you by thoughtbot, your expert strategy, design, development, and product management partner. We bring digital products from idea to success and teach you how because we care. Learn more at thoughtbot.com.Sponsored By:Airbrake: Deploy fearlessly and fix bugs faster with Airbrake Error & Performance Monitoring. Airbrake notifiers are available for all major programming languages and frameworks, and install in minutes, with an open-source SDK-based install and near-zero technical debt. Spend less time tracking down bugs and more time developing. Visit Frictionless error monitoring and performance insight for your app stack.Support The Bike Shed
undefined
May 23, 2023 • 25min

385: The Boring Parts of Tech

Joël is joined by thoughtbot Software Developer and Dirt Jumper Daniel Nolan. Dirt jumping is BMX-style riding 🏍️ with really enormous dirt jumps. But for a person who loves excitement in his spare time, for Daniel at work, it's not the new and shiny that interests him. When he dives into something, the "boring" parts of tech are what he finds most fulfilling. He wants to know the "why," and in this conversation, he explains how it sustains his career. This episode is brought to you by Airbrake. Visit Frictionless error monitoring and performance insight for your app stack. Debugging series Dependabot Coverband thoughtbot maintenance service Sentry New Relic Custom Rubocop rules Daniel Nolan Twitter Daniel Nolan GitHub Transcript: JOËL: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Joël Quenneville. And today, I'm joined with a guest, Daniel Nolan. DANIEL: Hey. JOËL: And, together, we're here to share a bit of what we've learned along the way. So, Daniel, what's new in your world? DANIEL: So, recently, I just picked up a dirt jumper bicycle, and I've been learning to get better at dirt jumping. I ride mountain bikes quite a bit. But jumping is something that I haven't been super comfortable with. JOËL: What is dirt jumping? DANIEL: So, Dirt Jumping is kind of more like BMX-style riding with really huge dirt jumps. If you do it right, you don't pedal. So you should be jumping and pumping and making your way around the track or the course without the need to pedal. So it's actually pretty interesting. And it's supposed to level up your mountain bike skills if you get good at this. JOËL: So the idea is you start up high somewhere, and you just kind of let the gravity bring you down? DANIEL: Yep, that's the idea. So you start up on a platform; usually, you drop in. And then, from there, you start the series of jumps or rollers, pick up speed, and then kind of go into some bigger jumps, and berms, and stuff and make your way around the course. It's pretty fun. JOËL: So you're coming down from a high, and then you hit a dirt ramp somewhere. You go up in the air. You fly off, and you're doing, like, a flip or something like that? DANIEL: Yeah, not quite there yet. Some of the people I ride with can do flips, and no handers, and stuff; definitely not there, but just getting comfortable on big dirt jumps. I think the scariest thing is not being able to see the landing. So it's, like, if it's just a little jump, like, you know where you're going. But if it's like one of those big jumps with a huge lift, you just have no idea what's on the other side. And no matter how, you know, even if you've hit it ten times, it's still scary because you can't see it. JOËL: How do you land safely when you can't see your landing place? DANIEL: There's a technique where you kind of push the bike down. So, like, once you're in the air and you've kind of leveled the bike out, and you spot the landing, you force the bike down to kind of accentuate that movement and make the bike go down. JOËL: Just so I get a better mental picture here, how high up are we talking about when you're flying off this ramp? DANIEL: So some of these dirt jumps are probably...on the ones that I'm riding, they lift to probably, like, you know, eight, nine-feet high, and you're probably getting, like, three to four feet in the air over that to clear it. JOËL: Wow. That's a little bit of elevation right there. DANIEL: Yeah. JOËL: I would probably be scared. DANIEL: The safe jumps have what they call a table on top, so there's no risk. Like, if you land on top of the jump, you're not going to die. But, yeah, typically, they're flat on top. So you have to have enough air and enough momentum to clear that flat part and land on the downside. JOËL: I like to do a lot of bouldering. In this case, I do it in a gym, so you're climbing up a wall that's maybe 15 feet high. Even at that height, I feel a little scared; not very good with heights. How do you feel when you're up 15-20 feet on a bicycle, and you don't know where you're going to land? DANIEL: It's scary. I mean, just, there's no way to get around it. But that's the whole reason I started getting into the dirt jumping is just try to get it to where it's more second nature, and you're not so terrified. JOËL: Kind of pushing some of your personal limits, then. DANIEL: Yeah, for sure. JOËL: So it sounds like you're introducing a lot of excitement and novelty in your personal life. And that contrasts to a recent conversation that we had where you'd mentioned that, at work, it's not the kind of shiny, new tech that excites you, or even kind of the scary parts. But you find that the boring parts of tech are what are most fulfilling to you. DANIEL: Yeah, I actually really do like diving into the more boring parts. And I think to give just a little history about myself and maybe why that might be, I'm a second career programmer. My original career, or what I thought was going to be my lifelong career, was I was an auto mechanic. So I was a certified VW tech in my early 20s. And I've always kind of had this passion for, like, why things are. I want to know why something is. So, when I dive into something, it's like, I want to know the why. I don't want to just know what the fix is. I want to know why that thing fixes it or whatever. So I find that getting into the more boring parts of programming, and especially in the Rails stack, allowed me to do this. So, for example, like, a gem that Dependabot can't upgrade, and it just sits there. The PR just sits there, and nobody wants to touch it. So then I come along, and I'm like, well, why won't it upgrade? Why can't we upgrade this thing? And I start diving into sort of breaking changes. Is there stuff like that? So fixing things, for me, has been something...since I was just a little kid, my mom said I always used to take things apart and put them back together. I always want to know the why. Doing some of the more boring stuff, you get to do a lot more of that. JOËL: So it sounds like really you're motivated by curiosity pretty strongly. DANIEL: Yeah, for sure. I don't want to just know what a quick fix is or something like that. I want to actually get in. I want to read this, you know, like, an example, like, a gem that won't upgrade, like, I want to go dive into that source code. I want to see what the source code is doing. I want to figure out the why, you know. I don't want to just Google for, like, hey, I can't upgrade this gem. What do you think I should do? So I've always been super curious. That's how I've been able to sustain in software development and not really get burn out. It's what makes me tick. JOËL: How do you feel about bug fixing or, like, chasing down bugs in general? Is that something that really scratches that itch? DANIEL: It definitely does. I feel it's, you know, very similar to somebody comes to you, and they've got a broken car. And they're like, "Hey, this thing's making this noise when I'm going down the highway at 50 miles an hour, you know, what is it?" You know, it's very much the same thing. Like, you get an end user, and they're like, "Hey, when I click this button in the browser, and, you know, this thing doesn't load," or, you know, I'm getting a 500 error." It's very relatable. I love diving into those type of things. Like, I love fixing bugs. JOËL: It's interesting that you related that back to your work with cars because it sounds like you were doing sort of the mechanical version of debugging. DANIEL: Definitely the mechanical version of debugging. But it's still...it's a lot of the same stuff. It's a lot of process of elimination and stuff like that, right? Like, you got a noise coming from the front left. It could be anything, you know, it could be the wheel. It could be brakes. It could be, I mean, there's a number of things it could be. So you kind of got to start going down the path of like, you know, well, it's not this, and it's not this, and it's not this. And it's very similar when you have a bug, you know, and you start down the path of, like, oh, well, I can click the button. The post is getting sent to the server. But, for some reason, you know, the parameters aren't going past the controller or something like that. So, you know, you maybe go look for some primitive params or something, I don't know. But it's very similar as, you know, just going through the process of, like, checking things off and trying to get to the root cause. JOËL: Yeah. So, when you joined software, you already had this skill kind of really built up pretty well. DANIEL: Yeah, I definitely did. Being a mechanic, a lot of times, I would get, like, the problems that nobody else wanted to deal with. Because people were like, oh, he likes troubleshooting electrical issues and stuff like that, so give it to him, you know. Whereas the other mechanics are just, you know, like, were more, like, oh, I want to rebuild the engine, or I want to put a new trans...like, it visibly needs an engine. Like, oh, there's a rod through the side of the block. It's leaking oil everywhere. Okay, yeah, like...versus, oh, it's got some electrical bug where, you know, one injector doesn't fire every 50th time, or something like that. And something that you just really have to, like, trace down and figure out why it's not happening. So I feel like I had a pretty good, no pun intended, toolbox coming into... JOËL: Nice. DANIEL: Software development as far as just problem-solving skills, I guess. JOËL: It's interesting. A few years ago, I interviewed a bunch of people about debugging and the parts they liked, the parts they didn't like, hopes, and fears. And most people I talked to actually enjoyed debugging, except that, oftentimes, when bugs come up, it's because they're blocking something else. And there are time pressures. And so all that extra context is what makes debugging stressful for most people that I talk to. But the actual act of debugging, that kind of process of elimination or trying to hunt down the source of a bug, many people I interviewed actually found that highly fulfilling. So it sounds like it taps into a lot of the same interests that you have. DANIEL: That's super interesting, yeah. And it is fulfilling, too, right? Like, you're going this hunting, and you kind of, like, put on your detective hat and go try to, like, figure out what the breaking thing is. And then you get the payoff also of like, okay, well, you know, if you actually fix it, you resolved it, and you get that little bit of payoff. And I think for any job for me to be fulfilling, I have to have that kind of that payoff where you start with something broken, and you fix it. You know, you start with an empty editor, and then you build out a web application or something like that. So it's just, like, having that payoff is definitely huge. You know, I just find that part of software development super fulfilling. JOËL: So you've mentioned debugging. You've talked a little bit about gnarly gem upgrades. What other types of work fit under that boring part of software heading for you? DANIEL: Putting in some tools for best practices maybe, you know, like setting up linters and stuff like that, automated code review kind of things. It's stuff that you tend to see, like, teams and stuff want, but they just never have the time. They're always building, you know, new features and stuff. So I think a lot of that stuff, like, gets pushed by the wayside. Refactoring code that's good enough. It's good enough, and it's working, but it could be a little cleaner, a little easier to read; kind of enjoy that, too. I don't know, do you have any things that you would consider boring programming work? JOËL: I think some types of features sometimes can feel boring, maybe a little bit beyond boring. It's scary or unpleasant to work on. Sometimes there are just parts of the code that are really gnarly to work with. I'm like, oh no, I've got the ticket that requires touching some of that gnarly code in a particular part of the app. There's one app, in particular, I'm thinking of that this was the wizard code, or the multi-step form processing code that had gotten really gnarly, and so nobody wanted to touch it. And if you had a ticket that required touching that code, it's like, oh no, you drew the short straw. DANIEL: Yeah. I've definitely had experiences like that. I had a feature I worked on at a previous job where it was...the feature was referred to as the black box because nobody knew how it worked. Nobody knew what it actually did. But they knew that it didn't produce the results they wanted. And they knew it needed to be refactored, so that was definitely one. I don't even know if I would say that was boring, but definitely, a scary part that nobody wants to touch. There's just all kinds of stuff that's boring. Like, if you're just constantly adding new features and doing new things, and adding to the app, there's code that's probably not used anymore. So using something like Coverband and going in and finding unused code and cleaning out that kind of stuff. Optimizing queries, again, you know, you build something, and it works. It's there. It's doing its thing. And nobody's complained that the endpoint's slow. But when you run it, you notice that there's like, you know, 70 N+1 queries. So you go, you know, you go touch that up a little bit. I feel like a lot of people and a lot of programmers just don't want to do that work, or it may not even be that they don't want to do that work. It's just a lot of times; there's maybe no time for it. So that's no fault of anyone in particular. But I think we need to, you know, figure out a way to make some more of these things fun. Maybe more teams need to build in, like, gem upgrade day or something. And, you know, like, go upgrade the ones that are hard to upgrade. Upgrade the ones that Dependabot can't, that have breaking changes. Or, I don't know, there's got to be some way where we can make some more of this, like, the tasks that keep the car running more enjoyable, right? 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 cut your debugging time in half. So why do developers love Airbrake? 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 of 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 helps 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 to include 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. Head on over to airbrake.io/try/bikeshed to create your FREE developer account today! JOËL: Would it be fair to describe the types of work that you've been talking about here, you've been describing as the boring parts of development, would it be fair to put those under the heading of maintenance? DANIEL: I think it would be fair to put it under maintenance, maybe even relating that back to cars. It's the same thing, right? Like, you can put a new paint job on the car, and you can get some new, shiny wheels. And you can, you know, put a turbocharger on it or something but, eventually, you know, you got to change your oil. You got to change your tires. You need to change your air filter, new windshield wipers, you know, so you can see when it's raining. These things are all just things that need to be done. Otherwise, no matter how shiny your car is, it's just not going to go anymore, right? So I feel like maybe most of these tasks are maintenance. It's not the shiny, new thing. It's just keeping the thing running. JOËL: And, I guess, traditionally, at thoughtbot, we've done engagements where we're either building new software or new features on existing software. Or we might be coming in and fixing some larger problems, maybe doing something like helping with a Rails upgrade or helping to backfill a test suite, some larger kind of chronic problems. But we recently introduced a maintenance service that is, instead of having people full-time there to do a particular task, it's more of so many hours a month to just do a lot of those boring things where we're doing like you said, potentially gem upgrades, or fixing bugs, or things like that. Is that a team that you would be interested in joining? DANIEL: So I actually got to work with Jeanine and [inaudible 16:05] on support and maintenance for about a month, month and a half maybe. I worked on an upgrade. And that's exactly what I did. It was upgrading a Rails 5.2 app to Rails 7. And yeah, it was not only super fun, but the other fun side of that, for me, is that a lot of times when I'm doing these things, and you find breaking changes, the gem is either, like, ten years old, and it can't be upgraded because there's nobody maintaining it anymore. So you maybe have to create a fork, or you maybe submit a patch or something. So this is a way that I've been able to get, you know, my feet wet in open source without really contributing to a specific open-source project. So I have tons of little commits on different gems here and there fixing stuff up or something I found along the way that couldn't be upgraded or something like that. So yeah, the support and maintenance team is definitely something that I'm interested in, and I had a good time working with them for that rotation. JOËL: And I think it's really interesting you're talking about the pattern of open-source contributions that you were having. And I think that's something that's really valuable to the community, just those little patches in various places because it's broken or is no longer compatible with other things. What you're doing not only helps unblock you and your client but also is probably unblocking a lot of other people in the community, so might have a larger impact towards other people than if you were putting all of your time into contributing to one more well-known gem. DANIEL: Yeah, for sure. You know, I know for sure, like, some of them I have a commit on Honeybadger, something that broke recently, a Sidekiq upgrade that broke, and there was just a small change to the way the error handling worked. And it was, like, causing just this flood of errors. And it was just a simple change. But I'm sure not only did it fix it for us and the app I was working on, but, yeah, I'm sure quite a few people benefited from that one. JOËL: So, for those listeners out there who are hearing you talk about some of this maintenance or boring work and maybe are feeling inspired to go and do that on their team, how would you recommend getting into that? DANIEL: Well, I mentioned Dependabot. If your team's already using something like Dependabot for, like, minor gem upgrades, maybe there's a PR that's stuck that Dependabot can't upgrade because there's some breaking changes in one of the gems it's trying to upgrade. That's a great place to start. You could run, I believe; it's bundle-outdated. And that will tell you what gems are in your gem file that are outdated and need to be updated. So any of them that are going to be major version bumps, you know, going from, like, two to three, typically, you'll usually have breaking changes somewhere you can kind of jump in and go fix those breaking changes. Maybe there's even breaking changes in another gem that may be related or something that you're trying to upgrade. And, you know, you can't upgrade past version two because the new gem you're trying to upgrade depends on that gem-specific version or something like that. So I feel like that's a great way you could jump in. Maybe some other ways would be if, you know, maybe you want to optimize queries or something like that. Maybe you have Sentry or some other type of software that reports on these things, New Relic, you know, so something like that you could go dive into and pick up an endpoint that's responding slow or something that has some N+1s being reported and go dive in, see if you can maybe touch those up. JOËL: Those are all great suggestions. I know I once worked with a developer who would dedicate...I think it was the first hour of his day. So he'd come into work in the morning, and before jumping in on feature work, the first hour of his day, he would just do small improvements on things and not just, like, refactoring for the sake of refactoring. But they're things like you're describing, like, oh, do we have a gem that needs to handle an update? Did one of our monitoring services highlight maybe some slow queries that I could tweak a little bit this morning? Or are there areas where we're feeling pain that we can make things better? And just by doing a little bit every day, he became known as the person on the team who is, like, having an impact, and making everybody's lives better, and making the codebase better, making the product better. And I really appreciated this person. DANIEL: Yeah, sounds like an angel. Like I was saying, you know, I kind of hinted out a little bit before...I think these things...and it could be because they're boring, or it could just be because you have stakeholders that are, like, hey, we need to get this new feature out. And I just feel like a lot of this stuff definitely gets pushed to the back burner often, so figuring out a way to incorporate some stuff into your day like that, or automating some of it, you know, using things like Dependabot and stuff like that. I think they're all just great ways to keep the app or the project in good shape. Another thing that I've done adding custom RuboCop rules to enforce things the way that you want them. So, like, it comes with a standard set of rules, but you find some pattern that's being, you know, repeated, and we don't want that pattern repeated. You know, spend the time to write a RuboCop rule so that that pattern doesn't get repeated. And you don't have to constantly police this in PRs, you know, you let the automated tool do it for you. But I've never really heard anybody get super excited about writing a Rubocop rule. JOËL: And they're valuable. DANIEL: Yeah, they're definitely valuable. JOËL: I think the most excited I've seen people get about RuboCop rules is typically as part of an incident report. So something went terribly wrong, and maybe production went down. And then you're doing a post-mortem, and then you realize, oh, in this way, some bad code made it through. And you decide how can we prevent this from happening again? And the consensus is, oh, maybe a Rubocop rule would have prevented this. So I think that's generally where people actually start caring about a Rubocop rule is after there's been some larger incident. DANIEL: Sure. We had something where I think, like, we first started using system specs on an app I was working on, and some people were using Path Helper, and some people were using URL Helper. And, for some reason, the ones that were using Path Helper would fail randomly. I don't really recall right off the top of my head why, but we wrote a RuboCop rule to just enforce using the URL for or the URL Helper instead of the Path Helper just to enforce that rule. So we didn't have to constantly police it, and it just made everybody's lives easier. Figuring out a way to set some time aside for this stuff or automating this stuff is definitely beneficial because you may not always have somebody on the team that's interested or that wants to champion this stuff. JOËL: Hey, you mentioned the word champion, and I like that word because it's the kind of thing that often doesn't get prioritized. And so you need somebody to advocate for that work getting done. And, generally, I've found this work is often cheaper to do sooner rather than later. If you postpone it too long, and now it's been ten years, and you've not done a Rails upgrade, and your app is still running on Rails 3. It's going to be very expensive to do that work. DANIEL: Yeah, the biggest cost of software is maintenance is definitely true. JOËL: Maintenance is valuable work, and we should celebrate it more. DANIEL: For sure. JOËL: On that note, shall we wrap up? DANIEL: I think so. JOËL: Thanks for joining us, Daniel. Where can people find you online? DANIEL: You can find me on Twitter or on GitHub. Both are danielnolan. JOËL: All right, thank you very much for joining us. STEPHANIE: Show notes for this episode can be found at bikeshed.fm. JOËL: This show has been produced and edited by Mandy Moore. STEPHANIE: 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. It really helps other folks find the show. JOËL: If you have any feedback for this or any of our other episodes, you can reach us @_bikeshed, or you can reach me @joelquen on Twitter. STEPHANIE: Or reach both of us at hosts@bikeshed.fm via email. JOËL: Thanks so much for listening to The Bike Shed, and we'll see you next week. ALL: Byeeeeeeee!!!!!!! ANNOUNCER: This podcast is brought to you by thoughtbot, your expert strategy, design, development, and product management partner. We bring digital products from idea to success and teach you how because we care. Learn more at thoughtbot.com.Sponsored By:Airbrake: Deploy fearlessly and fix bugs faster with Airbrake Error & Performance Monitoring. Airbrake notifiers are available for all major programming languages and frameworks, and install in minutes, with an open-source SDK-based install and near-zero technical debt. Spend less time tracking down bugs and more time developing. Visit Frictionless error monitoring and performance insight for your app stack.Support The Bike Shed
undefined
May 16, 2023 • 38min

384: Not All Numbers Are Numbers

Joël gives a recap after attending RailsConf 2023 in Atlanta, Georgia (and yes, there was karaoke! 🎤 🎶). Stephanie plugs the The Tightly Coupled Book Club Podcast from friends and fellow thoughtboters Aji and Mina Slater where they're reading The Rails Guides from cover to cover and treating it like a book club and having a discussions about the documentation as they read it together. Stemming from a Twitter thread by Joël, their main topic focuses on not all numbers being numbers. So: if someone is submitting a phone number through a form: How would you store that in the database? Would you store it as a string? Because sometimes it comes with some extra formatting. Would you normalize it and try to store it as an integer because it's a number? Thoughts, Dear Listener? This episode is brought to you by Airbrake. Visit Frictionless error monitoring and performance insight for your app stack. How to Decline by Anne Helen Petersen The Tightly Coupled Book Club podcast Rails Guides Michael Hartl Rails Tutorial Why the GOV.UK Design System team changed the input type for numbers Google’s libphonenumber GOV.UK design system’s open GitHub issue on phone numbers HTML numeric input mode Transcript: STEPHANIE: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Stephanie Minn. JOËL: And I'm Joël Quenneville. And together, we're here to share a bit of what we've learned along the way. STEPHANIE: So, Joël, what's new in your world? JOËL: I've just returned from attending RailsConf 2023 in Atlanta, Georgia, and it was so much fun. I got a chance to attend some really good talks. I got a chance to connect with other people in the community. I always love the hallway track or any of the events that happen in the evenings after the conferences. It's a lot of fun. STEPHANIE: Nice. I found it funny that you emphasized just returned because you literally walked through the door of your home and then got online to record this podcast with me. [laughs] JOËL: Productivity. STEPHANIE: What were some of your highlights from the conference? JOËL: I really appreciated a talk by Elle Meredith about how to say no. And she gave...I think it was nine sort of different ways that you might want to have a conversation about saying no to a request. They're almost like design patterns but for interpersonal conversations. And so she covered situations where you might want to say no to maybe someone who's higher up in a hierarchy than you, so a manager. But also, what it's like sometimes when it's the other way around if you're a manager and you have to say no to someone who reports to you, and how to handle some of those conversations. So I really appreciated the nuance that she had to share. And I think the strategies were just really practical. STEPHANIE: That's awesome. Yeah, I know we, as developers, love some good patterns and frameworks. That actually reminds me of something else that I'd read recently, a newsletter called Culture Study by this journalist Anne Helen Petersen. She recently sent out a dispatch about how to say no or decline requests through email. And I was just thinking that it's such a challenging thing to do. But having a script or seeing examples of how other people do it is really helpful to just make it easier the next time that you want to say no, but then you're not sure how. JOËL: It's not easy to say no. I think most people want to please, and it's much easier to say yes. And maybe even you want to believe that you can say yes, that you can do everything with limited resources and not have to prioritize. And then, of course, reality hits you, and you're in a worse situation than if you'd said no upfront or had at least an honest conversation about the limitations that we have and the prioritization that needs to happen. STEPHANIE: Yeah, absolutely. So, over in the thoughtbot Slack, I saw a lot of really awesome praise and even photos from the conference, including stuff about a thoughtbot-sponsored event that we hosted over at RailsConf. What was that like? JOËL: That was so much fun. So we hosted an event out in Centennial Park after day one and just had some lawn games, some snacks, some drinks. And people just came to hang out in the park and had a good time. And I got to chat with a lot of people. I think it somehow just felt really relaxed yet really social. Sometimes when you're in the hallway in the convention center, you'll see groups of people talking, but also kind of people awkwardly walking around and struggling to connect. And there are just so many people around. And if you don't know anyone, it can be really hard to kind of break in. And I felt that this setting...I'm not sure exactly why; maybe it was a smaller amount of people. Maybe it's because it's a more relaxed atmosphere. You're outside. Everyone was kind of mingling and talking and seemed to be having a good time. STEPHANIE: That's really cool. I'm so bummed to have missed it. Yeah, I hear you about the hallway track. It's like you're still kind of, you know, either in a convention center or a hotel, so there is just that vibe of formality. And taking it out of that venue and making it super casual, you know, I think that also almost allows people to not talk about tech, or the conference, or anything work-related and just have fun. JOËL: Definitely. Although there's definitely fun that happens in all sorts of ways after the conference as well. One of the evenings, I went out with a few other thoughtboters and some other attendees at the conference; we went to a karaoke bar. STEPHANIE: That sounds like a lot of fun. I think that's become almost a tradition for the thoughtbot crew whenever we do things out in the world, karaoke. And I'm trying to get escape rooms to be a conference tradition among my group of friends. So you and I, we participated in escape room the last conference that we were at together, and that was a lot of fun. So this is a thing that I hope to keep doing [laughs] next time I see you in person. JOËL: We didn't just participate. We broke the record. STEPHANIE: It's true. Yeah, I didn't want to brag on the podcast. But we did break the record. And we got to, like, write our names on a little poster to put in the office. And I hope it's still there, at that escape room company in Providence, Rhode Island. JOËL: I'd be curious to hear from some of our listeners what some of their traditions are when they go to a conference. Do you have something that you like to do with your conference friends when you meet up? Let us know at hosts@bikeshed.fm. And we'll give you a shout-out on one of the upcoming episodes. So, Stephanie, what's new in your world? STEPHANIE: Speaking of friends and community, I have a podcast to plug today. So our friends and fellow thoughtboters and married couple Aji and Mina Slater, they just launched a podcast called The Tightly Coupled Book Club Podcast. And what they're doing is reading The Rails Guides from cover to cover and kind of treating it like a book club and having a discussion about the documentation as they read it together. And I listened to the first two episodes this morning, and I really enjoyed it. I thought it was such a cool idea and a really great format as a person who enjoys talking about books and things I've read with you. I mean, sometimes we've joked that this is kind of like our two-person book club. But it's really cool to listen in on other people who are, you know, are really knowledgeable, or have a lot of experience about a thing, and then also share their experience reading something as they come across it. I thought that was really interesting too. There's a real-time aspect of it that I liked. JOËL: I love the idea of taking the book club concept and then reading the Rails Guides. What a really original idea. STEPHANIE: It's funny because the Rails Guides do kind of read like a book. I went on to the documentation today just to kind of give myself a refresher as I was listening. And you can download the guides on your Kindle. So, in some ways, they've kind of leaned into that format. And since a lot of it is also just, like, prose, it is more like paragraphs rather than quick bits or API reference. JOËL: Right, right. It's something that's meant to be read in larger chunks rather than just found through a search and then referencing one entry in a list of methods or something like that. STEPHANIE: Yeah. I think my other favorite part about doing an idea like this is I think we all kind of have our own different experiences with the Rails official docs and guides. And I really liked that they're just like, yeah, like, you know, the way that an individual developer approaches the documentation can be totally different. And they kind of talk about how they do it or how they don't do it. Kind of all with the intention of wanting to better understand Rails and also wanting to better support people who want to get into Rails and are kind of entering the universe from the documentation for the first time. JOËL: Yeah, and I think the Rails Guides, in particular, are often that first point of contact for a lot of newer Rails developers. I know that, for myself, when I was first getting into Rails, I was on those guides all the time. Between that and cherry-picking examples from the Michael Hartl Rails tutorial, that's kind of how I learned Rails. STEPHANIE: Yeah, I like that a lot. For other folks who want to hear more about just Mina and Aji's experience with the Rails Guides, you should all check out that podcast. 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 cut your debugging time in half. So why do developers love Airbrake? 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 of 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 helps 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 to include 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. Head on over to airbrake.io/try/bikeshed to create your FREE developer account today! JOËL: So this is a conversation we had the other day, and I'm curious what your take is on this. If someone is submitting a phone number through a form, how would you store that in the database? Would you store it as a string? Because sometimes it comes with some extra formatting. Would you normalize it and try to store it as an integer because it's a number? What's your take? STEPHANIE: Okay, to answer that question, I think I'm going to gripe a little bit first because the thing with phone numbers is that there are so many ways to format them. So, when you were saying, like, oh, you know, how would you input a number? I'm like; I don't know. Even if I were to write down a phone number on any given day, would I add the parentheses? Would I include the dashes? Do I add the country code? It honestly really depends. And it's just totally different just based on what the form is asking of me or what channel I'm doing it in. So I think phone numbers is an interesting example because there are so many ways of representing it. But I think that actually also answers the way that I would do it is saving it as a string. Because while a phone number is made up of numbers, it's not exactly a numerical value. JOËL: You're hitting on something pretty deep here about the fundamental nature of what a phone number is. What do you mean by saying it's not numeric? STEPHANIE: I guess it doesn't mean anything in mathematical terms, I suppose, is what I was trying to get at. Like, it happens to be in the U.S., at least, you know. JOËL: Always gotta qualify that, right? STEPHANIE: Right. It happens to be a 10-digit identifier, I suppose. I almost said number there, but I think I'm trying to avoid it for the sake of my argument. But it's not necessarily something we would try to do arithmetic on. It's not something that... JOËL: I'm kind of laughing at the idea of trying to do math on a phone number, adding two phone numbers together, doing some sort of, I don't know, add 20% to your phone number. Like, what does that even mean? STEPHANIE: Yeah, absolutely. It's something that mostly remains static, right? It's like when it changes, that means something different. It means that the way that you would reach someone via a phone call or just that kind of communication is more of an event that has changed rather than the value transforming doesn't mean anything on its own. JOËL: So you mentioned that this is not the kind of number that you can do arithmetic on. That kind of reminded me of an article from the UK's I want to say government design guidelines and how to design web forms that are going to be used by any service that's part of the UK Government. And they have this category of numbers that they call non-incrementable. And their suggestion is that even though these things are represented as numbers, they should not use the HTML number input for them because you're never going to hit that little plus or minus arrow to go up and down and change the number. And that, instead, it should just be a regular text input. STEPHANIE: Yeah, that's interesting because the idea of incrementing, for me, is definitely more attributed to the idea of a numerical value where it's a number and then what that number represents. So it could be weight. It could be money. It could be some other measurement. Another one could be quantity, right? If you have a shopping cart or something, and you're incrementing that value because you want to buy more of whatever item. That, to me, is where I see that type of input more frequently. And so it would make sense that, you know, a phone number where the person is usually inputting a fixed thing that, you know, because that is not something that they can change, or they are wanting to change in that form, would be represented with a different HTML input. JOËL: I don't know about you, but I feel like when I'm having a conversation with someone, occasionally, they'll just sort of mention something that my ears will kind of prick up because it feels like a keyword. And you mentioned earlier the keyword identifier, that a phone number to you feels more like an identifier than a number. And I want to dig into that because that feels really key to this conversation. STEPHANIE: Yeah. I think there are a lot of things that happen to have numbers in them because that's the characters we use to denote some kind of unique or mostly unique value [laughs] of something. So, like, most people have a phone number, some people don't, some people may have multiple. But, usually, that phone number is tied to a person or a business or some kind of...it's like a record of how to reach someone. JOËL: Yeah. I guess to a certain extent, a phone number is like a...it's not an ID for a person, but it's an ID for a phone, or for a SIM card, or a line, an account, something like that that's publicly shared out. But even though it's publicly shared out, it's effectively...I guess you might call it a third-party ID by the phone companies. If they're supposed to be globally unique, you might say the global telecoms consortium that have come up with this set of rules. STEPHANIE: [laughs] Yes, we're clearly not telecommunications experts over here [laughs] or just have a, you know, regular human-level understanding of how telephones work. [laughs] JOËL: But I think that's a really interesting idea because I think my instinct with phone numbers is I want to normalize them when I get them through a form. And yet I have very strong instincts that anytime I get an ID from a third-party service, let's say I'm interacting with an API, and I get a new user through there. The ID from the third-party service is there. When I save it into my database, I will create a new primary key for that row because I want to own my own primary keys. But I will have a row for that third-party ID, and I will make sure to not modify it. I will store it in its raw form. So why do I feel the need to normalize phone numbers? If they are third-party IDs, then maybe I should just be storing them in raw format as entered by the user. At the very least, maybe I should store them as strings rather than trying to turn them into numbers. STEPHANIE: Yeah, that's interesting. I mean, I do think phone numbers are a bit of an exception here in that you could think of it as a third-party ID. But it's also so ubiquitous in how our society functions. And the way people use it, it's like it's not a single service that this is owned by where you want to make sure that you're capturing it the way that that third party would. It's something that is so commonplace that it can end up having different forms because of the way that users interact with it. JOËL: I think one thing that's really interesting with third-party IDs is that even though they might come back as numbers like you said earlier, we don't do math on them. The main thing you ever do with a third-party ID is use it to make requests back to that third-party service. So, if I have a user I've pulled from some other service and I ever want to talk to that service again, I would need to use that third-party ID that I have stored in order to make sure that everything stays in sync. That's kind of what we do with a phone number, right? We store it. And then the reason we might want to store a phone number is because we might want to programmatically make a phone call or send a text message that's interacting back with that telecom's world. We might want a human to do that. But the effect is still kind of the same. We're not doing any transformations or work on it internally within the software. It's always when we want to make some kind of phone call, either manually by a person or automatically with a computer. And the only way we can do that and reach the right person is by using the ID that was given to us. STEPHANIE: Yeah, that's a really good point. I mean, I have seen many applications that do hand-roll their own validation or normalization on phone numbers. But I do think that there is a library for this published by Google I think. It's called Libphonenumber. And so it's an open-source library for parsing, validating, and formatting phone numbers for, I think, most countries. It's very comprehensive. JOËL: I think the difference maybe with a phone number and a form where you might want to do a little bit of polishing on it is that it is manually entered by a user. It definitely needs validation because a user manually typing in an ID into a form absolutely could have an error in it. Normalizing it for storage purposes, maybe, but at the very least, yeah, it needs to be validated because someone hand-typing in an ID is not something you want to rely on too heavily. STEPHANIE: Yeah. I mean, I'm curious if we can extrapolate this conversation further beyond phone numbers. It sounds like we're talking about this idea that values with numbers in them should not always be treated as integers. JOËL: Yes. And I have a great example of that that has actually burned me before. STEPHANIE: Ooh, what is it? JOËL: Zip codes. So, again, prefixing this, in the U.S., zip codes are typically a five-digit number. There's a variant that has more digits in it. And you'd think that you can store that...it's a five-digit number; you can store that in an integer column. And that does not work because you can start with a zero. And so if you store that as an integer, then what you really have is a four-digit integer. And then, when you try to put that back into an address, things get messed up. So it's really important to store U.S. zip codes as strings so that you can keep that leading zero if you need it. And, of course, the moment you introduce international zip codes, or I think postal codes is what most countries call it, now, all of a sudden, you've got letters in addition to numbers. I wanted to share one of the most delightful postcode bits of knowledge that I have. STEPHANIE: Please. JOËL: Which is that in Canada, postal codes alternate letters and numbers. And Canada decided that Santa Claus needed his own Canadian zip code. And his zip code is H0H 0H0. STEPHANIE: [laughs] JOËL: H0H 0H0 STEPHANIE: Of course it is. I like that a lot. Makes sense that he would reside in Canada, up in the frigid, chilly north. So you've mentioned that you were burned by this. Does that mean you were working with an application that did store postal codes as integers? And what was the impact or consequence of that? JOËL: So I was building a feature that required interacting with a zip code. And, as one does, I tested it out in development. And, as one also often does, I put in my own address. Now, I happen to live in Boston, and my zip code starts with a zero. So I happen to live in the one place that has that weird edge case. And immediately when I saw in dev how things happen, I was like, wait a minute, that's broken. That's not going to work. STEPHANIE: Yeah. Wow. I wonder if that has just been impacting users for a long time before that discovery. JOËL: It probably depends on the application, right? I guess you could...if you introduce that as a problem, you could try to add hacks on hacks to make it better. So you store it as an integer, but then when you get the integer out of the database, and you need to use it as an address, you then reformat it back. So you left-pad the number with zeros. STEPHANIE: Yeah, I can see some really interesting ways of trying to work around that. JOËL: But yeah, I think the best practice is definitely store your zip/postal codes as a string, not as an integer. STEPHANIE: I wonder what it is about these types of values that make us think that they are numbers or want to store them as integers. I think that the Rails default is to store primary keys in integers. And if you wanted to use UUIDs, for example, instead, you do have to have done that initial setup. I'm curious about the origin of using ints. And I know that that's like a whole story [laughs] in terms of the bite-size of that value. But yeah, it's just one of those origin stories that I'm wondering if that has kind of impacted our understanding of what primary keys look like. JOËL: At its core, I think this goes back to what we were talking about earlier. Primary keys the default in Rails is an auto-incrementing integer. And we store it as an integer so that the database can do a plus-one on it every time we insert another record. We don't want to do that with zip codes or with phone numbers. Now, quite possibly, within the U.S. Postal Service or whatever the standard is for establishing phone numbers, they might, because these are numbers, they might be doing some kind of incrementing somewhere. But there are patterns, definitely, that have been established. But they're not always necessarily incrementing. And they're not transparent to us in a way that we would care about them normally in an app. And we might care that, oh, we know that if it has a leading zero in the zip code, you're in this broad region or something like that. But, again, this is not really doing math so much as it's knowing the pattern in the ID. I know some ID-like numbers have checksum logic built into them; credit card numbers are something like this. So I don't know if you've ever tried to type in your credit card number in a form. Like, the outline goes red. It'll tell you there's an error and you've not submitted it. Nobody's making a background request to your bank. And the bank is like, wait a minute; this is a bad card number. The validation logic on the front end just immediately was able to tell the number is wrong. And that's because there are some checks and logic built in such that your number can be almost like self-verifying. We don't know that it's Stephanie's number, but we do know that it is a valid Mastercard. STEPHANIE: Yeah, that's really interesting because, you know, I know that there are just various combinations of digits in a credit card number that are straight up and valid. And I think that's another example of something that is more like an identifier as well. JOËL: You're right. I think so. It identifies a particular card, a piece of plastic that you have, and maybe line of credit or something like that. I'm not sure what the underlying modeling is exactly. But as a user of that credit card, [laughs] it represents a piece of plastic in my pocket. And that is a number that other services can use to talk to the card issuer. So it's an ID that you can use to make requests to Visa, or MasterCard, or whoever. So I think you're right; that does fall under the umbrella of a third-party ID. I think I probably would tend to try to store that as a string based on this conversation rather than as an integer, even though it is all numbers. I say that, though, and, of course, now I'm going to get people tweeting at me saying, "Did you know that American Express sometimes put a letter in their credit card numbers?" STEPHANIE: Oh, man. That would really throw a wrench in my understanding of how credit cards work. JOËL: [laughs] But, again, if you store it as a string, it doesn't matter. STEPHANIE: I'm really interested in the idea that a lot of these things we're talking about, you know, are often collected in forms and saved in our applications. Because we need to save information about our users in the context of whatever domain our application is working in. And I can kind of see it going a couple of ways where it's either, like, don't give that too much thought. Or we try to introduce a library that does a lot to make sure that it's kind of covered all of the different cases. Or, like, it's really covered kind of how we've been talking about credit card numbers and phone numbers, like, a really wide breadth of logic that exists because of the way that they are very prevalent in the human world, at least. And I'm curious, at what point do you think, you know, like, writing that first migration, how much energy would you put into making sure that those values are normalized correctly or that you're doing the right thing with those pieces of data? JOËL: I think, based on this conversation, I would probably lean into doing minimal normalization. And I think the thing that's special about this type of number that we're talking about is that we don't need to do any logic on it internally. We typically only use it when calling out to some third-party system. And assuming that third-party system will accept that identifier in its raw form, non-normalized, then why do I need to care or put that effort in? STEPHANIE: Yeah, that's a really interesting point. I think it definitely depends on what you're doing with it, right? Like, if you're a payment platform, obviously, you want to make sure that you get those credit card [laughs] values right and the way that you operate on them is as robust as possible. But for most applications, you might just be displaying the phone number, and that's about it. And minimal normalization and just formatting based on the way that your application handles it seems reasonable enough. JOËL: I think the main thing you need to be able to do with that number is to make a call to that third-party service system and have it work. So a phone number you need to be able to call it and connect to the right person on the other end. With a credit card number, you need to be able to charge it, and we need to be able to charge it successfully. That's really the main thing that you're concerned with it. If you can do that without normalizing, then you're fine. Now, you might need validating, which I think is a separate thing from normalizing. And that's really interesting because you can get all this fancy validation logic to check that there's the correct number of digits in the phone number or in the credit card and all that. And that's great. But you can also sometimes just try it. So I think we see this really commonly with things like email validation where we don't really trust that we can validate emails. Instead, we send you an email with a confirmation link. And the validation is that you were able to receive that and click that confirmation link. STEPHANIE: Oh yeah, that's an interesting way. I've never thought about that. But a way that we've solved that problem without having to accommodate every single way a person might try to input their email. JOËL: Similarly, you could do for a phone number, send a text with a confirmation number. And if you can receive that, then your phone number is good. And if you can't, then try to input your phone number again, assuming I'm dealing with a provider that can send to most numbers. I don't have to deal with all of the region-specific variations on how phone numbers work. Payments are really interesting because, typically, that is the main mode that you're trying to use them. It's not even like a validation thing. It's that we're going to make a call to your bank right now. And if this card gets declined, you're going to have to put your number in again. STEPHANIE: Yeah, I've certainly seen some differing trends over time around how those inputs are validated, though, right? Like, there are some websites that give you that real-time feedback. And, as a user, I think for me, it depends on whether or not I like it, right? It's, like, I've certainly encountered forms where I am like, oh, I'm appreciative that they're doing some input masking so that I don't accidentally type in a value that they are not willing to accept, and other times where the validation ends up getting in the way. When do you think that real-time feedback is important? JOËL: So I think it's all about shortening the cycle of making a mistake and fixing it. So, you know, it's annoying if you typo your credit card number, and then you submit it. And it takes a few seconds to go back to the provider. And then, oh, it comes back up and says, "Sorry, that was wrong." And then you've got to figure out what went wrong. If they had some logic that did that checksum math or something like that and said, "Wait a minute, this number is wrong," then you could fix it immediately without having to do a full-page submit and potentially lose or have to reload data that you filled in and if it's a larger form. So to get functional, you don't need that. But it's a nice layer on top of things to be able to have a shorter feedback loop where you immediately get feedback that tells you, wait a minute, that card number is not quite right. Maybe consider don't hitting that submit button. STEPHANIE: Yeah, I think it also definitely depends on the goals of your system. I'm remembering now that article you mentioned from the UK government's design system. I was perusing that. And I found that they have some very explicit guidelines around form inputs because part of their goal is to make this portal as accessible as possible for all of their citizens. And one thing that I remember was really interesting about how they considered their users was how if you enter a phone number, you can use the phone keypad-style of input. And the justification was that a lot of people are using this on mobile, so we want to make sure that we make this as accessible as possible for them since not everyone has access to a computer. And I thought it was really cool that they justified their reasoning. And I think they even have all of this stuff open to feedback. So I had found a GitHub issue, I think, called, like, telephone numbers. And they're like, hey, like, we want to hear your thoughts about how telephone numbers should be received as inputs and whether this is working for you. And I thought that was a really committed way to make sure that the way that the system is implemented really reflects the user's needs. JOËL: Yeah. And what's really cool about HTML is that we now have the ability to kind of decouple some of these things. And so, you might be typing in a text input, but you want to limit certain characters. You only want to be able to type in number characters. Does that mean that you have to use a number input? Well, not necessarily. With HTML5, you can put a regular expression pattern to limit what can be typed in this input. You can also have an input mode, which, for mobile, will control which keyboard shows up. Or it won't control; it tells the mobile operating system or the browser what you would like them to show, and it's up to them to implement that. And so, like you were saying, for a phone number, even if you're typing it into a, let's say, text input because you want to be able to...maybe the user wants to put in whitespace, or dashes, or whatever. But you still want that number pad to show up by putting an input mode numeric on it. You can get that keyboard, even though you're not in a numeric input. STEPHANIE: Yeah, I think that's a blessing and a curse that we do have these separate layers of abstraction, right? Because, on one hand, it gives us more flexibility. And then I've also seen it just run amok [laughs] and cause a lot of confusion about what being the source of truth, but I think that's a conversation for another day. JOËL: Yep. Form design accessibility, keyboard inputs. So yeah, I think coming back to the core question of today, when is a number maybe not a number? STEPHANIE: That's a big question that I think only the developer with the task at hand can answer. JOËL: On that note, shall we wrap up? STEPHANIE: Let's wrap up. Show notes for this episode can be found at bikeshed.fm. JOËL: This show has been produced and edited by Mandy Moore. STEPHANIE: 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. It really helps other folks find the show. JOËL: If you have any feedback for this or any of our other episodes, you can reach us @_bikeshed, or you can reach me @joelquen on Twitter. STEPHANIE: Or reach both of us at hosts@bikeshed.fm via email. JOËL: Thanks so much for listening to The Bike Shed, and we'll see you next week. ALL: Byeeeeeeee!!!!!! ANNOUNCER: This podcast is brought to you by thoughtbot, your expert strategy, design, development, and product management partner. We bring digital products from idea to success and teach you how because we care. Learn more at thoughtbot.com.Sponsored By:Airbrake: Deploy fearlessly and fix bugs faster with Airbrake Error & Performance Monitoring. Airbrake notifiers are available for all major programming languages and frameworks, and install in minutes, with an open-source SDK-based install and near-zero technical debt. Spend less time tracking down bugs and more time developing. Visit Frictionless error monitoring and performance insight for your app stack.Support The Bike Shed
undefined
May 9, 2023 • 43min

383: Code as Storytelling with Nicole Zhu

Engineering manager at Vox Media and author Nicole Zhu joins Stephanie on today's episode to discuss her writing practice. nicoledonut is a biweekly newsletter about the writing process and sustaining a creative life that features creative resources, occasional interviews with creative folks, short essays on writing and creativity, farm-to-table memes and TikToks, and features on what Nicole is currently writing, reading, and watching. This episode is brought to you by Airbrake. Visit Frictionless error monitoring and performance insight for your app stack. Kieran Culkin on learning about billionaires filming Succession The Home Depot skeleton Nicole Zhu's newsletter The Making of a Manager by Julie Zhuo Saving Time by Jenny Odell Transcript: STEPHANIE: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Stephanie Minn. And today, I'm joined by my friend and special guest, Nicole Zhu. NICOLE: Hi, I'm so excited to be here. My name is Nicole, and I am an Engineering manager at Vox Media and a writer. STEPHANIE: Amazing, I'm so thrilled to have you here. So, Nicole, we usually kick off the show by sharing a little bit about what's new in our world. And I can take us away and let you know about my very exciting weekend activities of taking down our Halloween skeleton. And yes, I know that it's April, but I feel like I've been seeing the 12-foot Home Depot skeletons everywhere. And it's becoming a thing for people to leave up just their Halloween decorations and, just as the other holidays keep rolling on, changing it up so that their skeleton is wearing like bunny ears for Easter or a leprechaun hat for St. Patrick's Day. And we've been definitely on the weird skeleton in front of the house long past the Halloween train for a few years now. Our skeleton's name is Gary. And it's funny because he's like a science classroom skeleton, so not just plastic. He's actually quite heavy. NICOLE: He's got some meat to the bones. [laughs] STEPHANIE: Yeah, yeah, and physiologically correct. But we like to keep him out till spring because we got to put him away at some point so that people are excited again when he comes back out in October. And the kids on our block really love him. And yeah, that's what I did this weekend. [laughs] NICOLE: I love it. I would love to meet Gary one day. Sounds very exciting. [laughs] I do get why you'd want to dress up the skeleton, especially if it's 12 feet tall because it's a lot of work to put up and take down for just one month, but that's fascinating. For me, something new in my world is the return of "Succession," the TV show. STEPHANIE: Oh yes. NICOLE: I did not watch yesterday's episode, so I'm already spoiled, but that's okay. But I've been getting a lot of Succession TikToks, and I've been learning a lot about the making of the show and the lives of the uber-rich. And in this one interview with Kieran Culkin, the interviewer asked him, "What's something that you learned in shooting the show about the uber-rich about billionaires that's maybe weird or unexpected?" And Kieran Culkin says that the uber-rich don't have coats because they're just shuttled everywhere in private jets and cars. They're not running to the grocery store, taking the subway, so they don't really wear coats, which I thought was fascinating. It makes a lot of sense. And then there was this really interesting clip too that was talking about the cinematography of the show. And what is really interesting about it is that it resists the wealth porn kind of lens because it's filmed in this mockumentary style that doesn't linger or have sweeping gestures of how majestic these beautiful cities and buildings and apartments they're in. Everything just seems very matter of fact because that is just the backdrop to their lives, which I think is so interesting how, yeah, I don't know, where I was like, I didn't ever really notice it. And now I can't stop seeing it when I watch the show where it's about miserable, rich people. And so I like that the visual language of the show reflects it too. STEPHANIE: Wow, yeah, that makes a lot of sense. The coat thing really gets me because I'm just imagining if I could be perfectly climate controlled all the time. [laughs] NICOLE: Right? Oh my gosh, especially you're based in Chicago [laughs], that is when you can retire the winter coat. That is always an important phase. STEPHANIE: Yeah, seriously. I also am thinking now about just like the montages of showing a place, just movies or shows filmed in New York City or whatever, and it's such...so you know it's like the big city, right? NICOLE: Mmm-hmm, mm-hmm. STEPHANIE: And all of that setup. And it's really interesting to hear that stylistically, that is also different for a show like this where they're trying to convey a certain message. NICOLE: Yeah, yeah, definitely. STEPHANIE: So I'm really excited to have you on The Bike Shed because I have known you for a few years. And you write this really amazing newsletter called "nicoledonut" about your writing practice. And it's a newsletter that I open every other week when you send out a dispatch. And last year at RubyConf, they had a conference track called Bringing Your Backgrounds With You. And there were talks that people gave about how the hobbies that they did outside of work or an identity that they held made them a better developer, like, affected how they showed up at work in a positive way. And as someone who has always been really impressed by the thoughtfulness that you apply to your writing practice, I was really curious about how that shows up for you as an engineering manager. NICOLE: Definitely a great question. And to provide a bit of context for listeners, I feel like I have to explain the newsletter title because it's odd. But there's a writer who I really love named Jenny Zhang, and her handle across the Internet is jennybagel. And so I was like, oh, that would be so funny. I should be nicoledonut. I do love donuts. My Neopets username was donutfiend, so it was -- STEPHANIE: Hell yeah. NICOLE: But anyway, so that was kind of...I was like, I need to come up with some fun title for this newsletter, and that is what I settled on. But yes, I've written personal essays and creative nonfiction. And my primary focus more recently these past few years has been fiction. And this newsletter was really kind of born out of a desire to learn in the open, provide resources, act as kind of a journal, and just process ideas about writing and what it means to kind of sustain a creative life. So it has definitely made me more reflective and proactively, like you said, kind of think about what that means in terms of how that transfers into my day job in engineering. I recently moved into management a little over a year ago, and before that, I was a senior full-stack engineer working on a lot of our audience experiences and websites and, previously, more of our editorial tools. So I think when it comes to obviously writing code and being more of an individual contributor, I think you had previously kind of touched on what does it mean to treat code as a craft? And I do think that there are a lot of similarities between those two things because I think there's creativity in engineering, of course. You have to think about going from something abstract to something concrete. In engineering, you're given generally, or you're defining kind of requirements and features and functionality. You may be make an engineering plan or something like that, an EDD, given those constraints. And then I think writing is very similar. You outline, and then you have to actually write the thing and then revise. I do think writing is not necessarily as collaborative as coding is, perhaps, but still similar overall in terms of an author having a vision, dealing with different constraints, if that's word count, if it's form or structure, if it's point of view, things like that. And that all determines what the outcome will be. You always learn something in the execution, the idea that planning can only take you so far. And at a certain point, you gather as much background knowledge and information and talk to as many people. Depending on the kinds of writing I do, I have or haven't done as much research. But at a certain point, the research becomes procrastination, and I know I need to actually just start writing. And similarly, with engineering, I think that's the piece is that once you actually start implementation, you start to uncover roadblocks. You uncover questions or complications or things like that. And so I think that's always the exciting part is you can't really always know the road ahead of you until you start the journey. And I also think that in order to benefit from mentorship and feedback...we can talk more about this. I know that that's something that is kind of a larger topic. And then another thing I think where the two are really similar is there's this endless learning that goes with each of them. I guess that's true of, I think, most crafts. Good practitioners of the craft, I think, take on that mindset. But I do think that obviously, in engineering, you have industry changes, new technologies emerging really frequently. But I do think that good writers think about that, too, in terms of what new novels are coming out. But also, how do you build a solid foundation? And I do think it's that contrast that applies in any craft is, you know, you want to have a good solid foundation and learn the basics but then keep up to date with new things as well. So I think there was this...there's this meme I actually did include in the newsletter that was...it's the meme of these two guys looking at different windows of a bus, and one looks really sad, and one looks really happy. But the two of them have the same caption, which is there's always more to learn. And so I think that is the two sides of the coin [laughs]. I think that is relevant in engineering and writing that I've kind of brought to both of those practices is trying to be optimistic [laughs] about the idea that there's always more to learn that that's kind of the thought of it. And then certainly, when it comes to management, I do think that writing has proven really valuable in that very obvious sense of kind of practical communication where I just write a lot more. I write a lot more things that are not code, I should say, as a manager. And communication is really at the forefront of my job, and so is demonstrating curiosity and building empathy, fostering relationships with people. And I do think that particularly writing fiction you have to be curious about people I think to be a writer. And I think that is true of managers as well. So I do think that has been a really interesting way that I didn't anticipate writing showing up in my day job but has been a really helpful thing and has made my work stronger and think about the people, the process, and kind of what we do and why a little differently. STEPHANIE: Yeah, absolutely. Wow, you got into a lot of different things I'm excited to keep discussing further. But one thing that I was thinking about as you were talking was, have you heard of the adage, I guess, that code is read many more times than it's written? NICOLE: Hmm, I think I have, yeah. STEPHANIE: I was thinking about that as you were talking because, in some ways, in most ways, actually, if you ascribe to that adage, I suppose, we write code for others to read. And I think there's an aspect of code telling a story that is really interesting. I've heard a lot of people advocate for writing, thoughtbot included, writing your tests like they're telling a story. And so when a future developer is trying to understand what's going on, they can read the tests, understand the setup, read what is being tested, and then read what the expected outcome is and have a complete picture of what's going on. The same goes for commit messages. You are writing little bits of documentation for people in the future. And I've also been thinking about how legacy code is just this artifact as well of all of the changes that an organization might have gone through. And so when you see something that you see a bit of code that is really weird or gets your spidey senses tingling, it's almost like, oh, I wonder what happened here that led to this piece left behind? NICOLE: Yeah, definitely. Now that you're talking about it, I also think of pull requests as a great way to employ storytelling. I remember there definitely have been times where myself or other engineers are working on a really thorny problem, and we always joke that the PR description is longer than the change. And it's like, but you got to read the PR description in order to understand what change you're making and why. And here's the backstory, the context to kind of center people in that. As a manager, I think about storytelling a lot in terms of defining purpose and providing clarity for teams. I was reading Julie Zhuo's "The Making of a Manager," and it was a really kind of foundational text for me when I first was exploring management. And she kind of boils it down to people, purpose, and process. And so I do think the purpose part of that is really tied to clear communication. And can you tell a story of what we're doing from really high-level vision and then more tactically strategy? And then making sure that people have bought into that, they understand, can kind of repeat that without you being there to remind them necessarily. Because you really want that message to carry through in the work and that they have that understanding. Vision is something I only recently have really started to realize how difficult it is to articulate. It's like you don't really understand the purpose of vision until you maybe don't have one, or you've been kind of just trying to keep your head afloat, and you don't have a Northstar to work towards. But I do think that is what plays into motivation, and team health, and, obviously, quality of the product. So yeah, that's kind of another dimension I've been thinking of. And also our foes actually. Sorry, another one. Our foes, I think, like outages and incidents. I think that's always a fun opportunity to talk about stories. There was a period of time where every time we had an incident, you had to present that incident and a recap of it in an engineering all-hands every month. And they ended up being really fun. We turned something that is ostensibly very stressful into something that was very entertaining that people could really get on board with and would learn something from. And we had the funniest one; I think was...we called it the Thanks Obama Outage because there was an outage that was caused by a photo of Barack Obama that had been uploaded in our content management system, as required no less, that had some malformed metadata or something that just broke everything. And so, again, it was a really difficult issue [laughs] and a long outage. And that was the result that I remember that presentation being really fun. And again, kind of like mythmaking in a way where that is something that we remember. We pay attention to that part of the codebase a lot now. It's taught us a lot. So yeah, I do think storytelling isn't always necessarily the super serious thing, but it can also just be team building, and morale, and culture as well. STEPHANIE: Yeah, absolutely. I think what you said about vision really resonates with me because if you don't have the vision, then you're also not making the best decisions you can be making even something as low-level as how you write the code. Because if you don't know are we going to be changing this feature a month from now, that might dictate how you go forth with implementation as opposed to if you know that it's not in the company's vision to really be doing anything else with this particular feature. And you then might feel a little more comfortable with a more rudimentary approach, right? NICOLE: Yeah, totally. Whether or not it's, we've over-optimized or not or kind of optimized for speed. Like, it's all about trade-offs. And I do think, again, like you said, having a vision that always you can check your decision-making against and inform the path ahead I think is very, very helpful. STEPHANIE: When you write, do you also keep that in mind? Like, do you write with that North Star? And is that really important to your process? NICOLE: I think it depends. I think that writing can be a little more at a slant, I suppose, is how I think of it because I don't always...just similar to work, I don't always come in with a fully-fledged fleshed-out vision of what I want a piece to be. The most recent piece I've been working on actually I did have kind of a pretty, I think, solid foundation. I've been working on this story about loneliness. And I knew that I wanted to base the structure on the UCLA...a UCLA clinic has this questionnaire that's 20 items long that is about measuring loneliness on a scale. And so I was like, okay, I knew that I wanted to examine dimensions of loneliness, and that would be the structure. It would be 20 questions, and it would be in that format. So that gave me a lot more to start with of, you know, here's where I want the piece to go. Here's what I want it to do. And then there have definitely been other cases where it's more that the conceit seems interesting; a character comes to mind. I overhear a conversation on the subway, and I think it's funny, and that becomes the first thing that is put on the page. So I definitely have different entry points, I think, into a draft. But I will definitely say that revision is the phase where that always gets clarified. And it has to, I think, because as much as I'm sometimes just writing for vibes, it's not always like that. And I do think that the purpose of revision is to clarify your goals so you can then really look at the piece and be like, is it doing what I want it to? Where is it lacking? Where's it really strong? Where's the pacing falling flat? And things like that. So I do think that sooner or later, that clarity comes, and that vision comes into focus. But it isn't always the first thing that happens, I think, because I do think the creative process is a little bit more mysterious, shall we say, than working on an engineering team. [laughs] STEPHANIE: Yeah. Well, you started off responding to my question with it depends, which is a very engineering answer, but I suppose -- NICOLE: That is true. That is true. You got me. [laughs] STEPHANIE: It applies to both. 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 cut your debugging time in half. So why do developers love Airbrake? 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 of 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 helps 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 to include 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. Head on over to airbrake.io/try/bikeshed to create your FREE developer account today! STEPHANIE: You mentioned revision. And so, I do want to talk about feedback because I think that is an important part of the revision process. And I have really loved what you've had to say about writing feedback and your experience with writing feedback, especially in writing workshops. And I have always been really curious about what we might be able to learn about receiving feedback in code review. NICOLE: When it comes to receiving feedback, I think I wrote a two-part series of my newsletter, one that was about providing feedback, one that was about receiving it. I think on the side of receiving feedback, first and foremost, I think it's important to know when you're ready to share your work and know that you can share multiple times. In writing, that can be I show a very early draft to my partner who is the person who kind of reads everything and anything at any stage. It's something less polished, and I'm really just testing ideas. But then obviously, if there's something that is more polished, that is something I would want to bring to a writing group, bring into a workshop, things like that. Similarly, as engineers, I think...thank God for GitHub drafts actually adopting literally the way in which I think of that, right? STEPHANIE: Yeah. NICOLE: You can share a branch or a GitHub PR in progress and just check the approach. I've done that so many times, and really that helped so much with my own learning and learning from mentors in my own organization was checking in early and trying to gut-check my work earlier as opposed to later. Because then you feel, I think, again, a bit more naturally receptive because you're already in that questioning phase. You're not like, oh, this is polished, and I've written all the tests, and the PR description is done. And now you want me to go back and change the whole approach from the ground up. That can feel tough. I get that. And so I think, hand in hand, what goes with that is whose feedback are you interested in? Is that a peer? Is it a mentor? I think obviously leaning on your own team, on senior engineers, I do think that is one of the primary, I think, expectations of a senior engineer is kind of multiplying the effectiveness of their peers and helping them learn and grow. So I do think that that's a really valuable skill to develop on that end, but also, again, just approaching people. And obviously, different teams have different processes for that, if it's daily stand-ups, if it's GitHub reminders, automated messages that get pulled up in your channel, things like that. But there are ways to build that into your day-to-day, which I think is really beneficial too. And then there's also the phase of priming yourself to receive the feedback. And I think there's actually a lot of emotional work that I don't think we talk about when it comes to that. Because receiving feedback can always be vulnerable, and it can bring up unexpected emotions. And I think learning how to regulate the emotional response to that is really valuable for us as people but obviously within the workplace too. So I've found it really helpful to reflect if I'm getting feedback that...well, first of all, it depends on the format. So I think some people prefer verbal feedback, some people will prefer written. I think getting it in the form of written feedback can be helpful because it provides you some distance. You don't have to respond in the moment. And so I've definitely had cases where I then kind of want to reflect on why certain suggestions might elicit certain reactions if I have a fight or flight response, if I'm feeling ashamed or frustrated, or indignant, all the range of emotions. Emotions are, to put the engineering hat on, are information. And so I think listening to that, not letting it rule you per se but letting it inform and help you figure out what is this telling me and how do I then respond, or what should I do next? Is really valuable. Because sometimes it's not, again, actually the feedback; maybe it's more about that, oh, it's a really radical idea. Maybe it's a really...it's an approach I didn't even consider, and it would take a lot of work. But again, maybe if I sit and think about it, it is the scalable approach. It's the cleaner approach, things like that. Or are they just touching on something that I maybe haven't thought as deeply about? And so I think there is that piece too. Is it the delivery? Is it something about your context or history with the person giving the feedback too? I think all of those, the relationship building, the trust on a team, all plays into feedback. And obviously, we can create better conditions for exchanging and receiving feedback. But I do think there's still that companion piece that is also just about, again, fostering team trust and culture overall because that is the thing that makes these conversations all the easier and less, I think, potentially fraught or high pressure. STEPHANIE: 100%. Listeners can't see, but I was nodding very aggressively [laughs] this entire time. NICOLE: Loved it. STEPHANIE: And I love that you bring up interpersonal relationships, team culture, and feelings. Listeners of the show will know that I love talking about feelings. But I wanted to ask you this exact question because I think code review can be so fraught. And I've seen it be a source of conflict and tension. And I personally have always wanted more tools for giving better feedback. Because when I do give feedback, it's for the person to feel supported to help push their work to be better and for us to do good work as a team. And I am really sensitive to the way that I give feedback because I know what it's like to receive feedback that doesn't land well. And when you were talking about investigating what kinds of feelings come up when you do receive a certain kind of comment on a code review or something, that was really interesting to me. Because I definitely know what it's like to have worked really, really hard on a pull request and for it to feel very precious to me and then to receive a lot of change requests or whatever. It can be really disappointing or really frustrating or whatever. And yeah, I wish that we, as an industry, could talk about this stuff more frequently. NICOLE: Yeah, for sure. And I do think that you know, I think the longer you work with someone, ideally, again, the stronger relationship you form. You find your own ways of communicating that work for you. I think actually what I've learned in management is, yes, I have a communication style, but I also am flexible with how I work with each of my reports, who, again, have very different working styles, communication styles, learning styles. I don't believe that the manager sets the standards. I think there is a balance there of meeting people where they are and giving them what they need while obviously maintaining your own values and practices. But yeah, certainly, again, I think that's why for perhaps more junior engineers, they might need more examples. They might not respond well to as terse a comment. But certainly, with engineers, senior engineers that I've worked with, when I was starting out, the more we developed a relationship, they could just get a little bit more terse. For example, they could be like, "Fix this, fix that," and I would not take it personally because we had already gone through the phase where they were providing maybe some more detailed feedback, links to other examples or gists, or things like that, and our communication styles evolved. And so I do think that's another thing to think about as well is that it doesn't have to be static. I think that's the value of a team, and having good team process, too, is ideally having arenas in which you can talk about how these kinds of things are going. Are we happy with the cadence? Are we happy with how people are treating each other and things like that? Are we getting timely feedback and things like that? That's a good opportunity for a retrospective and to talk about that in a kind of blameless context and approach that more holistically. So I do think that, yeah, feedback can be very fraught. And I think what can be difficult in the world of engineering is that it can be very easy to then just be like, well, this is just the best way for the work. And feelings are, like you said, not really kind of considered. And, again, software development and engineering is a team sport. And so I do think fostering the environment in which everyone can be doing great work is really the imperative. STEPHANIE: Yeah, I really like how you talked about the dynamic nature of relationships on a team and that the communication style can change there when you have built that trust and you understand where another person is coming from. I was also thinking about the question of whose feedback are you interested in? And I certainly can remember times where I requested a review from someone in particular because maybe they had more context about this particular thing I was working on, and I wanted to make sure that I didn't miss anything, or someone else who maybe I had something to learn from them. And that is one way of making feedback work for me and being set up to receive it well. Because as much as...like you said, it's really easy to fall back into the argument of like, oh, what's the best way for the work, or what is the cleanest code or whatever? I am still a person who wrote it. I produced a piece of work and have feelings about it. And so I have really enjoyed just learning more about how I react to feedback and trying to mitigate the stress that I feel in what is kind of inherently like a conflict-generating process. NICOLE: Yeah, yeah, definitely. Another thing that kind of popped into my head to one of the earlier questions we were talking about is in terms of similarities between writing and engineering, style and structure are both really, really important. And even though in engineering, like you said, sometimes it can be, I mean, there is a point with engineering where you're like, this line of code works, or it doesn't. There is a degree of correctness [laughs] that you do have to meet, obviously. But again, after that, it can be personal preference. It's why we have linters that have certain styles or things like that to try to eliminate some of these more divisive, shall we say, potentially discussions around, [laughs] God forbid, tabs or spaces, naming conventions, all this stuff. But certainly, yeah, when it comes to structuring code, the style, or whatever else, like you said, there's a human lens to that. And so I think making sure that we are accounting for that in the process is really important, and not just whether or not the work gets done but also how the work gets done is really important. Because it predicts what do future projects...what does future collaboration look like? And again, you're not just ever optimizing for one thing in one point of time. You're always...you're building teams. You're building products. So there's a long kind of lifecycle to think about. STEPHANIE: For sure. So after you get feedback and after you go through the revision process, I'm curious what you think about the idea of what is good enough in the context of your writing. And then also, if that has influenced when you think a feature is done or the code is as good as you want it to be. NICOLE: Yeah, definitely. I think when it comes to my writing, how I think about what is good enough I think there is the kind of sentiment common in the writer community that you can edit yourself to death. You can revise forever if you wanted to. It's also kind of why I don't like to go back and read things I've already published because I'm always going to find something, you know, an errant comma or like, oh, man, I wish I had rephrased this here. But I do think that, for me, I think about a couple of questions that help me get a sense of is this in a good place to, you know, for me generally, it's just to start submitting to places for publication. So one of those is, has someone else read it? That is always a really big question, whether it's a trusted reader, if I brought it to a workshop, or just my writing group, making sure I have a set of outside eyes, fresh eyes on the piece to give their reaction. And again, truly as a reader, sometimes just as a reader, not even as a fellow writer, because I do think different audiences will take different things and provide different types of feedback. Another one is what kinds of changes am I making at this point in time? Am I still making really big structural edits? Or am I just kind of pushing words and commas around, and it feels like rearranging deck chairs on the Titanic? They're not massive changes to the piece. And then the final question is always, if this were published in its current state right now, would I be happy with it? Would I be proud of it? And that's a very gut feeling that I think only an individual can kind of feel for themselves. And sometimes it's like, no, I don't like the way, like, I know it's 95% there, but I don't like the way this ends or something else. Again, those are all useful signals for me about whether a piece is complete or ready for submission or anything like that. I think when it comes to engineering, I think there's a little bit less of the gut feeling, to be honest, because we have standards. We have processes in place generally on teams where it's like, is the feature working? Have you written tests? Have you written a QA plan if it needs one? If it's something that needs more extensive documentation or code comments or something like that, is that something you've done? Has a bit more of a clear runway for me in terms of figuring out when something is ready to be shown to others. But certainly, as a manager, I've written a lot more types of documents I suppose, or types of communication where it's like organizational changes. I've written team announcements. I've written celebration posts. I've had to deliver bad news. Like, those are all things that you don't think about necessarily. But I've definitely had literally, you know, I have Google Docs of drafts of like, I need to draft the Slack message. And even though it's just a Slack message, I will spend time trying to make sure I've credited all the right people, or provided all the context, got all the right answers. I run it by my director, my peers, and things like that if it's relevant. And again, I think there is still that piece that comes in of drafting, getting feedback, revising, and then feeling like, okay, have I done my due diligence here, and is it ready? That cycle is applicable in many, many situations. But yeah, I certainly think for direct IC work, it's probably a little bit more well-defined than some of the other processes. STEPHANIE: Yeah, that makes sense. I really liked what you said about noticing the difference between making big structural changes and little word adjustments. I think you called it pushing commas around or something like that. NICOLE: [laughs] Yeah. STEPHANIE: I love that. Because I do think that with programming, there is definitely a big part of it that's just going on the journey and exploring different avenues. And so if you do suddenly think of, oh, I just thought of a completely different way to write this code, that is worth exploring even if you just end up going back to the original implementation. But at least you saw that thought through, and you're like, okay, this doesn't work because of X, Y, and Z, and I'm choosing to go this other route instead. And I think that, yeah, that is just a good practice to explore. NICOLE: Another example of storytelling, too, where it's like, you can tell the story in the PR description or whatever, in stand-up, to be like, I also did go down this path, XYZ reason. Here's why it didn't work out, and here's what we're optimizing for. And there you go. So I do think we talk...I guess product managers think more about buy-in, but I think that's true of engineers too. It's like, how do you build consensus and provide context? And so yeah, I think what you were saying, too, even if the path is circuitous or you're exploring other avenues, talking to other people, and just exploring what's out there, it all adds up to kind of the final decision and might provide, again, some useful information for other people to understand how you arrived there and get on board with it. STEPHANIE: 100%. I remember when I worked with someone who we were writing a PR description together because we had paired on some code. And we had tried three different things. And he wrote paragraphs for each thing that we tried. And I was like, wow, I don't know if I would have done that on my own. But I just learned the value of doing that to, like you said, prime yourself for feedback as well, being like, I did try this, and this is what I thought. And other people can disagree with you, but then at least they have the information, right? NICOLE: Definitely. STEPHANIE: So before we wrap up, the last thing that I wanted to talk about, because I think it's super cool, is just how you have a totally separate hobby and skill and practice that you invest time and energy into that's not programming. And it's so refreshing for me to see you do that because I think, obviously, there's this false idea that programmers just code all the time in their free time, in their spare time, whatever. And I'm really curious about how writing fits into your life as something separate from your day job. NICOLE: Yes, I've been thinking about this a ton. I think a lot of people, the last couple of years has forced a really big reckoning about work and life and how much we're giving to work, the boundaries that can be blurred, how capitalism butts its head into hobbies, and how we monetize them, or everything is a side hustle. And, oh, you should have a page running...oh, you should charge for a newsletter. And I think there's obviously the side of we should value our labor, but also, I don't want everything in my life to be labor. [laughs] So I do think that is interesting. Writing to me, I actually do not see it as a hobby. I see it as another career of mine. I feel like I have two careers, but I have one job, [laughs] if that makes sense. I certainly have hobbies. But for me, what distinguishes that from my writing is that with hobbies, there's no expectation that you want to get better. You approach it with just...it's just pure enjoyment. And certainly, writing has part of that for me, but I have aspirations to publish. I love it when my work can reach readers and things like that. But I do think that regardless having other interests, like you said, outside engineering, outside technology, it's a great break. And I do think also in technology, in particular, I notice...I think we're getting away from it, but certainly, there's an expectation, like you said, that you will have side projects that you code in your free time, that you're on Hacker News. I think there is a little bit of that vibe in the tech industry that I don't see in other industries. You don't expect a teacher to want to teach in their free time, [laughs] you know what I mean? But we have almost that kind of implicit expectation of engineers to always be staying up to date on those things. I think with writing and engineering; the two complement each other in some interesting ways. And they make me appreciate things about the other craft or practice that I may not previously have. And I think that with engineering, it is a team effort. It's really collaborative, and I really love working in that space. But on the flip side, too, with writing, I do love, you know, there's the ego part of it. You don't have individual authorship over code necessarily unless it's git blame level. But there's a reason why it's called git blame, [laughter] even the word is like git blame. I've literally had cases where I'm like, oh, this thing is broken. Who wrote this? And then I was like, oh, surprise, it was you six years ago. But I do think with writing; it's an opportunity for me to really just explore and ask questions, and things don't have to be solved. It can just be play. And it is a place where I feel like everything that I accomplish is...obviously, I have people in my life who really support me, but it is a much more individual activity. So it is kind of the right-left brain piece. But I've been reading this book called "Saving Time." It is what my microphone is currently propped on. But it's by Jenny Odell, who wrote: "How to Do Nothing." It's breaking my brain in a really, really, really good way. It talks a lot about the origin of productivity, how we think about time, and how it is so tied to colonialism, and racism, and capitalism, and neoliberalism, all these things. I think it has been really interesting. And so thinking about boundaries between work and writing has been really, really helpful because I really love my job; I'm not only my job. And so I think having that clarity and then being like, well, what does that mean in terms of how I divide my time, how I set examples for others at work in terms of taking time off or leaving the office on time? And trying to make sure that I have a good emotional headspace so that I can transition to writing after work; all those things. I think it is really interesting. And that also, ultimately, it's we're not just our productivity either. And I think writing can be very, again, inherently kind of unproductive. People joke that cleaning is writing, doing the dishes is writing, taking a walk is writing, showering is writing, but it is true. I think that the art doesn't talk about efficiency. You can't, I think, make art always more efficient in the same way you can do with engineering. We don't have those same kinds of conversations. And I really like having that kind of distinction. Not that I don't like problem-solving with constraints and trade-offs and things like that, but I also really like that meandering quality of art and writing. So yeah, I've been thinking a lot more about collective time management, I guess, and what that means in terms of work, writing, and then yeah, hobbies and personal life. There are never enough hours in the day. But as this book is teaching me, again, maybe it's more about paradigm shifting and also collective policies we can be putting in place to help make that feeling go away. STEPHANIE: For sure. Thank you for that distinction between hobby and career. I really liked that because it's a very generative mindset. It's like a both...and... rather than an either...or... And yeah, I completely agree with you wanting to make your life expansive, like, have all of the things. I'm also a big fan of Jenny Odell. I plugged "How to Do Nothing" on another episode. I am excited to read her second book as well. NICOLE: I think you'll like it a lot. It's really excellent. She does such interesting things talking about ecology and geology and geographic time skills, which is really interesting that I don't know; it's nice to be reminded that we are small. [laughter] It's a book that kind of reminds you of your mortality in a good way, if that makes sense. But much like Gary on your porch reminds you of mortality too [laughs] and that you have to put Gary away for a little bit so that his time can come in October. [laughs] STEPHANIE: Exactly, exactly. Cool. On that note, let's wrap up. Thank you so much for being on the show, Nicole. NICOLE: Thank you so much for having me. This was a blast. STEPHANIE: Show notes for this episode can be found at bikeshed.fm. JOËL: This show has been produced and edited by Mandy Moore. STEPHANIE: 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. It really helps other folks find the show. JOËL: If you have any feedback for this or any of our other episodes, you can reach us @_bikeshed, or you can reach me @joelquen on Twitter. STEPHANIE: Or reach both of us at hosts@bikeshed.fm via email. JOËL: Thanks so much for listening to The Bike Shed, and we'll see you next week. ALL: Byeeeeeeee!!!!!!!! ANNOUNCER: This podcast is brought to you by thoughtbot, your expert strategy, design, development, and product management partner. We bring digital products from idea to success and teach you how because we care. Learn more at thoughtbot.com.Sponsored By:Airbrake: Deploy fearlessly and fix bugs faster with Airbrake Error & Performance Monitoring. Airbrake notifiers are available for all major programming languages and frameworks, and install in minutes, with an open-source SDK-based install and near-zero technical debt. Spend less time tracking down bugs and more time developing. Visit Frictionless error monitoring and performance insight for your app stack.Support The Bike Shed
undefined
May 2, 2023 • 36min

382: Domain-Specific Languages

Joël has been integrating a third-party platform into a testing pipeline...and it has not been going well. Because it's not something she usually keeps up-to-date with, Stephanie is excited to learn about more of the open-source side of things in Ruby, what's new in the Ruby tooling world, and what folks are thinking about regarding the future of the language. Today's topic is inspired by an internal thoughtbot Slack thread about writing a custom matcher for Rspec. Stephanie and Joël contrast DSLs vs. Object APIs and also talk about: CanCanCan vs Pundit RSpec DSL When is a DSL helpful? Why not use both DSLs & Object APIs? Extensibility When does a DSL become a framework? This episode is brought to you by Airbrake. Visit Frictionless error monitoring and performance insight for your app stack. RubyKaigi 2023 Mystified by RSpec’s DSL? by Jason Swett Building Custom RSpec Matchers with Regular Objects FactoryBot Writing a Domain-Specific Language in Ruby by Gabe Berke-Williams Capybara Acceptance Tests at a Single Level of Abstraction CanCanCan Pundit Discrete Math and Functional Programming Transcript: STEPHANIE: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Stephanie Minn. JOËL: And I'm Joël Quenneville. And together, we're here to share a little bit of what we've learned along the way. STEPHANIE: So, Joël, what's new in your world? JOËL: I've been integrating a third-party platform into our testing pipeline for my client. It has not been going well. We've been struggling a little bit, mostly just because tests just kind of crash. Our testing pipeline is pretty complex. It's a lot of one script, some environment variables, does a few things, shells out to another script, which is in a different language. Does a few more things, shells out to another script, maybe calls out to rake, calls out to a shell script. There are four or five of these in a chain, and it's a bit of a mess. Somewhere along in there, something is not compatible with this third-party service that we're trying to integrate with. I was pairing this week with a colleague. And we were able to reproduce a situation where we were able to get a failure under some conditions and a success under other conditions. So these are basically, if we run the whole chain of scripts that call each other from the beginning, we know we get a failure. And if we skipped entirely the chain of scripts that set up things and then just manually try to invoke a third-party service, that works. And so now we know that there's something in between that's incompatible, and now it's just about narrowing things down. There are a few different approaches we could take. We could try to sort of work our way forward. We know a known point where it breaks and then just try to start the chain one step further and see where it fails. We could try to get fancy and do a binary search, like split it in half and then half and half again. We ended up doing it the other way, where we started at the end. We had our known good point and then just stepping one step back and saying, okay, now we introduce the last script in the chain. Does that work? Okay, that pass is great. Let's go one step further; two scripts up in the chain. And at some point, we find, okay, here's the one script that fails. Now, what is it within this script? And it was a really fun debugging session where we were just narrowing things down until we found the source of the bug. STEPHANIE: Wow, that sounds pretty complicated. It just seems like there are so many layers going on. And it was really challenging to pinpoint where the source of the issue was. JOËL: Definitely. I think all the layers made it really complicated. But having a process that we could follow and then kind of narrowing it down made it almost mechanical to figure out where the bug was once we got to a point where we had a known good point and a known bad point. STEPHANIE: Yeah, that makes sense. Kind of sounds like if you are using git bisect or something like that to narrow down the scope of where the issue could be. I'm curious because this is like a bunch of shell scripts and rake tasks or commands or whatever. What would have made this debugging process easier? JOËL: I think having fewer scripts in this chain. STEPHANIE: [laughs] That's fair. JOËL: We don't need so many scripts that call out to each other in different languages trying to share data via environment variables. So we've got a bit of a Rube Goldberg machine, and we're trying to patch in yet another piece in there. STEPHANIE: Yeah, that's really tough. I was curious if there was, I don't know, any logging or any other clues that you were getting along the way because I know from experience how painful it is to debug that kind of code. JOËL: It's interesting because I feel like normally logging is something that's really useful. In this particular case, we run into an exception at some point. So it's more of under what conditions does the exception happen? The important thing was to find that there is a point where it breaks, and there's a point where it doesn't, and realizing that if we ran some of these commands just directly without going through the whole pipeline, that things did work and that we were not triggering that exception. So all of a sudden, now that tells us, okay, something in our pipeline is wrong. And then we can just start narrowing things down. So yeah, adventures in debugging. Sometimes it's really frustrating, but then when you have a good process, and you find the bug, it's incredibly satisfying. STEPHANIE: I like that you used a process that can be applied to many different problems, in this particular case, debugging a testing pipeline. Maybe not something that we do every day, but certainly, it comes up, and now we have tools to address those kinds of issues as well. JOËL: So my week has been up and down with all of this debugging. What's been new in your world? STEPHANIE: I've been doing some travel planning because I'm going to RubyKaigi in Japan. JOËL: Whoa. STEPHANIE: This is actually going to be my first international conference, so I'm really looking forward to that. I just have never been compelled to travel abroad to go to a tech conference. But I'm really looking forward to going to RubyKaigi because now I've been to the U.S.-based conferences a few times. And I'm excited to see how things are different at an international conference and specifically a RubyKaigi because, obviously, there's a lot of really cool Ruby work happening over there in Japan. So I'm excited to learn about more of the open-source side of things of Ruby, what's new in the Ruby tooling world, and just what folks are thinking about in terms of the future of the language. That's not something I normally keep super up-to-date on. But I'm excited to be around people who do think and talk about these things a lot and maybe get some new insights into my own work. JOËL: Do you find that you tend to keep up more with some of the frameworks like Rails rather than the underlying language itself? STEPHANIE: Yeah, that's a good question. I do think because the framework changes a little more frequently, new releases are kind of more applicable to the work that I'm doing. Whereas language updates or upgrades are a little bit less top of mind for me because the point is that it doesn't have to change [laughs] all that much, and we can continue to work with things as expected and not be disrupted. So it is definitely like a whole new world for me, but I'm really looking forward to it. I think it will be really interesting and just kind of a whole other space to explore that I haven't really because I've usually been focused on more of the web development and industry work side of things. JOËL: What's a Ruby feature that either is coming out in the future or that came out in the last couple of releases that got you really excited? STEPHANIE: I think the conversation about typing in Ruby is something that has been on my radar but has also been ebbing and flowing over time. And I did see a few talks at RubyKaigi this year that are going to talk about how to introduce gradual typing in Ruby. And now that it has been out for a little bit and people have been using it, how people are feeling about it, pros and cons, and kind of where they're going to take it or not take it from there. JOËL: Have you done much TypeScript? STEPHANIE: I have been working more in TypeScript recently but did spend most of my front-end work coding days in JavaScript. And so that transition itself was pretty challenging for me where I suddenly felt a language that I did know pretty well. I was having to be in that...in somewhat of a beginner's mindset again. Even just reading the code itself, there were just so many new things to be looking at in terms of the syntax. And it was a difficult but ultimately pretty rewarding experience because the way I thought about JavaScript afterwards was much more refined, I think. JOËL: Types definitely, I think, change the way you think about code; at least, that's been my experience. STEPHANIE: Yeah, absolutely. I haven't gotten the pleasure to work with types in Ruby just yet, but I've just heard different experiences. And I'm excited to see what experts have to say about it. JOËL: That's the fun of going to a conference. STEPHANIE: Absolutely. So yeah, if any listeners are also headed to RubyKaigi, yeah, look out for me. JOËL: I was recently having a conversation with someone about the fact that a lot of languages provide ways to sort of embed many languages within them. So the Lisp family of languages are really big into macros and metaprogramming. Some other languages are big into giving you the ability to build your own ASTs or have really strong parsing capabilities so that you can produce your own, again, mini-language. And Ruby does this as well. It's pretty popular among the Ruby community to build DSLs, Domain-Specific Languages using some of Ruby's built-in abilities. But it seems to be a sort of universal need or at the very least a universal desire among programmers. Have you ever found yourself as a code author wanting to embed a sort of smaller language within your application? STEPHANIE: I don't think I have, to be honest. It's a very interesting question. Because I think the motivation to build your own mini-language using Ruby would have to be you'd have to have a really good reason for it, and in my experience, I haven't quite encountered that yet. Because, yeah, it seems like a lot of upfront work, a lot of overhead to introduce something like that, especially if it's not necessarily either a really, really particular domain that others might find a use for, or it just doesn't end up seeming worthwhile if I can just write regular, old Ruby code. JOËL: I think you're not alone. I think the Ruby community has been kind of a bit of a pendulum here where several years ago, everything that could be made into a DSL was. Now the pendulum kind of has been swinging the other way. And we see DSLs, but they're not quite as frequent. For those who maybe have not experienced a DSL or aren't quite familiar with the concept, how would you describe the idea? STEPHANIE: I think I would describe domain-specific languages as a bit of a mini-language that is created for a very particular problem space in mind to make development for that domain easier. Oftentimes, I've also kind of seen people describe the benefit of DSLs as being able to read that language as if it were plain English. And so, in my head, I have kind of, at least in the Ruby world, right? We see that a lot in different gems. RSpec, for example, has its own internal DSL, and many people really enjoy it because it took the domain of testing. And the way you write it kind of is how you might read or understand it in English. And so it's a bit easier to talk about what you're expecting in your tests. JOËL: Yeah, it's so high-level and minimal and domain-specific that it almost stops feeling like it's a programming language and can almost feel like it's a high-level configuration for this very particular domain, sometimes even to the point where the idea is that a non-programmer could read it and understand what's going on. STEPHANIE: I think RSpec is actually one of the first Ruby DSLs that you might encounter when you're learning Ruby for the first time. And I've definitely seen developers who are new to Ruby, you know, they're writing code, and they're like, okay, I'm ready to write a test now. And the project uses RSpec because that's what most of us use in our Rails applications. And then they see, like you said, almost a configuration language, and they are really confused. They're not really sure what they're reading. They struggle with the syntax a lot. And it ends up being a point of frustration when they're first starting out if they're not just copying and pasting other existing RSpec tests. I'm curious if you've seen that before. JOËL: I've definitely seen that. And it's a little bit ironic because oftentimes, an argument for DSL is that it makes things simpler that you don't even have to know Ruby; you can just write it. It's simpler. It's easier to write. It's easier to understand. And to a certain extent, maybe that's true. But for someone who does know Ruby and doesn't know your particular little domain language, now they're encountering something that they don't know. And they're having to learn it, and they're having to struggle with it. And it might behave a little bit weirdly compared to how Ruby normally works. And so sometimes it doesn't make it easier for adoption. But it does look really good in a README. STEPHANIE: That's totally fair. I think the other thing that's interesting about RSpec is that a lot of it is really just stylistic. I actually read a blog post by Jason Swett and the headline of it was "Mystified by RSpec's DSL? Some parentheses can add clarity." And he basically goes on to tell us that really RSpec is just leaning on some of Ruby's syntactic sugar of omitting parentheses for method calls. And if you just add the parentheses back in your it blocks or your describes, it can read a lot more like regular Ruby. And you might have a better time understanding what's going on when you realize that we're just passing our descriptors as arguments along with some blocks. JOËL: That's ironic given that oftentimes, the goal of these is to make it look like not Ruby. STEPHANIE: I agree; it is ironic. [laughs] 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 cut your debugging time in half. So why do developers love Airbrake? 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 of 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 helps 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 to include 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. Head on over to airbrake.io/try/bikeshed to create your FREE developer account today! JOËL: I think another drawback that I've seen with DSLs is that they oftentimes are more limited in their capabilities. So if the designer of the gem didn't explicitly think of your use case, then oftentimes, it can be really hard to extend or to support edge cases that are not specifically designed for that language in the way that plain Ruby is often much more flexible. STEPHANIE: Yeah, that's really interesting because when a gem does have some kind of DSL, a lot of effort probably went into making that the main interface that you would work with or you would use. And when that isn't working for your use case, the design of the underlying objects may or may not be helpful for the changes that you want to make. JOËL: I think it's interesting that you mentioned the underlying objects because those are often sort of not meant for public consumption when you're building a gem that's DSL forward. I think, in many cases, my ideal gem would make those underlying objects the primary interface and then maybe offer DSL as a kind of nice-to-have layer on top for those situations that maybe aren't as complex where writing things in the domain language might actually be quite nice. But keeping those underlying objects as the interface, it's nice to use and well-documented for the majority of people. STEPHANIE: Yeah, I like that too because then you can get the best of both worlds. So speaking of trying to make a DSL work for you, have you ever experienced having to kind of work around the DSL to get the functionality you were hoping to achieve? JOËL: So I think we're talking about the idea of having both a DSL and the underlying objects. And RSpec is a great example of this with their custom matchers. RSpec itself is a DSL, but then they also offer a DSL to allow you to create custom matchers. And it's not super well documented. I always forget how to define them, and so I oftentimes don't bother. It's just kind of too much of a pain for something that doesn't always provide that much value. But if it were easy, I would probably do it more. Eventually, I realized that you could use just regular Ruby objects as custom matchers. And they just seemed to respond to certain methods, just regular old objects and polymorphism. And all of a sudden, now I'm back into all of the tools and mechanisms that I am familiar with, like the back of my hand. I can write objects all day. I can TDD them. I can apply any patterns that I want to if I'm doing something really complicated. I can extract helpers. All of that works really well with the knowledge that I already have without having to sink a lot of time into trying to learn the built-in DSL. So, for the most part, now, when I define custom matchers, I'll often jump directly to creating a regular object and making it conform to the matcher interface rather than relying on the DSL for that. So once we go back to the test, now we're back in DSL land. Now we're no longer talking in terms of objects so much. We'll have some nice methods and they will all kind of read like English. So to pull a recent example that I worked on, I might say something like expect this policy object method to conform to this truth table. STEPHANIE: That's a really interesting example. It actually kind of sounds like it hits the sweet spot of what you were describing earlier in the sense that it has a really nice DSL, but also, you can create your own objects, and that has an interface that you can implement. And yes, have your cake and eat it too. [laughs] But the idea that then you're kind of converting it back to the DSL because that is just what we know, and it has become so normalized. I was talking earlier about okay; when is a DSL worthwhile? When is the use case a good reason to implement it? And especially for gems that I think that are really popular that we as a Ruby community have collectively used most of the time on our projects because we have oftentimes a lot of the same problems that we're solving. It seems like this has become its own shared language, right? JOËL: Yeah, there are definitely some DSLs that we all end up learning because they're just so prominent in the Ruby community, even Rails itself ships with several built-in DSLs. STEPHANIE: Yeah, absolutely. FactoryBot is another one, too. It is a gem by thoughtbot. And actually, in preparation to talk about DSLs with you today, I scoured our blog and found a really great blog post, "Writing a Domain-Specific Language in Ruby" by Gabe Berke-Williams. And it is basically like, here's how to write something like FactoryBot and creating your own little mini Ruby DSL for something that would be very similar to what FactoryBot does for fixtures. JOËL: That's a great resource, and we'll make sure to link that in the show notes. We've been talking about some of the limitations of DSLs or some aspects of them maybe that we personally don't like. What are maybe examples of DSLs that you do enjoy working with? STEPHANIE: Yeah, I have an example for this one. I really enjoy using Capybara's DSL for acceptance testing. I did have to go down the route of writing some custom selectors for...I just had some HTML elements within kind of a complicated table and was trying to figure out how to write some selectors so that I could write the test as if it were in, you know, quote, unquote, "plain English" like, within this table, expect some value. And that was an interesting journey. But I think that it really helped me have a better understanding of accessibility of just the underlying building blocks of the page that I was working with. And, yeah, I really appreciate being able to read those tests from a user perspective and kind of know exactly what they're doing when they're interacting with this virtual browser without having to run it in headful mode and see it for myself. JOËL: It's always great when a DSL can give you that experience of abstracting enough to where it makes the code delightful to work with while also not having too high a cost to learn or being too restrictive in what it allows you to do. Would you make a difference between something that's a DSL versus maybe just code that's written at a higher level of abstraction? So maybe to get back to your example with Capybara, it's really nice to have these nice custom matchers and all of these things to work with HTML pages. If I'm writing, let's say, a helper method at the bottom of a test, I don't think that feels quite like it's a DSL yet. But it's definitely a higher level than specifying CSS selectors. So would you make a difference between those two things? STEPHANIE: That's a good question. I think it's one of those you know it when you see it kind of questions because it just depends on the amount of abstraction, like you mentioned, and maybe even metaprogramming. That takes something from the core language to morph into what you could qualify as a separate language. What do you think about this? JOËL: Yeah, part of me almost wonders if this exists kind of on a continuum, and the boundary might be a little bit fuzzy. I think there might be some other qualifications that come with it as well. Even though DSLs are typically higher-level helpers, it's usually more than just that. There are also sort of slightly different semantics in the way that you would tend to use them to the point where while they may be just Ruby methods, we don't use them like Ruby methods, and even to the point that we don't think of them as Ruby methods. To go back to that article you mentioned from Jason, where just reminding people, hey, if you put params on this, all of a sudden, it helps you remember, oh, it's just a Ruby method instead of being like, oh, this is a language keyword or something. STEPHANIE: Yeah, I wonder if there's also something to the idea of domain specificity where it should be self-service within the domain that you're working. And then it has limitations once you are trying to do something separate from the domain. JOËL: Right, it's an element of focus to this. And I think it's probably also a language is not just one helper; it's a collection typically. So it's probably a series of high-level helpers, potentially. They might not be methods, even though that is ultimately one of the primary interfaces we use to run code in Ruby. So it's a collection of methods that are high-level, but the collection itself is focused. And oftentimes, they're meant to be used in a way where it's not just a traditional method call. STEPHANIE: Right. There's some amount of you bringing to the table your own use case in how you use those methods. JOËL: Yeah, so it might be mimicking a language keyword. It might be mimicking the idea of a configuration. We see that a little bit with ActiveRecord and some of the, let's say, the association and validation APIs. Those kind of feel like, yes, they're embedded in a class, but they feel like either keywords or even just straight-up configuration where you set key-value pairs of things to configure how a particular class is going to work. STEPHANIE: Yeah, that's true for a lot of things in Rails, too, if we're talking about routes and initializers as well. JOËL: So I've complained about some things I don't like about DSLs. I really like the routing DSL in Rails. STEPHANIE: Why is that? JOËL: I think it's very compact and readable. And that's an element that's really nice about DSLs is that it can make things feel very readable and, oftentimes, we read code more often than we write it. And routes have...I was going to say fewer edge cases, but I have seen some really gnarly route files that are pretty awful to work with, especially if you're mostly writing RESTful controllers, and I would recommend that people do. It's really nice to just be able to skim through a route file and be like, oh, these are the resources in my app and the actions I can do on each resource. And here are the ones that are nested. STEPHANIE: Yeah, it almost sounds like a DSL can provide guardrails towards the recommended way of tackling that particular domain. The routes DSL really discourages you from doing anything too complicated because they are encouraging you to follow the Rails convention. And so I think that goes back to the specificity piece of if you've written a DSL, it's because you've thought very deeply about this particular domain and how common problems show up and how you would want people to be empowered by the language rather than inhibited by it. JOËL: I think, thinking more about that, the word that comes to mind is declarative. When you read code that's written with DSLs, typically, it's very declarative. It's more just describing a thing as opposed to either procedural, a series of commands to do, or even OO, where you're composing objects and sending messages to each other. And so problems that lend themselves to being implemented through more descriptive and declarative approaches probably are really good candidates for a DSL. STEPHANIE: Yeah, I like that a lot because when we talk about domains, we're not necessarily talking about a business domain, which is kind of the other way that some folks think about that word. We're talking about a problem space. And the idea of the language being declarative to describe the problem space makes a lot of sense to me because you want it to be flexible enough for different use cases but all within the idea of testing or browser navigation or whatever. JOËL: Yeah. I feel like there's a lot of... there are probably more problems that can be converted to declarative solutions than might initially kind of strike you. Sometimes the problem isn't quite as bounded. And so when you want customizations that are not supported by your DSL, then it kind of falls apart. So I think a classic situation that might feel like something declarative is authorization. Authorization are a series of rules for who can access what, and it would seem like this is a great case for a DSL. Wouldn't it be great to have just one file you can just kind of skim, and we can just see all of the access rules? Access rules that are basically asking to be done declaratively. And we have gems like that. The original CanCan gem and then the successor CanCanCan are trying to follow that approach. Have you used either of those gems? STEPHANIE: I did use the CanCanCan gem a while ago. JOËL: What was your experience with that style of authorization? STEPHANIE: It has been a while but I do remember having to check that original file of like all the different authorizations kind of repeatedly coming back to it to remember, okay, for this rule, what should be allowed to happen here? JOËL: So I think that's definitely one of the benefits is that you have all of your rules stored in one place, and you can kind of scan through the list. My experience, though, is that in practice, it often kind of balloons up and has all of these edge cases in it. And in some earlier versions, I don't know if that's still a problem today, it could even be difficult to accomplish certain things. If you're going to say that access to this particular object depends not on properties of that object itself but on some custom join or association or something like that, that could be really clunky to do or sometimes impossible depending on how esoteric it is or if there's some really complex custom logic to do. And once you're doing something like that, you don't really want to have that logic in your...in this case, it would be the abilities file but inside because that's not really something you express via the DSL anymore. Now you're dropping into OO or procedural world. STEPHANIE: Right. It seems a bit far removed from where we do actually care about the different abilities, especially for one-off cases. JOËL: That is interesting because I feel like there's a bit of a read-versus write-situation happening there as well. It's particularly nice to have, I think, everything in one abilities file for reading and for auditing. I've definitely been in code where there's like three or four ways to authorize, and they're all being used inconsistently, and that's not nice at all. On the other hand, it can be hard with DSL sometimes to customize or to go beyond the rules that are built in. In the case of authorization, you've effectively built a little mini-rules engine. And if you don't have a good way for people to add custom rules without just embedding procedural code into your abilities file, it's going to quickly get out of hand. STEPHANIE: Yeah, that makes sense. On the topic of authorization, you did mention an example earlier when you were writing a policy object. JOËL: I've generally found that that's been my go-to pattern for authorization. I enjoy the Pundit gem that provides some kind of light scaffolding around working with policy objects, but it's a general pattern, and you can absolutely write your own. You don't need a gem for that. Now we're definitely not in the DSL world. We're not doing this declaratively. We're leaning very heavily on OO and saying we're just going to create objects. They talk to each other. They can do anything that any Ruby object can do and as simple or as complex as they need to be. So you have the full power of Ruby and all the patterns that you're used to using. The downside is it is a little bit harder to read and to kind of just audit what's happening in terms of permission because there's no high-level overview anymore. Now you've just got to look through a bunch of classes. So maybe that's the trade-off, flexibility, extensibility versus more declarative style and easy overview. STEPHANIE: That makes a lot of sense because we were talking earlier about guardrails. And because those boundaries do exist, that might not give us the flexibility we want compared to just writing regular Ruby objects. But yeah, we do get the benefit of, like you said, auditing, and at least if we don't try to do some really gnarly, custom stuff, [laughs] something that's easier to read and comprehend. JOËL: And, again, maybe that's where in the best of both worlds situation, you say, hey, I'm creating some form of rules engine, whether it's for describing routes, or authorization, permissions, or users can build custom business rules for a product or something like that. And it's all object-based under the hood. And then, we provide a DSL to make it nice to work with these rules. If a programmer using our gem wants to write a custom rule that just really extends what the ones we shipped can do, allow them to do that via the object API. We have all the objects available to you that underlie the DSL. Add more rules yourself. And then maybe those can be plugged back into the DSL like we saw with the RSpec and custom matchers. Or maybe you have to say, okay, if I have a custom rule object, now I have to just stay in the object space. And I think both of those solutions are okay. But now you've sort of kept those two worlds separate and still allowed people to extend. STEPHANIE: I like that as contributing to the language because language is never static. It changes over time. And that's a way that people can continue to evolve a language that may have been originally written at a certain time and place. JOËL: Moving on from DSLs, we got some listener feedback recently from James, who was listening to our episode on discrete math. And James really appreciated the episode and wanted to share a resource with us. This is the book "Discrete Math and Functional Programming" by Thomas VanDrunen. It's an introduction to discrete math as a theoretical concept taught side by side with the very practical aspect of learning to use the language standard ML, and both of those factor into each other. So you're kind of learning a little bit of theory and some practice, at the same time, getting to implement some discrete math concepts in standard ML to get a feel for them. Yeah, I've not read this book, but I love the concept of pairing a theoretical piece and a practical piece. So I'll drop a link to it in the show notes as well. Thank you, James. STEPHANIE: Yeah, thanks, James. And I guess this is just a little reminder that if our listeners have any feedback or questions they want to write in about, you can reach us at hosts@bikeshed.fm. JOËL: On that note. Shall we wrap up? STEPHANIE: Let's wrap up. Show notes for this episode can be found at bikeshed.fm. JOËL: This show has been produced and edited by Mandy Moore. STEPHANIE: 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. It really helps other folks find the show. JOËL: If you have any feedback for this or any of our other episodes, you can reach us @_bikeshed, or you can reach me @joelquen on Twitter. STEPHANIE: Or reach both of us at hosts@bikeshed.fm via email. JOËL: Thanks so much for listening to The Bike Shed, and we'll see you next week. ALL: Byeeeeeee!!!!!!! ANNOUNCER: This podcast is brought to you by thoughtbot, your expert strategy, design, development, and product management partner. We bring digital products from idea to success and teach you how because we care. Learn more at thoughtbot.com.Sponsored By:Airbrake: Deploy fearlessly and fix bugs faster with Airbrake Error & Performance Monitoring. Airbrake notifiers are available for all major programming languages and frameworks, and install in minutes, with an open-source SDK-based install and near-zero technical debt. Spend less time tracking down bugs and more time developing. Visit Frictionless error monitoring and performance insight for your app stack.Support The Bike Shed
undefined
Apr 25, 2023 • 41min

381: To TDD or Not to TDD?

It's gardening season! Stephanie swaps seeds with friends and talks about her Chicago garden. Joël recently started experimenting with a dedicated bookmark manager. They discuss the aspirational (and sometimes dogmatic) sides of TDD and explore when to test: first or after. How does that affect the tests? How does that affect the code? How does that affect workflow? Are you a "better" programmer because you 100% TDD? This episode is brought to you by Airbrake. Visit Frictionless error monitoring and performance insight for your app stack. Cassidy William's Productivity tools raindrop.io Bookmark Manager Simplifying Tests by Extracting Side-Effects Transcript: JOËL: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Joël Quenneville. STEPHANIE: And I'm Stephanie Minn. And together, we're here to share a bit of what we've learned along the way. JOËL: So, Stephanie, what is new in your world? STEPHANIE: It's gardening season here in Chicago. So right now, it is like mid-April as we're recording this, and we are just starting to get some warm weather. And this is usually the time that I do my garden planning for the season. And the other week, I went over to a friend's place, and we did a bit of a seed share. So we just each have collected fruit and vegetable seeds and herbs and all that. And a really fun way to collect more things to grow is to share with your friends. Seeds are super cheap, but I feel like you could just have like an infinite amount for all of the things that you might want to grow. And so it's really nice to be able to, yes, spread that gardening love around and share with your friends. JOËL: I'm imagining something like people trading collectible trading cards but the plant version. STEPHANIE: Yeah, exactly. The fun thing that we did, my friend and I, because, you know, you usually get a little envelope with between 10 and 50 or more seeds, and they're super tiny. Some of them are really teeny tiny, like with broccoli, for example, it's like I can't even explain. It's less than a millimeter, I swear. It's very easy to just lose them, so you want to keep them contained. But because we are sharing, we don't have a second envelope for the other person to take home with them. And so we actually made our own little envelopes with some origami paper that she had. And we folded it and stapled it and made it very cute. And so I came home with a bunch of these very adorable handmade envelopes with all of my new seeds. JOËL: Are you mostly doing vegetables, or are these flowers? STEPHANIE: Yeah, so we mostly focus on vegetables for our garden. And we do like to sprinkle some flower seeds in our yard. But that is more just like throw some seeds out there, and whatever happens to them happens. But with the vegetables, we put a little bit more effort because we usually try to have a good yield. So in past years, that has meant starting seeds indoors because, in Chicago, we have a shorter growing season than some warmer climate places. And the late summer vegetables like tomatoes, peppers those usually take a little bit longer. So if you want to get a good yield, you might want to start them inside a little early before it's warm enough for them to go outside. JOËL: So, do you have a garden plot out in your yard, or do you have a community garden plot? How does that work? STEPHANIE: I am really grateful to have a bit of backyard space. And we have three raised beds that we built that cover...I think each one is 3 feet by 10 feet, so quite a good amount of space. Yeah, we're able to grow a lot of food. Our highlights include shishito peppers. That's one that I really like to grow myself a lot because I usually don't see them in stores as frequently. We grow really great eggplants. Tomatoes, obviously, is a pretty popular beginner-friendly vegetable plant. And we like to grow a lot because then we can process it all and can some of it so we can have nice tomato sauce that's homegrown year round. JOËL: Hmm, sounds delicious. Do you experiment with the different varieties? STEPHANIE: We do. That's also a way that the seed sharing is really helpful because maybe I'll get some varieties of certain vegetables like cucumbers or whatever, but maybe my friend has a different kind. And I think we try to do a mix of growing the varieties that we know we like and then experimenting with some ones that are new to us. JOËL: It's hard to beat fresh vegetables in the summer. STEPHANIE: Yeah. I'm very excited, especially because during the fall and winter seasons here in Chicago, our local food is a little less exciting. It still can be good, but it's been a lot of root vegetables and the like when we try to eat seasonally in the other season. So I'm really looking forward to stuff that's just juicy and fresh, and it's just one of my biggest joys during the summer. What about you, Joël, what's new in your world? JOËL: I've recently started experimenting with a dedicated bookmark manager. This is not because I have been to too many bookstores and have all the free bookmarks they give you. These are the digital bookmarks to websites, and I've been really bad at managing those. I mostly just memorize the keywords I need to Google to get access to that website, which is a terrible way of doing things. And then I've got a mix of a few different browsers, which I don't sync, and have a couple of bookmarks. I use a little bit of Pocket, which is a tool by Mozilla. It's all right, but the search capabilities are not very good. So sometimes I'll know it's in there, but I can't find it. STEPHANIE: I'm so glad you brought up this topic because I am in a similar boat where I read a lot of things on the internet and have just thrown them all into my top-level bookmarks hierarchy. And that has not really been working for me, either. So I'm really curious to find out how you've been solving this problem. JOËL: So recently, I volunteered to be a mentor for first-time speakers at the upcoming RailsConf in Atlanta. And someone was asking me about designing slides, and we were talking a little bit about when should you use maybe a bulleted list on a slide versus when there are other options available. I knew that I had read years ago a fantastic resource on slide design. But try as I could, I could not Google this and get the page that I was looking for. This was shared to me by somebody else as part of a conference preparation group years ago, and so I reached out to this person. I was like, "Hey, so do you happen to remember that link you shared with me five years ago?" And this person says, "I do remember it. I don't have the link either." STEPHANIE: I've literally been in this exact same situation where I remembered that there was an article that I read, and I remembered exactly who shared it with me or who I talked about it with, and when I couldn't find it, trying to reach out to them and also not being able to find it through them. JOËL: So the story ends well because I was able to log into an old Slack group... STEPHANIE: Wow. JOËL: That had been created for the speakers at this conference and dig through the history. And luckily, I still had access to the group. I was still in that private channel for the speakers. And I found the link, and I was able to share it with others. So that was great. But then I started thinking; I can't keep living this way. I need something better. STEPHANIE: It's true. Even though we are expert Googlers as developers, sometimes the search just doesn't get you the thing you're looking for. JOËL: So, about this time, I'm scrolling Twitter as one does. And I saw a tweet from Cassidy Williams talking about some of the productivity tools that she's been using this year did a longer article about it. And I started reading it, and a tool that she mentioned there is Raindrop.io, which is an all-in-one bookmark manager. And I'm like, oh, that is exactly, I think, the missing piece of technology in my life right now. So I went up and signed up for it, and so far, it's been pretty good. I'm experimenting with it. But I've consolidated a lot of the links that were in my head or in some of these other places, put it in there, categorized them a little bit, tagged them. And hopefully, this becomes a better way so that when I want to reference a link for someone else either in a conversation or as a resource or even for myself, maybe when I'm writing an article, I'm like, oh, I know I read something that would act as a good resource here. I can go to Raindrop and get that article without any of these other shenanigans I had to do this time. STEPHANIE: Amazing. What is special about Raindrop as opposed to just your native browser bookmark capabilities? JOËL: It has some deeper structuring capabilities in terms of not everything has to be hierarchical. It has tags as well as categories. And I think most importantly, for me, it has search, which seems to be pretty good at surfacing things. It also has some somewhat smart capabilities where it will automatically figure out if the thing that you've linked is an article, or a document, or a video, something like that. So you can filter by these inferred types as well. It has the ability to sync across devices, which browsers can do if you're signed up for them. STEPHANIE: Nice. I like that it has that search functionality that you mentioned because I think I'm definitely in the boat of just scrolling through all of my untagged, unorganized bookmarks. And it's really tough to find what I'm looking for, especially if the meta title also doesn't quite tell me exactly the keywords that I'm needing to be scanning for in that moment. So I will definitely have to give it a try. JOËL: I believe you can get full-text search if you pay for the premium version (I'm currently trying the free version.), which in theory, could mean that it searches the contents of the article. It's not clear with that. But I do know they save a snapshot of the text of the article. STEPHANIE: That's really interesting because then it's almost like a search engine but scoped to the things that you have saved. JOËL: Yes. STEPHANIE: Nice. JOËL: I'll see how that goes, and maybe six months from now, I can talk a little bit about what the experience has been using that. STEPHANIE: Yeah, six months from now, you can tell us all about how you have no issues or qualms with how you've been managing bookmarks because everything is working perfectly well for you. [laughs] JOËL: JK, I've dropped this whole bookmark thing. STEPHANIE: That's true. That's also the flip side of trying out a new tool, [laughs], isn't it? 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 cut your debugging time in half. So why do developers love Airbrake? 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 of 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 helps 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 to include 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. Head on over to airbrake.io/try/bikeshed to create your FREE developer account today! STEPHANIE: So our topic for today is something that we've had in our topic backlog for a while, and I'm excited to talk about it. It's TDD, which I think is a very well-known, potentially controversial topic of discussion in the world of software development. And specifically, we wanted to talk about when TDD is useful and when you actually might also have some value in writing tests afterwards. And in preparation for this topic today, I actually have been TDDing most of my client work this week. JOËL: What? You're telling me you don't TDD 100% of the time? Are you even a real developer? STEPHANIE: I am a real developer, and I do not TDD 100% of the time. I'm just going to say it. It's on record. JOËL: You know what? Me too. STEPHANIE: Wow, I'm glad we could clear the air on that one. [laughs] JOËL: What percent of the time would you say that you do TDD? In this case, test first as opposed to maybe testing after you've written the code or maybe not testing at all. STEPHANIE: Hmm, that's an interesting question. A part of me wants to answer it in my ideal workflow terms. But I think that is less interesting than reality, which is I will usually at least try to test first if I'm feeling like I am up for it. So maybe the percentage is, I don't know, I really couldn't tell you, but I'm just going to throw out 40% of the time [laughs] because that seems pretty, I don't know, reasonable. Sometimes you wake up, and you're just like, I'm not going to do it today. [laughs] And other days, you wake up, and you're like, you know? It sounds like a fun exercise to do for this particular feature. So yeah, if I TDD 40% of the time, then I think maybe I write tests after another 40% or 50%. And then [laughs] I'm hesitant to say this on the air, but sometimes you code, and you don't write tests for it and would not recommend it for the majority of your work. But I'm just going to be real here that sometimes it happens. JOËL: It's always a trade-off in terms of the work you put in versus the value you're getting out of it. And sometimes, you get very little value out of a test. STEPHANIE: Yeah, that's real. It totally depends on what you're doing. JOËL: I think one thing that's interesting for us, because we're consultants, so we move from one project to another, is that some projects are set up in a way that they're very test friendly. It's easy to have a testing workflow with them. And then others are just incredibly painful to test because of the way the system has been architected. And I think a TDD purist would then tell us that this is a symptom of high coupling or other architectural problems; that's probably true. But also, you don't have time to re-architect the entire system, and so then it becomes a question of trade-offs. Can I test some things easily today? Can I refactor a few things that will make this local change somewhat easier to test? And then, where is it not worth the effort to make something testable? STEPHANIE: Yeah, I've definitely struggled with that, where a part of me wanted to test something very thoroughly or even do test-driven development and then ran into some obstacles along the way and having to be realistic about that effort. The other thing I was referring to around it depending is also the actual code you're working on. So maybe if you're just writing a script or something to automate some dev workflow, it's okay for that not to be tested. And I also do think that the decision to TDD is very dependent on whether you are writing net new code, or refactoring, or having to deal with legacy code. JOËL: That definitely makes a difference. For me, when I'm refactoring in the purest sense, changing structure without changing behavior, in theory, I should not be writing tests for that because there should already be existing tests, and I'm not changing behaviors. So the test suite should prove that my changes did not change behavior. In practice, oftentimes, there is not the coverage that needs to be there. I don't know about you; I feel like I often don't trust the code enough, where I'm a little bit scared to do a refactor if there isn't test coverage. How about you? STEPHANIE: I've been running into that issue a lot on my current client project where I've been making an intentional effort to add test coverage before I make any changes because that forces me to really understand how things work because either I read a piece of code and I just can't tell at all. Or I learn later on that I thought I understood something based on the class or the method names, but it turns out that there was actually some nuance in there or side effects or what have you that belied my understanding [laughs] of what it was doing. And after a few times of that lack of trust that you talked about popping up, I was like, okay, I think, at least for me, the way that I can feel good about the work that I'm doing is to set myself up for success in that way. JOËL: Do you ever find that the code that you write in a test-driven approach tends to end up different than code that you might write with a test-after approach? STEPHANIE: Yeah, I think this can actually be answered at a few different levels but let me start with talking about how I like to practice TDD. If I'm given a user story, I usually try to work outside in. So I will write a feature or acceptance test and that involves testing how the user would interact with our application. At that point, I will usually go with the most naive implementation to get the test passing, and so it probably won't look pretty. In a recent case, I was adding a new parameter to a controller, and I just put everything in the controller to get the test green. [laughs] And then, at that point, is when I gave that code a second pass and looked for areas to extract where I could. JOËL: That refactor step and the red, green refactor cycle is really important. STEPHANIE: Yeah, absolutely. I think that is where I find TDD to be the most valuable from that higher-level perspective. And I know that there are different schools of thought on this. But that helps ensure that at least I have written the code to make the feature work the way that I was hoping. And I use TDD less for driving design decisions just because I like to have something to react to that is helpful for me rather than having a blank slate of, okay, let me write a test with an idea about how an object's interface will look. And so that's what works for me. So I do think it's kind of a mix of like from an acceptance test level; I am at least writing code that I know works, but the shape of the code for me is less determined by how I test. JOËL: So when you're looking at code that you've written six months down the line, you generally can't tell the difference whether it was test-driven or written first and tested after. STEPHANIE: That sounds right. That's just how my process works. In fact, I think recently we, to go on a quick tangent, we talked about writing conference talks, and I think I even mentioned for me the process is looking at the thing and then revising. And I think that the design driving element of TDD that a lot of people like is a bit less effective for me personally. JOËL: Hmm. Would you say that TDD does not impact the shape of the code that you end up creating in response to the tests? Or when you're talking about design, are you mostly thinking in terms of the interface that you would have in the test itself, like, what arguments the constructor takes or things like that? STEPHANIE: I think I was talking more about the latter, the interface, the construction arguments. When I do test afterwards, I also will notice the way the setup of my test how that is feeling. And if it is feeling a bit unwieldy or is a bit complicated, that will cue me to maybe take another pass at the code itself. So that's actually one way that testing after can signal to me a way that I might want to change my code. JOËL: Okay, so you're getting some of those pressures that you get from testing, but you respond to them in a like second path? STEPHANIE: Yeah, I think so. I'm curious how you TDD and whether you notice changes in how your code looks. JOËL: I think there are a couple of things that TDD does in my workflow that are really nice. One is it keeps me focused in terms of getting the work done because you're just following from one failure to another. It also keeps me focused in terms of scope. It's really easy for my engineering brain to be like, oh, we could totally do this thing and all that, and it's like, no, that's not needed to solve the problem at hand. Because in TDD, you try the smallest solution that will solve your problem, and then you will refactor it to make it maybe nicer to work with. But you try not to add new behavior that's not required in order to pass the test, and that can be a really helpful forcing function for me. STEPHANIE: That's interesting because I was just thinking about how sometimes, at least with the outside-in approach that I was talking about, I will find that the scope of the ticket is too big as I make changes to get the desired quality of the code that I want. Like I mentioned, the naive implementation, like, sure, maybe everything is in a controller, but as soon as I'm starting to do that second pass, and I want to maybe change another class and to make it work for my needs, I will notice it start to sprawl a little bit. And that is usually a signal to me that, like, oh, maybe what I need first is just refactoring the objects that I'm hoping to use to get the desired implementation. And that ends up being a separate PR that I do first to then set myself up for making the change. JOËL: The classic make the change easy before you then go and make the easy change. STEPHANIE: Right. But that does mean that that initial feature test that I wrote won't ever be green. So I do have to kind of like back out of making that change and just be like, okay, today is not the day [laughs] that I'm going to get this feature working. JOËL: There are some times where I'm in a situation like that, and I will kind of recognize, oh, there's a refactor step that's happening right now as a sort of subtask. And so, I will make that refactor change that I need to and then commit only those files that were a part of that refactor and may be included as part of the PR with the feature change or maybe push it up and make it its own PR. But depending on what the refactor is, oftentimes, I can kind of do it sort of all more or less continuously but decide once I've done that refactor step, okay, commit time but only those files for the smaller set of changes, and then keep moving with that outside-in approach. One thing I have noticed about the style of code that I tend to produce when I TDD versus when I don't is how I will tend to decouple things. And so because coupled code is really annoying to test in isolation, TDD sort of forces me to do more dependency injection, passing objects to others. It will often force me or maybe not force me, but it gives me that wholesome pressure to maybe separate HTTP requests from more of the business logic in my code, which otherwise I might completely intermix because it's just so convenient. Even certain things like class methods, I might tend to overuse them or use them more if I'm not test driving than if I were. STEPHANIE: When you talk about coupling, I'm curious, do you end up mocking a lot in the tests that you are writing to drive your development? JOËL: No, but if I'm testing after, I probably will. Mocking, I think, is a sign of coupling generally. In tests where you're just passing objects to each other, generally, you can get away with passing in a test double or something, whereas if you're hard-coding dependencies, you often have to mock. STEPHANIE: Got it. That makes a lot more sense now. I think that does require a bit of thought upfront about what kinds of objects you might need and what they would provide for you in the thing that you're testing. JOËL: Yes. There's definitely a phase where let's say; I'm testing some kind of third-party integration; I'm just kind of trying to do it all in one object that has a mix of business logic and some HTTP request stuff. It gets really annoying as we're adding...maybe the first feature is okay. I use WebMock, and I stub out a request, and it's good. And then the second one, I feel like I'm kind of duplicating that. And then the third one, I've got to deal with retries. So now I've got to go back to the first one and add some two or three WebMocks because now we've got exponential backoff code that's happening here. And this new feature broke the old tests. And it just becomes this really annoying thing to do. And then I might start thinking, okay, how do I separate these two things? I have one place where I test the HTTP logic, the exponential backoff, the what to do if I get a 404 from the API. And then, separately, I can just have the business logic and test all of those branches there without having to touch any of the HTTP stuff. I think you could get there from a few different paths. So you could get there by sort of following a lot of classic design principles, things like SOLID, because they kind of converge on that general idea as well. You could even get there if you took more of a functional programming approach where you are really good at separating side-effectful code from, I'm going to use the term loosely here, pure functions. I've heard some people make the distinction between IO versus non-IO in code and how that affects the types of tests that you write for them. And separating those two is a thing that you might do, even if you weren't writing tests at all, if that's a design principle that you know to follow. STEPHANIE: Yeah, that's a great point. I was thinking, as you were talking about your approach for handling that potential feature with talking to a third party, that I've heard that particular task or problem in software development used as an example for a lot of those different techniques or strategies that you mentioned. And I suppose TDD really is just a tool, and it doesn't replace your experience or intuition. And earlier, when we were talking about times that you don't do TDD, I will have to say that if I am doing something that I've done many times before, I feel confident enough that I don't need to lean on that red, green refactor cycle. At that point, it's more muscle memory. And maybe I do forget a step along the way, but I have the experience to know how to debug that or to see the error and know exactly what it was that I did wrong. And in that case, I am tapping into something different than using TDD. JOËL: I think definitely, for a lot of things now, there are patterns that I have learned where even if I weren't TDDing, I might do a third-party integration using this pattern because I've done it via TDD enough to know that this is a structure that I find works very well in terms of the coupling of things. And then maybe if I want to fill in some tests afterwards, then I'll thank my past self that I'm using a pattern that plays nicely with that. One thing that I do notice happens sometimes is that when people add tests after the fact, they will add tests that are green but that don't necessarily fail if the code breaks. Have you ever seen that? STEPHANIE: I have seen that before. In fact, I just saw it recently where we had a false positive test. And I made a change expecting the test to fail, and it didn't, which is not great because the value that tests have are when they fail, you want to be alerted when something goes wrong. Just because they're green doesn't mean that everything works. It just means that they didn't detect a problem. And in this particular case, I don't know if the developer who wrote this test had TDDed or not. But I did notice that in the test, we were mocking a method, and that ended up being the cause of the false positive. JOËL: I'm always a little bit skeptical of mocks because I feel like I've seen so many either brittle tests or tests that will succeed all the time come out of mocks. I don't know if you've ever heard the term tautological test or a test that is a tautology. STEPHANIE: No, I haven't. What does that mean? JOËL: In its sort of most basic sense, it's a test that is always green no matter what the output is. Some people think of it more in terms of self-referential tests, like, oh, a thing equals itself, which, yes, it does, and those tend to be always green. But it's not always self-referential. It can be some other subtle ways. Typically this happens when mocking or specifically if you mock the system under test. It's very easy to write a test that is now going to always be green, no matter how the code changes. A fun fact about the word tautology is it comes from discrete math, which is the topic of my RailsConf talk. If you write out a truth table that shows all the possible inputs and whether or not something will be true or false, depending on what the inputs are, the output column is all true in a tautology, which tells you that no matter what the inputs are, you're going to get true out of that method or function or equation. And so, if this was a Boolean expression in Ruby, you could replace that by hardcoding true and get the same result. STEPHANIE: Yeah, that's what I was imagining, a function that just returns true. [laughs] JOËL: And that's effectively what you can accidentally write when you're creating a test that is a tautological test is one where you could have just replaced the entire thing with expect true to be true, and it would have the same effect. And, like you said, tests only have value when they fail. And a test that never fails has no value. So TDD has this red, green refactor cycle. I feel like you could probably come up with a cute slogan like that for a testing-after style. So maybe I guess you'd start off you write some code, then you write a test that theoretically passes for it. So you start green, but then you want to make sure you see that test fail, so you got to go red and then comment out the code or something. Then comment it back in to see that it goes back to green to make sure that not only does this test fail when the code is broken but also that bringing this test back is what makes it pass, which is an important distinction. So maybe it's a green, red, green, and then maybe refactor. Because one thing that I admired in the style that you were talking about earlier is that even when you test after, you include a refactor step. The test at the end is not the final step in your workflow. STEPHANIE: Yeah, that's a really good point. When you said green, red, green, I was thinking of a Christmas garland [laughs] or something like that. But yeah, I do think that stuff gets skipped sometimes. If you are testing after, you're backfilling tests for code you wrote, and at that point, you think you know how it will work, and so you're writing your tests kind of colored with that in mind. I like the injecting commenting something out or changing an input or something that you know should make the test fail, just so that you can confirm that you didn't just write a test that expects true to equal true or give you a false positive like that, then go back to green. And as you were saying that, it did make me think like, oh, well, that's like a whole extra step as opposed to TDD where we do just have red, green refactor. We don't have that extra step. But I think the effort is just like put in at a different point in time. JOËL: Agreed. It's important that you see the code fail and that you see it pass after the change. The order has changed a little bit, but those two kinds of core elements are present. Kind of by default, you have no choice when you're doing TDD. You have the ability to skip that if you're testing after, but ideally, you incorporate those in a robust test after workflow as well. STEPHANIE: Yeah. And I know I mentioned times when I've done something enough or used a pattern enough that maybe I'll just go ahead and implement it and then backfill with tests. And I also recognize that in those moments, I could have done something wrong, that there is some amount of wanting to check that the test failed. And I imagine there is some kind of balance to achieve there between the speed that you get by having that experience and knowing the direction you want to take things and applying a pattern that you've done a lot with being like, oh, we're all human, and sometimes we make mistakes. JOËL: In a situation where you feel like you're coding something that you've coded up 100 times before, you're very familiar with this. Do you find that a test after workflow is faster for you? STEPHANIE: Hmm, that's an interesting question. JOËL: Because I think that's often a motivation. It's like, I don't want to bother, like, I just have the idea. I know what to do. Let me just write that code and get it done. STEPHANIE: I think if I were introducing a new route or controller action or whatever, I don't need to go through the cycle of writing a test and it failing because I haven't added the action to the controller yet. It's like I know that that is the next logical step, and so maybe I might skip it there. But if I'm at the point where I'm working with business or domain logic, I think that's where is the value of test writing first because it's like, I passed the framework and passed my tools. And now, I'm working at working through the logic of the business problem itself. JOËL: So you're working in maybe slightly larger iterations of that red, green refactor cycle. STEPHANIE: Yeah, that's a good way to describe it. JOËL: I was recently working on a gem and tried to TDD it from scratch and went with micro iterations. And it was actually really fun, and there was a flow to it. And this is a greenfield side project. And it helped me stay focused. I think it did give me a decent design. I really enjoyed it. STEPHANIE: Nice. Was there something satisfying about seeing that green each time and kind of doing that bit of mechanical labor? And I can see how that can feel almost meditative. JOËL: Yes. And I think also because this was a problem that I didn't fully know how I was going to solve, TDD helped really focus me on solving sub-parts of that problem, things that I can hold in my head and solve in a minimalistic way and then iterate on. STEPHANIE: I like that a lot. You were using that technique, and that really helped for the task at hand, which was, in this case, a bit smaller in scope. I think the way you and I have been talking about TDD has been very realistic and very reasonable. And I'm curious what you think about people who kind of use it as the pinnacle of how you should write code. JOËL: I think that's really interesting because TDD is a really wonderful technique, and I wish more people used it. But it's kind of taken on a mystique of its own where if you do TDD or claim to do TDD 100% of the time, now, all of a sudden, you've put yourself on another level. And I think people even who choose for pragmatic reasons not to TDD all the time maybe feel a little bit of guilt or at least feel the need to explain themselves to other people to say, "Hey, I didn't TDD this here. Well, let me explain to you why that's okay, and I'm not a bad programmer." STEPHANIE: Yeah, I think we even alluded a little bit to that earlier in the show, and I could hear my hesitancy to be like, oh, I guess I'm going to say this and have all these people hear it. But I think that's a good point that it's okay for you not to do it 100% of the time. That doesn't make you any less of a programmer. Also, the way we've been talking about it also makes it sound like one of those things where it's like you do have to learn the rules before you can break them. And so there is value in learning it and doing it. And then you also, after having done it enough, know when you want to use it or when you don't. My advice for folks who haven't really done it before or don't quite see the value of it is just to try it and then decide for yourself. I think at the end of the day, we should all feel empowered to be able to decide how we work best. JOËL: It's also really valuable, I think, to maybe pair with someone who is really good at that and to get to see what their workflow is like. Oftentimes, there's almost a hump of getting into it where you are more productive without TDDing because you're not comfortable with the flow or with the techniques. And it takes a lot of expertise to get over that hump where maybe at the expert end of things, you are more productive with it. And on the less expert end, it just becomes a chore that takes up all of your time or ends up giving you results that aren't that great anyway. And so, how do you cross that chasm? STEPHANIE: Yeah, that's a really, really great point because, in some ways, when you first get started, it will feel slow. You are unlearning the ways that you have known to code before and trying to do it in a different way. And I really like your advice about trying to pair with someone who has expertise or has been practicing it for a long time. That was my first real introduction to it too. At this point, I had been a few years into my career and hadn't really tried it because it seemed very daunting, and seeing someone else verbalize their process and seeing their workflow was really helpful for me to get on board. JOËL: I think what I would like is for TDD to be a tool that is aspirational for a lot of people. If you're new to the technique and you've paired with somebody who's really good at it, and you see the flow that they have and be like, wow, that's really good. I would love to get that incorporated in the way that I work. Rather than a sort of measuring stick for how elite of a programmer you are. There's no sense in shaming people over the tools they use. STEPHANIE: Right. Because it should also be accessible, and if you make people feel bad about it, and then it's not accessible to folks. JOËL: On that note. Shall we wrap up? STEPHANIE: Yeah, let's wrap up. Show notes for this episode can be found at bikeshed.fm. JOËL: This show has been produced and edited by Mandy Moore. STEPHANIE: 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. It really helps other folks find the show. JOËL: If you have any feedback for this or any of our other episodes, you can reach us @_bikeshed, or you can reach me @joelquen on Twitter. STEPHANIE: Or reach both of us at hosts@bikeshed.fm via email. JOËL: Thanks so much for listening to The Bike Shed, and we'll see you next week. ALL: Byeeeeeee!!!!!! ANNOUNCER: This podcast is brought to you by thoughtbot, your expert strategy, design, development, and product management partner. We bring digital products from idea to success and teach you how because we care. Learn more at thoughtbot.com.Sponsored By:Airbrake: Deploy fearlessly and fix bugs faster with Airbrake Error & Performance Monitoring. Airbrake notifiers are available for all major programming languages and frameworks, and install in minutes, with an open-source SDK-based install and near-zero technical debt. Spend less time tracking down bugs and more time developing. Visit Frictionless error monitoring and performance insight for your app stack.Support The Bike Shed
undefined
Apr 18, 2023 • 32min

380: Remote Work Life

Joël has been working on his RailsConf talk about various aspects of discrete math useful in day-to-day work as a developer and going deep on some concepts from propositional logic and Boolean algebra, particularly DeMorgan's Laws, which explain how to negate a compound condition. Stephanie attended a meeting with a fun "Spicy Takes" topic. She gave a short talk on how frictionless technology may not be the best path forward and tried to argue in favor of more friction in our software. Together, they talk about ways they've made remote work work for them and things they'd like to try/do differently. This episode is brought to you by Airbrake. Visit Frictionless error monitoring and performance insight for your app stack. Taskmaster - Do Not Avoid Not Making the Bell Not Ring The Dark Side of Frictionless Technology Is Tech Too Easy to Use? How to Do Nothing by Jenny Odell Rubber duck Debugging Schedule Shutdown, Complete Bike Shed episode Transcript: STEPHANIE: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Stephanie Minn. JOËL: And I'm Joël Quenneville. And together, we're here to share a bit of what we've learned along the way. STEPHANIE: So, Joël, what's new in your world? JOËL: I've recently got accepted to speak at RailsConf. And I've been working on my talk about various aspects of discrete math that are useful in day-to-day work as a developer and going really deep on some concepts from propositional logic and Boolean algebra, particularly the DeMorgan's Laws, which explain how to negate a compound condition. So if condition one or condition two, if you want to negate that thing as a whole, you can't just negate both of the conditions individually. You will get a totally different result, and that's a really easy mistake to make. I don't always memorize exactly what to do. But I know enough in the back of my head when it comes up on a pull request to check it out and be like, oh, there's a negating of a compound condition here. Pay closer attention. There might be a bug. STEPHANIE: So are you saying that when you negate each condition individually, you get the opposite result that you want? JOËL: It's not opposite, just different. STEPHANIE: Just different, okay. JOËL: So De Morgan's Laws tell us that if you want to negate the compound condition as a whole, you negate the individual clauses but then also have to flip the sign in the middle. So if you're trying to negate condition one and condition two, it becomes not condition one or not condition two. STEPHANIE: I see. Wow, that's confusing because you'd think that there are just two outcomes, but really there are a lot more. JOËL: Yes. STEPHANIE: And that reminds me of when we've talked about on the show combinatorial explosions, which I know is a favorite topic of yours. JOËL: Combinatorics will definitely come up in the talk as well. It's sometimes hard to hold all the possibilities in your mind. And so I'm a big fan of truth tables to visualize what's happening and to be like, oh, when I make this thing negative, now all these things flipped into false when I want them to be true and vice versa. Okay, I've got a weird inverse going on here or something like that. STEPHANIE: I have a funny thing to share with you. Joël, have you ever heard of the show "Taskmaster"? JOËL: No, I'm not familiar with this. STEPHANIE: Okay, it's a British reality competition comedy show where the contestants are usually famous British actors or comedians. And they have to do just really insane, silly tasks. And usually, one of the more iconic ones is to eat as much watermelon as you can in a minute. But they're just presented with a whole watermelon without any tools or anything [chuckles] for cutting it up. And it's just very funny and very delightful. And one of the tasks that I watched recently was a situation where they had to follow these instructions, and the instructions were to do the opposite of the following statement: "You must under no circumstances not avoid not making the bell not ring." And they had a bell right in front of them. And so they had to figure out if they were supposed to ring the bell or not ring the bell based on those instructions and within a certain time limit. If they had the math skills that you were talking about, [chuckles] perhaps they would have been able to figure it out. JOËL: I would absolutely want to write that out as a more formal logic thing. Otherwise, it becomes...you just mess with your head. You get in almost a recursive space where like, wait, not not, does that cancel? Does it stay? And yeah, it gets really messy. STEPHANIE: Yeah, it was very funny to watch them try to figure that out on the spot. And I think there's a clip of it on YouTube that we can link [laughs] for our listeners. JOËL: That's amazing. What's new in your world? STEPHANIE: So last Friday...you and I are on the same team at thoughtbot called Boost, and every two weeks, we get together as a team, and we have a meeting where anyone can propose a topic. It's just a nice space for people to see each other and hang out. And one of our co-workers hosted that meeting and he chose the topic of spicy takes and asked for volunteers to sign up and give a quick couple of minutes lightning talk on the spicy take that they had. And it was so fun. We got some takes on how REST is not the best. We got some opposing opinions about Tailwind. And I ended up giving a short, little talk on how frictionless technology may not be the best path forward and was trying to argue in favor of a little more friction in our software. JOËL: What would friction look like in this scenario? STEPHANIE: I was really interested in exploring how by making our software so easy for users we eliminate some amount of attention and mindfulness into using technology. So I think for me friction would be presenting the user with more autonomy and choice rather than making decisions on their behalf. I don't totally know what that looks like, but I do know that things like one-click ordering or autoplay those things have made me bristle a little bit in certain contexts and wondering what other options do we have available to us to provide the features we want to provide to our users but maybe not in a way that is so convenient and easy to use that we lose that aspect of knowing what we're doing with our technology. JOËL: I feel like knowing you, you've probably read a couple of articles and some books on this topic. And if I wanted to dig more into this idea of a little bit more mindfulness or introducing a little bit of friction into my software world, where would you recommend I go to read? STEPHANIE: Yeah, that's a great question. When I was preparing the talk, I referenced a few articles that I'll link in the show notes, one from The Atlantic and one from The New York Times. And I liked them because one of them presented what I was getting at, the more philosophical approach of like, what does it mean for our attention to be? And what does it mean for our technology to be too easy? And the other one had more practical use cases for security and technology misinformation and abuse. So I liked that those two things complemented each other equally. And then I also would plug a book called "How to Do Nothing: Resisting the Attention Economy" by Jenny Odell. I read that book last year and really enjoyed it. And she talks a lot about just the current technology landscape and what we, as consumers and users, can do to reframe our relationship with it. And I think that book is for people who use technology in general. But as developers, I think we are in a unique position to extend that train of thought right into the things that we develop. JOËL: You know, a place where I do appreciate friction is in the physical world. If there weren't any friction, my chair would not stay put on the ground. My fingers would not press on the keyboard. So we need friction to be able to do our jobs. So you work from home; I work from home because thoughtbot is now fully remote. How has that been for you setting up a work environment in your home? STEPHANIE: So I've actually been working from home since 2019. So about a year before the pandemic, I had moved to Chicago and was still working for a company in New York. And so that was when I started working from home, and then have just been doing that ever since. So I think I have now really figured out a setup that works for me. I've been doing it for four years now, which is pretty wild to me when I think about it. It's interesting because I actually really enjoyed going into an office. And there are parts of that that I really miss. But I think I have just gotten used to it and have a setup that works well for me. JOËL: Are there any things that you like to do for your environment to help get yourself into maybe the zone a little bit more easily? STEPHANIE: Yeah. So my workspace is a separate room from the rest of my apartment, which is also really just one big room. [laughs] It's kind of like a loft-style situation, so I don't really have doors. But I am in what we call the sunroom, and it's actually kind of like an enclosed porch with a big window and lots of plants. And it's in the back of the apartment. And so whenever I'm in this space, it's because I'm working. And I think having that separation of home and work is really helpful. Because when I step into this space, I'm like, okay, now I'm at work, and I don't have as many distractions as I would if I were working in a different space like a bedroom or the living room. JOËL: I have to say whenever you're on a video call, the plants around you are iconic. STEPHANIE: Oh, thank you. Yeah, it's been a nice conversation starter. When I'm meeting a new person, they usually comment on the plants, and I can give them a little show and tell. And that's been really nice. JOËL: I feel like a lot of people who work from home have put a lot of work into creating fun backgrounds for their video calls. Maybe they're setting up a cool bookcase behind them or plants. People like to put something behind them that will make things interesting on a video call in a way that maybe we didn't need to when it was just a conference room and in an office. STEPHANIE: Yeah, absolutely. I was just on a meeting with someone who had a big pile of tiny rubber ducks. So he was also a developer and, I guess, had just amassed this very delightful rubber duck collection, and it was just in the background. And we got to joke about it for a little bit, and that was really fun. JOËL: Are these rubber ducks meant to be used during debugging sessions? STEPHANIE: Yeah, exactly. JOËL: So I'm in a somewhat different situation from you in that I don't have a separate room to set up a home office. I've resisted doing anything in my bedroom. Like you said, it's good to have that separation. So I work more in my kind of living room-dining room space. And something that I found is really valuable for me has been movement. So say I work an hour in one part of the room, and then I switch to a different place. And it's going to be maybe a different posture. So I'm working in a solid chair table for a while, and then maybe I switch to more of an easy chair situation. That I think has been really helpful for me ergonomically during the day is just making sure that I'm not always in the same position constantly all the time but actually incorporating change in movement throughout my day. STEPHANIE: I like that a lot. I actually do also end up sitting at my dining room table sometimes for a change of scenery. It's funny because there was a while when...when I'm at my office desk, I have a standing desk. And so usually if I'm in a meeting, I would be at my desk and people would see me standing. And I think someone at some point mentioned like, "Wow, you seem to stand all day." And I was like, "Oh, well, when I'm not in a meeting, that's when I'm sitting on the couch or a lounge chair or something." [laughs] I'm curious, though, because you are working in your dining living space if it's been harder to separate work and home life. JOËL: I think it was definitely an adjustment, but it's a thing that I learned to do. And I still try to keep some amount of separation, which is why I don't set up an office space in my room. But I've also gotten to the point where now that I work from home, I find myself leaving home much more frequently after the workday ends. I was surprised just how much social interaction you get just by default being in an office around people all the time. When you're at home all day, even if you're on calls, it's not the same. And so I've found myself more and more to stay in a healthy emotional, mental space, leaving the home in the evening to go do things with friends or with other people. And so even though I am an introvert who prior to working from home preferred to stay at home more evenings than not, I've started living almost more of what people would assume is an extrovert lifestyle where I'm out every evening. STEPHANIE: Wow, that's so interesting because I'm the opposite; where when I was commuting and going to an office, I found it much easier to stay out. I would just go to a bar or a restaurant after work. Whereas now it's a bit harder because I'm not already out and about in the world, and also I am in my comfy pants, and I'm just like, oh, I have to go out? I don't know if I'm up for that. [laughs] Though I also really...I think the downside is that I have been really missing some of that human contact. And there are weeks where I'm like, dang, I really didn't talk to people in the world very much. So it's actually been a bit of a bigger obstacle for me to find the energy to see people in the evenings after work. JOËL: It helps to make plans. STEPHANIE: Yeah, that's a good idea. JOËL: Or you can have people come to you. You mentioned you were doing that soup club. STEPHANIE: I did, yeah, back when the winter was first starting. I mentioned on the show that I was having people over for soup on Friday nights, and that was really great. That was nice because then I was like, okay, I have to sign off by 5:00 p.m. so I can start making the soup. [laughs] 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 cut your debugging time in half. So why do developers love Airbrake? 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 of 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 helps 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 to include 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. Head on over to airbrake.io/try/bikeshed to create your FREE developer account today! JOËL: So you mentioned that sometimes it's hard to leave the home because you're kind of in your comfy clothes, and you don't want to kind of get dressed to go out. Has working from home kind of changed the way you tend to dress? Do you ever do the thing where it's like, oh, I've got the formal top and then just sweats? STEPHANIE: Yeah. Like business on top and party in the bottom [laughter] or something like that is the phrase. My habits around getting ready in the morning have definitely changed; where I don't put as much energy or effort, or time into it as I did when I was working in an office. And that has been nice because I get that time back, and that is really valuable to me. Yeah, I'm also usually just in soft pants. [laughs] That has definitely been a very positive impact on my life. And I do try to make an effort to go out for coffee. And when I do that, I'm just like, yeah, how I go out is how I go out. I don't really mind. I'm very comfortable going out however I'm feeling that day. But I think getting the time back actually has been really important to me. JOËL: Hmm, I think for me, interestingly, that's become an interesting way to build a little bit of separation from personal life and work life. So I'm making a point to put on...I don't know how you describe it. I was going to say real pants, but it's not like sweats are not real pants. But yeah, I will put on the kind of thing that I would put on to go in the office. And for me, that's kind of a...it's a start to the day. It's a start to being more serious and transitioning to more of a work mindset. STEPHANIE: Yeah, absolutely. JOËL: As opposed to on the weekend, if I'm just hanging around in the same space, but I'm dressed differently, I don't feel like I'm in work mode. STEPHANIE: Yeah, yeah, that's fair. I've definitely noticed your fun sweaters that you wear in video calls and stuff. So I really appreciate that; yeah, you are just putting on clothes that make you feel like you're ready to dive into the work week. I'm really curious, do you find yourself being more productive working from home than you were working in an office? JOËL: I would say it's about even on average. There are probably days where more or less on one side or the other, but I would say it's similar. STEPHANIE: I think I'm actually much more focused at home. And I know that this is not true for everyone because I was chatting with a friend, and she was asking, like, "How do you stay focused at home?" She was telling me that she gets so distracted by all the things that she could be doing in her home life. And for me, because I really enjoyed the social aspect of being in an office, I found myself wandering into the kitchen not infrequently to go get some snacks, and oh, running into this person and having a little chat. And I think my presence also, I was available for other people to come to me and start a conversation or ask to go on a walk. And I think I actually really needed that external push to take breaks. Because now that I'm working from home by myself, I definitely just get into some rabbit holes, and it's tough for me to resurface. JOËL: Let me fix one more error, and then maybe the test will be green. Oh, that didn't fix it, but I'll bet one more would fix it. And keep doing that until it's like, oh, well, I'm going to push off my break for another 30 minutes, oh, another hour. And it's like, you know what? I'm just going to finish my day. STEPHANIE: That literally happens to me all the time. The lunchtime break is tough because I definitely will delay that by 15 minutes and then 30 minutes, and then oh no, it's like 2:00 p.m. Okay, let me just eat a snack, then. And then keep going until I finish whatever task, and then end up wishing that I had made a little more of an effort to take a real break. JOËL: Yeah, I was having a conversation recently with someone about how it's often easier to make space for other people than for yourself. So if somebody is like, "Hey, I want to take a break. Do you want to go take a walk?" You might be like, "Sure." Maybe I wasn't quite in a place where I wanted to take a break, but I'll make the time for you. Whereas when it's like, you know what? My body or my mind is telling me I need to take a break, but this test isn't green yet. So I'm going to almost deny myself here for the, I don't know, the good of the mission, whatever. It's not really a noble sacrifice. It ends up hurting you and the project in the longer run, but it's so much easier to do that. STEPHANIE: Wow. Okay, yeah, that really resonated with me because I find myself in situations where I don't think that I can take a break because I'm like, oh, I have all these red tests, and I need to get them in a place where I feel comfortable stepping away. But if someone asked me like, "Hey, I'm at your door. Let's go for a walk," I could just put it away and go for a walk and have a great time. And I would like to be able to do that for myself when I don't have someone prompting me. JOËL: There's something I really appreciated that someone who used to be at thoughtbot would do is this person would go for a walk every afternoon without fail and would drop a line in the Slack channel being like, "Hey, I'm stepping away for a walk." And, I mean, yeah, it's nice to know that, okay, this person's not reachable for the next 15 minutes or whatever. But that's not really, I think, the value that I got from it. It was more of seeing somebody else taking a break and it being a reminder for me too to be like, you know what? Maybe I should take a walk as well, like, it might be time for a break. STEPHANIE: Yeah, I like that a lot. I think it's kind of ironic that I have quote, unquote, "optimized" my setup so much that I don't get distracted that I miss out on the friction [laughs] (A little call back to earlier.) that I would like to, yeah, call more mindfulness to how I'm physically feeling, not even physically but also emotionally and intellectually and being prompted, like I said, externally because I am realizing now that I really need that. JOËL: And at least for us here in North America, it's now starting to be spring. And so I think sometimes winter can be its own barrier to be like, you know what? I should go and take a walk. I don't know if I want to put on all the layers and my boots and all of that and deal with the snow. Whereas now it's like, just walk out and there will be flowers and trees covered in blooms. And it's going to be amazing. STEPHANIE: Yeah, I'm really looking forward to that. I agree; I think when the weather is nice, that is definitely a bigger motivator for me because there's more to enjoy and more to look at. And I love being outside. When you do step away to take a break, what do you do in your home or outside your home? JOËL: So I'm a big fan of taking a walk. I live in a dense, walkable neighborhood, Downtown Boston. And so just walking around a few blocks is a great way to get a little bit of fresh air, just get some motion going because I've been sitting around for a long time. It's a lot of natural beauty as well. A lot of people have gardens, and there are a lot of trees planted along the roads. So it's just a really pleasant way to, in some ways, connect with a little bit of nature and be outside and reset. Do you find yourself when you're looking for a break gravitating outwards or inwards in your space? STEPHANIE: I like to make myself a snack, a cup of tea. Sometimes if I'm reading a good book, I'll get into the book for 20 minutes. And sometimes, if there's nothing to pick up, maybe I'll find myself on YouTube and watch a short little thing just to reset and have some fun. Sometimes I'll try to tackle some dishes. I think the other thing with working from home is that I now create more mess in my home. [laughs] I don't know if it's the same with you. But I, yeah, try to keep on top of that so that I don't have to do it later in the evening. JOËL: I think one of the things that's really nice about working from home is the ability to cook more because you're in that space. So I've found myself oftentimes more on my lunch break, maybe prepping some things for a stew or something that's going to braise, and then just having it sit on the stove all afternoon. And like I said, maybe a really quick break is just you get up, go check the pot on the stove, and you turn the heat down or stir it a little bit and then get back to work. STEPHANIE: Yeah, I like that a lot. I do that, too, with a pot of rice or beans or something like that. I also am definitely making my own food for lunch a lot more just because, being at home, you have your whole kitchen and fridge available to you, and I feel less pressure to get all that done the night before. JOËL: Right. I think I've been trying to incorporate a little bit more physicality to my breaks recently. And one thing that I've done for shorter breaks...if it is a longer break, it is nice to go out and take a walk. But for shorter breaks, I set up a pull-up bar, and I just try to go and do a set of pull-ups there. And I'm not great at it, so it's not like I'm there for 10 minutes doing 100 pull-ups. But it's a nice way to go from a very static mental mode to a quick break that just totally resets you into this active physical space. STEPHANIE: Yeah, I like that a lot because something like that requires your full attention and physical effort in that moment. So it's not like you can still really be thinking about work while you're in the middle of doing a pull-up, at least [laughs] that's my interpretation of [laughs] how you take those breaks. JOËL: I'm curious, are there any other kinds of lifestyle elements that you've changed or customized to help you have a better working-from-home experience? STEPHANIE: There was a past Bike Shed episode hosted by Steph Viccari and Chris Toomey, and I can't remember exactly what it was that they were talking about. It must have been working from home-related because Chris had mentioned a ritual that he had when he was finishing his workday where he would close his laptop and say, "Schedule shutdown complete." And I've been thinking about that a lot and trying to do a similar thing of just verbalizing, "I'm done with work now," to make it true. [chuckles] Otherwise, if I don't, I can find myself gravitating towards my laptop when I have a thought. Like, I have an idea like, oh, I just thought of a way to try to debug that test or whatever. And then I'll want to go back just really quickly to write it down on my work computer so it's there for me when I come back. But if I've said, "I am done with work today," that means I'm trying not to reopen the work laptop, and then I'll try to jot it down somewhere else. And that has been really helpful. JOËL: So, setting like an emotional boundary. STEPHANIE: Yeah, an emotional boundary that almost becomes physical in a way because when I was working in an office, I would never take my work stuff home with me, so I physically could not access it. And since I can't do that now, by verbalizing it, it's almost as if I've created a boundary in my head. JOËL: That's really powerful, the impact that you can have just by sort of verbalizing something. STEPHANIE: I will say that I also don't keep any work stuff on my personal devices and that was true even when I worked in an office, but I think it has actually been more helpful and important working remotely. It sounds like you've experimented with a lot of different ways to make remote working work for you. And I'm curious if there's anything else that you really want to change or anything that you would like to try or do differently. JOËL: I think an element that I've been experimenting with recently is actually working outside of the home, so something like going to the library or going to a coffee shop. Interestingly, I've tended to use those mostly for when I want to work on personal projects that are not work. So strangely enough, now I work in my home, and when I do things for myself that I previously would have maybe done in my home, now it's always at a coffee shop, at the library, something like that. So I still keep that separation, but it's inverted. STEPHANIE: Wow, that's really interesting. I also like to be in a more public space as well with my work. And just being surrounded by other people and busyness is very comforting for me. And it actually also helps with the rabbit hole because I think I am more present in my environment when I do have cues of people getting up around me or whatever. Though ironically, my wanting to be around other people does not really work well with meetings and collaborating and pairing with other people. [chuckles] And so when I have to do those things, even though I'm also socializing just in a different way, I usually have to be in a more quiet, private space. JOËL: Have you ever tried to maybe group your meetings on a particular day so that you have, let's say, an afternoon of uninterrupted time that you know you can just go to a coffee shop and be heads down and not have to take a call there? STEPHANIE: I haven't tried that. But I think that would be helpful because then it's kind of like the best of both worlds, right? Where I can say, "Hey, I can meet once I'm moved back into my private space," and also have that physical environment of being around other people. And I think I had previously thought just those things were mutually exclusive, but there are certainly ways that I'd love to try injecting that into my home-work setup. I'm really glad that we ended up talking about this because I think this will just be our future for a while. And it's always worth revisiting it and thinking about it and thinking if it's working for us or not. I'm really excited to try some of the new things that you mentioned. Like, we've been doing this for several years now, but there's always room for improvement and room to inject more fun and joy, and creativity in how we choose to do our work. JOËL: On that note. Shall we wrap up? STEPHANIE: Let's wrap up. Show notes for this episode can be found at bikeshed.fm. JOËL: This show has been produced and edited by Mandy Moore. STEPHANIE: 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. It really helps other folks find the show. JOËL: If you have any feedback for this or any of our other episodes, you can reach us @_bikeshed, or you can reach me @joelquen on Twitter. STEPHANIE: Or reach both of us at hosts@bikeshed.fm via email. JOËL: Thanks so much for listening to The Bike Shed, and we'll see you next week. ALL: Byeeeeeee!!!! ANNOUNCER: This podcast is brought to you by thoughtbot, your expert strategy, design, development, and product management partner. We bring digital products from idea to success and teach you how because we care. Learn more at thoughtbot.com.Sponsored By:Airbrake: Deploy fearlessly and fix bugs faster with Airbrake Error & Performance Monitoring. Airbrake notifiers are available for all major programming languages and frameworks, and install in minutes, with an open-source SDK-based install and near-zero technical debt. Spend less time tracking down bugs and more time developing. Visit Frictionless error monitoring and performance insight for your app stack.Support The Bike Shed
undefined
17 snips
Apr 11, 2023 • 42min

379: Feature Flags

Joël submitted a last-minute submission to RailsConf discreet math, which got picked up! 🎉 He'll be speaking at RailsConf 2023 in Atlanta at the end of April about why it's relevant to developers and all the different practical ways he uses it daily. Stephanie recommends headlamps for in-bed reading sessions and sets up the feature flags topic for today based on a project that must be released to the public in one go. This episode is brought to you by Airbrake. Visit Frictionless error monitoring and performance insight for your app stack. Joël's Railsconf talk Episode on Discrete Math Episode on the Fundamentals Strangler fig pattern Flipper gem Transcript: STEPHANIE: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Stephanie Minn. JOËL: And I'm Joël Quenneville. And together, we're here to share a bit of what we've learned along the way. STEPHANIE: So, Joël, what's new in your world? JOËL: So a few episodes ago, we had a guest, Sara Jackson, on and she was talking about some cool elements of discrete math and how those can be really practically useful to us as developers in our day-to-day work. I was really inspired by that conversation. And the day we recorded that, I think, was the last day that the RailsConf CFP was open. So I went and submitted a last-minute submission to RailsConf for this idea, and it got picked up. So I'm going to be speaking at RailsConf 2023 in Atlanta at the end of April about discrete math and why it's relevant to us as developers, and all the different practical ways that I use it on a daily basis. STEPHANIE: That's awesome. Congrats, Joël. I'm so excited for this talk. JOËL: Thanks. STEPHANIE: Was this an 11:59 p.m. submission? JOËL: Aaah, very close to that, yes. I don't recommend people to do this. But if inspiration hits you on the last day of the CFP, do it; go for it. I'd actually submitted two talk proposals. And I think maybe a little bit of the excitement in the energy for this last-minute one came through because that's the one that the committee picked. STEPHANIE: How did you know that you would want to turn this topic into a talk? JOËL: I think because I was excited to share about this to other people, and we'd kind of already done that on the show. But this is the sort of thing that's like, you know what? I'm kind of feeling a little bit of fire of this idea. I think more people should know about this. I think there's value in sharing this idea more broadly. What are some areas that I could do? I could maybe write a blog post. Oh, RailsConf, that's open until tonight. Let me put together a proposal because I'm excited about sharing this idea. STEPHANIE: Yeah, I think we chatted a little bit about discrete math as potentially a fundamental pillar of information or a skill set for developers back in our episode on just the fundamentals of what developers need to know. And I was just thinking as you were talking about it that that was an audio medium, but it's obviously kind of an academic topic. And so to have slides for it and almost make it kind of like a little mini-lecture but more fun [laughs] than sitting in a classroom, I think, could be a really cool application of this topic. JOËL: Yeah, I'm excited to take a very practical look at this. I've got 30 minutes to talk about it. I'm not going to give you the deep mathematical fundamentals. But if there are little bits of discrete math that I can show that are actually practically useful in a day-to-day situation, I think that would be incredibly valuable. So currently working on the talk, but the way I have it structured right now is very scenario-based. So we're going to look at some problems, look at just a tiny little bit of discrete math theory, and then see how that allows us to solve the underlying problem. STEPHANIE: Nice. I won't be attending RailsConf this year, but I really look forward to watching the video when it comes out. JOËL: Thank you. So, Stephanie, what's new in your world? STEPHANIE: So last night I was reading in bed, and I usually stay up a little bit later than my partner. And so he was going to bed, and at that point, I usually turn off the bedside table lamp and either move to the couch to keep reading or just go to bed as well. But I was really engrossed in my book, and I wanted to keep going. But I was so cozy in bed. I really didn't want to move to the couch because then you risk falling asleep on the couch, and nobody likes that. And so I was like, oh man, you know what I would really love? One of those book lights. And I got this really vivid memory of the clip-on ones I used to have as a kid that would clip onto the pages of my book and shine a light onto the page. And I was like, I feel like that technology must have gotten better [laughs] since I was a child. And I was like, okay, now I need to look up some doodad and buy a thing to help me solve this problem of reading in bed after hours. And I was scrolling through my phone for a little bit, but then I was like, well, I want to read right now, not after [chuckles] I've purchased this gadget. And it hit me that we have headlamps that we use for our camping trips and also just if we ever are stuck without electricity. And I grabbed one of those from the junk drawer, and I wore it to bed and was reading my book. And it was a pretty good experience. So I'm actually pretty happy that I didn't need to buy a new thing to solve this problem of mine. And yeah, it turns out that you can just use something that you have at home. JOËL: That's really cool. I feel like when I've used the headlamps before; normally, they're incredibly bright. Did you find that to be a problem for you? STEPHANIE: I was able to adjust the brightness on mine, so it was definitely on the lower end of the setting and, overall, just better than having the nightstand lamp on, which I think just totally brightens the room. And at least this was a more targeted area of light, and it's working so far. He didn't wake up or anything, so I would call that a success. And now I have it in my bedside drawer. And I think I look really silly, but that's okay. No one can see me anyway. [laughs] JOËL: That's kind of the whole point of it, right? STEPHANIE: Exactly. [laughs] So, aside from my bedtime routine, another thing that's new in my world is something project-related. So I wanted to bring this up to you and get your thoughts on the situation. So I want to talk about feature flags because I'm currently working on a pretty big project that has to be released to the public in one go. And so naturally, we reached for using feature flags to be able to release our work to production but not to make it accessible to users so that we could be working on this thing incrementally and not have a huge release where all of this code goes out. But as we've been building the feature, I am realizing that we are having to plug conditional code to check for this feature flag in a lot of different places. So, so far, we've been putting it in controllers. We've been putting it in a menu builder to show the user where they can navigate to. And then we've even been putting it inside of methods to change behavior based on whether the flag is on. And so that was kind of, I think, getting my spider senses a little bit tingling. And then recently, one of the bigger issues that our team had a discussion about was whether to include this conditional check for the flag in queries. So we are building on top of an existing model. But once the feature flag is on and customers are using it, the application will be able to create new records for that model. But they're of a different category with a different value for one of the attributes. And we end up clearing for this model in a lot of one-off places. And so once this thing is on, all of the records that are specific to this new feature will be included whenever we query for this model. And as we've been developing, it's been less of an issue because customers can't access the flow to create these new records. But someone brought up what if we release this, and it turns out that we have an issue and we want to turn it off; we want to roll it back? And at that point, those records will still have been created in the database and will then be included in those queries and what do we do then? And so we started getting into the weeds a little bit of, like, do we want to have some conditional query situation going on? We haven't quite landed on an answer, but things are getting a little hairy. And I am curious if this works. Any thoughts for you? JOËL: That's a really interesting problem to have. You mentioned having all of these conditionals kind of sprinkled everywhere for the feature flag kind of triggered your spidey senses a little bit. Do you have a sense a little bit of maybe why that feels wrong or maybe why you're feeling uncomfortable about this code? STEPHANIE: Yeah, I was thinking about it, and, in my opinion, the ideal world for feature flags would be you have the checks at the boundaries of your code or where a customer could interact with the application. And then you are able to, I guess, branch a little earlier so that they don't go down the flow at all where the changes are being made. And this seems to be a little bit of the opposite, where we end up having to check in a million different places because we aren't keeping that separation as explicit as I think it should be. JOËL: Hmm, so almost like it's not the feature flag that's the problem. The feature flag is just a symptom of tight coupling in the wider system. STEPHANIE: Yeah, that's definitely a smell that has emerged. But I also don't think that we have the luxury necessarily to decouple all of the places in the code as we are trying to add this new feature. Have you been in a situation like this before? JOËL: I think tight coupling, in general, is a thing I've seen in a lot of projects. I can't immediately think of a moment where it was highlighted by introducing a feature flag. Sometimes I think what can be tricky is if you have a feature that has a lot of cross-cutting concerns, then it's easy for that to kind of bleed into other things. There are a variety of techniques to try to, like you said, isolate the new code such that you don't need to conditionally branch on it everywhere. I wonder if there might be maybe a few important inflection points that you could introduce some sort of wrapper or push a conditional higher up the decision tree or something like that that might get 50%-80% of the way there and at least eliminate a lot of the pain. STEPHANIE: Yeah. I like the use of inflection points because I think that right now, our strategy has been everywhere as we are making changes, just putting it in as a guard when there's probably some degree of higher level thinking about, okay, we're now changing a bunch of internals of this class, but maybe the change that we're making is its own concept. And it could be a separate class, and that is when we choose to use that class like that as an inflection point. JOËL: I have this vague mental model in my mind of building a mechanical system and wanting to know where do I want it to be rigid and where do I want some sort of joints so that it can flex? And I don't want the entire system to be made out of joints because now it's a pile of spaghetti. It's important to be rigid in a lot of places. But in some places, I do need it to flex. And it's identifying what are those right places where it needs to bend to flex to different scenarios? And to me, that's a metaphor for when do we need abstractions, the ability to choose between different paths, the ability to maybe have some polymorphism? And when do we want to force everything to say, "No, all the code is going to behave in this one way?" STEPHANIE: Yeah, that's a great point. I am also kind of stuck on what you said earlier, where the feature is very cross-cutting, and I think that is true for this project at hand. And so that has been very challenging too. There's also a lack of trust that it will just work with the other parts that it's touching because we're actually extending something that was already a bit of a unique flow or a kind of a one-off situation. And it was built very particularly to support that one thing. And now here we are introducing something else for it to support and having to go in and change all of those individual places where we were making those one-off exceptions to now also be able to handle this new thing we're introducing. JOËL: I think, in many cases, I appreciate when people write code in that way and that they didn't try to abstract everything on that first difference. But now that I'm the one coming in doing the second one now, it's time to think, okay, clearly, we're trying to flex here. We probably need some sort of abstraction. Unfortunately, that means it does have to come into the time budget for this feature and say, look, we already have a special case here. Now we're going to add a second special case. We need to take the time to do a little bit of refactoring or a little bit of abstracting in order to make that work properly. STEPHANIE: Yeah, absolutely. I think the logic there originally was that, oh, we already have a special case for this thing. So it should be easy [laughs] to now add this other special case that's kind of based off of the original exception. And I actually think that worked against us a little bit because I'm mentioning we're introducing this new feature flag, and I'm also seeing remnants of that old feature flag that didn't get quite cleaned up as well, so just a lot more complexity in the different ways that the flow is going. JOËL: In some ways, you kind of see earlier failures with this exact same approach that you're trying to take. So it's a bit of a warning. STEPHANIE: Yeah. I want to avoid leaving those traces for future developers. There's definitely some degree of regret that I feel for all the times that I've introduced a feature flag and never cleaned [laughs] it up. So seeing just remnants of this same approach, like you mentioned, and wanting to do something differently to make sure that we aren't creating as much trouble for the next time around. JOËL: So you'd brought up cross-cutting concerns earlier. And I think some common situations for that is like, oh, we've got some code that changed in the model where we have to put conditions. But then we also have a parallel condition in the controller and a parallel condition in the view, and maybe even in the routing file, and it quickly becomes a mess. Sometimes you're able to sort of take all of those, and kind of put them in a different part of the app. So you might have a view file that is really complex and has all these conditionals. And maybe you kind of give up trying to make it all work in one file and say, you know what? For this special case, we're going to do it all in a separate view file. And maybe there's one top-level condition that says, if this thing is true, render the second view file; otherwise, render the first one. And now you've only got one condition instead of having it kind of sprinkled all over some other piece. STEPHANIE: Yeah, that actually is the approach we ended up taking for this project. And in this case, we have React on the front end. So we're rendering a completely different React component based on the flag. And that did solve a lot of the front-end-specific complexity. And still, I think we are seeing a lot of the coupling be an issue on the back end, which is interesting. 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 cut your debugging time in half. So why do developers love Airbrake? 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 of 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 helps 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 to include 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. Head on over to airbrake.io/try/bikeshed to create your FREE developer account today! JOËL: So you'd mentioned queries and how...it sounds like there's maybe an enum in the database that you're adding a new state to, but you want to exclude that new state from any existing queries. I almost wonder if this is a situation where you want to create a sort of no-op commit that could go out without the feature flag, and that would basically prevent all the existing queries from using this new enum. And maybe it introduces the new enum but behind something that blocks them from being used in the existing queries. Depending on how your queries are structured, maybe it's just in your main query; you have a where not extra line that excludes the values in that enum. If it's not nicely scoped, maybe you need some sort of default scope on the model to say, exclude anything that has this enum value. And now you can introduce that enum, and you can have all those records. And even if it's not behind a feature flag, everything will continue to work exactly as it does today, and that's your goal. And that is a fairly small scoped change. It's almost like a refactor in the classic sense of it, the make the change easy before you make the easy change. Although, in your case, it's maybe not that easy of a change. But then, after that, you can build on top of this with your work that might be behind a feature flag. STEPHANIE: Yeah, I like that approach a lot because that ensures that the existing behavior will continue to work as expected. And then that also is a good way to audit, I guess, all the places that we will need to consider when we are making the change. So we already have in mind all the places that things are touching, and it's not a surprise when we find out, oh, we missed this query, or whatever. I was also thinking about...I mentioned that we are querying one-off quite a bit with different filters. I was also thinking that maybe a query object could be a good use case here and wrapping existing business logic in a meaningful query. And then perhaps the new enum that we're introducing would have its own conceptual meaning. JOËL: When you talk about one-off queries, are these like custom queries built out directly in the view or in the controller? Or where are you seeing these one-off queries? STEPHANIE: Unfortunately, it's both the controller and in-service classes. [chuckles] JOËL: Okay. I was afraid you were going to say the view, which brings me back to my old PHP days because I definitely wrote queries in...I guess my entire app was basically the view at that time. I had just one PHP file, and HTML, SQL all went in there. The page submitted to itself. So there's a giant conditional that split the files like if POST versus if GET. STEPHANIE: Oof, that sounds pretty gnarly. And I feel like; in that case, you don't have the tools for the flexibility that you would have liked. JOËL: It turns out the frameworks are nice. It's a good thing to have. STEPHANIE: Good take. JOËL: I think going back to something we were talking earlier, we were talking about how to maybe incrementally ship parts of this, and the sort of no-op approach that I was talking about, I'm a huge fan of. I think it's similar to what's sometimes called the strangler fig pattern that allows you to sort of incrementally sometimes change over from one system to another. But I think a lot of the ideas from that pattern can apply to adding new behavior where you might want to start by introducing some sort of no-op system and then maybe conditionally branching within that and keeping things separate to then evolving to your final piece. And there was an article that I am a huge fan of by Adrianna Chang on the Shopify Engineering blog about this pattern. We'll link it in the show notes. But for those who are interested in digging into this pattern more, kind of wondering how it applies, I recommend reading this article. STEPHANIE: I'm really glad you mentioned that because the other thing I was thinking about that feels like such a trap with feature flags is that it kind of conflates two different things, at least in the way that I've seen it used on different teams where we are using it to hide work that we are incrementally shipping. And then it's also used as a deployment strategy. So maybe you might turn it on for X percent of customers, or you might just turn it on to 100% for everyone. But if something goes wrong, you can quickly turn it off. And for some reason, I'm thinking that those two things...maybe I'm not sure that one tool is the best thing for both of those concerns. JOËL: Yes. Sometimes feature flags are used to actually gate a feature. I tend to bucket the turning it on and turning it off as the same thing as turning it on for 50% of people. But sometimes, it's really used more for a kind of CI/CD process where you want everything that gets merged from a PR to immediately go out to the production server. But you might not be ready to have that particular feature get turned on just yet. But a lot of those things might get turned on pretty quickly, and then the feature flag might get removed fairly quickly as well. So they're not really features in the sense of product people are going to want to be like, okay, now we're ready to turn on this new feature for the big release day. They're very logistical. And they're really almost like another way to do version control but at the release level rather than via Git. Does that sound like a reasonable distinction to you, or is that different than what you're talking about? STEPHANIE: That's really interesting. I think you may have found a third [laughs] way that people use them because I have definitely seen that as well. I think for me, what you said about if you turn it on to 50% of people, that is essentially turning it on to 100% in the sense that if you are trying to mitigate risk and things go wrong, things are still wrong, and you have to figure out what to do then. And I'm glad you mentioned the strangler fig pattern because I think people on teams that I've been on at least have been using feature flags as a crutch for managing risk when they deploy and thinking that, oh, if something goes wrong, then at least we have this mechanism to stop the bleeding. Whereas if you were making sure that the code you are writing is in production but doesn't change the existing behavior because of the way you wrote it, that is a lot more resilient, I think, than just opening the gates and hoping for the best and having a safety net of turning it off. JOËL: I see what you're saying now. And I think you've hit on a really important thing. So when you're trying to build software incrementally, there's a bit of an anti-pattern where you go off on a long-running branch, and you build, and you build, and you build. And hopefully, you're keeping it in sync with the main branch, but maybe you're not. And at some point, there's a big merge, and it's scary and potentially dangerous. And then there's a release, and hopefully, everything goes well. And we generally agree that that style of development generally does not lead to the best outcomes. So we try to work incrementally. We try to merge back into the main branch as much as possible. But I think that many developers are kind of wired to think in that long-running branch approach. And so they kind of try to recreate it with feature flags. So it's like, oh yeah, technically, we're merging, like, we're on small branches, and we're merging back into main, but it's all gated behind this one feature flag, and then it's going to be a big bang release. And it may or may not break, and it's going to be scary. And it's going to be a lot of risk that we're trying to mitigate. But the more we're piling on behind this feature flag, the higher the risk becomes. So it ends up being kind of a long-running branch. STEPHANIE: Yeah, that's a really great connection. I think that is where some of the fear is coming from too. And we are thinking that, oh, we're relatively safe because we have this mechanism that at least we can react with very quickly rather than having to revert a change or something like that. But the way that we're using it on this project...and in general, I've seen other people do it this way. And that could be why this technique has proliferated a little bit. It is a bit concerning; I think, because it still is just okay; we're just going to release it and then hope for the best. JOËL: I think there are valid use cases for that kind of strategy, but I would like to see those come from a product perspective rather than a development perspective. So maybe as a business strategy, we decide that this series of features, we want them all to kind of show up at the same time. They're part of a larger package of changes that we want to release all at once. Now you're getting into product strategy. Oftentimes, it's better to release small things incrementally. But there are some times where you want to release a big thing that has multiple kind of sub-features all at once, and I think that's totally valid. Where I'm less comfortable with it is when it's coming from the developer side because it's more about, oh, we just want to protect all of these things and kind of release a massive change all at once. And that, I think, ideally is better managed by truly working incrementally with something like a strangler fig pattern. I think that manages to mitigate the risks while also avoiding some of the messiness that comes with the feature flag here. STEPHANIE: Yeah, I think the other way of working that I've noticed with feature flags gating larger features is having a QA team member manually going through all of the features behind the feature flag to make sure things are working as expected. But that is still different from real users using it. I think that is another form of reassurance that folks think we're getting with this strategy. But I think it's still limited in covering a production use case which is ultimately giving you the truest [laughs] reassurance that your application is working as expected for the people that are using it. JOËL: I think I'm fine with having a QA person turn a feature flag on on a staging server, try something out as part of the workflow as long as these features are generally kept small. And then we ship it, and we turn the feature flag on, and then maybe we remove it as part of the process later on. Where I get less comfortable is where you've got a team of people working for weeks behind a feature flag. And, again, I do understand that for product reasons, there are times where that's a valid thing, where there's a big set of changes that you don't want your customers to see. But if it's for developer reasons because we're concerned about coupling or we're concerned that something could break, then I get really uncomfortable with saying, okay, we're going to have a team of people working for several weeks behind a feature flag, and then we're going to need multiple QA people to test a ton of work that's all behind a feature flag. Now you're just kind of creating new risk while also trying to mitigate it and it kind of turns into a sort of weird zero-sum game. STEPHANIE: Yeah, I know what you mean. I think in those cases, too, you're only testing what you know. So you're only testing the edge cases and the different flows that you know about. And inevitably, customers are probably using the app [chuckles] in ways that are completely unexpected, and no amount of testing all the different cases that you think are comprehensive will account for the way that it's used by customers. JOËL: To be fair, I think a good QA person will catch a lot of weird edge cases. They know a lot of the ways that customers will try weird things. They often are really good at not being boxed into product or development's ideas of how the product should be used rather than how it can be used. That being said, real customers are a surprising and creative bunch, and they will absolutely do the unexpected. STEPHANIE: Yeah, that's a great point. I'm glad you mentioned that. JOËL: We've talked about a few different ways where maybe you're uncertain or uncomfortable about feature flags. Are there ways of using feature flags that you are 100% in favor of or that you're excited about, like, yes, feature flags are a great use in this scenario? STEPHANIE: First of all, I think one of the most delightful times that I've had with a feature flag is when we use the Flipper gem. At a previous company, I remember really enjoying that one over...I've seen more hand-rolled implementations of feature flags, but I do want to give that gem a little shout-out. I think they are most effective when you do have a new page or something that has a very clear boundary, and you want to make sure that no one can go to the URL and see the new features that way, at least that's like the most clear cut use case for them. And then, ideally, you have implemented everything. You have tested behind the feature flag. And then, the day of the release, we can just turn that thing on, and all is well. I hate to be that person to say simpler is better, but sometimes I think that is true. What about you? Do you have any instances where you felt a feature flag was really effective? JOËL: I appreciate feature flags in more traditional CD, continuous deployment-style systems, particularly once the team grows a little bit and you've got a lot of PRs going out. And you want to be able to maybe undo things without necessarily having to revert and redeploy code, or if you've got things where you don't want to have Git be the thing that's gating when customers get to see features. So maybe a person implements it on a particular day, but you don't want customers to see it until next week because that's when your marketing has said, if we're going to turn it on, do you really want that to sit in a PR for a week and then hit the merge button and that's going to be what ships it out to people? Like, that gets kind of clunky. I think you can get away with it when you're a small, fast-moving team. It doesn't work once you start scaling a little bit. And so I find that at that point, starting to introduce feature flags has been really helpful on teams I've worked on. And I've been part of that transition where we're feeling a lot of pain, and then we introduce feature flags and can move to more of a continuous deployment where you get your code reviewed; you merge it; it's good. And then it goes out, and at some point, we turn the feature on, and then maybe at some point, we come back and clean up the feature flag and say this is now permanently in. I've seen good success with that style of approach. STEPHANIE: Yeah, you bring up a good point about incorporating it into the CI/CD process. And that also makes me think, ideally, we would have some information as developers about how long we want this thing to be in that feature flag state because if you know, then you can claim ownership over it and make sure that it gets cleaned up. I think right now, what I've seen is we are using it in the development process, but then we're not necessarily communicating with product about how long it's supposed to stay this way and what are we supposed to do with it afterwards. A lot of that gets lost. JOËL: It is interesting that I think some feature flags are mainly product-focused, and then others are entirely developer-focused. In fact, maybe the product team doesn't even need to know that this is internally gated by a feature flag because it's more about internally how you manage the release process and continuous deployment. The fact that maybe physically pushing the code onto the server and having a feature be available to users is not exactly the same action might be a distinction that doesn't really matter to your product team. And if that's not a thing that they care about toggling for users, then that can be something that just stays internal to the dev team. And you say, okay, we're using that to manage risk or to allow us to merge code earlier, whatever the thing is, but then we clean them up ourselves, and nobody needs to know. Whereas some things are very much product-focused, and we say, okay, the product team wants this to be a thing they can turn on and off, or they want to run an experiment, and then they very much need to be in the know. And I think you were alluding to some feature flags that might be kind of halfway in between that. They're not clear-cut product ones, but they're not entirely just mechanical deployment flags. They kind of sit in that weird zone between the two. STEPHANIE: Yeah, absolutely. I think maybe there is a case to be made about this distinction, and people can then better use this tool and apply it to the actual problem that they're having. JOËL: I think it's helped me get a better feel for them by having a bit of that distinction in my mind, thinking of flags as these are either sort of mechanical developer flags, or these are products flags. And maybe there's a richer nomenclature that can be developed. But I think at least having that distinction has helped me think about these in a more structured fashion. STEPHANIE: Yeah, and even communicating that in the name of the flag, too, I think could be really valuable for other developers who come across it in the codebase. As for cleaning them up, I was just thinking about how it can be such a pain to then unwind the logic of the feature flag [chuckles] when you're removing them to figure out, okay, now that this thing is done, how do we actually want it to work? I think sometimes that ends up being a bit of a pain point and is what leaves them hanging around. JOËL: And then it's not obvious which of the two branches in a conditional should be kept. STEPHANIE: Right. And maybe that also depends on that distinction where you're talking about between a product release flag and a more internal development tool. JOËL: Yeah, I could definitely see a more product-focused one where it's possible that you might want to keep both and say, no, this is a thing that we want to be able to toggle on. In general, for the foreseeable future, don't remove this flag. I want to control it from a dashboard. Maybe we want this to become maybe not gated by a feature flag in the traditional sense, but we want to tie it to a subscription level on a user's profile. So keep all the conditionals in place, but now just branch off the user's subscription status rather than a global flag. STEPHANIE: Yeah, it turns out that feature flags can be really complicated. It's not just kind of a binary is it on or off [laughs] situation. It almost makes me wonder if some metadata would be helpful with flags to signal more information about them in the codebase. Like, are they a part of your application domain or not? It kind of gets a little fuzzy. JOËL: Definitely. Something could be experimental; something could be like we said, mechanical; something could be deeply integrated into the vision of the product where you know that you're going to want to branch in the future here for different types of customers. I've even been on projects that were multi-tenant, where we had just standard feature flagging setup, but different tenants would have different sets of flags turned on. So they were global configuration for their instance of the app, but each instance had their own unique config of flags turned on and off. STEPHANIE: That's really interesting because, in some ways, flags are a bit of a configuration. But then, when you are combining a lot of different flags to configure something, then maybe that is better done with a different approach. JOËL: I like doing that kind of thing with flags rather than configuration because then it can be done via an admin dashboard rather than having to make changes to a YAML or JSON and having to commit it. And in this particular projects case, it was really nice because it meant that we could sort of, again, find those flex points and say, okay, we know that some clients want things to behave in two or three different ways in this one particular place. We'll gate that behind a flag, and then you can enable the variant that you want for each client. And now the customer service reps can manage that, and not the dev team. STEPHANIE: Got it. Yeah, that is pretty cool. JOËL: So, in a way, feature flags can be a great way to empower other departments within the business instead of kind of centralizing control within the dev team. STEPHANIE: Yeah. I suppose you just provided another use case for them. [laughs] JOËL: I feel like there are probably some really interesting elements to dig into around the interaction between product design and the actual development of things and teams that are doing either business development or customer support. Or maybe just some kind of rep for a big client is sort of where a lot of the power to actually execute things is. That is not this episode today, but I think that could be a great follow-up episode to do sometime. STEPHANIE: Yeah, that's very interesting. I would love to talk about that in the future. JOËL: The short version is I'm a fan of empowering other people. STEPHANIE: There you have it, folks. [laughs] You heard it here first. Joël is a fan of empowering other people. On that note, shall we wrap up? JOËL: Let's wrap up. STEPHANIE: Show notes for this episode can be found at bikeshed.fm. JOËL: This show has been produced and edited by Mandy Moore. STEPHANIE: 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. It really helps other folks find the show. JOËL: If you have any feedback for this or any of our other episodes, you can reach us @_bikeshed, or you can reach me @joelquen on Twitter. STEPHANIE: Or reach both of us at hosts@bikeshed.fm via email. JOËL: Thanks so much for listening to The Bike Shed, and we'll see you next week. ALL: Byeeeeeee!!!!!! ANNOUNCER: This podcast is brought to you by thoughtbot, your expert strategy, design, development, and product management partner. We bring digital products from idea to success and teach you how because we care. Learn more at thoughtbot.com.Sponsored By:Airbrake: Deploy fearlessly and fix bugs faster with Airbrake Error & Performance Monitoring. Airbrake notifiers are available for all major programming languages and frameworks, and install in minutes, with an open-source SDK-based install and near-zero technical debt. Spend less time tracking down bugs and more time developing. Visit Frictionless error monitoring and performance insight for your app stack.Support The Bike Shed

The AI-powered Podcast Player

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