On The Bike Shed, hosts Joël Quenneville and Stephanie Minn discuss development experiences and challenges at thoughtbot with Ruby, Rails, JavaScript, and whatever else is drawing their attention, admiration, or ire this week.
Joël was selected to speak at RubyConf in San Diego! After spending a month testing out living in Upstate New York, Stephanie is back in Chicago.
Stephanie reflects on a recent experience where she had to provide an estimate for a project, even though she didn't have enough information to do so accurately. In this episode, Stephanie and Joël explore the challenges of providing estimates, the importance of acknowledging uncertainty, and the need for clear communication and transparency when dealing with project timelines and scope.
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: Big piece of news in my world: I recently got accepted to speak at RubyConf in San Diego next month in November. I'm really excited. I'm going to be talking about the concept of time and how that's actually multiple different things and the types of interactions that do and do not make sense when working with time.
STEPHANIE: Yay. That's so exciting. Congratulations. I am very excited about this topic. I'm wondering, is this something that you've been thinking about doing for a while now, or was it just an idea that was sparked recently?
JOËL: It's definitely a topic I've been thinking about for a long time.
STEPHANIE: Time? [laughs]
JOËL: Haha.
STEPHANIE: Sorry, that was an easy one [laughs].
JOËL: The idea that we often use the English word time to refer to a bunch of, like, fundamentally different quantities and that, oftentimes, that can sort of blur into one another. So, the idea that a particular point in time might be different from a duration, might be different from a time of day, might be different to various other quantities that we refer to generically as time is something that's been in the back of my mind for quite a while. But I think turning that into a conference talk was a more recent idea.
STEPHANIE: Yeah, I'm curious, I guess, like, what was it that made you feel like, oh, like, this would be beneficial for other people? Did everything just come together, and you're like, oh, I finally have figured out time [laughs]; now I have this very clear mental model of it that I want to share with the world?
JOËL: I think it was sparked by a conversation I had with another member of the thoughtbot team. And it was just one of those where it's like, hey, I just had this really interesting conversation pulling on this idea that's been in the back of my mind for years. You know, it's conference season, and why not make that into a talk proposal?
As often, you know, the best talk proposals are, at least for me, I don't always think ahead of time, oh, this would be a great topic. But then, all of a sudden, it comes up in a conversation with a colleague or a client, or it becomes really relevant in some work that I'm doing. It happens to be conference season, and like, oh, that's something I want to talk about now.
STEPHANIE: Yeah, I like that a lot. I was just thinking about something I read recently. It was about creativity and art and how long a piece of work takes. And someone basically said it really just takes your whole life sometimes, right? It's like all of your experiences accumulated together that becomes whatever the body of work is. Like, all of that time spent maybe turning the idea in your head or just kind of, like, sitting with it or having those conversations, all the bugs you've probably encountered [laughs] involving date times, and all of that coalescing into something you want to create.
JOËL: And you build this sort of big web of ideas, not all that makes sense to talk about in a conference talk. So, one of the classic sources of bugs when dealing with time are time zone and daylight savings. I've chosen not to include those as part of this talk. I think other people have talked about them. I think it's less interesting or less connected to the core idea that I have that, like, there are different types of time. Let's dig into what that means for us. So, I purposefully left that out. But there's definitely a lot that could be said for those.
STEPHANIE: Awesome. Well, I really look forward to watching your talk when it is released to the public.
JOËL: So, our listeners won't be able to tell, but we're on a video call right now. And I can see from your background that you are back at home in Chicago. It's been a few weeks since we've recorded together. And, in the last episode we did, you were trying out living somewhere in Upstate New York. How was that experience? And what has the transition back to Chicago been for you?
STEPHANIE: Yeah, thanks for asking. I was in Upstate New York for the whole month of September. And then I took the last two weeks off of work to, you know, just really enjoy being there and make sure I got to do everything that I wanted to do out there before I came home to, you know, figure out, like, is this a place where I want to move? And yeah, this is my first, like, real full week back at work, back at home.
And I have to say it's kind of bittersweet. I think we really enjoyed our time out there, my partner and I. And coming back home, especially, you know, when you're in a stage of life where you're wanting to make a change, it can be a little tough to be like, uh, okay, like, now I have to go back [laughs] to what my life was like before.
But we've been very intentional about trying to bring back some of the things that we enjoyed being out there, like, back into just our regular day-to-day lives. So, over the weekend, we were making sure that we wanted to spend some time in nature because that's something that we were able to do a lot of during our time in New York. And, yeah, I think just bringing a bit of that, like, vacation energy into day-to-day life so the grind of kind of work doesn't become too much.
JOËL: Anything in particular that you've tried to bring back from that experience to your daily life in Chicago?
STEPHANIE: Yeah. I think, you know, when you're in a new place, everything is very exciting and, like, novel. Before work or, like, during my breaks, I would go out into the world and take a little walk and, like, look at the houses on the street that I was staying at. Or there's just a sense of wonder, I suppose, where everywhere you look, you're like, oh, like, this is all new. And I felt very, like, present when I was doing that.
And over time, when you've been somewhere for a long time, you lose a little bit of that sense of, like, willingness to be open to new things, or just, like, yeah, that sense of like, oh, like, curiosity, because you feel like you know somewhere and, like, you kind of start to expect oh, like, this street will be exactly like how I've walked a million times [laughs].
But trying to look around a little more, right? Like, be a little aware and be like, oh, like, Halloween is coming around the corner. And so, enjoying that as, like, the thing that I notice around me, even if I am still on the same block, you know, in my same neighborhood, and, yeah, wanting to really appreciate, like, my time here before we leave. Like, I don't want to just spend it kind of waiting for the next thing to happen. Because I'm sure there will also be a time where I miss [laughs] Chicago here once we do decide to move.
JOËL: I don't know about you, but I feel like a sense of change, even if it is cyclical, is really helpful for me to kind of maintain a little bit of that wonder, even though I've lived in one place for a decade. So, I live in New England in the Northeast U.S. We have pretty marked seasons that change. And so, seeing that happen, you know, kind of a warm summer, and now we're transitioning into fall, and the weather is getting colder. The trees are turning all these colors.
So, there's always kind of within, like, a few weeks or a few months something to look forward to, something that's changing. Life never feels stagnant, even though it is cyclical. And I don't know if that's been a similar experience for you.
STEPHANIE: Yeah, I like that a lot because I think one of the issues around feeling kind of stuck here in Chicago was that things were starting to feel stagnant, right? Like, we're wanting to make a big change in our life. That's still on the table, and that's still our plan. But noticing change, even when you think like, ugh, like, this again? [laughs] I think that could really shift your perspective a little bit or at least change how you feel about being somewhere. And that's definitely what I'm trying to do, kind of even when I am in a place of, like, waiting to figure out what the next step is.
Speaking of change, I had a recent lesson learned or, I suppose, a story to share with you about a new insight or perspective I had about how I show up at work that I'd like to share.
JOËL: What is this new perspective?
STEPHANIE: Well, I guess, [chuckles], first of all, I'm curious to get your reaction on this. Have you ever heard anyone tell you estimates are lies?
JOËL: Yes, a lot. It's maybe cynical, but there are a lot of cynics in our industry.
STEPHANIE: That's true. Part of this story is me giving an estimate that was a lie. So, in some ways, there is a grain of truth to it [laughs]. But I wanted to share with you this experience I had a few weeks ago where I was in kind of a like, project status update meeting. And I was coming to this meeting for the first time actually. And so, it was with a group of people who I hadn't really met before. It was kind of a large meeting. So, there were a handful of people that I wasn't super familiar with. And I was coming in to share with this bigger group, like, how the work I had been doing was going.
And during that time, we had gotten some new information that was kind of making us reassess a few things about the work, trying to figure out, like, where to go next and how to meet our ultimate goal for delivering this feature. With that new information in mind, one of the project managers was asking me how long I thought it might take. And I did not have enough information to feel particularly confident about an answer, you know, I just didn't know.
And I mentioned that this was kind of my first time in this meeting. There were a lot of people I didn't know, including the person who was asking the question. And they were saying, "Oh, well, you can just guess or, like, you know, it doesn't have to be perfect. But could you give us a date?" And I felt really hard-pressed to give them an answer in that moment because, you know, I kind of was stalling a little bit. And there was still this, like, air of expectancy.
I eventually, I have to say, I made something up [laughs]. I was like, "Well, I don't know, like, three weeks," you know, just really pulling it out of thin air. And, you know, that's what they put down on the spreadsheet, and then they moved on [laughs] to the next item. And then, I sat there in the rest of the meeting.
And afterwards, I felt really bad. I, like, really regretted it, I think, because I knew that the answer I gave was mostly BS, right? Like, I can't even say how I came up with that. Just that I, like, wanted to maybe give us some extra time, in case the task ends up being complicated, or, you know, there are all these unknowns. But yeah, it really didn't feel good.
JOËL: I'm curious why that felt bad. Was it the uncertainty around that number or the fact that the number maybe you felt like you'd given, like, a ridiculously large number? Typically, I feel like when estimates are for a story, it's, like, in the order of a few days, not a few weeks. Or is it something else, the fact that you felt like you made it up?
STEPHANIE: I think both, where it was such a big task. The larger and higher level the task is, the harder it is to come up with an answer, let alone an accurate one. But it was knowing that, like, I didn't have the information. And even though I was doing as they asked of me [chuckles], it was almost like I lost a little bit of my own integrity, right? In terms of kind of based on my experience doing software development, like, I know when I don't know, and I wasn't able to say it. At least in that moment, didn't feel comfortable saying it.
JOËL: Because they're not taking no for an answer.
STEPHANIE: Yeah, yeah, or at least that was my interpretation of the conversation. But the insight or the learning that I took away from it was that I actually don't want to feel that way again [laughs], that I don't want to give a lie as an estimate because it didn't feel good for me. And the experience that I have knowing that I don't have an answer now, but there are, like, ways to get the answer, right?
What I wish I had said in that meeting was that I didn't know, but I could find out, or, like, I would let them know as soon as I did have more information. Or, like, here is the information that I do need to come up with something that is more useful to them, honestly, and could make it, like, a win for all of us. But yeah, I've been reflecting on [chuckles] that a lot. Because, in a sense, like, I really needed to trust myself and, like, trust my gut to have been able to do my best work.
JOËL: I wonder if there's maybe also a sense in which, you know, generally, you're a very kind of earnest person. And maybe by giving a ridiculous number there just to, like, check a box, maybe felt like you gave way to a certain level of cynicism that wasn't, like, true to who you are as a person.
STEPHANIE: Yeah, yeah, that feels real [laughs].
JOËL: Have you ever done estimation sessions where you put error bars on your number? So, you say, hey, this is my estimate, but plus or minus. And, like, the more uncertainty there is around a number, the larger those plus or minus values are to the point where I could imagine something as ridiculous as like, oh, this is going to take three weeks, plus or minus three weeks.
STEPHANIE: I like that. That's funny. No, I have not ever done that before or even heard of that. That is a really interesting technique because that seems just more real to me, where, again, people have different opinions about estimation and how effective or useful it is. But for organizations where, like, it is somewhat valuable, or it is just part of the process, I like the idea of at least acknowledging the uncertainty or the ambiguity or, like, the level of confidence, right? That seems like an important piece of context to that information.
JOËL: And that can probably lead to some really interesting conversations as well because just getting a big number by itself, you might have a pretty high certainty. I mean, three weeks is big enough that you might say, okay, there's definitely going to be some fuzziness around that. But getting a sense of the certainty can, in certain contexts, I find, drive really interesting conversations about why things are uncertain.
And then, that can lead to some really good conversations around scoping about, okay, so we have this larger story. What are the elements of it that are uncertain that you might even talk in terms of risk? What are the risky elements of this story or maybe even a project? And how do we de-risk those? Is there a way that we could remove maybe a small part of the story and then, all of a sudden, those error bars of plus or minus three weeks drop down to plus or minus three days? Because that might be possible by having that conversation.
STEPHANIE: Yeah, I like what you said about scope because the way that it was presented as this really big chunk of work that was very critical to this deadline, there was no room to do scope, right? Because we weren't even talking about what makes up this feature task. We hadn't really broken it down.
In some ways, I think it was very, like, wishful, right? To be like, oh yeah, we want this feature. We're not going to talk too much about, like, the specific details [laughs], as opposed to the idea of it, right? And that, I think, is, you know, was part of what led to that ambiguity of, like, I can't even begin to estimate this because, like, it could mean so many different things.
JOËL: Right. And software problems, often, a slight change in the scope can make a massive change in complexity. I always think of a classic xkcd comic where two people are talking about a task, and somebody starts by describing something that kind of sounds complex. But the person implementing it is like, "Oh yeah, no, that's, you know, it's super easy. I can do that in half a day." And then, like, the person making the ask is like, "Oh, and, by the way, one small detail," and they add, like, one small thing that seems inconsequential, and the person is just like, "Okay, sorry, I'm going to need a research team and a couple of PhDs. And it's going to take us five years."
STEPHANIE: That's really funny. I haven't seen this comic before, but I need to [laughs] because I feel that so much where it's like, you just have different expectations about how long things will take. And I think maybe that is where, like, I felt really disappointed afterwards. Because in my inability to, like, just really speak up and say, like, "In my experience, like, this is kind of what happens when we don't have this information or when we aren't sure," yeah, I just wasn't able to bring that to the table in that, you know, meeting.
And I really am glad we're having this conversation now because I've been thinking about, like, okay, when I find myself in this position again, how would I like to respond differently? And even just that comic feels really validating [laughs] in terms of like, oh yeah, like, other people have experienced this before, where when we don't have that shared understanding or, like, if we're not being super transparent about how long does a thing really take, and why does it make it complex, or, like, what is challenging about it, it can be, like, speaking in [chuckles] two different languages sometimes.
JOËL: I think what I'm hearing almost is that in a situation like what you found yourself in, you're almost sort of wishing that you'd picked one extreme or the other, either sort of, like, standing up to—I assume this is a project manager or someone...to say, "Look, there's no number I can give you that's going to make sense. I'm not going to play this game. I have no number I can give you," and kind of ending it there.
Or, on the other hand, leaning into, say, "Okay, let's have a nuanced conversation, and we'll try to understand this. And we'll try to maybe scope it and maybe put some error bars on this or something and try to come up with a number that's a little bit more realistic." But by kind of, like, trying to maybe do a middle path where you just kind of give a ridiculously large number that's meaningless, maybe everybody feels unfulfilled, and that feels, like, maybe the worst of the paths you could have taken.
STEPHANIE: Yeah, I agree. I like that everyone [laughs] feels slightly unfulfilled point. Because, you know, my estimate is likely wrong. And, like, what impact will that have on other folks and, you know, their work?
While you were saying, like, oh yeah, here were the kind of two different options I could have chosen, I was thinking about the idea of, like, yeah, like, there are different strategies depending on the audience and depending who you're working with. And that is something I want to keep in mind, too, of, like, is this the right group to even have the, like, okay, let's figure this out conversation? Because it's not always the case, right? And sometimes you do need to just really stand firm and say, like, "I can't give you an answer. And I will go and find the people [laughs] who I can work this out with so that I can come back with what you need."
JOËL: And sometimes there may be a place for some sort of, like, placeholder data that is obviously wrong, but you need to put a value there, as long as everybody's clear on that's more or less what's happening. I had to do something kind of like that today. I'm connecting with a third-party SAML for authentication using the service Auth0. And this third party I'm talking to...so there's data that they need from me, and there's data that I need from them. They're not going to give me data until I give them our data first, so this is, like, you know, callback URLs, and entity IDs, and things like that you need to pass.
In order to have those, I need to stand up a SAML connection on the Auth0 side of things. In order to create that, Auth0 has a bunch of required fields, including some of the data that the third party would have given me. So, we've got a weird thing where, like, I need to give them data so they can stand up their end. But I can't really stand up my end until they give me some data.
STEPHANIE: Sounds like a circular dependency, if I've ever heard one [laughs].
JOËL: It kind of is, right? And so, I wanted to get this rolling. I put in a bunch of fake values for these callback URLs and things like that in the places where it would not affect the data that I'm giving to the third party. And so, it will generate as a metadata file that gets generated and stuff like that. And so, I was able to get that data and send it over. But I did have to put a callback URL whose domain may or may not be example.com.
STEPHANIE: [laughs] Right.
JOËL: So, it is a placeholder. I have to remember to go and change it later on. But that was a situation where I felt better about doing that than about asking the third party, "Hey, can I get your information first?"
STEPHANIE: Yeah, I like that as sometimes, like, you recognize that in order to move forward, you need to put something or fill in that gap. And I think that, you know, there was always an opportunity afterwards to fix it or, like, to reassess and revisit it.
JOËL: With the caveat that, in software, there's nothing quite so permanent as a temporary fix.
STEPHANIE: Oof, yeah [laughs]. That's real.
JOËL: So, you know, caution advised, but yes. Don't always feel bad about placeholders if it allows you to unblock yourself.
STEPHANIE: So, I'm really glad I got to bring up this topic and tell you this story because it really got me thinking about what estimates mean to me. I'm curious if any of our listeners if you all have any input. Do you love estimates? Do you hate them? Did our conversation make you think about them differently? Feel free to write to 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: Byeeeeeeeeeeeee!!!!!
AD:
Did you know thoughtbot has a referral program? If you introduce us to someone looking for a design or development partner, we will compensate you if they decide to work with us.
More info on our website at tbot.io/referral. Or you can email us at referrals@thoughtbot.com with any questions.
Stephanie is engrossed in Kent Beck's Substack newsletter, which she appreciates for its "working thoughts" format. Unlike traditional media that undergo rigorous editing, Kent's content is more of a work-in-progress, focusing on thought processes and evolving ideas. Joël has been putting a lot of thought into various tools and techniques and realized that they all fall under one umbrella term: analysis.
From there, Stephanie and Joël discuss all the productivity tricks they like to use in their daily workflows. Do you have some keyboard shortcuts you like? Are you an Alfred wizard? What are some tools or mindsets around productivity that make YOUR life better?
Transcript:
AD:
Ruby developers, The Rocky Mountain Ruby Conference returns to Boulder, Colorado, on October 5th and 6th. Join us for two days of insightful talks from experienced Ruby developers and plenty of opportunities to connect with your Ruby community.
But that's not all. Nestled on the edge of the breathtaking Rocky Mountains, Boulder is a haven for outdoor lovers of all stripes. Take a break from coding. Come learn and enjoy at the conference and explore the charm of Downtown Boulder: eclectic shops, first-class restaurants and bars, and incredible street art everywhere. Immerse yourself in the vibrant culture and the many microbrew pubs that Boulder has to offer.
Grab your tickets now at rockymtnruby.dev and be a part of the 2023 Rocky Mountain Ruby Conference. That's rockymtnruby.dev, October 5th and 6th in Boulder. See you there.
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's new in your world?
STEPHANIE: So, I have a new piece of content that I'm consuming lately. That is Kent Beck's Substack [chuckles], Kent Beck of Agile Manifesto and Extreme Programming notoriety. I have been really enjoying this trend of independent content creation in the newsletter format lately, and I subscribe to a lot of newsletters for things outside of work as well. I've been using an RSS feed to like, keep track of all of the dispatches I'm following in that way so that it also kind of keeps out of my inbox. And it's purely just for when I'm in an internet-reading kind of mood.
But I subscribed to Kent's Substack. Most of his content is behind a subscription. And I've been really enjoying it because he treats it as a place for a lot of his working thoughts, kind of a space that he uses to explore topics that could be whole books. But he is still in the phase of kind of, like, thinking them through and, like, integrating, you know, different things he's learning, and acknowledging that, like, yeah, like, not all of these ideas are fully fleshed, but they are still worth publishing for people who might be interested in kind of his thought process or where his head is at.
And I think that is really cool and very different from just, like, other types of content I consume, where there has been, like, a lot of, especially more traditional media, where there has been, like, more editing involved and a lot of time and effort to reach a final product. And I'm curious about this, like I mentioned, trend towards a little less polished and people just publishing things as they're working through them and acknowledging that the way they're thinking about things can change over time.
JOËL: It sounds like this is kind of halfway between a book which has gone through a lot of editing and, you know, a tweet thread, which is pure stream of consciousness.
STEPHANIE: Yeah, that's a really great insight, actually. And I think that might be my sweet spot in terms of things I enjoy consuming or reading because I like that room for change and that there is a bit of a, you know, community aspect to Substack where you can comment on posts. But, at least in my experience, has seemed, like, relatively healthy because it is, you know, you're kind of with a community of people who are at least invested or willing to pay [chuckles] for the content. So, there is some amount of good faith involved.
His newsletter title itself it's called "Tidy First?" And so, that almost implies that it's, like, something he's still exploring or experimenting with, which I think is really cool. It's not like a I have discovered, like, the perfect way to do things, and, you know, you must always tidy first before you do your software development. He's kind of in the position of, this is what I think works, and this is my space for continuing to refine this idea.
JOËL: I'm curious: are there any sort of articles that you've read or just thoughts in general that you've seen from Kent that are particularly impactful or memorable to you?
STEPHANIE: Yeah. One I read today during my investment time is called Accountability in Software Development. And it was a very interesting take on the idea of accountability, not necessarily, like, when it's forced by others or external forces like a manager or, you know, your organization, but when it comes from yourself. And he describes it as a way to feel comfortable and confident in the work that he's doing and also building trust in himself and in his work but also in his teams.
By being transparent and literally accounting for the things that he's doing and sharing them, communicating them publicly, that almost ends up diminishing any kind of, like, distrust, or shame, or any of those weird kind of squishy things that can happen when you hide those things or, like, hide what you're doing. It becomes a way to foster the good parts of working with other people but not in a necessarily like, resentful way or in a hierarchical way. I was really interested in the idea of accountability, ultimately, like, for yourself, and then that ends up just propagating to the team.
JOËL: That's a really interesting topic because I think it sort of sits at the intersection of the personal and the technical.
STEPHANIE: Yeah, absolutely. He mentions more technical strategies or tasks that kind of do the same thing. You know, he mentions test-driven development, as well as, like, a way of holding yourself accountable to writing software that, you know, doesn't have bugs in it. So, I think that it can be applied to, you know, exactly both of those, like, interpersonal stuff and also technical aspects too, anyway, that's what's new in my world. Joël, what about you?
JOËL: So, this year, I've been putting a lot of thought into a variety of tools and processes. And I think I've come to the realization that they all really fall under one kind of umbrella term, and that would be analysis. It's a common step in some definitions of the traditional software development lifecycle. And it's where you try to after you've kind of gathered the requirements, try to break them down and understand what exactly that means from a technical perspective, what needs to happen. And so, a lot of the things that have been really fascinating to me this year have been different techniques that I can use to become better at that sort of phase.
STEPHANIE: Wow. That's very powerful, I think. And honestly, the first thing that comes to mind is, how do you make time for it?
JOËL: I think we all do it to a certain extent. You know, you pick up a ticket, and there is a prose description of some work to be done, hopefully not telling you directly, like, just go make a change to this class, but here's a business problem to be solved. And then you have to sort of figure out how to break it down. So, this can be as simple as, oh, what objects, what classes do I need to introduce for this change? But it might be more subtle in terms of thinking, okay, well, what are the edge cases I need to think about? Where are things that could fail, and how am I going to handle failure?
So, there's a variety of techniques that you can use to get better at all of these. You can use them kind of at the micro level when thinking about just a ticket. You can use them when working on a larger epic, a larger initiative, a whole project because I think analysis fits into kind of all of these levels. And so, I think those are the techniques that have been most exciting to me this year and that have really connected.
STEPHANIE: That is very exciting. It's triggering a lot of thoughts for me about how I incorporate analysis into my work and how that has actually evolved; where I think before, earlier in my career, I assumed that the analysis had been done by someone else who knew better than me or who knew more than me. And that by the time that you know, a piece of work kind of landed in my lap, I was like, okay, well, I just want to know what to do, right? Like, I want someone else to tell me what to do [laughs]. But now I think I have taken it upon myself to do more of that and, like, have realized that it's part of my role.
And sometimes it will now be kind of a flag or, like, a signal to me when that hasn't been done. And I can tell when I receive a ticket, and it's, like, maybe missing the business problem or doesn't have enough information. And determining whether that is information that I need to go and find out, or if there's someone else who I can work together with to do that analysis with, or having a better understanding of, like, what is within my realm of analysis to do, and what I need to encourage other people to do analysis for before the work is ready for me.
JOËL: I think there is an interesting distinction between more traditional requirements gathering and analysis, where traditional requirements gathering is getting all that business problem information from product people, from customers, things like that. The analysis step is often a little bit more about breaking down a business problem into, like, what are the technical ramifications of that?
But there can be a little of a synergy there where sometimes, once you start exploring the technical side of it, it might bring up a lot of edge cases that have impacts on the product side, on the business side. And then you have to go back to the businesspeople and say, "Hey, we only talked about sort of the happy path. What happens if payment is declined? What do we want to do there?" And now we're back in sort of that requirements gathering phase a little bit more rather than purely analysis.
But it can come out of an analysis phase where you've done maybe some state machine diagramming to try to better understand how things flow from one phase to another. Or maybe you were building out a truth table for some complex logic and realized, wait a minute, there's an edge case I didn't handle. It's not a strictly linear process. The two kind of feed into each other and, honestly, into the implementation side as well.
STEPHANIE: Yeah, I'm with you there. I'm thinking about a piece of work that I've been working on, where we were thinking of doing a database migration and adding some new columns to a table. But the more I dug into it, the more I realized that that was the first idea or the immediate idea that came from a need that I had limited information about. And what was nice was I was able to sit on it for a little bit, get some input from others. And I realized that there were all of these things that I couldn't answer yet.
And someone, I think literally asked in a code review if you've already done this analysis, between knowing that these columns will be the kind of extent of what you need versus, you know, will the data end up needing more columns? And should the data model be a little more flexible to that potential change? And they said, "If you had already done this analysis, then, like, otherwise, it looks good to me." And I was like, "Oh, I didn't." [laughs]
And that encouraged me to go back to some cross-functional members of the team and ask more questions. And that has taken more time. That was another challenge that I had to encounter was saying like, "Yeah, we started this, and we made some progress. But actually, we need to revisit a few things, like a few parts of the premise, before continuing on."
JOËL: Are there any techniques or approaches that you particularly enjoy when it comes to doing an analysis or that maybe are go-to's for you?
STEPHANIE: Reminding myself to revisit my assumptions [laughs], or at least even starting by being really clear about what I'm assuming, right? Because I think that has to happen first before you can even revisit them is having an awareness of what assumptions you're making. And I actually think this is where collaboration has been really helpful, where I've been working on this task with another developer on my team. And when we've been talking about it, I found myself saying, "Oh, I'm assuming this," right? Or, like, I'm assuming that the stakeholder knows what they need [laughs]. And that's why we're going to do it this way, where we were kind of given the pieces of data that we should be persisting.
And the more that we had that conversation, the more I realized, like, actually, like, I'm not convinced that they have that full picture of, like, what they need in the future. And because we're making this decision now, like, we are turning, you know, literally from, like, the abstract into, like, a concrete change [chuckles] in the database, now seems like...now that we're faced with that decision, it seems like a good time to revisit the assumption that I was making.
And that has proved helpful in making ultimately, like, a more informed decision about, like, which way to go technically. But I personally have found a lot of value in verbally processing it with someone else. It's a lot harder for me to identify them, I think, when I'm in my own head.
JOËL: That's really interesting that you keyed in on the idea of assumptions. I typically think of assumptions being, like, so important mostly in debugging rather than analysis. In fact, I wrote a whole blog post about why listing your assumptions is so important as part of your debugging process.
Now, like, my mind is spinning a little bit. I'm like, oh, I wonder if I could use some of those, like, debugging techniques as part of more of my analysis step. And could that make me better? So, I think you've put me on a whole, like, thought track of, like, oh, how many of these debugging techniques can I use to make my analysis better? So, that's really cool.
STEPHANIE: Yeah, and vice versa. So, a few minutes ago, I'd asked you how you make time for that analysis. Because I was thinking that, you know, in my day-to-day work, I'm juggling so many things. I often find myself running out of time and not able to do all of it. And that, I think, leads us really well into our topic for this episode, which is productivity tricks and ways that we make the most use out of our limited time.
JOËL: I think I may have a maybe a bit of a controversial opinion on productivity tricks. I feel like a lot of productivity tricks don't actually make me that much faster. Like, maybe I save a couple of minutes a day, maybe 5 or 10 a day with productivity tricks. And, sure, that adds up over the course of a year. But there are other things I could do in terms of, like, maybe better habits, better managing of my schedule that probably have a much more significant impact.
Where I think they are incredibly valuable, though, is not directly making me better with my time management but managing my focus, allowing me to kind of keep in the flow and get things done without getting sidetracked. Or just kind of giving me the things that I need in the moment that I need them so that I'm not getting on to a subtask that I don't really need to be doing.
STEPHANIE: Yeah. I really like that reframing of what helps you focus because as I was brainstorming ways that I stay on track for my work, I think I ended up discovering a similar theme where it wasn't so much, like, little snippets and tools for me, as opposed to how I structure all of the noise, I guess, in my day-to-day work and being able to see what it is that I need to care about the most right now.
JOËL: I think one of the things that I've tried to do for myself is to make it easy to have access to the information and the tools that I need. Probably one of the most useful bits of that is a combination of the documentation viewer Dash and the...I'm not sure what it would be called– launcher, productivity manager tool for Mac. Alfred, with a CMD + Space, it brings up this bar I can type into. And then you can trigger all sorts of things from there.
And so I can type the name of a language or some kind of keyword that I have set up and the name of a method. And then, all of a sudden, it'll show me everything like, you know, top five results. And I can hit Enter, and it will bring up the documentation for that.
So, if I want to say, oh yeah, what is the order of the arguments for Enumerable's inject method (which I constantly forget)? You know, it's a few keyboard shortcuts, you know, CMD + Space Ruby Enumerable inject. It's fuzzy finding, so I probably don't even need to type all of that. Hit Enter, and I have the documentation right in front of me. So, that makes it so that I can get access to that with very little amount of context shifting.
STEPHANIE: Yeah. I like what you said about how the tools are really helping you, like, narrow down, like, the views of, like, what is most important for you in that moment, and it's doing a little bit of that work for you. I think the couple of tools and apps that I actually did want to share are kind of similar.
One MacOS app I really like is called Rectangle for windows management, which is really crucial for me because I don't enjoy like, swiping and tabbing between applications. I would much prefer just seeing, usually, just two things. I try to keep my screen limited to two different windows at once because once it gets more than that, I'm already just, like, overwhelmed [laughs].
And as I'm trying to focus a little bit more on just having, like, one thing be the focus of my attention at a time, Rectangle has been really nice in just really quickly being able to do my windows resizing. So, I usually have, like, either things split between my screen half and half. Like, right now, I have your face on my screen as we record this podcast, and then my notes editing software for taking notes about what we talk about.
During my development workflow, it's usually, you know, just my editor, my terminal, and then maybe my browser ends up being, like, the thing that I tab into. But I'm able to just, like, set that all up, and as I need those windows to change depending on what my focus has been shifted to, to kind of make more space for whatever I'm reading, or looking at, or processing visually. The keyboard shortcuts that Rectangle...that I have now, you know, ingrained into my fingers [laughs] has been really helpful. It's like, I'm not fussing with just, like, too many things open.
JOËL: I have yet to, like, dive into a window manager. I'm still in the clunky world of CMD tabbing. But maybe I should give that a try.
STEPHANIE: For me, it has helped even just, like, identify the things that I need to give more space to on my screen and aggressively, like, cut everything else [laughs]. So, that's a really great MacOS app.
And then, the other one is actually kind of a similar vein. It's called Meeter, M-E-E-T-E-R. And it has been really helpful for managing my meetings, especially my video call meetings where the video call software that's being used for the meeting may be variable. And also, when I have multiple email addresses that meetings are being sent to, you're able to sign into all of your calendar accounts. And it provides a really nice view of all of your meetings.
It has a really, like, minimal, I guess, design in your toolbar, where it shows you how many minutes until your next meeting. And from that toolbar button, you can click to go to the video conferencing software directly for whatever meeting is up next. And you don't have to, you know, scramble to open Google Meet, or Zoom, or Webex, or whatever it is. And that's [chuckles] been nice, again, just kind of, like, cutting down on the amount of stuff that I need to remember and shift through to get to my destination.
JOËL: I think I'm hearing kind of two themes emerge out of some of the things that we've shared. And I'd like to maybe explore them a little bit; one is the power of keyboard shortcuts. And I think that's maybe what a lot of us think of when we think of productivity apps, at least developers, right? We love keyboard shortcuts.
And then, secondly, I think I'm hearing automation, right? So, you don't have to go through and, like, find that email or calendar link to find the Zoom link or whatever. It shows up in your toolbar. So, maybe we can dig into a little bit of the idea of keyboard shortcuts. Are you a person who like customizes a lot of keyboard shortcuts? And is that a part of your kind of productivity setup?
STEPHANIE: Well, a while ago, we had talked about not keyboard shortcuts in the context of productivity, but I think I had mentioned that I was trying to use my mouse less [chuckles] because I was getting a little bit of wrist pain. And I think that actually has rolled into a little bit of, you know, just, like, more efficient navigation on my computer.
I think my keyboard shortcut usage is mostly around window management, like I mentioned. I do feel like I have, like, a medium amount of efficiency in my editor. Sometimes, when I'm pairing with other people who use Vim, I'm, like, shook by how fast they're moving. And I have figured out what works for me in VS Code, and I don't think I need to get any faster. You know, I've just accepted that [laughs].
In fact, it's almost, like, the amount of speed and friction that I have, in my experience, is actually a little more beneficial for the speed that my mind works [laughs]. It kind of helps me slow down when I need to think about what I'm doing as opposed to just, like, being able to, like, do anything at my fingertips, and kind of my brain is just not able to think that fast.
And then navigating Slack, which is where I also spend a lot of my time on my computer. Now, using Slack with my keyboard shortcuts has been really helpful because, again, I'm not, like, mindlessly browsing or clicking around. I'm just looking at my unread messages. One non-keyboard shortcut I really like with Slack is Command + K, which is the jump-to feature. And so, I'm using that to go to a specific channel that I know I'm looking for or my own personal DMs, where I keep a lot of notes as well. And, honestly, I think that's, like, the extent of my keyboard shortcut usage. I'm curious what your setup is in regards to that, though.
JOËL: I think I'm similar to you in that I have not kind of maxed out the productivity around keyboard shortcuts. You'd mentioned the jump to in Slack. Several pieces of software have something kind of like that. It might be some sort of omnibar, or a command palette, or something like that, where you really just need to know...CMD + K, or CMD + P, CTRL + P are common ones. Then you can sort of, like, type a few characters to just describe the thing you want to do, or a search you want to make, or something like that.
Just knowing that one keyboard shortcut for your one piece of software gets you, I don't know, 80% of the productivity that you want. It's kind of amazing. I love the idea of an omnibar.
STEPHANIE: Yeah, I hadn't heard of omnibar as a phrase before, but that feels very accurate. I like that a lot, too, where it's, like, oftentimes, I don't do whatever particular thing enough necessarily for it to justify a keyboard shortcut, for me at least. I'm still able to be fast enough to get to, like I said, that final destination or the action that I want to take with a more universal shortcut like that.
JOËL: In my editor...so I use Vim, and I got used to Vim's keyboard-based navigation. And that is something that I deeply appreciate, maybe not so much for speed but being able to almost kind of feel one with the machine. And the cursor moves around, and I don't have to, like, think about moving it. It's really a magical sort of feeling. And it's become so much muscle memory now that I can just sort of...the cursor jumps around, things change out. And I'm not, like, constantly thinking about it to the point where now, if I'm in any other editor, I really want to get those shortcuts or, I guess, maybe not shortcuts but a Vim-style navigation, keyboard-based navigation.
STEPHANIE: Yeah, it sounds like it's not so much the time savings but the power that you have or the control that you have over your tools.
JOËL: Yes. And I think, again, the idea of focus. Navigation has stopped becoming a thing where I have to actively think about it. And I feel like I really do just sort of think my fingers are on the keyboard. I'm not having to, like, do a physical motion where I switch my hands. Like, I'm typing, and I'm writing code, then I have to switch my hand away to a mouse to shift around or, like, move my hand off the home row to, like, find the arrow keys and, like, move around. I just kind of think, and the cursor jumps up. It's great.
Maybe I'd be the same if I'd put a lot of time into getting really good at, you know, maybe arrow-based navigation. I still think the mouse you have to move your hand off. It breaks just in the tiniest little way the flow. So, for me, I really appreciate being fully keyboard-based when I'm writing code.
STEPHANIE: Right. Being one with the keyboard. As you were talking about that, I very viscerally felt, you know, when you encounter a new piece of technology, and you're trying to navigate it for the first time, and you're like, wow, like, that takes so much mental overhead that it's, you know, just completely disruptive to the goal that you're trying to achieve with the software itself.
JOËL: Yeah, it is a steep learning curve.
So, we've talked about custom keyboard shortcuts in the editor. But it's common for people to augment their editor with plugins, maybe even some kind of, like, snippet manager to maybe expand snippets or to paste common pieces in. Is that something that you've done in your editor setup? I think you said you use VS Code as your sort of daily editor.
STEPHANIE: Yeah, that's right. I actually think I almost forgot about some of my little bits of automation because they are just so spelled for me [laughs] that I don't have to think about them. But you prompting me just now reminded me that there are a few that I'd like to shut out.
Snippets-wise, I mostly use them for when I'm writing tests and just having the it blocks or the context blocks expand out for me so I don't have to do any of that typing of the setup there. And since I do use a terminal outside of my editor...I know that some people really like kind of having that integrated and being able to run tests even faster without having to switch to a different application, but I like having them separate.
There is a really great plugin called Go to Spec where you can be in any, you know, application code file, and it will pull up the spec file for you. I've been really enjoying that, and that is what helps my test writing be a little more automated, even though I'm having it in separate applications.
JOËL: That is really useful. So, as a Vim user, I also have a plugin that does something similar, where I can switch to what's considered the alternate for a particular file, which is typically the spec, or if I'm in the spec, it'll switch to the source file that the spec is testing.
STEPHANIE: And then, I do have one really silly one, which is that I got so sick and tired of not remembering how to, you know, type the symbols for string interpolation in Ruby that has also become a snippet where the hash key and the [inaudible 28:48] brackets can [laughs] populate it for me.
JOËL: I love it.
So, Stephanie, I'd like to go back to something you were talking about earlier in the show. When you were sharing about what was new in your world and, you mentioned that you subscribe to the Substack and that you subscribe to, actually, a lot of newsletters, and you said something that really caught my attention. You were saying that you don't want these all cluttering up your email inbox. And instead, you send all of these to an RSS reader application. What kind of application do you like to use?
STEPHANIE: I use Feedbin for this. And I actually think that this was recommended by Chris Toomey back in the day on a previous Bike Shed episode before you and I hosted the show. But that has been really awesome. It has a just, like, randomly generated email address you can use when you sign up for newsletters. You use that instead.
And I really like having that distinction because I honestly treat my email inbox as a bit of a to-do list, where I am archiving or deleting a lot of stuff. And then the things that remain in my inbox are things that I need to either respond to, or do, or get back to in some way. And then yeah, when I've completed it, then that's when I archive or delete.
But now that we do have all this great content back in email form, I needed a separate space for that, where I similarly kind of treat it as, like, a to-read list. And yeah, like, I look at my unreads in the newsletter RSS reader that I'm using and go through that when I'm in a blog-reading kind of mood.
JOËL: I really like that separation because I'm kind of like you. I treat my inbox as a to-do list. And it's hard to have newsletters come in and, like, I'm not ready to read them. But I don't want them in my to-do, or, like, they'll just kind of sit there and get mixed in and maybe, like, filtered down to the bottom. So, having that explicit separation to say, hey, here's the place I go to when I am in a reading mood, then I can read things.
I think there's also I've sort of trained myself to only check my email during certain times. So, for example, I will not check my work email outside of working hours. But if I'm on the subway going somewhere and I've got some time where I could do some reading, it would probably be a good thing to be going through some kind of newsletter or something like that. So, I either have to remember to go back to it, or what I tend to do is just scroll Twitter and hope that someone has shared that link, and then I read it there, which is not a particularly effective way of doing things. So, I might try the RSS feed reader tool. What was it called?
STEPHANIE: Feedbin.
JOËL: Feedbin. All right, I might try to get into that.
STEPHANIE: Yeah, I look forward to hearing if that ends up working for you because I agree, having the two separate spaces has been really helpful because I don't want to get distracted by my email/to-do list inbox if I'm just wanting to do a bit of reading, enjoy some content.
So, one more theme around productivity that I don't think we've quite mentioned yet, but maybe we've talked a little bit around, is the idea that it's, at least for me, it's a product of time and energy. So, even if you have all the time in the world, you know, you can just stare into space or, like, stare at a line of code and not get [laughs] anything done.
JOËL: I know the feeling.
STEPHANIE: Right? I am kind of curious how or if you have any techniques for managing that aspect. When your focus is low like, how can you kind of get that back so that you can get back to doing your tasks or getting what you need to do done?
JOËL: If I have the time, taking a break is a really powerful thing, particularly taking a break and doing something physical. So, if I can go outside and take a walk around the block, that's really helpful. And if I need a shorter thing that can be done in, like, five minutes or something, I have a pull-up bar set up in my place. So, I'll just go up and do a few sets there and get a little bit of the heart rate slightly up, do a little bit of blood pumping. And that sometimes can help reset a little bit.
STEPHANIE: Nice. Yes, I'm all for doing something else [chuckles]. Even when you know that this is a priority or is kind of urgent or whatever, but you just can't get yourself to do it, I've found that asking myself the question, "What would make this task easier for me right now?" has been helpful during those moments. And, for me, that might be grabbing a friend, like, maybe I'm blocked because I'm really just unmotivated. But having someone along can kind of inject some of that energy for me.
And then, there's a really great blog post by a woman named Mandy Brown. It's called Energy Makes Time. And she talks about how doing the things that fill our cup, actually, you know, even though it seems like how could we possibly have time to be creative, or, like you said, maybe do something physical, those seem, like, lower on the priority list.
But when you kind of get to the point where you just feel so overwhelmed and can't do anything else, and you just go do those things that you know feel good for you, you kind of come back with a renewed perspective on your to-do list. And you can see, like, what things actually aren't that critical and can be taken off. Or you just find that you have the capacity or the energy to get the things that you are really dreading out of the way.
So, that has been really helpful when I just am feeling blocked. Instead of, like, feeling bad about how unproductive [chuckles] I'm being, I take that as a sign of an opportunity to do something else that might set me up for success later.
JOËL: Yeah. I think oftentimes, it's easy to think of productivity in terms of, like, how can I maybe eliminate some tasks that are not high value through clever automation, or keyboard shortcuts, or things like that? But oftentimes, it can be more about just sort of managing your focus, managing your energy. And by doing that, you might have a much higher impact on both how productive you feel—because that's an important thing as well, in terms of motivation—and, you know, how productive you actually are at getting things done.
STEPHANIE: Right. At least for me, like, not all TDM is bad and needs to be automated away, but, like, my ability to, like, handle it in the moment. Whereas yeah, sometimes maybe I've just run the same few lines that should be just a script [chuckles], that should just be, you know, one command, enough times that I'm like, oh, like, I can't even do this anymore because of just, like, other things going on. But other times, like, it's really not a big deal for me to just, you know, run a few extra commands. And, like, that is perfectly fine.
JOËL: I love writing a good Vim macro. Yeah. So, it's important to think beyond just the fun tools and the code that we can write. Kind of think a little bit more at that energy and that mental level.
That said, there are a ton of great tools out there. We've named-dropped a bunch of them in this episode. For our listeners who are wondering or who weren't, like, necessarily taking notes, we've linked all of them in the show notes: bikeshed.fm. You can find them there.
STEPHANIE: 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: Byeeeeee!!!!
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.
Joël describes an old-school object orientation exercise that involves circling nouns in a business problem description. The purpose is determining which nouns could become entities or objects in a system. Stephanie shares she's working from the Hudson Valley in New York as a trial run for potentially relocating there. She enjoys the rail trails for biking and contrasts it with urban biking in Chicago.
The conversation between Joël and Stephanie revolves around mentorship, both one-on-one and within a group setting. They introduce a new initiative at thoughbot where team members pair up with principal developers for weekly sessions, emphasizing sharing perspectives and experiences.
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 was recently having a conversation with a colleague about some old-school object orientation exercises that people used to do when trying to do more of the analysis phase of software, ones that I haven't seen come up a lot in the past; you know, 5, 10 years.
The particular one that I'm thinking about is an exercise where you write out the sort of business problem, and then you go through and you circle all of the nouns in that paragraph. And then, from there, you have a conversation around which one of these are kind of the same thing and are just synonyms? Which ones might be slight variations on an idea? And which ones should become entities in your system? Because, likely, these things are then going to be objects in the system that you're creating.
STEPHANIE: Wow, that sounds really cool. I'm surprised that it's considered old school or, I guess, I haven't heard of it before. So, it's not something in my toolbox these days. But I really like that idea. I guess, you know if you're doing it on pen and paper, it's obviously kind of timeless to me.
JOËL: And you could easily do it, you know, in a Google Doc and underline, or highlight, or whatever you want to do. But it's not an exercise that I see people really doing even at the larger scale but even at, the smaller scale, where you have maybe a ticket in your ticketing system, and it has a paragraph there kind of describing what needs to be done. We tend to just kind of jump into, oh, we're going to build a story and do the work and maybe not always think about what are the entities that need to happen out of that.
STEPHANIE: I think the other thing that I really like about this idea is the aligning on shared vocabulary. So, if you find yourself using different words for the same idea, is that an opportunity to pick the vocabulary that best represents what this means? Rather than a situation that I often find myself in, where we're all talking about the same things but using different words and sometimes causing a little bit more confusion than I think is necessary.
JOËL: Definitely. It can also be a good opportunity to connect with the product or businesspeople around; hey, here are two words that sound like they're probably meaning the same thing. Is there a distinction in your business? And then, you realize, wait a minute, a shopping cart and an order actually do have some slight differences. And now you can go into those. And that probably sparks some really valuable learning about the problem that you're trying to solve that might not come up otherwise, or maybe that only comes up at code review time, or maybe even during the QA phase rather than during the analysis phase.
STEPHANIE: Yeah. I think that's really important for us as developers because, as we know, naming is often the hardest part of writing code, right? And, you know, at that point, you are making that decision or that distinction between maybe a couple of different terms that you're using to describe an idea and putting that down then will continue on to be read. And just propagating that down the line of, is this name actually what we mean? Or maybe we are using words that, at this lower level, make more sense, but when interacting or communicating with business stakeholders or product folks, they are using a different term.
And I really like the idea of that activity being a cross-functional one where you can kind of agree on how to move forward there. Because lately, I've been finding myself oftentimes using both words where the product folks are describing it this way, and then we've, on the engineering side, have decided that, okay, we're actually going to call our database table this other thing, and now having to type out both [chuckles] meanings each time because I know that my audience is in both camps.
JOËL: Yeah. There's, I think, a lot of value in using the business terms where possible. If you don't use them, there has to be a good reason. There's a slight distinction for the technical term. We're using it to say, hey, it's different from the business idea in interesting ways that only matter to the dev team.
STEPHANIE: Is there a name for this activity?
JOËL: I don't know, just circling nouns or underlining nouns.
STEPHANIE: Cool. Maybe we can come up with something. [laughs] Or someone else can tell us if they know what this kind of exercise is called.
JOËL: Gotta name the naming activity. So, how about you, Stephanie, what's new in your world?
STEPHANIE: So, I have a pretty exciting life development to share. I am currently working from a different location than my home in Chicago. I'm in the Hudson Valley in New York for the next month because my partner and I are considering moving out here. And we are just kind of looking for a different pace of life a little bit. And we are taking this month as a trial run to see if we want to, you know, be out here permanently. And I've been having a great time so far.
One thing that I've really enjoyed is all of the rail trails out here. So, a lot of old railroad tracks have been repurposed for outdoor recreation, and they are great for biking, or running, or even just walking. And I've been able to hop on my bike, you know, and bike a few minutes, and then I'm on the trail and just kind of surrounded by trees and forests. And that's been really nice because I missed having access to nature kind of, like, right outside my door.
JOËL: So, you used to do quite a bit of urban biking in Chicago. But it sounds like now you're getting a chance to do more kind of nature biking.
STEPHANIE: Yeah, it's a big difference for me because urban biking was always pretty rough or a little scary just, you know, having to bike with traffic. And I got a lot better at it. But now I'm, you know, biking completely off the roads. And I don't have to worry too much about cars. And I can, you know, just enjoy the fresh air around me and just be a lot more relaxed, I think, than I was able to when I was commuting in the city.
JOËL: So, here's the real question. At this new location that you're staying at, do you have a bike shed?
STEPHANIE: Not yet. But we now could have a bike shed because there's a lot more space out here, too. So, I could theoretically have my bike shed in my nice, big yard right next to my garden. And these are all [laughs] the hopes and dreams I have for my future life.
JOËL: Before you build the bike shed, you can have six months of discussion about what color you want to paint it.
STEPHANIE: Yeah, that's why I have this podcast, actually. [laughter] So, look out for that in what's new in my world is considering paint colors for a theoretical future bike shed in a place where I yet don't live.
JOËL: You're going to become an expert in the Pantone color palettes.
STEPHANIE: I hope so. That would be a great addition to my title. So, another thing that's new in both of our shared worlds is a new initiative on Boost, the team we're on, that you have been involved in. It's pairing sessions with the principal developer.
JOËL: Yes. So myself and, another principal developer at thoughtbot have been doing weekly pairing sessions, where we take Tuesday afternoons and pair with one of the other members of the team on their client project doing whatever. So, it's not, a, like, pull someone in when you need help or anything that's more kind of targeted in that way. It's more of a you sign up for this ahead of time. And you just know that on this week, you get someone to pair with you who can hopefully bring in a different perspective a lot of experience, and pair with you on your particular project.
STEPHANIE: Yeah. I'm so excited about this initiative because I've not been staffed on a project with you before or the other principal developer who's involved. And I have really wanted to work with you all and be able to learn from you. And I think this is a really cool way to make that expertise more accessible if you just don't happen to be working on a project together.
JOËL: Yeah. One of the challenges I think of the principal role is that we want it to be a role that has a high impact on the team as a whole. But also, we are people who can be staffed on pretty much any client project that gets thrown at us and can easily be staffed on projects that require solo work. Whereas there are some teammates who I think it's the developer position that we guarantee they're never staffed solo.
And so, that can often mean that our principals get staffed on to the really technically challenging problems or the solo problems, but then there's maybe not as much room to have interactions with the rest of the team on a day-to-day basis.
STEPHANIE: Yeah. I think the key word you said that had me nodding my head was impact. And I'm curious what your hopes are for this effort and what kind of impact you want to be having for our team.
JOËL: I think it's impact on a few different levels, definitely some form of knowledge sharing. Myself and the other principal developer have decade plus experience each in the field, have deep knowledge in a lot of different things like test-driven development, object modeling, security, things like that that build on top of kind of more basic developer skills that we all have. And those are all, I think, great ways that we can support our team if there's any interest in those particular skills or if they come up on a particular project.
And knowledge sharing works both ways, right? I think anytime you're pairing with someone else, there's an opportunity to learn on both sides. And so, I think a really important thing when you're pairing with someone, even if you're kind of maybe more explicitly the mentor figure, is to kind of keep that open mind and look for not only what can I give, how can I teach, but what can I learn from this other person?
STEPHANIE: Yeah, absolutely. I guess I'm wondering...and I know this is a pretty new programming so far, but is there anything you've learned or anything that surprised you that you weren't expecting when you, you know, first conceived of the idea based on how it's been going?
JOËL: Something that really surprised me, there's some feedback I got after one of the pairing sessions, where this colleague who we'd paired together...and I felt like I hadn't contributed a ton, like, this colleague just really had it and was just kind of going through and doing things. So, I was kind of, like, leaving that pairing session being like, oh, I don't know if I added a ton of value here.
And then, this colleague reached out to me and said, "Oh, you know, I felt, like, this huge boost of confidence because we were pairing together, and you were just kind of nodding along and basically saying yes to all of my choices." And I hadn't really considered that that can be a really valuable aspect of this sort of pairing. Sometimes you know the right thing to do, like, you've got it. But it's really easy to second-guess yourself. And just having someone along to, you know, give you that thumbs of like, yeah, this is the thing to do, can give you that confidence boost and kind of keep you moving in a way that feels really positive.
STEPHANIE: Wow. I love that. That's really powerful, and I get that. Because, you know, obviously, it's very valuable to have your colleagues help generate different ideas that you might not have considered. But that validation can be really useful. And, you know, that's just not something you get when with a rubber duck. [laughs] The rubber duck can't respond, and [laughs] nod along.
So, I think that's really cool that you were able to provide some of that confidence. And, in fact, I think that is contributing to their growth, right? In terms of helping identify, you know, those aspects that they're already really strong at, as well as developing that relationship so they know you're available to them next time if they do need someone to either do that invalidating or validating of an idea.
JOËL: Yeah, there's a lot of power, I think, in kind of calling out people's strength and providing validation in a way that can really help someone get to the next level in their career. And it feels like such a simple thing. But yeah, sometimes you can have the biggest impact not by kind of going in and helping but just kind of maybe, like, standing back a little bit and giving someone a thumbs up. So, definitely one of the biggest surprises or, I think, one of the biggest lessons learned for me in the past few weeks of doing this.
STEPHANIE: That's very cool.
JOËL: So, Stephanie, you've also been doing some pairing or some mentoring from what I hear.
STEPHANIE: Yeah. So, on my current client work, I have been pairing with a new hire on my client team who recently graduated from college. And this is his first job in software development. And I have been thinking and learning a lot through this experience because one of my goals was to get better at coaching, specifically the idea of asking guiding questions to help someone, you know, arrive at their own solution instead of, you know, making the suggestions myself or kind of dictating where to go.
And this has kind of been a progression for me of kind of starting from, well, you know, I have the way that I want to do it. And the person I'm working with who maybe has less experience, like, they might not know where to go. So, we're just going to go along with my idea. And then the next step was offering a few different ideas, like a menu of options and kind of having that discussion about which way to go.
And now, I really wanting to practice letting someone else lead entirely and helping them start thinking about the right things but ultimately not giving them the answer. But hopefully, like, the questions I've been asking means that they are able to get to a well-informed answer where they've thought through some of the things that I would think about if I were in the position of making the decision or figuring out how to implement.
JOËL: Is this mostly asking questions to get them to think about edge cases, or is this, like, a Socratic approach to teaching?
STEPHANIE: Could you describe Socratic approach for me?
JOËL: So, the Socratic approach is a teaching approach that is question-based, where you kind of help the student come to the conclusions themselves by answering questions rather than by telling them the answer.
STEPHANIE: Oh, interesting. I think a little bit of both. Where it's true, I am able to see some edge cases that folks with less experience might not consider because they just haven't had to run into them before or fight the fires when [laughs] their code in production ends up being a big issue or causes a bug.
But I think that's just part of the work where there is kind of, like, a default dynamic that might be fallen into when two people are working together, and their experience levels differ, where the person who has less experience is wanting to lean on the more senior person to tell them where to go, or to expect to be in that position of just learning from them and not necessarily doing as much of the active thinking. But I was really interested in flipping that and doing a bit of a role reversal because I think it can be really impactful and, you know, help folks earlier in their career, like, really level up even more quickly than just watching, but actually doing.
And so, the questions I've been asking have been a lot more open-ended in terms of, like, asking, "What do you think about this code that we're looking at?" Or, like, "Where do you want to go next?" And based on, you know, their answers, digging in a little more, and, at the end, maybe, like, giving that validation that we were talking about earlier. I was like, "Great. Like, I think that's a great path forward," or, "I think that's a good idea to spend our time on right now."
But the open-ended questions, I think, are also ones that I also would have liked when I was in that position of learning, where having someone trust that I could draw on my past experience but, like, also knowing that they were there to support and maybe orient me if I ended up straying too far off the path.
JOËL: How have you navigated situations where maybe you're asking a question about "What do you want to do next?" and they pick something that maybe would work but is not your sort of preferred approach, or maybe something that seems like it would work well enough but, you know, there's maybe a better approach? How do you navigate that? Do you let them take their approach and maybe kind of let them run into some of the edge cases and problems and then say, "Hey, let me show you something new"? Do you probe a little bit earlier? Or do you say, "Hey, that's good, but why don't we try my way"? How do you navigate that kind of situation?
STEPHANIE: That is so hard. It's really challenging. Because if you kind of know that there's maybe a more effective way, or a cleaner way, or whatever, and you're seeing your pair or your mentee kind of go down a different path, you know, it's so easy to just kind of jump in and be like, "Oh, actually, like, let me save you some time, and effort, and pain and just kind of tell you that there's something else we could try."
But I think I've been trying to sit on my hands a little bit and let them go down that path or at least let them finish explaining kind of what their thought process is and giving them the opportunity to do that act of thinking to see it through without interrupting them because I think it's really important to, you know, just honor the process that they're going through.
I will say, though, that I also try to keep an eye on the time. And I am also, like, holding in my head a bit of a higher level, like, the project status, any deadlines, what's on our plate for the sprint. And so, if I'm seeing that maybe the path they want to go down might end up taking a while or we don't quite have enough time for that, to then come back and revisit and adjust and reiterate on, like, their first solution. Then that is usually an opportunity where I might offer them another way or say, like, "Hey, like, this is what I'm thinking," because of those things I mentioned before with deadlines or something I'm considering.
But I generally try not to impose any of that as, like, this is what we will do so much as saying, "This is what I think we should do." Because I really want to hone in on the idea that, like, everyone just has opinions [laughs] about how they want to do things. And I'm not claiming mine is the perfect way or even the best way, but just what I'm thinking in this moment.
JOËL: Yeah, time permitting, I've really appreciated scenarios where you give people a chance to do the non-optimal solution and run into edge cases that kind of show why that solution is not optimal and then backtrack out of it and then go to the optimal path. I think that's a lesson that really sticks much longer. So, I've even done that in scenarios where I'm building some training material. And I'll kind of purposely have the group go down the sort of obvious path, but that turns out to be non-optimal.
And then, you hit a wall where things don't work, and then you have to backtrack. And it's like, okay, so that's why we don't do it that way that may have seemed obvious. Because then everybody remembers as opposed to...I mean, you could just go down this other path, and somebody asks you a question, "Why don't we go down this thing?" And then, they just...maybe they have to remember it, or it becomes a thing where it's like, oh, but, like, we were told that's a bad way to do it. And now you have this sort of, like, weird, like, absolutism about, like, oh, but, you know, Joël said that was bad. So, we just got to remember that's the bad thing.
And it's not about the morality of that choice that I think can come through when you're kind of declaring a path good and a path bad, but instead, having experienced, hey, we went down this path. There were some drawbacks to it, which is why we prefer this other path. And I think that tends to stick a lot more with students.
STEPHANIE: Yeah. I really like what you said about not wanting to inject that, like, morality argument or even kind of deny them the opportunity to decide for themselves how they thought that path went or, like, how they thought the solution was. If you just tell them like, "No, don't go there," you're kind of closing the door on it. And, yeah, they might spend a lot of time afterwards thinking that, like, that will always be a bad option without really forming an opinion for themselves, which I think is really important. Because, you know, once you do get more experience, that is pretty much, like, the work [laughs] that we're doing all of the time.
But another thing that I think is also such a skill is assessing your own work, like, after you go down the path or, like, once you have something working, being able to come back to it and look at it and be like, oh, like, can this be better, right? And I think that can only happen once you have something to look at, once you have, like, a first draft, if you will, or do the less optimal implementation or naive implementation.
JOËL: So, when you're trying to prompt someone to kind of build that skill of self-review or self-reflection on some of the work that they've done, how do you as a pair or a mentor help stimulate that?
STEPHANIE: Yeah. I think with early career folks, one thing that is an easy way to start the conversation is asking, "Are there any places that could be more readable?" Because that's, I think, an aspect that often gets forgotten because they're trying to hold so much in their heads that they are really just getting the code to work. And I think readability is something that we all kind of understand. It doesn't include any jargon about design patterns that they might not have learned yet. You know, even asking about extracting or refactoring might be not where they are at yet.
And so, starting with readability, for example, often gets you some of those techniques that we've learned that have, you know, specialized vocabulary. But I have found that it helps meet them where they're at. And then, in time, when they do learn about those things, they can kind of apply what they've already been doing when kind of prompted with that question as, like, oh, it turns out that I was already kind of considering this in just a different form.
JOËL: And I think one thing that you gain with experience is that you have kind of a live compiler or interpreter of the language in your head. And so, sometimes for more complex code, I, as an experienced developer, can look at it and immediately be like, oh yeah, here's some edge cases where this code isn't going to work that someone newer to the language would not have thought of.
And so, sometimes the way I like to approach that is either ask about, "Oh, what happens in this scenario?" Or sometimes it's something along the lines of, "Hey, now that we've kind of done the main workflow, there's a couple of edge cases that I want to make sure also work. Let's write out a couple of test cases." So, I'll write a couple of unit tests for edge cases that I know will break the code.
But even when we write the unit tests, my pair might assume that these tests will pass. And so, we'll write them; we'll run them and be like, "Oh no, look at that. They're red. I wonder why." And, you know, you don't want to do it in a patronizing way. But there's a way to do that that is, I think, really helpful. And then you can talk about, okay, well, why are these things failing? And what do we need to change about the code to make sure that we correctly handle those edge cases?
STEPHANIE: Yeah, that's really great. And now, they also have learned a technique for figuring out how to move forward when they think there might be some edge cases. They're like, oh, I could write a test, and they end up [laughs] maybe learning how to do TDD along the way. But yeah, offering that strategy, I think, as a supplement to having supported them in their workflow, I think, is a really cool way to both help them learn a different strategy or tactic while also not asking them to, like, completely change the way that they do their development.
JOËL: So, we've talked about ways that we can coach and mentor in a more of a one-on-one setting. But it can also happen in more of a group setting. And an initiative that I've been involved in recently is, once a quarter, the principals on thoughtbot's Boost team are running a training session on a topic that we choose.
And we chose this month to make it really interactive. We created an exercise. We talked a little bit about it, had people break out into breakout rooms for a pretty short time—it was like 20 minutes—and come up with a solution. And then brought it back to the big group to talk through some of the solutions. All of that within 45 minutes, so it's a very kind of dense-packed thing. And I think it went really well.
STEPHANIE: Yeah. So, hearing that makes me think that the group wasn't actually going to get to a solution in necessarily that short amount of time. But I'm wondering if that was maybe intentional. Like it was never really about coming to the optimal solution but just the act of thinking about it or practicing how you would do that problem-solving without as much of a focus on the outcome.
JOËL: So, yes and no. I think, as you said, the discussion, the journey is more important than the outcome. But also, because we wanted people to have a realistic chance at coming up with some kind of solution, we specifically said, "We don't want code. Don't write a code solution to this." Instead, we suggested people come up with some kind of diagram.
So, the problem was, we have some sort of business process where you start by...you have an endpoint that needs to receive some kind of shopping cart JSON and then goes through a few different steps. You have to validate it. You have to attempt to charge their card, and then eventually, it has to be sent off to a warehouse to be fulfilled.
And so, we're asking them to diagram this while thinking a little bit about data modeling and a little bit about potential edge cases and errors. People came up with some really interesting diagrams for this because there's multiple different lenses from which you could approach that problem.
STEPHANIE: That's cool. I really like that you left it up to the groups to figure out, you know, what kind of tools they wanted to use and the how. You mentioned different lenses. So, I'm taking it that you didn't necessarily share what the steps of starting to consider the data modeling would be. Did you prompt the group in any way? How did you set them up before they broke out?
JOËL: So, we had a document that had a problem definition; part of this involved talking to a few external services, so things like attempting to charge their card. I think there was a user service they needed to do to pull some user information. And then, there's that fulfillment center that we submit to the warehouse with your completed order. And so, we had sample JSONs for all of these. Again, the goal is not for them to write any code that deals with it but more to think about: okay, we need information from this payload to plug into this one. And then, if they want to add any sort of intermediate steps, they can do that.
And I think sort of two common lenses that you could look at this is from more of an action standpoint, so to say, okay, well, first, we receive this payload, and then we make a call to this endpoint, and we try to do a thing and then success or failure, and then kind of go down this path and success or failure, and kind of keep going down that path until you finally reach that fulfillment endpoint.
So, it's almost like a control flow diagram. But you could also take more of a data-centered approach and talk about how the data evolves as it goes through this process. And so, you start with, like, a raw JSON payload. And maybe that gets parsed into a shopping cart object, which then gets turned into a temporary order, which then gets turned into a validated order, which then is combined with a credit card charge to create a fulfillment order, which can then be sent off to the warehouse. And that perspective will completely change the way you think about what the code actually needs to be when you create it.
STEPHANIE: Got it. That's cool. So, I'm curious, you know, what went into figuring out what the prompt would look like? I guess, like, where did you start? Did you already know that there would be these two different ways of thinking about or lenses to data modeling that you're, like, oh, like, maybe these groups will go down this route? Or was it, I guess, a bit of a surprise that when you came together, you found out kind of the different approaches?
JOËL: We already knew that there would be multiple approaches, and we chose not to specify which one to take. I think now this is getting into almost like curriculum design and more kind of the pedagogy side of things, which I'm, you know, excited and passionate about. I don't know, is that something that you've done at all for some of your projects or areas where you've been coaching people?
STEPHANIE: It's not been. But I actually do think it's a bit of a goal of mine to lead a workshop at some point at a conference because I really like the hands-on stuff that I get to do day-to-day, you know, working one-on-one with people. And, you know, I also am on the conference circuit. [laughs] And I was thinking that maybe workshops could be a really cool way to bring together those two things of like, well, I am enjoying that experience of working one-on-one, but it is, oftentimes, you know, just on our regular day-to-day work. And so, I would be really curious about how to develop that kind of curriculum for teaching purposes.
Do you find yourself starting with problems you see on client work and kind of stripping that down into something maybe a little more general, or do these problems kind of just come up spontaneously? [chuckles]
JOËL: So, workshop design is, I think, its own really fascinating topic, and honestly, we could probably do a whole episode on it. But the short of it is I typically work backwards from an end goal. So, just like when I'm writing a blog post, I have one big thing I want people to learn from a workshop, and then everything works backwards from there. Anything that is part of the workshop has to be building towards that big goal, that one thing I want people to learn. Otherwise, I strip it out.
So, it's an exercise in ruthlessly cutting to make sure that I'm not overwhelming people and, you know, that we can fit in the time that we have because there's always not enough time in a workshop. And people can very easily get sidetracked or overwhelmed. So, as much as possible, have everything focusing in towards one goal.
Circling back to the mentoring side of things, I'm curious what you see is maybe some of the biggest challenges as a mentor or a coach.
STEPHANIE: Well, I think, for me, it was, in some ways, like, seeing myself in that role as mentor. Like, oftentimes, that was decided for me by someone else as, like, "Oh, hey. We have a new hire, and, like, would you be their onboarding buddy?" Or, you know, a manager kind of identifying, like, oh, like, Stephanie has been in this role for, you know, a few years now. She's surely ready to mentor [laughs] new folks or people joining the team.
And that was really hard for me because I was like, well, I still have so much to learn [laughs], you know, like, how could I possibly be in that position now? You know, I am still learning from all these other people who are mentors to me.
So, one thing that took me a long time was learning that I did have things that I knew that other people didn't. And I started to think of it more as this, like, ring of overlapping circles where, you know, we all probably do share some common knowledge. But we all are also experts in different things, and everyone always has something to teach. Even if you're just, like, a few months or, like, a year ahead of someone else, that is actually a really powerful spot to cultivate peer mentorship, and where I think learning can really thrive.
There's a really great talk about this by Adam Cuppy called Mentorship in Three Acts, where he talks about that peer mentorship, where someone just knows, like, a little more than someone else. That can be really powerful and can be a good entry point for people who are interested in getting into mentorship but are kind of worried that, like, oh, they are, you know, not a senior yet.
You know, when you're at a similar experience level as who you're working with, there is a little bit less of what we were describing earlier of, like, that dynamic of knowing what to do but kind of wanting to hold back and let them discover for themselves. In that peer mentorship dynamic, you know, both people are, like, really deep in it, kind of trying things out, experimenting, learning, and that ends up being really fruitful time for both of them.
JOËL: Based on your experience, would you say that maybe that's the best place to start for someone who's looking to get into mentorship, so kind of pursue more of a peer mentorship scenario?
STEPHANIE: Yeah. I would definitely say that it has helped me a lot. I've had a lot of peer mentorship relationships in the past, where maybe there just wasn't someone on the team who could mentor me at the time. Or maybe I was wanting to collaborate a little bit more and feeling like I did have some ideas and opinions that I wanted to talk about, or share, or get some feedback on. Reaching across my level was really helpful in starting to create that space.
Yeah, I was really surprised by all the things that I was learning and all the things that the other person was learning from me that I think was a good wealth of experience for me to then bring to the next step when I found myself kind of in that position of supporting others who were more junior.
JOËL: I'd like to also shout out Exercism.io as a great place to get started with mentoring. For those who are not aware, Exercism is a platform where they have a bunch of exercises that you can go through to learn a language. And you can go through them on your own, but you can also go through them with a mentor. Somebody will basically give you a little mini code review on your exercise or maybe help you out if you're stuck. And this all happens asynchronously.
And it's volunteer-run. So, they just have people from the community who volunteer to be mentors on there to help coach people through the exercises. We'll put a link in the show notes to the page they have, kind of explaining how the mentorship works and how to sign up. But I did that for a while. And it was a really rewarding experience for me. I thought that I'd be mostly helping and teaching, but honestly, I learned so much as part of the process.
So, I would strongly recommend that to anybody who wants to maybe dip their toe a little bit in the mentoring coaching world but maybe feels like they're not quite ready for it. I think it's a great way to start.
STEPHANIE: Ooh, that sounds really cool. Yeah, I know that, especially for folks who maybe are working a little bit more independently, or are a bit isolated, or don't have a lot of people on a team that they're able to access; that sounds like a really great solution for folks who are looking for that kind of support outside of their immediate circle.
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.
Stephanie has another debugging mystery to share. Earlier this year, Joël mentioned that he was experimenting with a bookmark manager to keep track of helpful and interesting articles. He's happy to report that it's working very well for him!
Together, they discuss tactics to ensure the easiest route also upholds app health and aids fellow developers. They explore streamlining test fixes over mere re-runs and how to motivate desired actions across teams and individuals.
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's new in your world?
STEPHANIE: So, I have another debugging mystery to share with the group. I was working on a bug fix and was trying to figure out what went wrong with some plain text that we're rendering from a controller with ERB. And I was looking at the ERB file, and I was like, great, like, I see the method in question that I need to go, you know, figure out why it's not returning what we think it's supposed to return. I went down to go check out that method. I read through it ran the tests.
Things were looking all fine and dandy, but I did know that the bug was specific to a particular, I guess, type of the class that the method was being called on, where this type was configured via a column in the database. You know, if it was set to true or not, then that signaled that this was a special thing. You know, I made sure that the test case for that specific type of object was returning what we thought it was supposed to. But strangely, the output in the plain text was different from what our method was returning.
And I was really confused for a while because I thought, surely, it must be the method that is the problem here [laughs]. But it turns out, in our controller, we were actually doing a side effect on that particular type of object if it were the case. So, after it was set to an instance variable, we called another method that essentially overwrote all of its associations and really changed the way that you would interact with that method, right? And that was the source of the bug is that we were expecting the associations to return what we, you know, thought it would, but this side effect was very subvertly changing that behavior.
JOËL: Would it be fair to call this a classic mutation bug?
STEPHANIE: Yeah. I didn't know there was a way to describe that, but that sounds exactly right. It was a classic mutation bug. And I think the assumption that I was making was that the controller code was, hopefully, just pretty straightforward, right? I was thinking, oh, it's just rendering plain text, so not [laughs] much stuff could really be happening in there, and that it must be the method in question that was causing the issues.
But, you know, once I had to revisit that assumption and took a look at the controller code, I was like, oh, that is clearly incorrect. And from there, I was able to spot some, you know, suspicious-looking lines that led me to that line that did the mutation and, ultimately, the answer to our mystery.
JOËL: Was the mutation happening directly in the controller? Or was this a situation where you're passing this object to a method somewhere, and that method, you know, in another object or some other file is doing the mutation on the record that you passed in?
STEPHANIE: Yeah, that's a great question. I think that could have been a very likely situation. But, in this particular case, it was a little more obvious just in the controller code, which was nice, right? Because then I didn't have to go digging into all of these other functions that may or may not be the ones that is doing the mutation. But the thing that was really interesting is that it seems like that method that does this mutating is pretty key to the type of object that we're working with, as in most places it's used, that mutation happens. And yet, it's kind of separated from the construction of that object.
And I was, I think, a little bit surprised that it wasn't super obvious that throughout the application, this is the way that we treat this special object. And I had wished that maybe that was a bit more cohesive or that it was kind of clear that this is how we use this in our domain. And it was, like, lacking that bit of clarity around how things are used in practice as opposed to trying to keep those in isolation.
JOËL: Yeah. Because now you have sort of two different diverging use cases for using this object that are incompatible, one that's trying to use the object as is and the other that's depending on this mutation. Now you can't have both.
STEPHANIE: Right. As far as I can tell, in most cases, you know, we're using it with a mutation, and maybe there is a good reason for those ideas to be separate. But it certainly did not make my life easier trying to solve this particular bug.
JOËL: I'm hearing you mention the idea of ideas being separate; definitely kind of triggers some pathways in my modeling brain, where I'm already thinking, oh, maybe this should be a decorator, or maybe this is just a straight-up transformation. We just have a completely different kind of object rather than mutating the underlying record.
STEPHANIE: Yeah, definitely. I think there could have been some alternative paths taken. At the time, that was kind of decided as the way forward for how to treat this particular domain object. So, that's my fun, little mystery where I got to, you know, play the detective role for a bit. Joël, what's new in your world?
JOËL: So, earlier this year, on an episode of The Bike Shed, I mentioned that I was experimenting with a bookmark manager to kind of keep track of articles that I find are helpful that I might want to reference later on. I wasn't sure if it was going to be worthwhile and mentioned that I'd report back. I'm happy to report that it is working very well for me.
So, the tool is Raindrop.io. They have an app. They have a website. And I have been sort of slowly filling it with some of my most commonly referenced articles. I had pulled some in initially, and then kind of over time, when I find myself referencing an article using my old-fashioned approach, which was just remember the keywords in the title and Google them, now I'll do that, link the article to someone else, and then add it to Raindrop so that the next time I'm starting to look for things, I have these resources available.
And I try to curate a little bit by doing things like tagging them and categorizing them so that when I need references for something, I don't just have to go through my personal memory and be like, oh yeah, what articles do I have on data modeling that I think might be a good fit here? Instead, I can just go to the data modeling section of Raindrop and be like, oh yeah, these five are, like, my favorites that I link to all the time.
STEPHANIE: Wow. We did a whole episode on how to search recently. And we totally forgot to mention things like bookmark managers or curating your own little catalog of go-to articles. In some ways, now you have to search within your bookmark manager [laughs].
JOËL: That's true. Sometimes, it's searching if I'm looking for a particular article, and sometimes, it's more browsing where I'm looking at a category, or a tag, or something like that, which maybe would have been another interesting distinction to explore on the How to Search episode.
I do want to give a shout-out to the most recent article that I looked up in my bookmark manager here, Railway-Oriented Programming. It's an article on how to deal with pieces of code that can error and how to sort of compose those sorts of methods. So, you now have a whole sort of chain of different functions that can error or not in different sorts of ways.
And it uses this really powerful metaphor of railway with different types of junctions and how you might try to, like, fit them all together so that everything connects nicely. And it's just a really beautiful metaphor. And I was doing some work on error handling, in particular, and I wanted to reference something and that was a great resource for that piece of work.
STEPHANIE: Very cool. I'm really intrigued. I love a good metaphor. I am curious: is this programming language and framework agnostic and not about Rails?
JOËL: Actually, so this is written on an F# blog. So, the code is all in F#. And it leans a little bit into some functional programming concepts, but the metaphor is more generic. So, it's a really fun way to think about when you're programming, and you're not just going through the happy path. But what are all the side branches that you might have to deal with, and how do those side branches come back into the flow of your program?
STEPHANIE: Very cool. I can also see some really excellent visuals here if you were to use this metaphor as a way of understanding complexity.
JOËL: Absolutely. In fact, this article has some pretty amazing visuals, so strong recommend. We'll link it in the show notes.
STEPHANIE: So, a few episodes ago, we talked about code ownership at scale because my client project that I'm working on is for a company with hundreds of developers. So, it's quite a big codebase, quite a big team. One of the main issues that I, at least, struggle with on a day to day is flaky tests in CI. When I, you know, I'm wanting to merge a change, I often have to run the test suite a few times to get to green and be able to merge and deploy.
And this is an interesting topic to me because when you're really trying to just get your changes through and mark that ticket as done, it's very tempting to just hit that, you know, retry button and let it sit and just hope for the best, as opposed to maybe investigate a little further about why that test was flaking and see if there's something that you could do about it.
So, I wanted to talk to you about the idea of making the right thing easy or how, at both a team level and an individual level, we can set ourselves and our team up for success rather than shoulder this burden [laughs] and just assume that things are the way they are.
JOËL: That's a really powerful question. Because I think by default, oftentimes, the less helpful thing is the path of least resistance, so, in this case, hitting that rerun button on a test suite, which I've absolutely done. But there's a lot of other situations in our work where, just sort of by default, the path of least resistance is the thing that's maybe less helpful for the team.
STEPHANIE: Ooh, I noticed that you kind of reframed what I said. I was using the term, you know, the right thing, but you then reworded it into the helpful thing. And that actually gets me thinking about these words are kind of subjective, right? What is helpful to someone could be different to what's helpful to someone else. And I'm kind of curious about your definition of the helpful thing.
JOËL: Yeah, I mean, sometimes it's very easy to sort of bring absolutes and [inaudible 11:26] judgments to code, you know, when we talk about writing good code, and being good programmers, being good at our jobs, not doing the bad things. And I think that sort of absolutism sometimes can, like, be very restrictive, and kind of takes us down paths that are not optimal for ourselves, for our teams, for our products. So, I'd like to think a little bit more relativistically have a little bit more of elasticity in the way that we formulate some of these ideas.
STEPHANIE: Yeah. I really like that reframing, and I appreciate the nuance there. I think for me, when I think of doing the helpful thing, I'm hoping to ease the day-to-day workflow for other developers because that also includes myself, right? Like, I've certainly been there feeling frustrated or just kind of tired of retrying [laughs] the test suite over and over again.
I'm also thinking about helpful, as in what will be helpful for future developers regarding the product? And can we make it robust now so that we're not dealing with bug reports later for things that we maybe we're trying to throw under the rug or just kind of glance over? Do you have any other guiding principles around what is helpful and what's not?
JOËL: I think that the time horizon you mentioned is really interesting because you have to balance sometimes short-term value versus kind of long-term. And is it worth it to maybe not fix that flaky test today so that we can ship as soon as possible? Or is it worth investing a little bit of time today so that tomorrow or next week is better? If you're a solo developer on a tiny project, that might be of personal benefit only. But on a larger team, you know, that might benefit not just you but a larger amount of people.
STEPHANIE: I just imagined the trolley problem [laughs] a little bit about, you know, the future developers and whose lives, not lives but whose happiness, the developer happiness you'll save [laughs] when you're on that track and making the decision about benefit now versus benefit later.
JOËL: No connection to railway-oriented programming, by the way.
STEPHANIE: I am really interested in also talking about barriers to doing the helpful thing or taking that extra step, right? Because I think identifying those barriers is really important to then, hopefully, break them down so that we are creating that path of least resistance.
JOËL: That's interesting that you mentioned these as barriers because I think, in my mind, I was thinking about the same idea but from, like, a completely mirror perspective, the idea of incentives. Why do incentives push you in one way versus the other?
STEPHANIE: I like that a lot. I think maybe there are, like, two different levers, right? Or maybe they are two sides of the same coin, where you do have incentive, and then you also have things that disincentivize you.
JOËL: This reminds me a little bit of the idea of the tragedy of the commons. So, in the case of flaky tests, everybody as a whole on your project has a worse experience. And project velocity slows when there are flaky tests. But you, as an individual developer, are incentivized to ship features quickly and efficiently. And the fastest way you can get your individual feature to production is by hitting that rerun button. Even though, collectively as a whole, every time we do that, instead of fixing the flakiness, we're adding a tiny, little bit of extra slowness that will accrete over time.
STEPHANIE: Yeah. It's kind of difficult to imagine really the negative impact that it's having collectively, right? You're kind of like, oh, I'm feeling this pain, but you're not always, like, really hearing about it from others, and we might just be silently suffering together [laughs]. I do think that once it's been identified as like, oh, like, we're all actually, like, really impacted by this, okay, great, let's make it a priority.
And so, now, let's say I am slightly incentivized to go and investigate the flakiness of a test rather than hit the rerun button this time around. I am wanting to talk about those barriers I was referring to a little bit because I've been in this position where I'm like, okay, like, I have some extra time today. So, why don't I look into this?
But then I go down that path, and now I'm looking at a test written by someone many years ago, you know, I don't know this person, and I don't know this domain. I don't know who to talk to to figure out even where to start. I may or may not feel equipped with the right tools to be able to address it.
And then, I think the biggest challenge is not feeling like it matters, right? Once I'm hitting this barrier, I'm like, is it worth the effort? At that point, maybe a little bit demoralized because, well, this is just one, and we have so many other flaky tests, like, what's one more?
JOËL: That's really interesting that you mentioned that sort of morale factor because it's absolutely the case on every flaky test suite I've seen. I think that kind of points to almost, like, an exponential cost to ignoring the problem. If someone fixed it early, yeah, it's slightly annoying, but you get it done. You fix it, and then you move on. When it feels like there's now this insurmountable pile of these and that any work you do here doesn't bring you any closer to the goal because it's effectively infinite, yeah, now, there is no incentive at all to do that work.
STEPHANIE: So, to avoid that, we talked about incentives, right? And I'm kind of curious: what ways have you seen or experienced that did make you feel motivated to take that extra step or at least try to avoid that point of thinking that nothing matters? [laughs]
JOËL: So, I'm going to start with, I think, what's maybe a classic developer answer, and I'm curious to get your thoughts on it because I think I have very mixed feelings about this. The idea of programmer discipline—we just need to kind of take more pride in our craft and pursue excellence, choose to do the right thing, even when it's hard every day. Because I hear a lot of that in our communities. How do you feel about that sort of maybe a bit of a mindset change? And how effective has that been?
STEPHANIE: Whoa, yeah, that's a really great point because I think I also feel quite conflicted about it. Because sometimes I can find it in myself to be, like, you know, I have the energy today to want to uphold, like, a certain level of quality that would make me feel good about doing my best work. And then, there are other days where I am, you know, just tired, [laughs] or feeling a little bit lazy, feeling just not confident that it will be worth it. Because there's also, I think, some external forces, right?
I've certainly been in the position where we were only rewarded or celebrated for shipping fast. That was the praise we were getting at retros. But then that actually really disincentivized me from wanting to do the helpful thing when the time came, right? When I'm in my development process, and I'm at, like, that crossroads. Because I'm like, well, I've been trying to do the right thing, but, like, no one is celebrating me for it. What if it takes away time from doing the thing that is considered successful? And, like, does it have an impact on me and my job?
So, you can, you know, kind of go down that spiral pretty quickly. And, in that case, like, no amount of personal, like, individual [laughs] feelings of responsibility can really overcome those consequences if, like, you're working on a team where that is just simply not valued, and there are other people who have authority to impart consequences, I suppose.
JOËL: Yeah. It's, you know, you have that maybe some amount of personal motivation. You feel like you're swimming upstream. And so, maybe the question then is, how do we reorient maybe some of the incentive structures in a team to try to make it so that if you are, let's just say, chasing some of those extrinsic rewards and you're trying to get praise from your teammates, or move forward in your career, whatever it is that is rewarded and valued on your team, how can that be harnessed to push people in a direction to get some of these extra tasks done?
STEPHANIE: Yeah. I will say, though, it is a little bit of both. And I think that was maybe why we're both kind of conflicted about it. Because on the individual level and, in general, knowing what my values are and, like, wanting to do good work and uphold quality, there are times where I don't always behave according to those values. Like I said, I am feeling tired, or maybe it's, like, almost 5:00 o'clock, and I just want to, you know, push my thing [laughs] so I can go and go on with my day.
What has helped me is having an accountability buddy. Maybe it's in code review, or maybe it's when I'm pairing, or maybe just talking about a problem that we're facing, right? And I might get into that sort of lizard-brain mentality of just wanting to do the easy thing. But as soon as someone else points it out or is, like, you know, like, "That's not quite aligning with what I know your, like, hopes and goals are for this project or how you want to do your work," usually, that's enough to be like, "Yeah, you're right." [laughs] And I'll take another pass at it.
JOËL: And I think we've kind of come back full circle here in that you mentioned that sort of the lizard brain side of you wants to just do the easy thing with the implication that, in this case, the easy thing is the thing that's maybe not useful to the team long term. What if we could restructure things a little bit so that the easy thing was the most beneficial thing for the team? And now you're not having to use discipline to fight the lizard brain side of you, but you're actually working with it.
One thing I've seen teams do with flaky tests is to not necessarily fix them immediately. Like, maybe you do rerun them, but when they happen, create a ticket for them and put them into the planning board. And so, now, these are things that get prioritized. They're things that might be fairly quick to do. So, it might be a fun, like, fast ticket for someone to pick up at the end of the week. It now counts towards velocity if tracked, so people, hopefully, get rewarded for doing that work. Is that something that you've seen? And how effective do you think that is in maybe making fixing flaky tests easier thing for a team?
STEPHANIE: Yeah, that is actually something that we are doing on my team right now, and I think it's great. I like the idea of tracking it, right? Because then you could also see over time, like, whether we have been getting better at reducing flaky tests, you know, then it's also really clear when someone is preoccupied with that work, and they don't get assigned something else.
One way that I've seen it not work as well as we hoped is when other work consistently gets prioritized over those flaky test tickets, and, you know, sometimes it happens. I think that's also information, though, about the team and how the team is spending its time compared to how the team thinks it should be ideally spending its time where, you know, we can say all we want, like, yes, like, we really want to make sure our test suite is robust. But when other things are consistently getting prioritized over it, then you can point to it and say, do we actually believe this if we're consistently not behaving according to that belief?
I found that challenging to have that conversation. But I do think that the concreteness of adding it to our workload for a given period of time is at least providing information rather than it being things that, like, developers are doing one-off or kind of just on their own time.
JOËL: Another solution that I've seen people do, and this is a classic developer solution, is tooling. If you have better tooling around a particular problem, sometimes you can shift that cost, that time of work it takes so that it's easier to do the best thing rather than to not...or at least make it easy enough that it's less of a big decision, like, oh, do I really want to invest that much work into something?
And a classic example of this, I think, is when you're trying to get into more of a test-driven development workflow. Having a test suite that's fast and, really importantly, having a near-instant way to run a test from your code editor makes a big difference in terms of adopting that workflow.
Because if the cost of running a test is too high, then yeah, the easy path is to just say, you know what? I'm not going to run a test. I'm going to just run it once at the end after I've written 100 lines of code or an entire feature. And now I am not getting the benefits of TDD. And that might kind of get into a negative cycle where because I'm not seeing the benefits, I do it even less. And then eventually, I'm just, like, you know what? Forget this whole thing.
STEPHANIE: I think that also applies to testing in general, where if it, you know, is feeling really challenging. I have definitely seen people start to get into that mindset of, is this worth my time to do at all? And it's a very slippery slope, I think.
That almost makes me think about, like, okay, like, what are some other ways to lift that task up and to elevate it into something that's worthy of saying, like, "Hey, like, that was really hard, and you did a great job. And that was really awesome that you persevered through that challenging thing." Sharing the pain points is really important, not only to, like I mentioned earlier, to, like, communicate that, oh, maybe, like, more people than you think are going through the same thing, but also to be able to identify when someone went out of their way to do the helpful thing and seeing that someone was willing to do it because, for them, being helpful is important.
When I see someone on my team take on kind of a difficult task to make things easier for others and then share about it, I feel really inspired because I think, wow, like, that could be me as well. You know, there's that saying that many hands make light work. And I also think that's true of tackling these kinds of barriers, where if we all feel this collective responsibility or, like, wanting to help out the group, it ends up literally being easier.
JOËL: I think something I'm hearing here as well is the value of giving praise. If somebody goes out of their way to make life easier for the rest of your team, give them a shout-out, whether that's in your team's Slack channel, maybe it's at an all-hands meeting, and you shout out some work that they've done or, you know, you put their name on a slide in your slide deck at some point, or whatever it is the mechanism within your team. Having a way to shout out people who've done some of this work that can be sometimes a little bit thankless is a great way to motivate seeing more of that.
STEPHANIE: Yeah. I was just thinking that it can be really powerful because, like you said, a lot of it is thankless, but also, we may not even realize the impact it's having on others until you give that shout-out and express, like, "Wow, like, that change, you know, I've been bothered by this issue for so long and, you know, that really made an impact on me," just keeping that cycle of gratitude going.
JOËL: So, I think we've kind of identified three maybe main areas of ways where you can help to incentivize these behaviors. You can do it through kind of process. We talked about the example of pulling the flaky tests as actual cards to be worked through on a board.
It can be technical by introducing some tooling that makes it much easier to do the work that you're trying to do.
And it can be personal by praising people, preferably in public, for taking that extra step. And I think all three of those can be part of a strategy to make it easier or more attractive for people to do work that benefits the team as a whole, even if they don't see an immediate return to that on a per-day level.
STEPHANIE: Yeah. I like that we kind of talked about these three different categories. And people in all different types of roles can, hopefully, take something from what we've shared, right? If you are a manager or leader of a team, maybe you can investigate your processes. If you're an individual contributor and you notice your colleague doing something that you, you know, kept meaning to but just didn't have time for, recognize that work. It really does take a holistic approach, but I think an impact can be made at every level.
JOËL: Agreed. I think for managers and more senior team members, that's really almost, like, part of their job description is to think about these kinds of things. How can we incentivize this work? How can we shift the team in a particular direction? There's a particular onus on them to do this right, to think about this, to model some of this behavior.
STEPHANIE: Yeah, absolutely.
JOËL: For someone who's really senior on a team also, they're often the ones who are tasked or who maybe take the initiative to build some of this more complex tooling so that these tasks are easier for more junior people. Maybe that's tinkering with some things and building an editor plugin that makes it easier to do some work. Maybe it's building a Rails generator so that the proper files get generated that maybe people wouldn't think to have when they're building certain work. Maybe it's building an RSpec matcher to make it easier for people to test some of the nuances of what we're hoping to do, catching some of these edge cases.
Whatever it is, sometimes there are things that the more junior members of our teams aren't aware of, and having a senior person take time out of their day to build these things so that now the entire team can be more productive can be a really helpful thing to do.
STEPHANIE: Yeah, that's a great point. And I think that also comes from having a pulse on what people are struggling with, right? So, you know, oh, it would be good to invest my energy into building a script to make this manual process easier because I keep hearing about people having issues with it or it being a challenge.
So, I would even recommend posing the question of, like, how do people feel about being able to fix that flaky test, right? Like, is it intimidating? What are those barriers? Because your team knows best about what that experience is like. And if that is not something on your radar, maybe there are opportunities to incorporate it into where you're evaluating team morale and happiness.
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: 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.
Joël shares he has been getting more into long-form reading. Stephanie talks about the challenges she faced in a new project that required integrating with another company's system.
Together, they delve into the importance of search techniques for developers, covering various approaches to finding information online.
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: Something I've been trying to do recently is get more into long-form reading. I read quite a bit of technical content, but most of it are short articles, blog posts, that kind of thing. And I've not read, like, an actual software-related book in a few years, or at least not completed a software-related book. I've started a few chapters in a few. So, something I've been trying to do recently is set aside some time. It's on my calendar. Every week, I've got an hour sit down, read a long-form book, and take notes.
STEPHANIE: That's really cool. I actually really enjoy reading technical stuff in a long-form format. In fact, I was similarly kind of trying to do it, you know, once a week, spend a little bit of time in the mornings. And what was really nice about that is, especially if I had, like, a physical copy of the book, I could close my computer and just be completely focused on the content itself.
I also love blog posts and articles. We are always talking on the show about, you know, stuff we've read on the internet. But I think there's something very comprehensive, and you can dig really deep and get a very deeper understanding of a topic through a book that kind of has that continuity.
JOËL: Right. You can build up a larger idea have more depth. A larger idea can also cover more breadth. A good blog post, typically, is very focused on a single thing, the kind of thing that would really probably only be a single chapter in a book.
STEPHANIE: Has your note-taking system differed when you're applying it to something longer than just an article?
JOËL: So, what I try to do when I'm reading is I have just one giant note for the whole book. And I'm not trying to capture elements or, like, summarize a chapter necessarily. Instead, I'm trying to capture connections that I make. So, if there's a concept or an argument that reminds me of something perhaps similar in a different domain or a similar argument that I saw made by someone else in a different place, I'll capture notes on that. Or maybe it reminds me of a diagram that I drew the other day or of some work I did on a client six months ago.
And so, it's capturing all those connections is what I'm trying to do in my notes. And then, later on, I can kind of go back and synthesize those and say, okay, is there anything interesting here that I might want to pull out as an actual kind of idea note in my larger note-taking system?
STEPHANIE: Cool, yeah. I also do a similar thing where I have one big note for the whole book. And when I was doing this, I was even trying to summarize each chapter if I could or at least like jot down some takeaways or some insights or lines that I like felt were really compelling to me. And, like, something I would want to, in some ways, like, have created some, like, marker for me to remember, oh, I really liked something in this chapter. And then, from there, if I didn't capture the whole idea in my note, I knew where I could go to revisit the content.
JOËL: And did you find that was helpful for you when you came back to the book?
STEPHANIE: Yeah, it did. I usually can recall how, like, I felt reading something. You know, if something was really inspiring to me or really relatable, I can recall that, like, I had that experience or emotion. And it's just, like, trying to find where that was and that this is a system that has worked well for me.
Though, I will say that summarizing each chapter did kind of remind me of, like, how we learned how to take notes in school. [laughs] And I think, you know, middle school, or whatever, I recall a particular note-taking format, where you, you know, split the page up into, like, an outline with all the chapters, and you tried to summarize it. And so, it did feel a little bit like homework [laughs]. But I can also see the value in why they taught me how to do that.
JOËL: I was recently having a conversation with someone else about the idea of almost, like, assigning yourself the college-style essay question after finishing a book to try to synthesize what you learned.
STEPHANIE: Whoa, that's really cool. I can see how that would really, like, push you to synthesize and process what you might have just consumed. And, also, I'm so glad I'm not in school anymore [laughs] so that I don't have to do that on a regular basis. [laughs] I'm curious, Joël, what book are you reading right now?
JOËL: I've been reading Domain Modeling Made Functional, which is a really interesting intersection between functional programming, Domain-Driven Design (DDD), and a lot of interesting kind of type theory. And so, that sort of intersection of those three Venn diagrams leads to this really fascinating book that I've been going through. And I think it connects with a lot of other things that I've been thinking about.
So, I'll be reading and be like, oh, this reminds me of this concept that we have in test-driven development. Or this reminds me of this idea that we do when we do a product design sprint. And this reminds me of this principle from object-oriented design. And now I'm starting to make all these really interesting connections.
STEPHANIE: Awesome. Well, I hope to hear more about what you've learned or kind of what you're thinking about going through this book in future episodes.
JOËL: This is not the last time we hear about this book, I'm pretty sure. So, Stephanie, what's new in your world?
STEPHANIE: So, I have a little bit of a work update to share. So, lately, I've been brought in to work on a feature that is integrating with another company's system. And the way that I was brought into this work was honestly just being assigned a task. And I was picking up this work, and I was kind of going through the requirements that had been specked out for me, and I was trying to get started. And then, I realized that I actually had a lot of questions. It just wasn't quite fully fleshed out for the level of detail that I needed for implementing.
And for the past couple of weeks, we've been chatting in Slack back and forth as I tried to get some of my questions answered. They are trying to help me, but also the things that I'm saying end up confusing them as well. And then, I end up having to try and figure out what they're looking for in order to properly respond to them.
And I had not met these people before. These are folks from that other company. And, you know, I'd only just seen their little Slack profile pictures. So, I didn't know who they were. I didn't know what role they had and kind of, like, what perspective they were coming to these conversations from. And after a while, I was feeling a little stressed out because we just kept having this back and forth, and not a lot of answers were coming to fruition.
And I really ended up needing the nudge of the manager on my client team to set up a meeting for us to all just talk synchronously. And I think I had...not that I had been avoiding it necessarily, but I guess I was under the impression that we were at the point where we could just, you know, shoot off a question in Slack and that there would be a clear path forward. But the more we kept pulling on that thread, the more I realized that, oh, like, we have a lot of ambiguity here.
And it really helped to meet them finally, not in person but, like, over a video call. [laughs] So, this happened yesterday. And, you know, even just, like, going around doing introductions, like, sharing what their role was at the company helped me just understand, like, who I was talking to. You know, I realized, oh, like, the level of technical details that I had been providing was maybe too much for this group.
And I was able to have a better understanding of what their needs were, like hearing kind of the problem that they had on their end. And I realized that, oh, like, they actually aren't going to provide me the details for implementation that I was looking for. That's up to me. But at least now I know what their higher-level needs are so that I can make the most informed decisions that I can.
JOËL: Fascinating. So, you thought that this was going to be, like, the technical team you're going to work with. And it turns out that this was not who they were.
STEPHANIE: In some ways. I think I thought by providing more technical details that would be helpful, but it ended up being more confusing for them. And I think I was similarly kind of frustrated because the ways that I was asking questions or communicating also wasn't getting me the answers that I needed as well.
But I felt really great after the meeting because I'm like, wow, you know, it doesn't have to be as stressful. You know, when you start getting into that back and forth on Slack, at least I find it a bit stressful. And it turns out that the antidote to that was just getting together and getting to know each other and hashing out the ambiguity, which does seem to work better in a more synchronous format.
JOËL: Do you have kind of a preference for synchronous versus asynchronous when it comes to communication?
STEPHANIE: That's a good question. I think it's kind of a pendulum for me. I'm in my asynchronous communication is a bit better for me right now phase, but only because I am just so burnt out on meetings a lot of the time that I'm like, oh, like, I really don't want to add another meeting to my calendar, especially because...I amend my statement; I'm burned out of meetings that don't go well. [laughs]
And this meeting, in particular, was different because, you know, I realized, like, oh, like, we are not on the same page, and so how can we get there? And kind of making sure that we were focused on that as an agenda. And I found that ultimately worked out better than the async situation that I was describing, which I'm thinking now, you know when things aren't clear, text-based communication certainly does not help with that.
JOËL: So, meetings, sometimes they're actually good.
STEPHANIE: Yeah, that's my enlightened discovery this week.
JOËL: So, this episode is kind of a special one. We've just hit 400 episodes of The Bike Shed. So, this is episode number 400. It's also my 50th Episode as a co-host.
STEPHANIE: Right. That's a huge deal. 400 is a really big number. I don't know if I've ever done 400 of anything before [laughs].
JOËL: The Bike Shed has been going on for almost ten years now. The first episode up on the website is from October 31st, 2014, so just about nine years from that first episode.
STEPHANIE: Wow. And it's still going strong. That's really awesome. I think it's really special to be a part of something that has been going on for this long. And, I don't know, maybe there are still listeners today from back in 2014. I would be really excited to hear if anyone out there has been listening to The Bike Shed throughout its whole lifespan. That's really cool.
JOËL: Looking back over the last 50-ish episodes you and I have done, do you have a favorite episode that we've recorded?
STEPHANIE: This may be a bit of recency bias. But the episode that we did about Software Heuristics I really enjoyed. Because I think we got to bring to the table some of the things we believe and the way we like to do things and kind of compare and contrast that with each other. And I always find people's processes very fascinating. Like, I want to know how you think and where your brain is at when you approach a problem. So, I really enjoyed that topic. What about you? Do you have any highlight episodes?
JOËL: I think there's probably two for me. One is the episode that you and I did on Specialized Vocabulary. I think this really touched on a lot of really interesting aspects of writing software that's going to scale, software that works for a team, and also kind of personal growth and exploration.
The second one that I think was really fun was the episode I did with Sara Jackson as a guest talking about Discrete Math because that's an episode that I got really excited about the topic. And right after recording the episode, it was the last day of the call for proposals for RailsConf. And I just took that raw excitement, put together a proposal, hit submit before the deadline. And it got accepted and got turned into a talk that I got to give on stage. So, that was, like, just a really fun journey from exciting episode with Sara and then, like, randomly turned into a conference talk.
STEPHANIE: That's awesome. That makes me feel so happy. Because it just reminds me about how the stuff we talk about on the show can really resonate with people, you know, enough to become a conference talk that people want to attend.
And I also really like that a lot of the topics we've gotten into in the past 50 episodes when we've taken over the show have been a bit more evergreen and just about, you know, the software development experience and a little bit less tied to specific news within the community.
Speaking of evergreen topics, today, I wanted to discuss with you an evergreen software skill, and that is searching or Search-Driven Development, even if you will.
JOËL: Gotta always get that three-letter acronym, something DD.
STEPHANIE: Yeah. I am really curious about how we're going to approach this topic because a lot of folks might joke that a big part of writing software is knowing what to Google. Do you agree with that statement or not?
JOËL: Yes and no. There's definitely value in knowing what to Google. It really depends on the kind of work that you're doing. I find that I don't Google that much these days. There are other tools that I use when I'm particularly, like, searching through documentation, but they tend to be less sort of open-ended questions and more where it's like, oh, let's get the actual documentation for this particular class or this particular method from the standard library.
STEPHANIE: Oh, interesting. I like that you pointed out that there are different scopes of things you might want to search for. So, am I hearing correctly that when you have something specific in mind that you are just trying to recall or wanting to look up, you know, you're still using search that way, but less so if you are trying to figure out how to approach solving a problem?
JOËL: So, oftentimes, if I'm working with a language that I already have familiarity with or a framework that I have familiarity with, I'm going to lean on something more specific. So, I'm going to say, okay, well, I don't exactly remember, like, the argument order for Enumerable's inject method. Is it memo then item, or item then memo? So, I'll just look it up. But I know that the inject method exists. I know what it does. I just don't remember the exact specifics of how to do that.
Or maybe I want to write a file to disk, and I don't remember the exact method or syntax to do that. There are some ways that you can do it using a bunch of instance methods. But I think there's also a class method that allows you to kind of do it all at once. So, maybe I just want to look up the documentation for the file class in Ruby and read through that a little bit. That's the kind of thing where I suppose I could also Google, you know, how to save file Ruby, something like that. But for those sorts of things where I already roughly know what I want to do, I find it's often easier just to go directly to the docs.
STEPHANIE: Yeah, yeah, that's a great tip. And I actually have a little shortcut to share. I started using DuckDuckGo as my search engine in the past year or so. And there's this really cool feature called Bangs for directly searching on specific sites. From my search bar, I can do, let's say, bang Rails and then my query. And it will search directly the Rails Guides website for me instead of, you know, just showing the normal other results that might come up in my regular search engine. And the same goes for bang Ruby doc. That one shows ruby-doc.org, which is my preferred [laughs] Ruby documentation website.
I've really been enjoying it because, you know, it just takes that extra step out of having to either navigate to the site itself first or starting more broadly with my search engine and then just scrolling to find the site that I'm looking for.
JOËL: Yeah. I think having some kind of dedicated flow helps a lot. I have a system that I use on my machine. It is Mac-specific. But I use a combination of the application Dash and the application Alfred. It allows me, with just a few keyboard shortcuts, to type out language names. So, I might say, you know, Ruby inject, and then it'll show me all the classes that have that method defined on it, hit Enter, and it pops up the documentation. It's downloaded on my machine, so it works offline. And it's just, you know, a few key presses. And that works really nicely for me.
STEPHANIE: Oh, offline search. That's really nice. Because then if you're coding on a plane or something, then [laughs] you don't have to be blocked because you can't look up that little, small piece of information you need to move forward. That's very cool.
JOËL: That is really cool. I don't know how often I've really leaned into the offline part of it. I don't know about you; I feel like I don't code on airplanes as much as I thought I would.
STEPHANIE: That's fair. I also don't code on airplanes, but the idea that I could is very compelling to me. [laughs]
JOËL: Absolutely. So, that's the kind of searches that I tend to do when I'm working in a language that I already know, kind of a day-to-day language that I'm using, or a framework that I'm already pretty familiar with. And this is just looking at all the things I haven't gotten to the point where I've fully memorized, but I have a good understanding of.
What about situations where maybe you're a little bit less familiar with? So maybe it's a new framework, or even, like, a situation where you're not really sure how to proceed. How do you search when there's more uncertainty?
STEPHANIE: Yeah, that's a good question. I do think I start a bit naively. The reason that we're able to be more specific and know exactly where to go is because we've built up this experience over time of scrolling through search results and clicking, you know, maybe all of them on the first page, even, and looking at them and being like, oh, like, this is not what I want. And then, seeing something else, it's like, oh, this is more helpful and kind of arrived at sources that we trust.
And so, if it's something new, I don't really mind just going for a basic search, right? And starting more broadly might even be helpful in that process of building up the experience to figure out which places are reputable for the thing that I'm trying to figure out.
JOËL: Yeah, especially when there's a whole new landscape, right? You don't really know what are the places that have good information and the ones that don't. For some things, there might be, like, an obvious first place to start. So, recently, I was on a project where I was trying to do an integration between a Rails app and a Snowflake data warehouse. And so, the first thing I did—I'm not randomly Googling—I went to the Snowflake website, their developer portal, and started reading through documentation for things.
Unfortunately, a lot of the documentation is a bit more corporatey and not really helpful for Ruby-specific implementation. So, there's a few pieces that were useful. There were some links that they had that sent me to some good places. But beyond that, I did have to drop to Google search and try to find out what kinds of other things the community had done that could be helpful.
Now, that first pass, though, did teach me some interesting things. It gave me some good keywords to search for. So, more than just Ruby plus Snowflake or something like that like, I knew that I likely was going to want to do some kind of connection via ODBC. So, now I could say, okay, Ruby plus ODBC integration, or Ruby plus ODBC driver and see what's happening there. And it turns out that one of the really common use cases for ODBC and Ruby is specifically to talk to Snowflake. And one of the top results was an article saying, "Hey, here's how you can use ODBC to get your Rails app to talk to Rails." And then I knew I struck gold.
STEPHANIE: That's really cool. The thing that I was picking up on in what you were saying is the idea of finding what is most relevant to you. And maybe that is something that the algorithm serves you because, like, it's, like, what a lot of people are searching for, you know, a lot of people are engaging with, or matching with all these keywords that you're using.
My little hack that I've been [chuckles] using is to use Slack and lean on other people who have maybe a little more, even just, like, a little more experience than me on the subject, and seeing, like, what things they're linking to, and what resources they're sharing. And I've found that to be really helpful as a place to start. Because, at that point like, my co-workers are narrowing down the really broad landscape for me.
JOËL: I really like how you're sort of you're redefining the question a little bit here. And that, I think, when we talk about search, there's almost this implicit assumption that search is going to be searching the public internet through Google or some other alternative search engine. But you're talking about actually searching from my private corpus of data, in this case, either thoughtbot or maybe the client's Slack conversations, and pulling up information there that might be much more relevant or much more specific to the work that you're trying to do.
STEPHANIE: Yeah. In some ways, I like to think of it as crowd-sourced but, like, a crowd that I trust and, you know, know is relevant to me and what I'm working on. I actually have a fun fact for you. Did you know that Slack is actually an acronym?
JOËL: No, I did not know that. What does it stand for?
STEPHANIE: It stands for Searchable Log of All Communication and Knowledge.
JOËL: That is incredibly clever. I wonder, is this the thing where they came up with that when they made the original name? Or did someone go back later on, you know, a few years into Slack's life and was like, you know what? Our name could be a cool acronym; here's an idea.
STEPHANIE: I'm pretty sure it was created in Slack's early days. And I think it might have even helped decide that Slack was going to be called Slack as opposed to some of the other contenders for the name of the software. But I think it's very accurate. And that could just be how I use Slack. I'm a very heavy search power user in Slack. [laughs]. So, I find it very apt.
You know, obviously, I use it a lot for finding conversations that happened. But I really do enjoy it as a source of discovery for a specific topic, or, you know, technical question or idea that I'm wanting to just, like, filter down a little bit beyond, like you said, the public internet. In fact, I have found it really useful for when you encounter errors that actually are specific to your domain or your app.
Obviously like, you will probably be less successful searching in your search engine for that because it includes, you know, context from your app that other people in the world don't have. But once you are narrowing it down to people at your company, I've been able to get over a lot of troubleshooting humps that way by searching in Slack because likely someone within my team has encountered it before.
JOËL: So, you mentioned searching for error messages in particular. And I feel like that is, like, its own, like, very specific searching skill separate from more general, like, how do I X-style questions. Does that distinction kind of line up with your mental map of the searching landscape?
STEPHANIE: Yeah. I guess the way that I just talked about it now was potentially a bit confusing because I was saying instead of how you might search for errors normally, but I did not talk about how you might search for errors normally. [laughs] But specifically, you know, if I'm popping error messages into my search engine, I am removing the parts of the stack trace that are specific to my app, right? Because I know that that will only kind of, like, clutter up my query and not be getting me towards a more helpful answer as to the source of my issue, especially if the issue is not my application code.
JOËL: Right. I want to give a shout-out to an article on the thoughtbot Blog with a wonderful name: Indiana Jones and the Crypt of Cryptic Error Messages by Louis Antonopoulos. All about how to take an error message that you get from some process in your console and how to make that give you results when you paste it into a search engine.
STEPHANIE: I love that name. Very cool.
JOËL: So, you've talked a little bit about the idea of searching some things that are not on the public internet. How do you feel about kind of internet knowledge bases, private wikis, that kind of thing? Have you had good success searching through those kinds of things?
STEPHANIE: Hmm, I would say mixed success, to be honest. But that's because of maybe more so the way that a team or a company documents information. The reason I say mixed results is because, a lot of the time, the results are outdated, and they're no longer relevant to me. And it doesn't take that much time to pass for something to become outdated, right? Because, like, the code is always changing. And if, you know, someone didn't go and update the documentation about the way that a system has changed, then I usually have to take the stuff that I'm kind of seeing in private wikis with a bit more skepticism, I would say.
JOËL: Yeah, I think my experience mirrors yours as well. Also, some private wikis have just become absolutely huge. And so, searches just return a lot of results that are not really relevant to what I'm searching for. The searching algorithms that these systems use are often much less powerful than something like Google. So, they often don't sort results in a way that are bringing relevant things up to the top. So, it's more work to kind of sift through all of the things I don't care about.
STEPHANIE: Yeah, bringing up the size of a wiki and, like, all of the pages, that is a good point because I see a lot of duplicate stuff, but that's just, like, slightly different. So, I'm not sure which one I'm supposed to believe. One really funny encounter that I had with a private wiki, or actually it was, like, a knowledge base article that was for the internal team...it was documenting actually a code process. So, it was documenting in more human-readable terms, like the steps an algorithm took to determine some result. But the whole document was prefaced by, "This information came from an email that was sent way long ago." [laughs]
JOËL: That's an epic start to a Wiki article.
STEPHANIE: Yeah. And there was another really funny line that said, "The reason for this logic is because of a decision made by (This person's name.)," like a business decision that (some random person name). No last name either, so I have no idea [laughs] who they could be referring to and any of the, like, historical context of why that happened. But I thought it was really funny as just a piece of, like, an artifact, of, at the time, when this was written, that meant something to someone, and that knowledge kind of has been diluted [laughs] over the years.
JOËL: Yeah, internal wikis, I feel like, are full of that, especially if they've had a few years to grow and the company has changed and evolved.
So, now it's time for hot takes.
STEPHANIE: Yeah, I'm ready for them.
JOËL: We are now in the fancy, new age of AI. Is ChatGPT going to make all of this episode obsolete?
STEPHANIE: I'm going to say no, but I'm also biased, and I'm not a ChatGPT enthusiast. I've said it on air. [laughs] I can't even say that I've used it. So, that's kind of where I'm coming from with all this. But I have heard from folks that, convenient as it may be, it is not always 100% accurate or successful.
And I think that one of the things I really like about kind of having agency over my search is that I can verify, as a human, the information that I'm seeing. So, you know, when you're, like, browsing a bunch of Stack Overflow questions and you see, you know, all these answers, at least you can, like, do a little bit of, like, investigation using context clues about who is answering the question, you know, like, what experience might they have?
If you encounter something on a blog post, for example, you can go to the about page on this person's blog and be like, who are you? [chuckles] And, like, what qualifies you to give this information? And I think that is really valuable for me in terms of evaluating whether I want to go down a path based on what I'm seeing.
JOËL: So, I've played with it a tiny, little bit, so not enough to have a good sample size. And I think it can be interesting for some of those less constrained kind of how do I style questions. I'm not necessarily looking for, like, an exact code sample. But even if it just points me towards, oh, I need to be looking at this particular class in this standard library and read through that documentation to build the thing that I want. Or maybe it links me to kind of the classic blog posts that people refer to when talking about this thing.
It's a good way sometimes to just narrow down when you're kind of faced with, you know, the infinity of the internet, and you're kind of like, oh, I don't even know where to start. It gives you some keywords or some threads to follow up on that I think can be really interesting.
STEPHANIE: The infinity of the internet. I love that phrase. I don't think I've heard it before, but it's very evocative for me [laughs]. And I like what you said about it helping you give a direction and to kind of surface those keywords. In fact, it almost kind of sounds like what I was mentioning earlier about using Slack for, right? And, in that case, the hive mind that I'm pulling from is my co-workers. But also, I can see how powerful it would be to leverage a tool that is guiding you based on the software community at large.
JOËL: Something I'd be curious to maybe lean into a little bit more are some of those slightly more specified questions where it does give you a code snippet, so something like writing a file to disk where, right now, it's, you know, five characters. I just pop up Alfred and type up Ruby F, and it gives you the file docs, and it's, you know, right there. There's usually an example at the top of the file. I copy-paste that and get working.
But maybe this would be a situation where some AI-assisted tools would be better. It could be searching through something like ChatGPT. It could be maybe even something like Co-pilot, where, you know, you just start typing a little bit, and it just fills out that skeleton of, like, oh, you want to write a file to disk in Ruby. Here's how it's typically done.
STEPHANIE: Yeah, you bring up a good point that, in some ways, even the approaches to searching we were talking about originally is still just building off of algorithms helping us to find what we're looking for, right?
Though, I did really want to recommend an awesome talk from Kevin Murphy, from a RailsConf a couple of years ago, that's called Browser History Confessional: Searching My Recent Searches. The main message that I really enjoyed from this talk was the idea of thinking about what you're searching for and why because that will, I think, help add a bit of, like, intentionality into that process. You know, it can be very overwhelming, but let that guide you a little bit.
One of the things that he mentions is the idea of revisiting your own assumptions with search. So, even if you think you know how to do something, or you might even know, like, how you might want to do it, just going to search to see if there's any other implementations that you haven't thought of that other people are doing that might inform how you approach a problem, or at least, like, make you feel even more confident about your original approach in the first place.
I thought that was really cool. That's not something that I do now, but definitely, something that I want to try is to be, like, I think I know how to do this, but let me see what other people are doing because that might spark something new.
JOËL: We'll put a link in the show notes to this talk. But I was lucky enough to see it in person. And also would like to second that recommendation. It is worth watching.
From this conversation that you and I have had, I'm having, like, two main takeaways. One is kind of what you just said, the idea of being a little bit more cognizant of, what kind of search am I doing? Is this a sort of broad how do I X, where I don't even really know where to start? Is this, like, something really specific where you just don't know what kind of syntax you want to use? Is it an error message where you just want to see what other people have done when they've encountered this? Or any other, like, more specific subcategories. And how being aware of that can help you search more effectively.
And secondly, don't limit yourself to the public internet. There's a lot of great information in your company's Slack or other instant messaging service, maybe some kind of documentation system internal, some kind of wiki. And those can be a great place to search as well.
STEPHANIE: If we missed any other cool searching tips or tricks or ways that we might be able to improve our processes for searching as developers, I would really love to hear about them. So, if any listeners out there want to write in with their thoughts, that would be super awesome.
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: Byeeeeee!!!!!!
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.
Stephanie experienced bike camping. Joël describes his experience during a week when he's in between projects.
Stephanie and Joël discuss the concept of code ownership, the mechanisms to enforce it, and the balance between bureaucracy and collaboration. They highlight the challenges and benefits of these systems in large codebases and emphasize that scaling a team is as much a social challenge as it is a technical one.
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's new in your world?
STEPHANIE: This weekend, I went bike camping for the first time. So, it was my turn to try out the padded bike shorts and go out on a long ride, combining two things that I really enjoy: biking and camping. It was so awesome. We did about 30 miles outside of the city of Chicago to close to the Indiana border. And we were at a campground that's owned by the forest preserves where I'm at. It was so much fun.
I packed all my stuff, including my tent and sleeping bags. And it was something that I never really imagined myself doing, but I'm really glad I did because I think it'll be something that I want to kind of do more of in the future, maybe even do multi-day bike camping trips.
JOËL: So, what's your verdict on the bike shorts?
STEPHANIE: Definitely a big help. Instead of feeling a little bit sore an hour or so along the bike ride, it kind of helped me stay comfortable quite a bit longer, which was really nice.
JOËL: Would you do this kind of trip again?
STEPHANIE: I think I would do it again. I think the next step for me is maybe to go even farther, maybe do multiple stops. Yeah, I was talking to my partner about it who came along with me, and he was saying, like, "Yeah, now that you've done that many miles in one day and, you know, camped overnight, you can really go anywhere. [laughs] You can go as far as you want."
And I thought that was pretty cool because, yeah, he's kind of right, where I can just pack up and go and, you know, who knows where I'll end up? Not that I would actually do that because of my need to plan. [laughs] I'm not that go-with-the-flow. But there was definitely something really special about being able to get from A to B with just, like, my physical body and not relying on any other kind of transportation.
JOËL: Yeah, there's a certain freedom to that spontaneity that's really nice.
STEPHANIE: Yeah. And I actually went with a group called Out Our Front Door. And if anyone is in Chicago and is interested in doing this kind of thing, they do group bike camping adventures, and they make it really accessible. So, it's a very easy pace. You are with a group, so it's just really fun. They make it really safe. And I had a really great time. There was about 60 of us actually at camp, and they had rented out the entire campground, so it was just our group.
And they even had a live reggae band come out and play music for us while we had dinner. And that was a really nice way for me to do it as a first-timer because there was stuff already planned for me, like meals. And I didn't have to worry about that because I was already, you know, just worrying about making sure I got there with all of my stuff. So, if that sounds interesting to you and you're in Chicagoland, definitely check them out.
JOËL: That's a great way to bring in newer people to say, let's have a semi-organized thing, where all you have to focus on is the skill itself, you know, can I bike the 30 miles? Rather than planning all the logistics around it.
STEPHANIE: Yeah, exactly. Joël, what's new in your world?
JOËL: So, speaking of planning and logistics, this week, I'm in between projects at thoughtbot. And on the Boost team that I'm on, we've introduced a kind of special rotation for people who are in between projects where we have an internal project, where just internal strategic initiatives that we want to push forward. Whoever is unbooked gets to work on that. So, it's a small team with a very high churn.
And one of the things that we do is every week; we have somebody act as the project manager for that team. And I was in between projects this week. I was assigned that project manager job. And so, I've been doing that in addition to some of the tickets myself, and that's been really interesting.
STEPHANIE: Cool. I really like how that role is rotated among team members.
JOËL: Yes. And the whole team itself is very high churn. So, somebody might be on that for just one week and then rotate off, and a new person comes in; maybe someone's on there a couple of weeks while we're waiting to find them a project.
But we're always looking to prioritize booking people onto new client projects. And so, whoever is on that team, typically, is there for a short period of time. And so that means that the project manager role has to rotate a lot. But also, just in general, as you're managing tickets, you have to deal with the fact that people are not going to be on this project long-term. This is just, they're here for a few days, and they get some things done, and then they're moving off. And I think that presents some unique challenges in terms of the project management side of things.
STEPHANIE: Yeah. What kind of challenges did you find interesting in this role for the week that you were on it?
JOËL: So, in particular, I think making sure that outstanding work from the previous week gets done, especially when the people who were working on that ticket are no longer working on it. So, they may have done some partial work and then moved on to something else. And then, you have to ascertain the state of the ticket. Has it been completed? If it's only partial, what parts have and haven't? Can this be passed on to somebody else? Is there some unique knowledge that the previous person had? Has the code been pushed up? That kind of thing.
STEPHANIE: So, that reminds me of something I heard about the idea of being expendable. You know, there are certain industries where anyone else with that skill set can kind of step in and take over for another worker without a lot of issues, and they can continue on doing that work. So, I'm thinking about, you know, maybe doctors or pharmacists where they have that, like, shared skill set, and everything is documented enough so that they can just take whatever their case is. And if someone is out, it's not a big deal because people can just step in. And I'm curious about if this is something that could work for software development.
JOËL: I think it is important to have a team where nobody is irreplaceable. When it comes down to individual tickets, one of the things that I've been pushing for is that, at the end of the week, I would like to not see any tickets remain in the in-progress column. We're using a Kanban-style board. So, ideally, all work either moves to the done column or moves to the to-be-done column for next week. And it's no longer owned by anyone, so people have removed their faces from it. Ideally, though, if you pick up a ticket during the week, you get it to completion.
So, one thing that I've been really pushing with our team this week is splitting tickets up. If this feels like it's bigger than a few days, then it needs to be split up, and part of it gets done moves to the done column. Part of it might be some work that somebody else is going to pick up next week; move that to the to-do column. And so, that way, at the end of the week, we have, ideally, a column full of things that were pushed over the finish line that are done.
And then, we have a column of things to be done next week that nobody has kind of called dibs on yet. So that then next week, when we have a new group of people coming in, you don't just look at this column of to-do things. It's like, well, all of these have someone's face on them. I'm not able to pick up anything, so now what do I do? By having those all kind of fresh and available to be picked up, you make it easy for the next batch of people to hit the ground running on Monday morning.
STEPHANIE: That's really interesting. You said you were doing this Kanban style, but it almost kind of sounds like one-week sprints in a way.
JOËL: Kind of, because the way we book people onto clients is typically on a per-week basis. And so, if there's going to be a gap between clients, typically, it's in increments of a week. Because they're on the project for a week, it doesn't necessarily mean that we're tracking the tickets on a per-week thing. So, it's not like, oh, we're committing to doing all of these tickets by the end of a particular time or anything like that.
We are working in a more Kanban style where there's a backlog, and you pull tickets, and whatever gets done gets done. What we do try to do, though, is not have individual tickets hang in the in-progress column over a week boundary. So, there's a nuance there. I guess there's some ways in which maybe it feels a little bit sprint-like. But I think we are running in much more of a Kanban-style workflow.
STEPHANIE: Yeah, that makes sense.
JOËL: It's really to deal with that churn and the idea that even though the ticket might stick around for a while or maybe it gets split up into multiple small tickets, the people are switching constantly. And so, making the workflow play nicely with the fact that the team is churning on a weekly basis kind of adds an extra, you know, a little bit of spice to the project management side of things.
STEPHANIE: Did you find yourself being the one to break down tickets to make sure that they weren't larger than a week's worth of work? Or did you work with the developer themselves to find opportunities to break out what they were working on if we got to the mid-week and progress wasn't looking like it would be completed by the end?
JOËL: I've left this up to individual developers. This is more of a broad conversation I had with our team, kind of saying, "Hey, here's our goal. We want to get some things done by the end of the week. If we don't think we can get them done, here are some strategies I recommend. I'm available to pair if people want it." But I didn't go through and estimate all the tickets and split them up.
I did a little bit of, like, grooming ahead of time. So, I had a sense of when we started the week if tickets felt roughly sized correctly. But oftentimes, you know, that kind of thing, you start working on it, and then you realize, wait a minute, this is a bigger ticket than I thought.
STEPHANIE: Yeah. I think even just having someone check in and be like, "Hey, how is progress? Can I support you in making sure that you're able to get to somewhere that feels completed by the end of the week so that the rest of the work is set up for someone new to take on?" That seems really valuable to me.
Because as an individual, I'm like, yeah, I don't know, I'm maybe heads down just deep and trying to get my thing done, but maybe not so aware of progress and relative to how much time I've spent on it. And having just someone prompt me on that could help kind of pull myself out a little bit, you know, come out for some air and be like, oh, actually, you know, this is a good spot for me to break this down.
Do you have any insights into this week that you might be bringing with you into client work or anything like that?
JOËL: And I think this has just given me an even deeper appreciation for breaking tickets down. Because of that arbitrary end-of-the-week deadline, I think that forces more tickets to break down in a way that I might say, oh, well, I picked up a ticket on Thursday for a client. It can totally bleed into next week; that's fine. It's still a fairly short ticket, just, you know, I started the work later. And so, trying to make sure that tickets get scoped down really tightly, I think, is an area where I could probably benefit from that discipline on client projects as well. You know, even if I'm not doing it to the extreme, I'm doing it this week.
STEPHANIE: Yeah. I would be really curious to find out if next week the folks who are on this project feel like they're in a good spot to, you know, keep on making forward momentum because they can just pull from the backlog and not have to go and do that knowledge transfer.
JOËL: Right. I will see with all of this, right? Maybe even with all the conversations and things, maybe we'll end the week, and I'll have 10 cards in the in-progress column. And it'll be like, okay, we tried a thing this week, mixed success. How do we want to iterate on that idea next week? Potentially with a different team.
STEPHANIE: Right, exactly.
JOËL: I feel like one way to maybe summarize the type of work that I was doing this week is that it's a kind of a scaling challenge. But over time, the team itself is small, but it's constantly churning. And I think you've been working on a team where it's kind of had a similar problem but in a different dimension. You're scaling over team size, actually a massively large team, and seeing some of the challenges there. What are some of the things that you've been facing?
STEPHANIE: Yeah. So, my current client project, I'm working on a codebase where there are hundreds of developers also working and committing to this codebase daily. And this codebase is really massive. There is so much stuff going on. And I've really only explored the world of the particular team that I'm on.
But I recently had to do a little bit of work in some code that is owned by a different team. And I actually really appreciated the way that we were able to collaborate across, I guess, ownership boundaries. And I was really interested in talking about some of the different ways that we've seen the idea of, like, who is owning, and, like, who is accountable for areas of the codebase once you reach a certain size.
So, what was really convenient about the way that I was working was that in my pull request, there was an automated step that told me I needed specific owner approval on the code that I was writing because I was touching some files that were owned by a different team. And it gave me all of the handles for the people on that team. So, I knew who to go talk to.
And it ended up being that that team had a public Slack channel specifically for people outside to ask them questions about their domain. And they had a rotating ambassador system. And so, in the Slack channel, in the channel topic, it said who was the ambassador for that week. So, you know, I saw who it was. I got to @ them and say, like, "Hey, like, I'm working on some of these files for this feature for my team. And, like, here's my pull request. Could you give me a review?"
JOËL: The more you're describing this, the more this is feeling very large team, almost bureaucratic systems. I'm hearing public Slack channels, which implies that teams have private Slack channels. I'm hearing, like, a rotating ambassador.
One word that you mentioned that I'd like to dig into a little bit is the idea of ownership because I think that the concept of ownership is present on probably most teams, but it probably means wildly varying things. And it sounds like on your team, it's a very kind of codified thing. So, what does ownership look like on your project?
STEPHANIE: Yeah, I love that you asked that question because you're right; it is codified, literally, in the codebase. There are ownership files that are in the repo itself where they've specified, like, all of the models that a team owns, you know, down to the names of the files themselves, or maybe a namespace. It has the team name and all of the team members' handles. So, that's how it was able to tell me in an automated way, like, hey, reach out to these people.
It was really interesting because it was pretty frictionless on my end, where all I had to do was see that, you know, I couldn't submit my pull request until I got that approval. But it was enough friction to be, like, well, you can't just, you know, change files in this domain without someone with extra context taking a look.
JOËL: This reminds me a little bit of a system that GitHub has where you have this CODEOWNERS file that you can add to a repo. Have you messed around with that at all, or kind of seen how that looks?
STEPHANIE: I have a little bit. I think I've only seen it in the context of being notified that someone is wanting to submit a pull request, but I'm not sure if it does gate merging based on ownership. Do you know if that's the case?
JOËL: I don't. I think you can set it up to automatically request reviews from owners. And on a large repo, the owner could be...I assume this is based maybe on directories, or it might be a regex pattern. I forget the exact details. But you can have owners for partial parts of the code instead of owners of the entire repository. So, then, if you make a change to a particular part of the code, it would ping the correct person automatically to review your code, which sounds like a really nice feature.
STEPHANIE: Yeah, absolutely. I think for the project that I'm working on, this definitely seemed like a custom process that they, at one point, decided to enforce. I'm not really sure about the history of how this came to be. But I found it actually quite a good way to meet people who are working in other parts of the codebase.
The person who happened to be ambassador that I pinged was so helpful in just, you know, making sure that I kind of understood the parts of the code that they owned that were honestly, like, quite complex. Like, I would not have felt confident just going ahead and making those changes necessarily myself because this is a pretty legacy codebase. There are quite a few gotchas, and they were able to point some [laughs] of them out to me.
Yeah, having that extra confidence was helpful for the particular feature I was working on. But it did also kind of give me a little pause because I've not worked at such a scale where there was so much uncertainty about the domain and that being so diffused across like I mentioned, hundreds of people.
JOËL: Do you think that this ownership system that's in place helps manage the complexity of scaling up to a team of hundreds of developers? Or does it feel like it kind of just adds a lot of process that gets in your way?
STEPHANIE: Ooh, that's a good question. It seems like kind of a chicken-and-the-egg situation because I felt better with someone else's input, right? Like, with someone else with more domain knowledge than me about what I was touching to be, like, "Yeah, like, this looks good to me," giving the plus one.
Whereas if that didn't exist, maybe I would have tried to seek it out on my own. But I would not have known where to start, right? I would have to ask around and be like, "Hey, like, who has worked in this directory before?" or whatever. Or I could have just went ahead and merged my code and hope my lack of context didn't really cause any huge problems, like outside of what was covered by the tests. But this is helpful for, like, where the codebase is at, you know, and the size it has grown.
JOËL: Do you think requiring an owner to review the code puts maybe an undue burden on the person who's the owner and that they might end up spending a lot of time reviewing code because they now kind of manage that part of the app?
STEPHANIE: Yeah, that's a really good question. I think it can. But I also feel a little better that that role is rotated, that everyone on the team gets the opportunity to really, like, focus on that. And I'm pretty sure the way it works is that that is their main focus for the sprint, or the week, or whatever, and that they're not assigned any other feature work but to prioritize being that ambassador. So, in some ways, that is a lot of process, right?
And there is that trade-off of having to allocate someone specific to answer people's questions. But at least from what I've seen, it does seem like a necessity because people do have questions, right? And I think they have figured out a system where it's very clear who you're supposed to talk to, and that accountability aspect of it has been met. Because I've also, like, worked on teams where that role is not well defined. People don't want to do it. And it's almost kind of a bystander effect where someone asks a question, but no one is specifically responsible for answering it, and so no one answers it.
JOËL: Oh yeah. Yes. And then you get kind of the cost of the bureaucracy without the benefits of kind of diffusing that knowledge.
So, we've been talking a lot about how this kind of ownership system can be really beneficial despite the overhead for a team that's 200 or 300 developers and where nobody knows all of the code or all of the nuances. And kind of at the other extreme, it's absolutely not worth it for a team of two or three developers where everybody knows the code, and there's kind of shared ownership of the project.
Somewhere in between, there is where you start having maybe some of those conversations about scaling the team, and do we need to introduce more process? In your experience, where do you think introducing some sort of ownership system like this starts becoming valuable? Or maybe what are some of the questions that a team should ask themselves to gauge, like, at the size we're at right now, would we get value from an ownership system?
STEPHANIE: Yeah, that's a really good point because as you were saying that, I was just starting to think of, yeah, I've certainly worked on projects where I have reviewed every piece of code that is to be merged, right? And then, at some point, that starts to change where, like, I can't do that anymore. And that transition has always been really interesting to me.
And then, I think there is, like you mentioned, another one where it's like, okay, now we aren't able to review everything, but, like, how do we trust that the code that is being merged, even if we don't all share that same context, is up to the quality we want it or is bug-free? Because without that context, there's always the opportunity that something might be missed.
I think I've seen that on teams, you know, really look like more bugs than usual, right? And maybe there is, like, actually, like, a big problem, and the site is down. And maybe there is, like, a post-mortem or something to discuss, like, why this happened. And, you know, it turns out that the siloing or, like, the lack of context sharing was partly involved.
And so, I do think there are definitely symptoms when we're starting to firefight a little more [chuckles] that might be kind of an indicator that the app has grown to a point where some context is being lost, and there are not guardrails in place to do our best to, like, share it, like, when we can and not when it's too late.
JOËL: Would it be fair to say that your recommendation is the team should not have an ownership system and kind of stick to everybody reviews all the code as they grow until they start hitting actual pain points, such as real bugs caused and, at that point, let that pain or maybe even the post-mortem be the thing that triggers the introduction of an ownership system?
STEPHANIE: I think so. I have not seen something like that proactively introduced. I would be curious if anyone has experienced something like that. But, you know, I think it's okay for change to be a little painful, right? And that's part of the growing pains of becoming a larger team, or organization, or codebase and continuing to reevaluate. Though, I guess I would be a little cautious about, you know, jumping straight to introducing processes or policies, right? Because those can be really hard to undo if they end up not being actually helpful for the root cause of the problem.
But, like, how you experimented with making sure that, you know, we didn't have any in-progress tickets for that project. The idea of just trying something and seeing how it works and kind of getting the team's feedback that is really valuable to me, at least as an IC. And, yeah, just making sure, like, you know, hearing from all of your team members on how those processes are changing the way they work and if it's feeling good or not.
Like I said, I enjoyed the process on my client project because it helped me feel more confident that the code that I was changing...because I can't possibly gain all of the knowledge that the owners of that area of the code have. It's just not going to happen. But also, I can imagine it being maybe not so good for someone else, right? It kind of being a barrier or being frustrating because, oh no, they really need to merge the code. And maybe they made the smallest change in a file owned by another team, right? And having to jump through that hoop.
JOËL: Yeah, that has absolutely never happened to me.
STEPHANIE: Really? Because it sounds like it has.
[laughter]
JOËL: Yes, it absolutely has. We've been kind of throwing around the idea of ownership the idea of team almost interchangeably as if they're one-to-one. And I want to lean a little bit into this idea of the team. Because I think there's an implicit assumption here that, within a team, there's enough knowledge sharing that happens, enough shared context, that everybody can kind of understand all of the code for their team, and that knowledge is just shared around, so you don't need these extra processes within teams.
But maybe once you start having multiple teams as part of your engineering department, then there starts to be some friction or some lost context that needs some mechanism to get around. Does that sound about right to you?
STEPHANIE: Ooh, I think that depends because even within my team, we are working on different projects, and I am definitely not on top of, you know, what some other folks are working on. And even within our team, there are silos. The difference there, though, is that I know who they are. Like I still am in contact with them in our daily syncs, that the barrier to finding someone who has the right information is much lower.
So, yeah, I think that is definitely a part of it, too, if, like...I think just the social barrier, even of, like, reaching out to someone you don't know and being like, "Hey, like, can you review my code?" that is [laughs] kind of...can be a little scary. And the dynamics definitely feel different within a team and between teams.
JOËL: Yeah, and definitely just the idea of, like, someone you see every day for your daily sync, you're going to feel much more comfortable reaching out to them for help or for a quick review than to a total stranger.
So, it's interesting that you mentioned the social aspects of things. I don't know if you're familiar with Conway's Law, the idea that the technical structures of our code, over time, end up reflecting the social structures of our teams.
STEPHANIE: Yeah, that is something that makes a lot of sense on the project that I'm working on now, where the boundaries, like I mentioned, between teams and between different namespaces are semi-rigid, I suppose, right? Rigid enough that, you know, there is a process but not so high that it becomes a burden, at least in my opinion.
But for another feature that I worked on, I actually had to interact with an external system that's owned more by the parent company of my current client. And that process was definitely more rigid. And I had to figure out who to email and had to, you know, look up this person's profile in the company directory to make sure that, you know, I was talking to the right person who had information that was relevant to me.
And then, you know, even, like, the technical aspect of talking to this external service had a lot of various barriers and, you know, special authorization and configuration that I needed to set up. So, definitely felt that in terms of the different levels of ease and talking to systems owned by different parties.
JOËL: So, the fact that there's, like, an actual, like, departmental or even, like, corporate boundary, definitely showed up in, like, a very hard boundary in the code as well.
STEPHANIE: Yeah, absolutely.
JOËL: And I think taking this to an extreme, I've seen this happen when teams want to introduce microservices. And oftentimes, the boundaries of those microservices are not necessarily driven entirely by technical reasons, but they're often by social reasons. So, we can say, hey, this team is going to own this service, and everybody else only needs to interact with a public API. And we can make all sorts of changes internally, and you never need to know that. They will never break your code. And also, we don't need to bother each other or feel the need to fully deeply understand the internals of each system.
STEPHANIE: Yeah. Once you're introducing APIs that are accessible to a certain group of people and having to navigate, you know, making changes to the API or aligning in the expected structure of the, you know, communication that you're sending between them, that is definitely a pretty rigid boundary [laughs] and ends up being a lot of overhead to talk to those systems. And I certainly have been in the position of trying to communicate with the people who built and designed those systems and figuring out how to get on the same page.
And even just recently, I was accidentally sending something as an array, and they were expecting it as a string. And that caused all these problems of making the request happen, you know, successfully. And we didn't even realize it until someone pulled out the doc that had the API schema and pointed out that there was some miscommunication along the way.
JOËL: And that can be such a hard boundary around even, like, the idea of ownership. So, you were talking about how, earlier, when you were working in code that's maybe owned by another team, they might want to review it before it gets merged. So, there's a bit of a gatekeeping there.
When a team transitions fully to microservices, I've seen it go almost, like, more extreme where it's even, like, you don't even change the code. You submit a ticket into our system. We will prioritize it, and then eventually, we will build your feature. But you don't even get to make a change to the code and have us approve it. We're going to make all that because we own it. So, it kind of feels like taking that ownership idea and then just really running to a full extreme.
STEPHANIE: Yeah, right. That makes a lot of sense in the lens of Conway's Law if those are the processes they have in place for navigating cross-team collaboration or communication. Because, at some point, maybe they just reached a level where it had to be enforced that way because maybe things were getting dropped, or more casual lower barrier connection was too overwhelming or just not working for the organization.
JOËL: I think what I've been hearing just now and then just more broadly throughout the episode is that while there's a lot of interesting technical solutions that can make things better, at its root, scaling a team is a social problem. And it's all about how your teams communicate with each other so that you can scale smoothly and that the system doesn't suffer from adding more people.
STEPHANIE: Yeah. I think this is an area where I would love to hear any thoughts from our listeners about how their organizations handle something similar because I find all of this really interesting. And, you know, it ends up impacting my day-to-day work in a very real way. And so, if other places have figured out how that scaling and, you know, social and technical boundaries work in a way that feels good, I would love to know.
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.
Want a cool cucumber salad? Joël's got you covered. Stephanie has evolved and found some pickles she enjoys.
Experienced programmers use a lot of heuristics or "rules of thumb" about what makes their code better. These aren't always true, but they work in most situations. Stephanie and Joël discuss a range of heuristics, how to use them, how to come up with them, how to know when to break them, and how to teach them to more junior devs.
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, as of the recording of this, summer is in full swing, and it's the time of year where we have all these, you know, fresh vegetables out, so I've been really enjoying a lot of those. I think this week; in particular, I've been going into, like, all the variations on cucumber salads.
STEPHANIE: Ooh.
JOËL: Yeah. So, that's been kind of fun for me. A fun thing I've been doing to spice this up is pickling mustard seeds to add as a topping. That's actually really amazing. It adds just a little bit of acidity, a little bit of crunch, a little bit of texture. And it's pretty.
STEPHANIE: That sounds so delicious. And also, I was going to share something about pickles about what's new in my world. [laughs] But first, I am curious, what has been your go-to cucumber salad that you put this pickled mustard seed situation on top?
JOËL: So, cucumbers and tomatoes is just the base of everything. And then, it kind of goes with random things I have in my fridge. A little bit of goat cheese on top can be a great topping, big fan of balsamic glaze. You can just get, like, a bottle of that at the grocery store, the pickled mustard seeds. I've recently been trying topping with a fried egg.
STEPHANIE: Ooh, that sounds really fun. It kind of, like, adds a bit of savoriness and creaminess and maybe even, like, the crunchy fried edges. That sounds really yummy.
JOËL: Particularly if you do it over easy where the center is not fully cooked. When the egg breaks, you effectively get salad dressing for free.
STEPHANIE: That sounds so delicious.
JOËL: Summer vegetables, they're great.
STEPHANIE: They are great. Last year, I did have a cucumber garden, as in a garden, and a few cucumber plants that were too prolific for me, to be honest. I found myself overrun with cucumbers and having to give them away because we just didn't eat them enough. And this year, we scaled back a little bit [laughs] on the cucs. But I am so excited to bring up what's new in my world now because it's, like, so related, and we did not plan this at all. But I have a silly little thing to share about my own pickle journey. So, I used to be a pickle hater.
JOËL: You know what? Same.
STEPHANIE: Oh my gosh, incredible. Another new thing we've learned about each other. I really, like, wanted to like pickles because, you know, when you order a sandwich in a restaurant, it always comes with the pickle spear. And neither me nor my partner were into pickles, and we would always leave the spear uneaten on the plate, and we felt so bad about it. I felt really bad about it.
And so, every, like, three to six months or so, I'd be like, okay, I'm going to gather the courage to try the pickle again and see if maybe my taste buds have changed, and this time I'll like it. And, you know, I would try a bite and just be like, no, no, I don't think it's for me. [laughs] But I guess I was just so primed to do something about, like, wanting to eliminate this really inconsequential food waste. But every time it happened, I would just, you know, [laughs] be, like, oh, if only I loved pickles.
And I got my friend, who is a pickle connoisseur, to help me figure out, like, what pickles I might like. So, I asked her to come up with, like, a pickle sampler for me because I really hadn't tried all too many. And that actually really helped me find which ones were a little more palatable to me. So, I found out that I liked the sweeter ones. There's, like, a bread and butter pickle that can be quite sweet. Your diner pickle can be very different from a jar of, like, fancy pickles. [laughs]
JOËL: Definitely.
STEPHANIE: One day, she gifted me a jar of, like, Polish gherkins that were delicious.
JOËL: Hmmm.
STEPHANIE: I was like, wow, I can just snack on these. So, the thing that's new is that this time, I went to an Eastern European grocery store, and I bought my own jar of pickled gherkins. And that was something that Stephanie, like, two years ago, would never even do. [laughs]
JOËL: That's really cool that you got a chance to sort of explore a broader range of what was available in the pickle world and then were able to find kind of your niche there and discover something new that you actually like.
STEPHANIE: Yeah, it was very fun. And now I feel like my whole world has opened up to, you know, pickley and fermented things and just, like, get to enjoy even more snacks.
So, to move away from pickles, recently, on my client project, I've been pairing a lot more with other client developers. And one thing that has come up is, you know, talking about our reasoning or our thought process for when we're pairing on some code. And I realized that I have built up a lot of either intuition or maybe some rules that I like to follow when I'm writing code, writing a test, or even doing a code review. And I've realized that you know, as developers, we often use these kinds of shortcuts or heuristics to help orient us as we're doing our work.
JOËL: Yeah. I think that's definitely something that either comes yourself from experience or sometimes is passed along, and you get to benefit from somebody else's experience. They learned the hard way a lot of these tips and tricks, and now they kind of pass on some of these guidelines to us. Do you have any favorites that you reach for frequently?
STEPHANIE: So, one way I like to approach a problem is to start messy [laughs] and to kind of see what that gets me and then where to go from there. I find that it's a little bit easier for me to draw on things that I've, you know, learned or picked up and tips once I have something in front of me to react to. So, maybe I will just go with the naive implementation and just write all of the code in one method, you know, in a class. And from there, now that it's out of my system, can I kind of come back in with a finer tooth comb and then apply more of a sustained effort to clean things up, right?
And, to me, the question I find myself asking is, like, can this be extracted further? And so, you know, if I have everything in one giant method, then yes, [laughs] there is likely, you know, many opportunities to extract that, and maybe I will see something like, oh, the way that I spaced out this code that might be a signal to me that, like, these are some ideas that are grouped together, and I can pull something out there.
JOËL: Do you have a heuristic around when to stop extracting?
STEPHANIE: That's a good point. I think I tend to stop when I have kind of pulled out the classes that make sense to me. And, at that point, you know, like, maybe there is more extraction that can be done. But at a certain point, you know, you then get these really tiny classes that maybe don't hold their weight. And I think that's also true of methods that then call other methods, and that's the only thing that they do.
Then it's like, well, is this too extracted that it's not really giving a future reader helpful information, right? I want the extraction to improve readability. And that tends to be another lens through which I am applying to this idea of, like, can I extract further? Is this extraction helpful for understanding this code?
JOËL: I like the idea of looking at the code through multiple lenses. And so, sometimes you look at it through the lens of, yeah, are there enough moving parts here? Or does it feel kind of brittle and all in one place? And then sometimes completely shifting your lens and saying, you know what? Let's put myself in the seat of someone who's looking at this code for the first time. Can I understand it?
So, structuring and extracting code is a big part of the work that we do. And I also happen to have a couple of heuristics that I like to use. One is separate branching code from doing code. So, if I have an if...else condition, I try not to put ten lines of logic inside each branch; instead, I have just a call out to a method so that the only thing the conditional does is to choose which path you go, and then each individual path is its own method.
Similarly, if I'm writing a method, I'm not going to have a bunch of logic then a conditional mixed in together. So, my heuristic is a method gets to do one of two things. It either gets to choose a path to take or it gets to do a thing, but you can't mix and match both.
STEPHANIE: Yeah, that makes a lot of sense. I really appreciate a well-named method that is, you know, determining, like, what condition needs to happen because then that helps me, yeah, like, avoid having to hold all of this information about this condition or this other condition, and this other condition in order to figure out what path I'm trying to take.
JOËL: And the naming and the readability, I think, is a big part of this. Another heuristic that I like to use that kind of converges on the same result is trying to write each method at a single level of abstraction. So, if I am writing a method that has some kind of high-level terms it's using, I'm not going to also mix in a lot of low-level implementation. And then, similarly, if it's a method that's doing a lot of, like, low-level nuts and bolts things, I'm going to try not to pull in some of these higher-level domain name methods in there.
And so, by separating things out so that every method reads one level of abstraction, you make it much easier for the reader to go through and figure out what's happening. Are we kind of getting that more 10,000-foot view, getting a sense of what's happening, and saying, okay, we want to process the user form, and then we want to send off an email, and then we want to, you know, write to a file? Or are we going through, okay, we're going to increment a counter so that we get exponential back off on our [inaudible 10:28] request? Those two things do not belong together in the same method.
STEPHANIE: Yeah, absolutely. I really like this heuristic. And I have been applying it more and more and found it really useful for making sure that you're handling your errors correctly, especially because, at different levels of abstraction, you want to do different things with your errors, right?
An implementation error that's raised because, you know, you're calling something accidentally on nil, or maybe a third-party service is down, and you get a custom error, whatever that is, those concerns are different from how you want to handle things at the controller level. And oftentimes, I see those things really mixed together, and honestly, I think leads to a lot of buggy code when you're trying to handle things that can go wrong at the wrong level of abstraction.
JOËL: Yeah. Is there a good heuristic around what level you think is best to trigger an exception? Or maybe, more generally, just being aware of different levels of abstraction and knowing that catching or triggering errors at each level will have different impacts.
STEPHANIE: I think more of the latter, the having an awareness of what kinds of errors might be possible and what impact that has on the user, right? The user being either an actual customer or, you know, another developer who has to read a notification from an error monitoring service. [laughs]
JOËL: This is really interesting to me because I think we've now bridged the concept of heuristics into the idea of mental models. So, the heuristic is write your methods at a single level of abstraction, but that then leads into a mental model where maybe code is structured in three or four different layers. You've got a low level, a mid-level, a high level, something like that, of abstraction. And now, you can use that mental model to start thinking about what are the impacts of exceptions at each layer?
And then, maybe you complete the circle by creating a heuristic that relies on that mental model, maybe, I don't know, raise in the low-level rescue at the top level or something. I'm making something absolutely arbitrary up right now. But somehow, we've gone from heuristic, which creates a mental model, which then allows us to build new heuristics on top of that, and that seems like a virtuous cycle to me.
STEPHANIE: Yeah, absolutely. I think what I'm also picking up is the idea that you do need a mental model, or you do need to draw on your own ideas about something in order to apply the heuristic, right? You know, someone could tell you to separate branching code from doing code. But maybe you don't know what that means or, like, maybe you don't see why that's important. And sure, you can still apply it and try your best to follow it. But, in some ways, I think that the best heuristics are ones that you've kind of developed for yourself based on your own experience.
JOËL: That's really interesting. I think once you've built from your own experience, I definitely feel like they're really impactful because you've kind of synthesized 2, 5, 10, 20 years of experience doing some of this work into, oftentimes, like, you know, a pithy one-line sentence, 5, 6 words that convey an approach that you've found works best, you know, maybe 80% or 90% of the time. The power of synthesis for your own self-learning I think it's really hard to understate.
So, I'm curious if there's any other heuristics that you commonly use that you kind of created yourself based off your own experience rather than just having it be more of a broadly received idea from the community.
STEPHANIE: I think, for me, it's more so that the experience has helped affirm certain heuristics and also made me feel more comfortable with letting others go. And one that I heard a lot but, like, didn't quite understand until really working through it deeper is the idea of feeling pain when you write a test, and that being a signal of opportunities to try different design with your code. And I just didn't know what that pain was at the beginning. Like, what does that even mean? [laughs] Like, how can a test cause me pain?
But on my own, I realized, oh, like, actually, I get really frustrated when I need to stub out a whole method chain, right? And I find myself having to go look up how to do that or just spending a lot of time having to do something that I haven't done before. Maybe the pain comes from having to change a lot of files because, oh no, like, I also broke 20 other tests in the process.
But when you're first starting out, oftentimes, you, like, don't know that that is not normal [laughs]; at least, that was true for me. And so, that was something that I had heard about, like, if you are feeling pain when writing a test, then, like, maybe reconsider your code design. But when you don't know how to identify what that pain is, and you also, like, don't know where to go from there, I find that, you know, the heuristic can only help you so much.
JOËL: Yeah. Maybe that's something that's challenging with a heuristic in that they're often expressed as these pithy sentences. But if you're not familiar with some of the underlying concepts, that might make them harder to apply, which is unfortunate because, oftentimes, these heuristics that we've developed as a community are targeted to newcomers to help them kind of avoid the mistakes that we've made along the way.
STEPHANIE: I think what really helped me the most in connecting a heuristic that's commonly expressed and my own experience is when I've had someone ask me about how I'm feeling when I'm, you know, making some kind of decision or when I'm reading some code. Like, what do I think of this, or what has been my experience with this? And giving me the opportunity on the spot to synthesize that information. Because otherwise, it's hard to figure out, you know, like, what is just normal? This is just life as a developer [laughs]. And what are opportunities to maybe gain some more insight about the work itself?
JOËL: One thing that I've learned over time as a developer, and I'm not sure if this quite rises to the level of a heuristic, but a lot of, like, pain and frustration in development doesn't necessarily have to be that way. And it's not necessarily because I'm bad at the job or I'm too new to the technology or whatever. It can often be a sign of underlying design issues or the fact that the system was modeled with certain assumptions that are no longer true. These can often be signals that you can make things better.
So, I think if I had to reduce this idea down to a clever one-liner, it'd be something along the lines of, it can be better, or it doesn't have to be this bad. You're writing a test, and it's really annoying. There might be a better way to structure the underlying code that would make the test better. You're having to do some, like, really clunky code to deal with something. Is there maybe a better object design that would make a lot of that pain go away, or at least kind of quarantine it in a certain part of the codebase?
STEPHANIE: I actually think you're really onto something because what I was just hearing, I love that, like, it can be better. It's less prescribed, I guess, than some other heuristics, like, you know, do not repeat yourself, or whatever.
JOËL: Classic.
STEPHANIE: [laughs] It really encourages, like, the individual to think a little deeper. And it actually reminded me of another...this is actually a bit of a pithy saying, but I find it to be really useful. And I'm curious if you've heard it before. It's a systems thinking heuristic, and the phrase is, the purpose of a system is what it does.
JOËL: Ooh, I have heard that, and I'm trying to remember what context.
STEPHANIE: So, it was coined by a systems thinking expert. Stafford Beer, I think, is his name. And I recently learned about it from a friend. But I think the cool thing is that it can be applied to literally anything [laughs] because everything is a system, you know, or not just software. But I have found a lot of value in applying it to just, like, is this function doing what it says it does, right? Or is it actually also doing, like, a side effect? And turns out, maybe we want to bring that into alignment with what the name of the function is, or try pulling that out, or whatever. I think it can also be true of test suites.
I don't know if this is a heuristic or not. But the idea that we should always be testing or all tests are good, yeah, I guess that could pass as a heuristic. By bringing this perspective of the purpose of a system is what it does, it's like, well, is the test suite also so bloated and takes so long and so flaky that it is actually hindering development? And if that is the case, then maybe there is some reevaluation necessary, right? Rather than just claiming that it's helping us have more confidence in our code when that may or may not be true.
JOËL: You brought up an interesting idea here, which is that heuristics aren't always right. So, you're talking about the idea that a heuristic like good code is tested code might not be correct in 100% of the cases. Like, how accurate does a heuristic need to be in order for it to be really valuable? You know, you're hoping for something that's, like, 90% correct that you can follow most of the time, except in some edge cases, or something maybe as low as, like, 50% where it's a coin toss whether the heuristic applies in the situation or not. Are those still useful? Or are they maybe more confusing than otherwise?
STEPHANIE: Oh wow. That's a really interesting way to frame it because I don't know if I've ever stored information about how well my heuristics are serving me. [laughs] But I do really like the idea that you can use a heuristic as a guiding principle just to try and that you can always back out of it, right?
So, if you're wanting to take DRY to the extremist of extremes, just for fun or just to see how that might go, you can go down that path and, at any point, decide, okay, like, I like this, or I don't like this, and choose a different path. But the idea of kind of tracking, like, how well they're working for you that is really interesting to me, and not something I've tried before.
JOËL: I love the idea of taking a heuristic and, like, doing a side project whose whole goal is just to kind of push that heuristic to the extreme, to the breaking point so that, that way, you get an intuition of, like, when does it work for you? When does it not? That sounds like a really fun exercise for someone to do. Is that something that you've done yourself?
STEPHANIE: Not to the point of a whole side project, but just like I like to try pickles randomly every now and then to see if I like them, [laughs] will just try a new technique and see how it goes. In an episode a while back, we talked about whether we TDD or not, and, to be honest, I don't do it, you know, 100% of the time or all the time. But one day, I did decide to TDD a full-stack feature from start to finish just for fun [laughs], and I enjoyed it. I learned some things about it.
And I think now I've kind of integrated the parts that I liked about it into my development flow. Like, I'm not always going to do it. But I think it also just helped me figure out, like, okay, like, what is this thing about that people claim that is the pinnacle of how we should be writing our code? And how can I decide for myself, like, whether it works for me or just pick and choose the parts of it that work for me?
JOËL: Yeah. That just seems like a really valuable exercise. There are definitely too many heuristics out there to do that for everything. But I guess I've never thought of it quite so concretely. But I almost wonder if I should, like, add this to my kind of personal growth plan to say, like, once a year, I'm going to take a heuristic and kind of push it to an extreme and see what I can learn about it.
STEPHANIE: I actually think what's really cool is the process of, like, any individual developer figuring out what kinds of heuristics they want to follow, as opposed to, you know, like, a mass proclamation that, like, this is the way, right? Are there any heuristics that you have maybe picked up and then let go of because you realized that, you know, they weren't working enough or frequently enough for you or that you just didn't like?
JOËL: I don't know about, like, fully letting go, but definitely kind of recontextualize and sometimes even sort of rewrote them a little bit to work for me. So, a classic one would be the idea that shorter code is more readable. So, it's common to see comments on a pull request sort of like, "Hey, you could make this shorter by doing this." And that can be true to a certain extent. When you get to the point where you're playing code golf, it becomes absolutely unreadable.
But also, there's a point where sometimes using some other heuristics will result in longer code but actually make it more readable on the whole. And so, packing everything into one method might be overall shorter, so it's fewer lines to read going through a class. But maybe extracting some methods or doing that separating branching code from doing code might lead to an overall longer class but an also overall more readable one. So, I think there's probably a lot of caveats that go with that idea. Oftentimes, shorter can be more readable with, you know, two or three asterisks that maybe go a little bit more into the why that is the case.
STEPHANIE: Yeah. I like the contextualizing. That actually reminded me of a talk that I watched recently by Hillel Wayne. It's called Intro to Empirical Software Engineering. And he basically, like, does a deep dive into all these studies about software practices that we think are, quote, unquote, "good," like, as a community or as an industry. And it's like, well, like, how do we actually know? Like, show me the research, right?
And one of the studies that he included was trying to determine if using abbreviations for variable names or using the full words made the code easier to debug or not. And so, the main example that he was using was employee number as a variable, and the abbreviation was EMP num. And it turns out that there was no difference in how easy it was to debug. But the approach that each group that was studied differed.
So, the folks who had the full names, the full words for the variable names, were kind of using an approach of just scanning the code and being able to understand at a higher level the domain, right? Whereas the folks who were debugging with just abbreviations had to work at a bit of a lower level and, you know, or maybe using breakpoints and debugging the code that way.
And I thought that was really cool because, first of all, I think it kind of was trying to prove that, like, we don't actually know if one is better or not. But what is important and interesting to me is the idea that, like, you can choose the method that you like better or that works for you and the human side of it, right? The impact it has on our process.
JOËL: That's really cool. I'll have to go and watch that talk. Building this kind of context and nuance around a heuristic, though, takes a lot of time, takes experience. And part of the value of a heuristic is that we're collapsing down maybe our own experience or somebody else's experience into something that doesn't require you to necessarily do all that work upfront.
How do you feel about sharing and kind of targeting a lot of these heuristics to newer coders who are kind of trying to get better at their craft and looking for ways to improve without necessarily having to do, you know, five years of experience digging into a particular topic? Do you think heuristics are helpful, or do they maybe mislead?
STEPHANIE: I really value when they're presented as an opinion, as opposed to a true fact about code. [laughs] Because I really appreciate when someone is able to explain to me why they chose readability in this particular scenario or why they chose speed and performance. Or maybe they were making a trade-off between accessibility and, you know, something else. To just, like, tell someone, "Oh yeah, like, DRY code is better code," or to just tell someone that without the explanation with, like, offering them the opportunity to reflect themselves on, like, oh, like, where have I seen DRY code that was easier for me to read? That seems a little less helpful in terms of investing in their growth.
JOËL: Yeah. Definitely, I think sharing some of the purpose behind it can often be really useful because most of these heuristics are never an end unto themselves. They're a means to some other end. So, you're not writing code that's DRY just because you want to be cool. You're writing code to be DRY because you're trying to improve readability, make it easier to change so you don't have to change it in multiple places. You want to maybe reduce the chance of certain types of bugs.
These are all actual purposes of what you want to do in your code. DRY is just one way of getting there. But oftentimes, we might skip that part and just be like, hey, you should make your code DRY because DRY is the best. And it can be, but it's in service to these other goals.
STEPHANIE: I think when I am sharing those types of heuristics that are more commonly held, I also do like to preface, like, some people think this, or some people like to do things this way, just to be clear that they don't have to like it or do it. In general, I always prefer injecting more nuance [laughs] into the conversation. But yeah, like, it is a really personal process, I think, and figuring out, like, how any individual makes decisions about, like, all the code they're writing. You have to make a million [laughs] decisions every time you do it.
So, yes, like, those heuristics do provide a shortcut. And also, I think it's worth taking the time to think about if it's working, especially for the specific context that you're applying it, right? Because that also can change. And, I don't know, maybe I'm just skeptical of any one size fits all solution.
JOËL: I think for myself, with many heuristics, as a beginner coder, I had a bit of, like, a spiral journey, or maybe kind of going up a set of stairs. So, as a brand-new developer, I would make a lot of duplication bugs in my code, where, you know, I would have the same value in multiple places, and then I'd change it in one place, and I don't remember to change it in other places, and the code breaks.
And so, being introduced to the idea of DRY actually helped my code get quite a bit better. It was, like, a net positive on my experience because I was not getting burned by all these bugs quite so frequently. And so, for a while, just throwing more DRY into my code just made my life better. And then, eventually, you kind of hit that plateau where I don't run into the pain of these bugs anymore. But now I keep doing more DRY somewhat mindlessly. And I end up with this pile of abstractions that are actually really brittle or frustrating to work with. And now, I have to rethink some of the assumptions behind the heuristic.
And then, at that point, yep, maybe recontextualize a little bit, learn about when it's good, when are the trade-offs not worth it. Now I have a better understanding, and I kind of go on another growth bit where it makes a lot of my code better until maybe I hit another plateau. I've kind of maxed out the benefits. I start seeing some of the pain, and then, again, I have to go through this cycle again. And maybe the approach you were talking about earlier, where you do a side project and kind of push a heuristic to its breaking point, is a way to kind of speed run that process.
STEPHANIE: Yeah, that's really interesting because you're just committing to it and trying to learn everything you can from it in a very concentrated setting. I also wonder, and it's totally fine if you don't know, but if someone had told you kind of all of those reasons you listed about why DRY code, like, what that achieves, if that may have reframed how you were thinking about applying it. Or was that also something that had to come from doing it enough?
JOËL: I think as a brand-new developer, a lot of that would have gone over my head. I was still really shaky on the concept of abstraction. When is it useful? When is it not? So, a lot of those more subtle pitfalls, I think, would not have been relevant to me at that point in my career, even the concept of readability, right? When I'm a brand-new programmer, I'm still getting used to reading a lot of code.
And so, the idea that code might be written in a way that's unreadable or more challenging to read, it might just feel like, oh, I just need to get better, improve myself. It's not that the code is written in a hard-to-read way. It's just I don't have enough experience at reading code. And I think that's a common thing that we do as beginners at everything, right? We start by blaming ourselves when things get hard.
STEPHANIE: Yeah. I was just thinking that, you know, if you are sharing heuristics with a newer developer or an early-career developer, at the end of the day, like, really, I'm not sure about the value of just dropping it on them and letting them run [laughs] with it. But I think what could be really, really effective is just having a sustained relationship with them and, like, continuing that conversation. It's, like, maybe in a code review or in a pairing session being like, "Oh yeah, like, I see you're practicing DRY. Like, what do you think about how this made this piece of code different?" And kind of baking in that process of self-discovery along the way and speeding it up in that way as well.
JOËL: So, what you're really saying is the one heuristic to rule them all is code in community.
STEPHANIE: I love that. I'm totally with you.
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.
Stephanie is consciously trying to make meetings better for herself by limiting distractions. A few episodes ago, Joël talked about a frustrating bug he was chasing down and couldn't get closure on, so he had to move on. This week, that bug popped up again and he chased it down! AND he got to use binary search to find its source–which was pretty cool!
Together, Stephanie and Joël discuss dependency graphs as a mental model, and while they apply to code, they also help when it comes to planning tasks and systems. They talk about coupling, cycles, re-structuring, and visualizations.
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's new in your world?
STEPHANIE: So, I'm always trying to make meetings better for me [chuckles], more tolerable or more enjoyable. And in meetings a lot, I find myself getting distracted when I don't necessarily want to be. You know, oftentimes, I really do want to try to pay attention to just what I'm doing in that meeting in the moment. In fact, just now, I was thinking about the little tidbit I had shared on a previous episode about priorities, where really, you know, you can only have one priority [laughs] at a time. And so, in that moment, hopefully, my priority is the meeting that I'm in.
But, you know, I find myself, like, accidentally opening Slack or, like, oh, was I running the test suite just a few minutes before the meeting started? Let me just go check on that really quick. And, oh no, there's a failure, oh God, that red is really, you know, drawing my eye. And, like, could I just debug it really quick and get that satisfying green so then I can pay attention to the meeting? And so on and so forth. I'm sure I'm not alone in this [laughs]. And I end up not giving the meeting my full attention, even though I want to be, even though I should be.
So, one thing that I started doing about a year ago is origami. [laughs] And that ended up being a thing that I would do with my hands during meetings so that I wasn't using my mouse, using my keyboard, and just, like, looking at other stuff in the remote meeting world that I live in. So, I started with paper stars, made many, many paper stars, [laughs] and then, I graduated to paper cranes. [laughs] And so, that's been my origami craft of choice lately.
Then now, I have little cranes everywhere around the house. I've kind of created a little paper crane army. [laughs] And my partner has enjoyed putting them in random places around the house for me [laughs] to find. So, maybe I'll open a cabinet, and suddenly, [laughs] a paper crane is just there. And I think I realized that I've actually gotten quite good at doing these crafts.
And it's been interesting to kind of be putting in the hours of doing this craft but also not be investing time, like, outside of meetings. And I'm finding that I'm getting better at this thing, so that seemed pretty cool. And it is mindless enough that I'm mentally just paying attention but, yeah, like, building that muscle memory to perfecting the craft of origami.
JOËL: I'm curious, for your army of paper cranes, is there a standard size that you make, or do you have, like, a variety of sizes?
STEPHANIE: I have this huge stack of, like, 500 sheets of origami paper that are all the same size. So, they're all about, let's say, two or three inches large. But I think the tiny ones I've seen, really small paper cranes, maybe that would be, like, the next level to tackle because working with smaller paper seems, you know, even more challenging.
JOËL: I'd imagine the ratio of, like, paper thickness to the size of the thing that you're making is different.
STEPHANIE: At this point, they say that if you make 1,000, then you bring good luck. I think I'm well on my way [laughs] to hopefully being blessed with good luck in this household of my little paper crane army.
JOËL: It's interesting that you mentioned the power of having something tactile to do with your hands during a meeting, and I definitely relate to that. I feel like it's so easy, even, like, mindlessly, to just hit Command-Tab when I'm doing things on a screen. Like, my hands are on the keyboard. If I'm not doing something, I'm just going to mindlessly hit Command-Tab. It's kind of like on your phone sometimes. I don't know if you do this, like, just scrolling side to side. You're not actually doing anything. You just want motion with your fingers.
STEPHANIE: Yes. I know exactly what you're talking about. And it's funny because it's a bit of a duality where, you know, when you are in your development workflow, you want things to be as quick and convenient as possible, so that Command-Tab, you know, is very easy. It's just built in, and that helps speed up your, you know, day-to-day work. But then it's also that little bit of mindlessness, I think, that can get you down the distraction path.
When I was first looking for something to do with my hands, to have, like, a little tactile thing to keep me focused in meetings, I did explore getting one of those fidget cubes; I have to say. [laughs] It's just a little toy, you know, that comes with a bunch of different settings for you to fidget with.
There's, like, a ball you can roll, you know, with your thumb, or maybe some buttons to click, and it gives you that really satisfying tactile experience. And I know they work really well for a lot of people, but I've really enjoyed the, I guess, the unexpected benefits [chuckles] of getting better at a hobby [laughs] while spending my time at my work.
Joël, what is new with you?
JOËL: So, a few episodes ago, I talked about a really kind of frustrating bug that I was chasing down that was due to some, like, non-determinism in the environment. And it kind of came, and then it went away. And I wasn't able to get sort of closure on that and had to move on. Well, this week, that bug popped up again, and this time, I was actually able to chase it down. So, that felt really exciting. And I got to use binary search to try to find the source of it, which made me feel really cool.
STEPHANIE: Oooh, do tell. What ended up being the issue?
JOËL: I'm connecting to an external Snowflake data warehouse, and ActiveRecord tries to fetch the schema and crashes as part of that with some cryptic error that originates from the C extension ODBC Ruby driver package. I figured out that it's probably something to do with, like, a particular table name or something in the table metadata when we're pulling this schema that we're not happy about. But I don't know which table is the one that it's not happy with.
Well, this time, I was able to figure out, by reading through some of the documentation, that I can pull subsets of the schema. So, I can pull the first n values of that schema, and it won't crash. It only crashes if I try to fetch the entire set, which is what is happening under the hood. At that point, you know, I could fetch each row individually, but there's hundreds of these. So, you know, I try, okay, what happens if I try to fetch 1,000 of these? Is it going to crash? Because it's a massive system. So, yes, I get a crash.
So, I know that a table less than a thousandth in the list of tables is what's causing the problems. So, okay, fetch 500 halfway in between there. It's still going to crash. Okay, 250, 125. I then kind of keep halving all the time until I find one that doesn't crash. And now I know that it is somewhere between the last crash and this one. So, I think it was between 125 and 250. And now I can say, okay, well, let's fetch the first, you know, maybe 200 tables, okay, that crashes. And I keep halving that space until you finally find it. And then, like, okay, so it's this one right here.
Now, the problem is the bad table actually crashes. So, I think it ended up being, like, number 175 or something like that. So, I never get to see the actual table itself. But because the list of tables is in alphabetical order, and I can see because I can fetch the first 174 and it succeeds, so I can tell what the previous 5, 6, you know, previous 174 are.
I can pretty easily go and look at the actual database and the list of tables and say, okay, well, it's in the same order. And the next one is this one, and hey, look, there is some metadata there that has some very long fields that are longer than one might expect, specifically going over a potentially implied 256-character limit. That seems somewhat suspicious. And, oh, if we remove this table, all of a sudden, everything works.
STEPHANIE: Wow, binary search, an excellent debugging tool [laughs] when you have no idea, you know, what could possibly be causing your issue.
JOËL: It's such a cool tool. Like, I'm always so happy when I get a chance to use it. The problem is, you need a way to be able to answer the question, like, have I found it? Yes or no? Or, generally, is it greater or less than this current position?
STEPHANIE: Well, that's really exciting that you ended up figuring out how to solve the bug. I know last time we talked about it, you kind of had left off in a space of, hopefully, we won't run into this issue again because it's no longer happening. But it seems like you were also set up this time around to be able to debug once it cropped up again.
JOËL: Yes. So, binary search is really cool. It's got this, like, very, like, fancy computer science name. But in reality, it's a fairly simple, straightforward technique that I use fairly frequently in my development. And there's another kind of computer sciency fancy-sounding concept that I use all the time. You've all heard me reference this multiple times on the show. You're right; we're finally doing it. This is the dependency graph episode.
STEPHANIE: Woo. [laughter] It's time. I'm excited to really dig into it because, you know, as someone who has heard you talk about it a lot, you know, and is maybe a little less familiar with graph theory and how, you know, it can be applied to my day to day work, I'm really excited to dig into a little bit about, you know, what a regular developer needs to know about dependency graphs to add to their toolbox of skills.
JOËL: So, I think at its core, the idea of a dependency graph is that you have a group of entities, some of which depend on each other. They can't do a task, or they can't be created unless some other subtasks or dependent actions take place. And so, we have a sort of formal structural way of describing these things. Visually, we often draw these things out where each of the pieces is like a little bubble or a circle, and then we draw arrows towards the things that it depends on.
So, if A cannot be done without B being done first, we draw an arrow from A to B. That's kind of how it is in the abstract. More concretely, this kind of thing shows up constantly throughout the work that we do because a lot of what we do as developers is managing things that are connected to each other or that depend on each other. We build complex systems out of smaller components that all rely on each other.
STEPHANIE: Yeah, I think it's interesting because I use the word dependency, you know, very frequently when talking about normal work that I'm doing, you know, dependencies as in libraries, right? That we've pulled into our application, or dependencies, like, talking about other classes that are referenced in this class that I'm working in. And I never really thought about what could be explored further or, like, what could be learned from really digging into those connections.
JOËL: It's a really powerful mental model. And, like you said, dependencies exist all over our work, and we often use that word. So, you mentioned something like packages, where your application depends on Rails, which in turn depends on ActiveRecord, which in turn depends on a bunch of other things. And so, you've got this whole chain of maybe immediate dependencies, and then those dependencies have dependencies, and those dependencies have dependencies, and it kind of, like, grows outward from there.
And in a very kind of simplistic model, you might think, oh, well, it's more, like, a kind of a tree structure. But oftentimes, you'll have things like branches on one side that connect back to branches on the other. And now you've got something that's no longer really tree-like. It's more of a sort of interconnected web, and that is a graph.
STEPHANIE: I think understanding the dependencies of your system has also become more important to me as I learn about things that can go wrong when I don't know enough about what my system is, you know, relying on that I had kind of taken for granted previously. I'm especially thinking about packages like we were mentioning, and, you know, not realizing that your application is dependent on this other library, right? That's brought in by a gem that you're using. And there's maybe, like, a security issue, right? With that.
And suddenly, you have this problem on your hands that you didn't realize before. And I know that that has been more of a common discussion now in terms of security practices, just being more aware of all the things that you are depending on as really our work becomes more and more interconnected with the things available to us with open source.
JOËL: I think where understanding the graph-like nature of this becomes really important is when you're doing something like an upgrade. So, let's say you do have a gem that has a security problem, and you want to upgrade it to fix that security issue. But the upgrade that includes the security patch is also a breaking upgrade. And so, now everything else in your system that depends on that gem or on that package is going to break unless you have them in a version that is compatible with the new version of that gem.
And so, you might have to then go downstream and upgrade those packages in a way that's compatible with your app before you can bring in the security patch. And a lot of that can be done automatically by Bundler. Bundler is software that is built around navigating dependency graphs like that and finding versions that are compatible with each other.
But sometimes, your code will need to change in order to upgrade one of these downstream gems so that you can then pull in the upgrade from the gem that needs a security patch. And so, understanding a little bit of that graph is going to be important to safely upgrading that gem.
STEPHANIE: So, I know another application of dependency graphs that you have thought about and written a blog post for is RSpec let declarations and how a lot of the time when we are using let, you know, we are likely calling other variables defined by let. And so, when you are encountering a test file, it can be really hard to grok what data is being set up in your test.
JOËL: Yeah, so that is really interesting because you can define something that will get executed in a lazy fashion if it gets referenced. But then not only is the let lazy and will not trigger unless it's referenced, but a let can reference other lets, which are also lazy, and only get triggered if they get referenced.
So, you might have a bunch of lets defined in any order you want throughout a file, and they're all kind of interconnected with these references to each other. But they only get triggered if something calls it directly or it's in this, like, chain of dependencies. And getting a grasp on what actually gets created, which lets will actually execute, which ones don't in a file can quickly get out of hand. And so, thinking of this in terms of a dependency graph has been a really helpful mental model for me to understand what's going on in a complex test file.
STEPHANIE: Yeah, absolutely. Especially when sometimes the lets are coming from all over the place, you know, maybe a describe block hundreds of lines away, or even a completely different file if you are using a shared context that's being pulled in. So, I can see why this was a complex problem that could be made a little simpler with plotting out a dependency graph.
And in preparation for this episode, I was doing a little bit of my own exploration on this because I certainly know, you know, the pain of trying to figure out what is being executed in my tests when there are a lot of lets that reference each other. And in the blog post, you kind of gave a little step-by-step of how you could start with creating a dependency graph for the test that you're working with.
And I was really curious if this process could be automated because, you know, I do enjoy, you know, pulling out the pen and paper [chuckles] every now and then. But I'm not, like, a particularly visual person. God forbid I, like, draw a circle, but then, like, don't have enough space for the rest of the circles. [laughs] So, I was really hoping for a tool that could do this for me, especially if, you know, you do, you have a lot of tests that you have to try to understand in a relatively short amount of time. And so, I ended up doing something kind of hacky with RSpec and overriding let definitions to automate this process.
JOËL: That's really cool. So, is the tool that you're trying to build something where you feed it in a spec file, and it gives you some kind of graphical representation like an SVG or something as output?
STEPHANIE: Yeah. I did consider that approach first, where you feed in the file, but then I ended up going with something more dynamic where you are running the test, and then as it gets executed, tracing the let definitions and then registering them to build your dependency graph.
JOËL: So, you've got some sort of internal modeling that describes a dependency graph. And then, somehow, you're going to turn that, you know, a series of Ruby objects into some kind of visual.
STEPHANIE: Yeah, exactly. And the bulk of that work was actually done with a library called RGL, which stands for just Ruby Graph Library. [laughs] And what's nice is that it has a really easy interface for plugging in the vertices and edges of the dependency graph that you want to build. And then, it is already hooked up with Graphviz to, you know, write the SVG to a file. And so, I ended up really just having to build up an array of my dependencies and the connections to each other and then feed it into the constructor of the graph.
JOËL: And for all of our listeners, you mentioned Graphviz. That is a third-party tool that can be installed on your machine that can generate these SVG diagrams from...I believe it has its own sort of syntax. So, you create, I believe it's dot, D-O-T, so dot dot file. And based off of that, it generates all sorts of things, but SVG being potentially one of them.
STEPHANIE: Yeah. The nice thing was that I actually didn't end up having to use the DSL of Graphviz because the RGL gem was doing them for me.
JOËL: Nice. So, it plugs in directly.
STEPHANIE: Yeah, exactly. And I was really curious about using this gem because I, you know, just wanted to write Ruby, especially to plug into other things that are already in Ruby. And I found that surprisingly easy, thanks to all of the RSpec config options that they make available to you, including an option to extend the example group class, which is actually where let and let bang is defined.
And so, I ended up overriding those classes and using, you know, the name of the let that you're defining and then the block to basically register the dependencies. And I also ended up exploring a little bit with using Ruby's built-in parser to figure out in the block that's being passed to the let, what parts of that block could potentially be a reference to another let.
JOËL: That's really cool. Did you get any fun results from that?
STEPHANIE: I did. It worked pretty well in being able to capture all of the let declarations, and other lets that it references. And so, I was able to successfully, you know, like, generate a visual dependency graph of all of the lets, so that was really neat.
The part that I was really kind of excited about trying next, though I didn't end up having time to yet, was figuring out which of those let values are executed by way of the let bang, right? Which is eager or what is referenced in the test that then gets executed as well. And so, the RGL library is pretty neat and has some formatting options, too, with the Graphviz output. So, you can change the font color or styling options for different, you know, nodes and edges. And so, I was really curious to pursue this further, maybe, and use it to show exactly what gets evaluated now that I have successfully mapped my let graph.
JOËL: Right. Because the whole point of this exercise is that not the entire graph is going to get evaluated. The underlying question is, what data actually gets created when my test runs? And so, you build out this whole dependency graph, and then you can follow a few simple rules to say, okay, this branch gets called, this branch gets called, this series of things gets called. And okay, this subset of let blocks trigger, and therefore this data has been created for my given test.
STEPHANIE: Yeah. Though I will say that even where I got so far to, just seeing all of the let definitions in a spec file was really helpful to have a better understanding, you know, if I do have to add a test in here, and I'm thinking about reaching for a pre-existing let declaration, to be like, oh, like, it actually, you know, goes on to reference all of these other things that may be factories [chuckles] that are created might make me, you know, think twice, or just have a little better understanding of what I'm really dealing with.
JOËL: Right. The idea that when you're calling out to a let, or a factory, or something else that's just a node in a large graph, you're not necessarily referencing just one thing. You might actually be referencing the head of a very long chain of things that maybe you don't intend to trigger the whole thing.
STEPHANIE: Yeah, exactly.
JOËL: So, in that sense, having a sort of visual or at least an idea of the graph can give you a much better sense of the cost of certain operations that you might have to do.
STEPHANIE: The cost of the operations certainly, especially when, you know, you are working in a legacy codebase, and you, you know, like, maybe don't know how everything plays together or is connected. And it's very tempting to just reach for [chuckles] the things that have been, you know, created or built for you. And I'm certainly guilty of that sometimes on this client project, where the domain is so complex, and there are so many associated models.
And I'm like, well, like, let me just, you know, use this let that already, you know, has a factory set up for what I think I need for this test. But then realizing, oh, actually, like, it is creating all these things, and do I really need them? I think it can be really challenging to unravel all of that in your head. And so, with this very scrappy tool that I [chuckles] built for my own purposes, you know, maybe it makes it, like, one step easier to try to fully understand what I'm working with and maybe do something different.
JOËL: One aspect that I think is really powerful about dependency graphs is that it takes this kind of, like, abstract concept that we oftentimes have an intuitive sense around, the idea that we have different components that depend on each other, and it shows it to us visually on, like, a 2D plane. And that can be really helpful to get an understanding or an overview of a system.
You mentioned that RGL uses Graphviz to generate some SVGs. A visual tool that I've been using to draw some of my dependency graphs has been mermaid.js. It has a syntax that's, like, a text-based syntax, but it's almost visual in that you have a piece of text and name of a node. And then, you'll draw a little ASCII arrow, you know, two dashes and a greater than sign to say this thing depends on, and then write another name, and just have a row, like, a bunch of entries to say; A depends on B. A also depends on C. C depends on D, and so on, and, like, build up that list. And then Mermaid will just generate that diagram for you.
STEPHANIE: Yeah. I've used Mermaid a few times. One really helpful use that I had for it was diagramming out a bunch of React components that I had and wanting to understand the connections between them. And I think you can even paste the Mermaid syntax into your GitHub pull request description, and it'll render as the graph image.
JOËL: Yeah, that's what's really cool is that Mermaid syntax has become embedded in a lot of other places in the past few years. So, it's really easy to embed graphs now into all sorts of things. You mentioned GitHub. It works in pull requests descriptions, comments, I think pretty much anywhere that Markdown is accepted. So, you could put one in your README if you wanted.
Another place that I use a lot, Obsidian, my note-taking tool, allows me to embed graphs directly in there, which is really much nicer than previously; sometimes, when I wanted to express something as a visual, I would use some sort of drawing tool to do something and export an image, and then embed that in my note. But now I can just put in this text, and it will automatically render that as a diagram.
And part of what's really nice about that is that then it's really easy for me to go and change that if I'm like, oh, but actually, I want to add one more connection in here. I don't have to re go back to, hopefully, a file that I've saved somewhere and, like, change an image file and re-export it. I just, you know, I add one line of text to my note, and it just works.
STEPHANIE: That's awesome. Yeah, the ability to change it seems really useful.
So, we've talked a little bit about tools for creating a visual aid for understanding our dependencies. And now that we have our graph, maybe we might have some concerning observations about what we see, especially when perhaps some of our dependencies are pointing back to each other.
JOËL: Yes. So, I think you're referencing cycles, in particular. That would be the formal term for it. And those are really interesting. They happen in dependency graphs. And I would say, in many cases, they can be a bit of a smell. There's definitely situations where they're fine. But there are things that you look at, and you're like, okay, this is going to be a more complex kind of tricky bit of the graph to work with.
Some cases, you just straight up can't have them. So, I want to say that the way RSpec lets are set up, you cannot write code that produces cycles. But you might have...I think Ruby allows classes to reference each other in such a way that it creates a cycle, and not all languages do that. So, Elm and F#, I believe, require that modules cannot reference each other. The fancy term for this is a dependent acyclic graph, or DAG, which basically just means that there are no cycles in that graph.
STEPHANIE: Yeah. What you said about classes referencing each other is very interesting because I've definitely seen that. And then, if I have to go about changing something, maybe even it's just the class name, right? Now there's no way in which I can really make just one change. I have to kind of do it all in one go.
JOËL: I think that's a common property of a cycle, and a graph is that changes that happen somewhere in that cycle often need to be all shipped together as one piece. You can't break it up into smaller chunks because everything depends on everything else. So, it has to be kind of boxed together and shipped as one thing.
STEPHANIE: And you'd mentioned that cycles, you know, can be a bit of a code smell. And if the goal is to be able to break it up so that it is a little bit more manageable to work with, how would you go about breaking a cycle?
JOËL: So, I think breaking a cycle is going to vary a little bit based on your problem domain. So, are you modeling a series of classes that are referencing each other? Is this a function call graph? Is this even, like, a series of tasks that you're trying to do? But typically, what you want to do is make sure that eventually, at some point, like, something doesn't loop back to referencing something higher up in your hierarchy. And so, oftentimes, it ends up being about what is allowed to know about what? Do you have higher-level concepts that can know and depend on lower-level concepts but not vice versa?
And again, we are talking about this a little bit at the abstract level. But in terms of, let's say, different code modules, or classes, or something like that, commonly, you might say, well, we want some sort of layering where we have almost, like, more primitive types of classes at the bottom. And they don't get to know about anything above them. But the ones above that might be more complex that are composed of smaller pieces know about the ones below them. And you might have multiple layers kind of like that that all kind of point down, but nothing points up.
STEPHANIE: That is a very common heuristic. [chuckles] I think you were basically just describing how I also understand creating React components, where you want to separate your presentational ones from your functional ones. And, yeah, it makes a lot of sense that as soon as you start adding that complexity of, you know, those primitive classes at the bottom, starting to, you know, point to things higher up or to know about things higher up, that is where a cycle may be accidentally introduced.
JOËL: It's interesting just how many design principles that we have in software. If you dig into them a little bit, you find out that they're about decoupling things, and oftentimes, it's specifically breaking up cycles. So, one way that you might have something like this that actually has dependency in the name, the dependency inversion principle, where what you're effectively doing is you're taking one of those dependency arrows, and you're flipping it the other way. So, instead of A depending on B, you're flipping it. Now B depends on A, and that can be enough to break a cycle.
STEPHANIE: So, one thing I've picked up from our conversations about dependency graphs is that oftentimes, you know, when you're trying to figure out where to start, you want to look for those areas or those nodes where there's nothing else that depends on it.
JOËL: Yeah. I think you have those nodes that, if this were a tree, you would call them the leaf nodes. In the case of a graph, I'm not sure if that's technically correct, but they don't depend on anything. They're kind of your base case. And so, you can, you know, if it's a function, you can run it. If it's a file, you can load it; if it's a class, also you can load it up and not have to do anything else because it has no dependencies. And knowing that those are there, I think, can be really useful in terms of knowing an order you might want to execute something in. And this is really interesting for one of my favorite uses of a graph, which is breaking down a series of tasks that you need to do.
So, commonly, you might say, okay, I have a large task I need to do. I break it down into a series of subtasks. And, you know, maybe I draw out, like, a bulleted list and, you know, task 1, 2, 3, 4, 5. The problem is that they're not necessarily just a flat list. They all have, like, orders, like dependencies between each other. So, maybe one has to happen before 2, but it also has to happen before 3, which needs to happen before two, and, like, there's all these interconnections.
And then, you find out that you can't ship them independently the way you thought initially. So, by building up a graph, you end up with something that shows you exactly what depends on what. And then, like you said, the parts that are really interesting where you can start doing work are the ones that have no dependencies themselves. Other things might depend on them, but they have no dependencies. Therefore, they can be safely built, shipped, deployed to production, and they can be done independently of the other subtasks.
STEPHANIE: Yeah. I was also thinking about things that could be done in parallel as well. So, if you do have multiple of those items with no dependencies, like, that is a really good way to be able to break up that work and, yeah, identify things that are not blocked.
JOËL: For a complex set of tasks, it's great to see, okay, these two pieces have no dependencies. We can have them be done in parallel, shipped independently. And then you can just kind of keep repeating that process. Because once all of the tasks that have no dependencies have been done, well, you can almost, like, remove them from the graph and see, okay, what's the new set of things that have no dependencies? And then, keep doing that until you've eventually done the whole graph.
And that may sound like, oh okay, we're just kind of using a little bit of intuition and working through the graph. It turns out that this is a, like, actual, like, formal thing. When it comes to graphs, it's a traversal algorithm called topological sort is the fancy name for it, and it basically, yeah, it goes through that. It gives you a list of nodes in order where each node that you're given has no dependencies that have not been evaluated yet.
So, it works from effectively to use our tree terminology, from the leaf nodes to the root, potentially roots plural, of the graph, and each step is independent. So that's a lot of, like, fancy terminology, and getting a little bit of, like, computer science graph theory into here.
So, my, like, general heuristic is that graphs should be evaluated from the bottom up when you're trying to evaluate each piece independently. So, when you do that, you get to do each piece independently, as opposed to if you're evaluating from the top down. So, starting from the one thing that depends on everything else, well, it can't be shipped until all of its dependencies have been shipped.
And all the transitional dependencies can't be shipped until their dependencies have been shipped. And so, you end up being not able to ship anything until you've built the entire graph. And that's when you end up with, you know, a 2,000-line PR that took you multiple weeks and might be buggy. And it's going to take a long time to review. And it's just not what anybody wants.
STEPHANIE: I'm glad you brought this up because I think this is where I am really curious to get better at because oftentimes, when I am breaking down a complex task, it's quite hard for me to see all of the steps that need to happen. And so, you know, you maybe start out with that, like, top-level node, like, the task that needs to be done as you understand it immediately. And it's really hard to actually identify the dependencies and, like, the smaller pieces along the way. And because you're not able to identify that, you think that you do have to just do it all in one go.
JOËL: Yeah, that sort of root node is typically the overarching task, the goal of what you want to do. And a common, I think, scenario for something like this would be, let's say, you're doing a Rails upgrade. And so, that root node is upgrade Rails. And a common thing that you might want to do is say, okay, let's go to the gem file, upgrade Rails, see what breaks, and then just keep fixing those things. That's working from the top down.
And you're going to be in a long-running branch, and you're going to keep fixing things, fixing things, fixing things until you have found all the things but done all the things. And then you do a big bang upgrade that may have taken you weeks. As opposed to if you're working from the bottom up, you try to figure out, okay, what are all the subtasks? And that might take some exploration. You might not know upfront.
But then you might say, okay, here, I can upgrade RSpec versus a dependency, or I need to change the interface of this class and ship all these pieces one at a time. And then, the final step is flipping that upgrade in the gem file, saying, okay, now I've upgraded Rails from 4 to 5, or whatever the version is that you're trying to do.
STEPHANIE: I think you've really hit the nail on the head when it comes to trying to do something but not knowing what subtasks may compose of it and getting into that problem of, you know, having not broken it down, like, enough to really see all the dependencies.
And, you know, maybe this is a conversation [chuckles] for another episode, but the skill of breaking up those tasks and exploring what those dependencies are, and being able to figure them out upfront before you start to just do that upgrade and then see what happens, that's definitely an area that I want to keep investing in. And I'm sure other people would be really curious about, too, to help them make their jobs easier.
JOËL: I think one tip that I've learned that's really fun and that connects into all of this is sometimes you do end up with a cycle in your dependencies of tasks. A technique for breaking that up is a pattern that I have pitched multiple times on the show: the strangler fig pattern. And part of why it's so powerful is that it allows you to work incrementally by breaking up some of these cycles in your dependency graph.
And one of the lessons that I've learned from that is that just because you have sort of an initial set of subtasks and you have a graph of them doesn't mean that you can't change them. If you're following strangler fig, what you're actually doing is introducing one or more new subtasks to that graph. But the way you introduce them breaks up that cycle. So, you can always add new tasks or split up existing ones as you get a better understanding of the work you need to do. It's not something that is fixed or set in stone upfront.
STEPHANIE: Yeah, that's a really great tip. I think next time, what I really want to explore, you know, your heuristic of going from bottom up, yeah, sure, it sounds all fine and dandy. But how to get to a point where you're able to see everything at the bottom, right? And, like, when you are tasked, or you do start with the thing at the top, like, the end goal. Yeah, I'm sure that's something we'll explore [chuckles] another day.
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.
Joël has been fighting a frustrating bug where he's integrating with a third-party database, and some queries just crash. Stephanie shares her own debugging story about a leaky stub that caused flaky tests.
Additionally, they discuss the build vs. buy decision when integrating with third-party systems. They consider the time and cost implications of building their own integration versus using off-the-shelf components and conclude that the decision often depends on the specific needs and priorities of the project, including how quickly a solution is needed and whether the integration is core to the business's value proposition.
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: My world has been kind of frustrating recently. I've been fighting a really frustrating bug where I'm integrating with a third-party database. And there are queries that just straight-up crash. Any query that instantiates an instance of an ActiveRecord object will just straight-up fail. And that's because before, we make the actual query, almost like a preflight query that fetches the schema of the database, particularly the list of tables that the database has, and there's something in this schema that the code doesn't like, and everything just crashes.
Specifically, I'm using an ODBC connection. I forget exactly what the acronym stands for, Open Database connection, maybe? Which is a standard put up by Microsoft. The way I'm integrating it via Ruby is there's a gem that's a C extension. And somewhere deep in the C extension, this whole thing is crashing. So, I've had to sort of dust off some C a little bit to look through. And it's not super clear exactly why things are crashing. So, I've spent several days trying to figure out what's going on there. And it's been really cryptic.
STEPHANIE: Yeah, that does sound frustrating. And it seems like maybe you are a little bit out of your depth in terms of your usual tools for figuring out a bug are not so helpful here.
JOËL: Yeah, yeah. It's a lot harder to just go through and put in a print or a debug statement because now I have to recompile some C. And, you know, you can mess around with some things by passing different flags. But it is a lot more difficult than just doing, like, a bundle open and binding to RB in the code.
My ultimate solution was asking for help. So, I got another thoughtboter to help me, and we paired on it. We got to a solution that worked. And then, right before I went to deploy this change, because this was breaking on the staging website, I refreshed the website just to make sure that everything was breaking before I pushed the fix to see that everything is working. This is a habit I've picked up from test-driven development. You always want to see your test break before you see it succeed.
And this is a situation where this habit paid off because the website was just working. My changes were not deployed. It just started working again. Now it's gotten me just completely questioning whether my solution fixes anything. The difficulty is because I am integrating [inaudible 03:20] third-party database; it's non-deterministic. The schema on there is changing rather frequently.
I think the reason things are crashing is because there's some kind of bad data or data that the ODBC adapter doesn't like in this third-party system. But it just got introduced one day; everything started breaking, and then somehow it got removed, and everything is working again without any input or code changes on my end. So, now I don't trust my fix.
STEPHANIE: Oh no. Yeah, I would struggle with that because your reality has come crashing down, [laughs] or how you understood reality. That's tough. Where do you think you'll go from here? If it's no longer really an issue in this current state of the schema, is it worth pursuing further at this time?
JOËL: So, that's interesting because it turns into a prioritization problem. And for this particular project, with the deadlines that we have, we've decided it's not worth it. I've opened up a PR with my fix, with some pretty in-depth documentation for why I thought that was the fix and what I think the underlying problem is. If this shows up again in the next few days, I'll have that PR that I can pull in and see if it fixes things, and if it doesn't, I'll probably just close that PR, but it'll be available for us if we ever run into this again.
I've also looked at a few potential mitigating situations. Part of the problem is that this is a, like, massive system. The Rails app that I'm using really doesn't need to deal with this massive database. I think there's, you know, almost 1,000 tables, and I really only care about a subset of tables in, like, one underlying schema. And so, I think by reducing the permissions of my database user to only those tables that I care about, there's a lower chance of me triggering something like this.
STEPHANIE: Interesting. What you mentioned about, you know, having that PR continue to exist will be really helpful for future folks who might come across the same problem, right? Because then they can see, like, all of the research and investigation you've already done. And you may have already done this, but if you do think it's a schema issue, I'm curious about whether the snapshot of the schema could be captured from when it was failing to when it has magically gotten fixed. And I wonder if there may be some clues there for some future investigator.
JOËL: Yeah. I'm not sure what our backup situation is because this is a third-party system, so I'd have to figure out what things are like in the admin interface there. But yeah, if there is some kind of auditing, or snapshots, or backups, or something there, and I have rough, you know, if I know it's within a 24-hour period, maybe there's something there that would tell me what's happening.
My best guess is that there's some string that is longer than expected or maybe being marked as a CHAR when it should be a VARCHAR, or maybe something that's not a non-UTF-8 encoded character, or something weird like that. So, I never know exactly what was wrong in the schema. There's some weird string thing happening that's causing the Ruby adapter to blow up.
STEPHANIE: That also feels so unsatisfying [laughs] for you. I could imagine.
JOËL: Yeah, there's no, like, clean resolution, right? It's a, well, the bug is gone for now. We're trying to make it less likely for it to pop up again in the future. I'm trying to leave some documentation for the next person who's going to come along, and I'm moving forward, fingers crossed. Is that something you've ever had to do on one of your projects?
STEPHANIE: Given up? Yes. [laughter] I think I have definitely had to learn how to timebox debugging and have some action items for when I just can't figure it out. And, you know, like we mentioned, leaving some documentation for the next person to pick up, adding some additional logging so that maybe we can get more clues next time. But, you know, realizing that I do have to move on and that's the best that I can do is really challenging.
JOËL: So, you used two words here to describe the situation: one was giving up, and the other one was timebox. I think I really like the idea of describing this as timeboxing. Giving up feels kind of like, defeatist. You know, there's so many things that we can do with our time, and we really have to be strategic with how we prioritize. So, I like the idea of describing this as a timeboxing situation.
STEPHANIE: Yeah, I agree. Maybe I should celebrate every time that I successfully timebox something [laughs] according to how I planned to. [laughs]
JOËL: There's always room to extend the timebox, right?
STEPHANIE: [laughs] It's funny you bring up a debugging mystery because I have one of my own to share today. And I do have to say that it ended up being resolved, [chuckles] so it was a win in my book. But I will call this the case of the leaky stub.
JOËL: That sounds slightly scary.
STEPHANIE: It really was. The premise of what we were trying to figure out here was that we were having some flaky tests that were failing with a runtime error, so that was already kind of interesting. But it was quickly determined it was flaky because of the tests running in a certain order, so--
JOËL: Classic.
STEPHANIE: Right. So, I knew something was happening, and any tests that came after it were running into this error. And I was taking a look, and I figured out how to recreate it. And we even isolated to the test itself that was running before everything else, that would then cause some problems. And so, looking into this test, I saw that it was stubbing the find method on an ActiveRecord model.
JOËL: Interesting.
STEPHANIE: Yeah. And the stubbed value that we were choosing to return ended up being referenced in the tests that followed. So, that was really strange to me because it went against everything I understood about how RSpec cleans up stubs between tests, right?
JOËL: Yeah, that is really strange.
STEPHANIE: Yeah, and I knew that it was referencing the stub value because we had set a really custom, like, ID value to it. So, when I was seeing this exact ID value showing up in a test that seemed totally unrelated, that was kind of a clue that there was some leakage happening.
JOËL: So, what did you do next?
STEPHANIE: The next discovery was that the error was actually raised in the factory setup for the failing tests and not even getting to running the examples at all. So, that was really strange. And digging into the factories was also its own adventure because there was a lot of complexity in the factories. A lot of them used hooks as well that then called some application code. And it was a wild goose chase.
But ultimately, I realized that in the factory setup, we were calling some application code for that model where we had stubbed the find, and it had used the find method to memoize a class instance variable.
JOËL: Oh no. I can see where this is going.
STEPHANIE: Yeah. So, at some point, our model.find() returned our, you know, stub value that we had wanted in the previous test. And it got cached and just continued to leak into everything else that eventually would try to call that memoized method when it really should have tried to do that look-up for a separate record.
JOËL: And class instance variables will persist between tests as long as they're on the same thread, right?
STEPHANIE: Yeah, as far as I understand it.
JOËL: That sounds like a really frustrating journey. And then that moment when you see the class instance variable, and you're like, oh no, I can't believe this is happening.
STEPHANIE: Right? It was a real recipe for disaster, I think, where we had some, you know, really complicated factories. We had some sneaky caching issues, and this, you know, totally seemingly random runtime error that was being raised. And it was a real wild goose chase because there was not a lot of directness in going down the debugging path. I feel like I went around all over the codebase to get to the root of it. And, in the end, you know, we were trying to come up with some takeaways.
And what was unfortunate was that you know, like, normally, stubbing find can be okay if you are, you know, really wanting to make sure that you are returning your mocked value that you may have, like, stubbed some other stuff on in your test. But because of all this, we were like, well, should we just not stub find on this really particular model? And that didn't seem particularly sustainable to make as a takeaway for other developers who want to avoid this problem.
So, in the end, I think we scoped the stub to be a little more specific with the arguments that we wanted to target. And that was the way that we went forward with the particular flaky test at hand.
JOËL: It sounds like the root cause of the problem was not so much the stub as it was the fact that this value is getting cached at the class level. Is that right?
STEPHANIE: Yes and no. It seems like a real pain for running the tests. But I'm assuming that it was done for a good reason in production, maybe, maybe not. To be fair, I think we didn't need to cache it at all because it's calling a find, which is, you know, should be pretty quick and doesn't need to be cached. But who knows? It's hard to tell. It was really old code. And I think we were feeling also a little nervous to adjust something that we weren't sure what the impact would be.
JOËL: I'm always really skeptical of caching. Caching has its place. But I think a lot of developers are a little too happy to introduce one, especially doing it preemptively that, oh well, we might need a cache here, so why not? Let's add that. Or even sometimes, just as a blind solution to any kind of slowness, oh, the site is slow; let's throw a cache here and hope for the best.
And the, like, bedrock, like, rule zero of any kind of performance tuning is you've got to measure before and after and make sure that the change that you introduce actually makes things better. And then, also, is it better enough speed-wise that you're willing to pay any kind of costs associated to maintaining the code now that it's more complex? And a lot of caches can have some higher carrying costs.
STEPHANIE: Yeah, that's a great point. This debugging mystery an example of one of them.
JOËL: How long did it take you to figure out the solution here?
STEPHANIE: So, like you, I actually was on a bit of the incorrect path for a little while. And it was only because this issue affected a different flaky test that someone else was investigating that they were able to connect the dots and be like, I think these, you know, two issues are related. And they were the ones who ultimately were able to point us out to the offending test if you will. So, you know, it took me a few days. And I imagine it took the other developer a few days. So, our combined effort was, like, over a week.
JOËL: Yep. So, for all our listeners out there, you just heard that Stephanie and I [laughs] both went on multi-day debugging journeys. That happens to everyone. Just because we've been doing this job for years doesn't mean that every bug is, like, a thing that we figure out immediately.
So, separately from this bug that I've been working on, a big issue that's been front of mind for me on this project has been the classic build versus buy decision. Because we're integrating with a third-party system, we have to look at either building our own integration or trying to use some off-the-shelf components. And there's a few different levels of this.
There are some parts where you can actually, like, literally buy an integration and think through some of the decisions there. And then there's some situations where maybe there's an open-source component that we can use. And there's always trade-offs with both the commercial and the open-source situation. And we have to decide, are we willing to use this, or do we want to build our own? And those have been some really interesting discussions to have.
STEPHANIE: Yeah. I think you actually expanded this decision-making problem into a build versus buy versus open source because they are kind of, you know, really different solutions with different outcomes in terms of, you know, maintenance and dependencies, right? And that all have, like, a little bit of a different way to engage with them.
JOËL: Interesting. I think I tend to think of the buy category, including both like commercial off-the-shelf software and also open-source off-the-shelf software, things that we wouldn't build custom for ourselves but that are third-party components that we can pull in.
STEPHANIE: Yeah, that's interesting because I had a bit of a different mental model because, in my head, when you're buying a commercial solution, you, you know, are maybe losing out on some opportunities for customization or even, like, forking it on your own. So, with an open-source solution, there could be an aspect of making it work for you. Whereas for a commercial solution, you really become dependent on that other company and whether they are willing to cater [laughs] to your needs or not.
JOËL: That's fair. For something that's closed-source where you don't actually have access to the code, say it's more of a software as a service situation, then, yeah, you're kind of locked in and hoping that they can provide the needs that you have. On the flip side, you are generally paying for some level of support. The quality of that varies sometimes from one vendor to another. But if something goes wrong, usually, there's someone you can email, someone you can call, and they will tell you how to fix the problem, or they will fix it on their end.
STEPHANIE: For the purposes of this conversation, should we talk about the differences, you know, building yourself or leaning on an existing built-out solution for you?
JOËL: The project I'm working on is integrating with a Snowflake data warehouse, which is an external place that stores data accessible through something SQL-like. And one of the things that's attractive about this is that you can pull in data from a variety of different sources, transform it, and have it all stored in a kind of standardized structure that you can then integrate with. So, for pulling data in, you can build your own sort of ingestion pipeline, if you want, with code, and their APIs, and things.
But there are also third-party vendors that will give you kind of off-the-shelf components that you can use for a lot of popular other data sources that you might want to pull. So, you're saying; I want to pull from this external service. They've probably got a pre-built connector for it. They can also do things like pull from an arbitrary Postgres database on some other server if that's something you have access to.
It becomes really attractive because all you need to do is create an account on this website, plug in a few, like, API keys and URLs. And, all of a sudden, data is just flowing from one third-party system into your Snowflake data Warehouse, and it all just kind of works. And you don't have to bother with APIs, or ODBC, or any of that kind of stuff.
STEPHANIE: Got it. Yeah, that does sound convenient. As you were talking about this, I was thinking about how if I were in the position of trying to decide how to make that integration happen, the idea of building it would seem kind of scary, especially if it's something that I don't have a lot of expertise in.
JOËL: Yeah, so this was really interesting. In the beginning of the project, I looked into a little bit of what goes into building these, and it's fairly simple in terms of the architecture. You just need something that writes data files to typically something like an S3 bucket. And then you can point Snowflake to periodically pull from that bucket, and you write an import script to, you know, parse the columns and write them to the right tables in the structure that you want inside Snowflake.
Where things get tricky is the actual integration on the other end. So, you have some sort of third-party service. And now, how do you sort of, on a timer maybe, pull data from that? And if there are data changes that you're synchronizing, is it just all append-only data? Or are you allowing the third-party service to say, "Hey, I deleted this record, and you should reflect that in Snowflake?" Or maybe dealing with an update. So, all of these things you have to think about, as well as synchronization.
What you end up having to do is you probably boot up some kind of small service and, you know, maybe this is a small Ruby app that you have on Heroku, maybe this is, like, an AWS Lambda kind of thing. And you probably end up running this every so many seconds or so many minutes, do some work, potentially write some files to S3. And there's a lot of edge cases you have to think about to do it properly. And so, not having to think about all of those edge cases becomes really enticing when you're looking to potentially pay a third party to do this for you.
STEPHANIE: Yeah, when you used the words new service, I bristled a little bit [laughs] because I've definitely seen this happen maybe on a bit of a bigger scale for a tool or solution for some need, right? Where some team is formed, or maybe we kind of add some more responsibilities to an existing team to spin up a new service with a new repo with its own pipeline, and it becomes yet another thing to maintain. And I have definitely seen issues with the longevity of that kind of approach.
JOËL: The idea of maintaining a fleet of little services for each of our integrations seemed very unappealing to me, especially given that setting something like this up using the commercial approach probably takes 30 minutes per third-party service. There's no way I'm standing up an app and doing this whole querying every so many minutes, and getting data, and transforming it, and writing it to S3, and addressing all the edge cases in 30 minutes. And it's building something that's robust.
And, you know, maybe if I want to go, like, really low tech, there's something fun I could do with, like, a Zapier hook and just, like, duct tape a few services together and make this, like, a no-code solution. I still don't know that it would have the robustness of the vendor. And I don't think that I could do it in the same amount of time.
STEPHANIE: Yeah. I like the keyword robustness here because, at first, you were saying, like, you know, this looked relatively small in scope, right? The code that you had to write. But introducing all of the variables of things that could go wrong [laughs] beyond the custom part that you actually care about seemed quite cumbersome.
JOËL: I think there's also, at this point, a lot of really interesting prioritization questions. There are money questions, but there are also time questions you have to think about. So, how much dev time do we want to devote upfront to building out these integrations? And if you're trying to move fast and get a proof of concept out, or even get, like, an MVP out in front of customers, it might be worth paying more money upfront to a third-party vendor because it allows you to ship something this week rather than next month.
STEPHANIE: Yeah. The "How soon do you need it?" is a very good question to ask. Another one that I have learned to include in my arsenal of, you know, evaluating this kind of stuff comes from a thoughtbot blog by Josh Clayton, where he, you know, talks about the build versus buy problem. And his takeaway is that you should buy when your business is not dependent on it.
JOËL: When it's not part of, like, the core, like, value-add that your business is doing. Why spend developer time on something that's not, like, the core thing that your product is when you can pay someone else to do it for you? And like we said earlier, a lot of that time ends up being sunk into edge cases and robustness and things like that to the point where now you have to build an expertise in a, like, secondary thing that your business doesn't really care about.
STEPHANIE: Yeah, absolutely. I think this is also perhaps where very clear business goals or a vision would come in handy as well. Because if you're considering building something that doesn't quite support that vision, then it will likely end up continuing to be deprioritized over the long term until it becomes this thing that no one is accountable for maintaining and caring for.
And just causes a lot of, honestly, morale issues is what I've seen when some service that was spun up to try to solve a particular problem is kind of on its last legs and has been really neglected, and no one wants to work on it. But it ends up causing issues for the rest of the development team. But then they're also really focused on initiatives that actually do provide the business value. That is a really hard balancing act that I've seen teams struggle with.
JOËL: Earlier this year, we were talking about the book Sustainable Rails. And it really hammers home the idea of a carrying cost for the code, and I think that's exactly what we're talking about here. And that carrying cost can be time and money. But I like that you also mentioned the morale effects. You know, that's a carrying cost that just sort of depresses the productivity of your team when morale is low.
STEPHANIE: Yeah, absolutely. I'm curious if we could discuss some of the carrying costs of buying a solution and where you've seen that become tricky.
JOËL: The first thing to look at is the literal cost, the money aspect of things. And I think it's a really interesting situation for the business models for these types of Snowflake connectors because they typically charge by the amount of data that you're transmitting, so per row of data that you're transmitting. And so, that cost will fluctuate depending on whether the third-party service you're integrating with is, like, really chatty or not.
When you contrast that to building, building typically has a relatively fixed cost. It's a big upfront cost, and then there's some maintenance cost to go with it. So, if I'm building some kind of integration for, let's say, Shopify, then there's the cost I need to build up front to integrate that. And if that takes me, I don't know, a week or two weeks, or however long it is, you know, that's a pretty big chunk of time. And my time is money.
And so, you can actually do the math and say, "Well, if we know that we're getting so many rows per day at this rate from the commercial vendor, how many weeks do we have to pay for the commercial one before we break even and it becomes more expensive than building it upfront, just in terms of my time?" And sometimes you do that math, and you're like, wow, you know, we could be going on this commercial thing for, like, two years before we break even. In that case, from a purely financial point of view, it's probably worth paying for that connector.
And so, now it becomes really interesting. You say, okay, well, which are the connectors that we have that are low volume, and which are the ones that are high volume? Because each of them is going to have a different break-even point. The ones that you break even after, you know, three or four weeks might be the ones that become more interesting to have a conversation about building. Whereas some of the others, it's clearly not worth our time to build it ourselves.
STEPHANIE: The way you described this problem was really interesting to me because it almost sounds like you found the solution somewhere in the middle, potentially, where, you know, you may try building the ones that are highest priority, and you end up learning a lot from that experience, right? That could make it easier or at least, like, set you up to consider doing that moving forward in the future if you find, like, that is what is valuable.
But it's interesting to me that you kind of have the best of both worlds of, like, getting the commercial solutions now for the things that are lower value and then doing what you can to get the most out of building a solution.
JOËL: Yeah. So, my final recommendation ended up being, let's go all commercial for now. And then, once we've built out something, and because speed is also an issue here, once we've built out something and it's out with customers, and we're starting to see value from this, then we can start looking at how much are we paying per week for each of these connectors? And is it worth maybe going back and building our own for some of these higher-volume connectors? But starting with the commercial one for everything.
STEPHANIE: Yeah, I actually think that's generally a pretty good path forward because then you are also learning about how you use the commercial solution and, you know, which features of it are critical so that if you do eventually find yourselves, like, maybe considering a shift to building in-house, like, you could start with a more clear MVP, right? Because you know how your team is using an existing product and can focus on the parts that your business are dependent on.
JOËL: Yeah, it's that classic iterative development style. I think here it's also kind of inspired by a strategy I typically use for performance, which is make it work before you try to make it fast. And, actually, make it work, then profile, then measure, find the hotspots, and then focus on making those things fast. So, in this case, instead of speed, we're talking about money. So, it's make it work, then profile, find the parts that are expensive, and make the trade-off of, like, okay, is it worth investing into making that part less expensive in terms of resources?
STEPHANIE: I like that as a framework a lot.
JOËL: A lot of what we do as programmers is optimization, right? And sometimes, we're optimizing for execution time. Sometimes we're optimizing for memory cost, and sometimes we're optimizing for dollars.
STEPHANIE: Yeah, that's really interesting because, with the buy solution, you know very clearly, like, how much the thing will cost. Whereas I've definitely seen teams go down the building route, and it always takes longer than expected [laughs], and that is money, right? In terms of the developer's time, for sure.
JOËL: Yeah, definitely, like, add some kind of multiplier when you're budgeting out that build alternative because, quite likely, there are some edge cases that you haven't thought about that the commercial partner has, and you will have to spend more time on that than you expected.
STEPHANIE: Yeah, in addition to whatever opportunity cost of not working on something that is driving revenue for the business right now.
JOËL: Exactly.
STEPHANIE: So, the direction of this conversation ended up going kind of towards, like, what is best for the team at, like, a product and company level. But I think that we make these decisions a lot more frequently, even when it comes to whether we pull in a gem or, you know, use an open-source tool or not. And I would be really interested in discussing more of that in another episode.
JOËL: Yeah. That gets into some controversial takes, right? It's the evergreen topic of: do we build it ourselves, or do we pull in some kind of third-party package?
STEPHANIE: Something for the future to look forward to. 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: 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.
Stephanie had a small consulting win: saying no to a client. GeoGuessr is all the rage for thoughtbot's remote working culture, which leads to today's topic of forming human connections in a virtual (work) environment.
Transcript:
JOËL: And this is just where it ends.
[laughter]
Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm 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's new in your world?
STEPHANIE: So, I have a small consulting win, or even just a small, like, win as a human being [laughs] that I want to share, which is that I feel good about a way that I handled saying no to a stakeholder recently. And, you know, I really got to take them where I can get it because that is so challenging for me. But I feel really glad because we ended up kind of coming out the other side of it having a better understanding of each other's goals and needs.
And so, basically, what happened was I was working on a task, and our product owner on our team asked me if it could be done by next week. And immediately, I wanted to say, "Absolutely not." [laughs] But, you know, I took a second and, you know, I had the wherewithal to ask why. You know, I was kind of curious, like, where was this deadline coming from? Like, what was on her radar that, like, wasn't on mine?
And she had shared that, oh, you know, if we were able to get it out before this big launch, she was thinking that it actually might make our customer support team's lives easier because we were kind of taking away access to something before some new features rolled out. And, you know, there might be some customers who would complain. And with that information, you know, that was really helpful in helping me understand. And I'm like, yeah, like, that seems like a helpful thing to know, so I could try to strive for it. Because I also, like, want to make that process go easier as well.
But I told her that I'd let her know because I honestly wasn't sure if it was possible to do by next week. And after a little bit of, you know, more digging, kind of seeing how my progress was going, in the end, I had to say that I didn't feel confident that we could finish it in time for that deadline because of the other risks, right? Like, I didn't want to just release this thing without feeling good about the plan that we had. And so, that was my small, little win in saying no, and I feel very proud of myself for it.
JOËL: I'm proud of you too. That's not easy to just do in the first place, and then to do it well is a whole other level. It sounds, though, that you came out of the other side with the client with almost, like, a better relationship.
STEPHANIE: Yeah, I think so. In general, you know, I really struggle when people do end up getting into that debate of, like, "Well, I need this." And someone else says, "Well, I need this other thing." And, you know, at some point, it kind of gets a bit unproductive, right? But I think this was a very helpful way for me to see a path forward when maybe we, like, have different priorities. But, like, can we better understand each other and the impact of them to ultimately, like, make the best decision?
The other thing that I wanted to share that I learned recently was there was a recent RailsConf talk by Elle Meredith, and it was about strategies to say no, and I watched it. And one really cool thing that I learned was that the word priority, you know, when it was first created, it actually didn't really have, like, a plural form. There was really only ever, like, a singular priority. And it wasn't until, I think, you know, the recent century or something like that, that people started to use it in a plural form. And that was really enlightening to me.
I think it made me rethink the word and how I use it, and it made a lot of sense, too. Because at any given moment, you know, really, you can't be doing more than one thing; I mean, you can try. I know that I have been guilty of multitasking. But that, you know, doesn't always serve me. I never end up doing all of the things that I'm trying to do well. And I would be really curious to kind of, you know, when I do feel that urge, like, think a little bit about, like, what is the one thing that I should be doing right now that is the highest priority?
JOËL: I would definitely second that recommendation for this talk. I actually got to see it live at RailsConf, and it was excellent.
STEPHANIE: So, Joël, what's new in your world?
JOËL: I got to participate in a really fun event at thoughtbot today. We got together with some other people on the Boost Team and played a few rounds of GeoGuessr. And for those who are not familiar with this game, it drops you randomly somewhere in the world in Google Street View. You can move around. And there's a timer, and you have to drop a pin on a map where you think you are.
So, you're walking through the streets, and you're like, okay, well, I don't know this language. I'm not sure where we're going. You know, with the vibes going here, I'll bet, you know, this looks like maybe southern China, and then you drop a pin. And oh no, turns out it was actually Singapore. And there's all these little hints and things. People who are really into it have learned all these tricks, and they can be really good. Sara Jackson, who is our resident GeoGuessr expert, is excellent at this. But it was a good time.
STEPHANIE: Yeah, it was really fun. I liked that we played a cooperative mode where we were all kind of helping each other out. And so, maybe someone is, like, exploring on the map and sees a street sign and is like, "Oh, like, that looks like this language." And someone else is like, "Oh yeah, like, that is that." Or like, "No, I think it's actually this other language," and sharing all of the different, like, pieces of information that we're finding to get closer and closer to what it might be.
And then we celebrate whoever ends up getting the closest because, at some point, it's kind of just, like, just a luck of the pin, right? Where maybe you happen to click on, like, the right place. But it's always really exciting when we're like, wow, like, Sara was only 500 kilometers away in finding the exact place that we were served. So, I had a good time as well.
JOËL: So, speaking of cooperative events, this was a work event that we did. We just got together and played a game. And, for me, that was a really fun way to connect with some of my colleagues. I'm curious, what are your thoughts on things that you've seen done well in companies that are remote-first that really foster a sense of connection and community among a team?
STEPHANIE: I think this worked especially well today because it was kind of scheduled in regular time that we have as a team to me. And sometimes, you know, the meeting topics are a bit more work-focused. But what I really like is that anyone on the team can host one of these meetings. We have them biweekly, and we just call them Boost biweeklies. Boost is the team that Joël and I are on.
JOËL: Naming is the hardest problem in computer science.
STEPHANIE: It really is. But I really like that people can bring, you know, a little bit of their own flavor to this meeting. So, whoever is host just kind of comes up with something to do. And sometimes it's like show and tell. You know, other times it is more of like, you know, what's the update on some of the projects that we're doing? Other times, it's the Spicy Takes Lightning Talks that we've kind of mentioned on the podcast before. And yeah, it is just a really nice, like, time for us to get together.
And I also feel like I learn something about my co-workers every time that we meet, whether it's the person who is hosting the meeting and kind of where their interests are. I think someone even did, like, chair yoga once and guided the team in doing that. Or because they are more casual, right? Sometimes we just play a game, and I really enjoy that nice break in my day.
JOËL: Do you find that the particular style of these meetings makes you feel more connected to your colleagues? Would you prefer just kind of game day one, like we had today, versus maybe, like, lightning talks or a presentation on security or something like that?
STEPHANIE: I actually think the diversity is what makes it special. I get to see, you know, a bunch of different sides of my co-workers and, you know, some days, the topic is a little more serious, and that can be really connecting. Another Boost Team member had hosted a biweekly where we kind of shared the challenges of, like, consulting work and, like, onboarding onto a new project and sharing what might be difficult and, like, how we might be feeling when we do join a new project.
And I think that was really helpful because it was very validating for something that I thought, like, maybe I felt a little bit more alone in. And the tone was a little bit more, like, earnest and serious. But I came away with it feeling very supported by my team, right? And other times, it is just silliness and fun [laughs], which, you know, is also important. Like, we need to have fun every once in a while.
JOËL: That's awesome. Do you feel like when you go to these meetings, you're looking more for knowledge or looking more for connection?
STEPHANIE: I think both because knowledge sharing is also, you know, can be really helpful. Like, I have enjoyed learning that, you know, so and so is, like, a GeoGuessr expert, Sara, right? And so, if I ever, like, find myself needing [chuckles] someone to go to about my Google Street View or world geography questions, I know that I can go to her. And, like, knowing that about her, like, makes me feel more connected to her. So, I think both are true.
So, we have been talking about a meeting style form of connecting in a remote workplace, but I'm really curious about your thoughts on asynchronous versus synchronous communication and how you find connection with a format that is more asynchronous, not just, you know, being in a meeting together.
JOËL: That's really challenging. I think I personally find that something that's mostly synchronous with maybe a little bit of a lag works pretty well for me, so something like Slack, where it's not exactly real-time because someone could take some time to come back to me. But for working hours overlap, there's likely some close-to-synchronous conversation happening.
But, you know, I can still get up and, you know, refill my cup of coffee, or it's not quite like I'm sitting in front of a camera. So, I think that, for many things, hits the sweet spot for myself. But there's definitely some things where I think you want a higher, like, information density. And that's, I think, where the synchronous face-to-face meeting really shines.
STEPHANIE: Information density. I haven't heard that phrase before, but I like it.
JOËL: The idea being, you know, how much information or how many words are you sharing back and forth, you know, per minute or something like that. And when you're talking on a call, you can do a lot more of that than you can going back and forth over Slack or writing an email.
STEPHANIE: So, I would say that at thoughtbot, we have a pretty asynchronous Slack culture, which I think can be quite different from other, you know, places I've worked at before or other Slack spaces that I've seen. And I actually find it a little bit harder to engage in that way. We have a dev channel where, you know, people chat about different technical topics. And sometimes, you know, those threads go, like, 40 replies long. And I think you tend to engage a lot more in those.
And I'm curious, like, does that scratch the itch for you in terms of that perfect, like, async, kind of some amount of lag for you to be doing other things, kind of doing your work, but then being able to come back and pick up the conversation where I left off?
JOËL: Yes, that is really nice because, you know, maybe I have a meeting or something, and I'm not there when the conversation starts, but I don't miss out. And I get to join in, you know, maybe 30 minutes after everyone else. You know, sometimes you don't want to just, like, restart a conversation that's happened and is done. But some of these things will kind of be going on and off all day. And those can be really fun, especially sometimes, like, a new person joins the thread and brings in a totally new perspective or a new angle that kind of, like, breathes new life into it and kind of gives everyone a new perspective.
STEPHANIE: Nice. I also think there's something to the idea of seeing more people engage with something that then invites other people to engage with it.
JOËL: I would agree with that. It's definitely exciting to see a thread, and it's not like, oh, it's empty, and I'm the only one who's put a response in here. When there is a lot of back and forth, you can almost feel the excitement. And that gets me hyped to, like, keep it going.
STEPHANIE: At a previous workplace in our Slack, we had a, like, virtual Jeopardy channel.
JOËL: Ooh.
STEPHANIE: And so, there was a little Jeopardy bot. And I guess whenever someone, you know, had a low on what they were doing, they would just start, you know, tagging the bot to pose a question. And anyone can answer, right? But once you kind of got the ball rolling, you would see other people start playing as well. And it would get really active for segments of 30 minutes or so.
And I always really enjoyed that because, yeah, it was a way for me to remember like, oh yeah, there's, like, other people also, like, typing away on their little keyboards, and we're all here together. But it was really interesting to see, like, when someone got it rolling, like, oh, other people, like, joined in.
JOËL: Yeah, being able to see small things like that can really build a sense of connection, even if you're not yourself directly participating.
STEPHANIE: Yeah. I think another thing I've been trying out lately is letting people know that I'm in a meeting space and offering to virtually co-work. So, you know, during the early days of when thoughtbot went remote, we had a lounge virtual meeting space for people to hang out with and, you know, get that face time that they weren't getting anymore since we weren't in the office. And, you know, I think that has kind of decreased in terms of engagement over, you know, several years now. And obviously, people have a lot of meeting fatigue and stuff like that.
But I was kind of in a mood to revive it a little bit because, yeah, I kind of got over the meeting fatigue and was wanting more face time with people. And the unfortunate thing, though, is that, like, no one was showing up to this room anymore. So, you know, even if someone wanted to hang out in it, you know, they go in. They see no one's there, you know, maybe they stay for a few minutes, but then they're like, okay, well, I'm just going to leave now.
And a couple of thoughtboters and I have been trying to revive it where we'll post in our general channel, like, "Hey, like, I'm in this meeting room. Like, come hang out for the next hour if you would like." And that's been working well for me. I have had a few, like, really nice lounge, virtual co-working hangout sessions. Even if one person shows up, honestly, like, that fulfills my want to just, like, speak to another human. [laughs]
JOËL: What does virtual co-working look like? Are you just kind of each doing work, but you've got a video camera on, and you're just aware of the presence of someone else? Do you kind of have, like, random breaks where you talk? What is that experience like?
STEPHANIE: Oh yeah, that's a good question. I have to say; for me, I'm just talking to the other [laughs] person at that point. I'm not really doing a whole lot of work. And, you know, in some ways, I almost think that, like, in those moments, I am really wanting to chat with someone and, like, that's okay, right?
JOËL: It's like a virtual water cooler for you.
STEPHANIE: Yeah, exactly. Like, that would be the moment if I were working in office that I would wander into the kitchen looking for a snack but also an unsuspecting victim to start [laughs] a conversation with.
JOËL: I feel you. I feel you. I have absolutely done that.
STEPHANIE: Yeah. And that's actually what makes me feel a little less guilty about it. Because, you know, when I was working in the office, like, that was such a big part of my day, and it's kind of what kept me motivated. And at home, I do find myself, like, a lot more productive. In fact, like, I think I am because I'm, you know, not spending that time wandering into the kitchen. But at what cost? [laughs] At the cost of, like, me feeling very, like, lonely and, like, kind of burnt out at the end of the day.
So, injecting my day with some of these moments, I think, is important to me. And also, again, like, I know that I'm being really productive in my, like, heads-down-time that I want to, you know, allow myself to just like, get that dose of connection.
JOËL: I know, for me, when we were doing things like this in person as well, those conversations that happen, yes, there's some random, frivolous stuff, but sometimes, it is a conversation related to work that I'm doing. Because, you know, someone who's not on my project is like, "Hey, how's your project going?" Or whatever. I'm like, "Oh, well, I'm, you know, doing this ODBC connection, and I'm kind of stuck." And, you know, we kind of talk about a few things. It's like, "Oh, did you know about this gem?" And it's like, "Wait, why didn't I talk to you earlier? Because this totally solves my problem."
STEPHANIE: Yeah, I think that being a sounding board is so valuable as well. So, I guess I enjoy virtual co-working, not necessarily, you know, us, like, sitting together and doing our work separately. Though I know that there's value in that, especially in real life. Like, I remember reading an article. I'll try to find it and link it. But the idea of just, like, sharing space with someone can be, like, a form of bonding.
But I do really enjoy just hearing about what other people are working on and just kind of, like, asking questions about it, right? And maybe we do take away, like, a new perspective or, like, have some insights about, like, the work itself. And, yeah, we don't really get that when we're working remotely by ourselves because there's no one to turn to and be like, "Hey, what do you think about this problem?"
JOËL: I love how no matter what the topic is that we're discussing on this show, you always have a book or an article or something that you've read that you can reference. And I think that's amazing.
STEPHANIE: Thank you.
JOËL: So, you're talking about things that have really helped you feel a deeper sense of connection. I had a realization recently about the power of physical items. In particular, as consultants, sometimes we work with clients who, for security reasons, want us to work on a dedicated laptop for this particular client. And so, we'll have clients maybe—well, now that we're remote—ship us a laptop, and we work on that laptop when we're doing client stuff, and then on our thoughtbot laptops when we're doing thoughtbot things.
And when I've been on clients like that, I have felt much more isolated from the thoughtbot team. And just, like, physically switching over to the thoughtbot laptop, all of a sudden, gives me that feeling of connection. And there's something I can't quite explain about the power of the physical item. And, say, I'm working on the thoughtbot laptop today with, you know, thoughtbot Slack in the background or whatever, and I feel more connected to my colleagues.
STEPHANIE: Yeah, that is really curious. Did you also have thoughtbot communication channels open in your client laptop during that time?
JOËL: I did, and yet still felt more separation.
STEPHANIE: Yeah, that's really interesting. The way you're describing it, it was almost like, you know, the main laptop that you work with, with your, like, all of the settings that you like, all of your little shortcuts, you know, the autocomplete to the whatever, like, channels of communication that you are used to seeing. In some ways, that almost feels like home a little bit. And I wonder if working on a client laptop almost kind of feels like, you know, being in a stranger's house, right?
JOËL: There's definitely an element of that. Yeah, all the little things I've fine-tuned, some of the productivity software I have on there that are just, you know, I can one by one set them up on the client laptop, depending on permissions. But yeah, it's never quite the same.
STEPHANIE: So, when you are in a situation where you're mostly working from a client laptop and maybe embedded in their Slack workspace, embedded in their team, how do you go about investing in connection with your client team?
JOËL: So, you know what's kind of weird? Is that when I'm on a client laptop, I feel less connected to my colleagues at thoughtbot, but the reverse is not necessarily true. I don't feel more connected to colleagues on a client team on a client laptop than I would on my thoughtbot laptop. So, I'm not exactly sure what the psychology is going on there. But I feel kind of most connected to both when I'm working on my thoughtbot laptop, which is perhaps a bit strange.
STEPHANIE: Oh, yeah, that is interesting. I think, in general, there's an aspect of joining a new client team and trying to figure out the culture there and how you might engage with it, right? And how what you bring to the table kind of fits in with how they do things, and how they talk about things, and how they behave. In some ways, it's kind of, like, you know, an outsider joining this, like, in-group, right? So, I've definitely realized that the ways that I engage and feel connected at thoughtbot, like, may or may not work for the client team that I'm joining.
JOËL: Yeah. And onboarding onto a client team is not just a technical exercise, right? It's also a social process where you want to get to know the other people on your team, get to sort of integrate into the way they work, their processes, hopefully, build a little bit of, like, personal connection with individuals because all of those are going to help me do my job better tomorrow, and the day after, and the week after that.
STEPHANIE: Yeah. I had mentioned previously that one thing that I've been enjoying on my client team is our daily sync question. So, a random question will be generated, you know, like, "What are you eating for dinner today?" Or, like, "What are you looking forward to this weekend?" And folks are able to share. And the fun thing is that sometimes the answer to the question is longer than their work update itself.
JOËL: Nice.
STEPHANIE: But that is actually the, you know, the beauty of it because we all just, like, get to laugh and get to, you know, chime in. And I'm like, "Oh yeah, like, that sounds delicious, like, what you're eating for dinner tonight." But, like, that would not work for our Boost Team's sync because, you know, it's a much bigger meeting with sometimes up to, you know, 20 to almost 30 people and, like, we can't quite have as much time spent talking about the fun question of the day. So, I definitely think that, you know, it depends your team size, and makeup, and whatnot.
JOËL: Are those questions kind of preset, or do you all get to contribute questions to the list?
STEPHANIE: We brainstormed the questions one retro when we were realizing that we were kind of getting a little bored of the existing question that we had. And we came up with a handful that is plugged into, like, a website, or, like, an app that randomly, you know, picks the question of the day. And so, I think, again, when we get a little bored of the ones that we have in rotation, we'll throw in some curveballs in there.
JOËL: Have you ever considered adding "What's new in your world?" to this rotation?
STEPHANIE: It's funny you mentioned that because it's actually the question that we got a little bit stale on. [laughs]
JOËL: Really?
STEPHANIE: And we needed to inject some new life into, yeah. It's a classic, you know. But I think the variety is nice, especially since we're meeting almost every day. And before we started recording, you and I were just talking about how even sometimes it's tough to think of something that's new in our world [laughs] because we don't always live the most interesting and, you know, new lives. And sometimes, we kind of just have to dig deep to come up with something, and we only meet weekly. [laughs]
JOËL: I can definitely see how doing this daily might be more challenging. I think there's also value in questions that are a little bit more focused. Part of what's fun for this podcast is that "What's new in your world?" is so kind of broad. But maybe for something daily, having something really specific, like, what did you eat for dinner tonight? Means that you aren't just kind of drawing blanks in your mind, like, uh, uh, what is new in my world? What have I done? I don't know; I have a boring life. I don't do anything. Kind of panic mode that you can sometimes get when you hit a meeting.
And so, I do know that when I've been sometimes in situations with people where you have questions like that, I've tended to really appreciate the more targeted ones.
STEPHANIE: Yeah, that's so interesting you mentioned that because I think in social situations, there's usually maybe, like, someone who is really good at asking those, like, specific questions to get the group talking and, like, you know, engaged in a fun conversation, and that specificity helps.
One thing that I was just wondering about is the value of meeting every day in a sync kind of format, and I'm curious if you think that is important to you. If you have been on other teams that don't meet every day, maybe they have, like, a virtual check-in, right? Like, a virtual reminder to share what they're working on as opposed to meeting synchronously.
JOËL: I think I've seen sort of different purposes for sync meetings. Sometimes it's very kind of project-heavy, right? You're talking about the tickets you're working on for today. The reason you're having that is specifically for status updates or because you are blocked, and you want somebody else to help unblock you. So, it's very process-focused. I think that varies team to team, but it can be really helpful.
Even I've been on projects where it's maybe me and one other person, and we'll have kind of an informal just call each other up every morning and say, "Hey, here's what I'm working on today. Here's kind of roughly the strategy I plan to take on it. And we'll go back and forth." And for something like that, it inevitably also somewhat turns into a bit of a social call, so that's planning and social. And I think that can be really strong.
STEPHANIE: Yeah, I like that a lot.
JOËL: That's not necessarily going to be the case for every team, every project, especially with larger teams. And I feel like for something like the Boost Team at thoughtbot, we have a daily sync. We're not all working on the same project. So, I don't want to know about the specific details of the ticket you're working on. I'm more interested in getting just a little bit of face time with the whole of our team to feel a connection.
And, you know, maybe if you've got something cool that you want to share, and that can be a win. It can even be a struggle. And we can all kind of empathize, right? That, like, "Oh, I dropped production database this morning, and I'm kind of freaking out," is a totally fine thing to share. But "I am working on ticket 1, 2, 3, 4 to add some text to a part of the page," that's not particularly useful to me in the kind of sync that we have for the thoughtbot Boost Team.
STEPHANIE: Yeah, absolutely. I think knowing, like, who the audience is of the meeting and, like, how they might be able to support you or be there for you is helpful in making them feel a little more relevant and personal. And I had mentioned that our Boost daily meetings or daily syncs, you know, are a little too big for people to really get into, you know, sharing a fun, personal anecdote, or whatever.
But one thing that I really enjoy is that whoever goes last in giving their update gets to choose the sign-off for everyone. So maybe that's like, okay, we'll just go out on a wave, and we all wave. Or maybe it's, you know, like, making a little heart with your hands. And then there's some folks on the team who go really wild and, you know, come up with something totally unexpected. And I think, you know, that spontaneity is so fun. And we all share it in this collective act of...I'm trying to think of a funny one lately, maybe, like, sinking down into your chair until you disappear from the view [laughs]. That's a good one.
JOËL: Sometimes it's those, like, small social rituals that can be really meaningful.
STEPHANIE: Absolutely. Do you have a favorite sign-off that you have either requested or have done?
JOËL: So, I typically just go for the wave if I'm last because I've not thought about it. But I generally think it's fun to have everybody try to mimic an emoji. So, it might be like, oh, everybody do the, you know, See-No-Evil emoji, or everybody do the party parrot. Those are pretty fun to sign off on.
STEPHANIE: Oh yeah, [inaudible 29:15] pausing is good. I think another one I like is, "Everyone do your best impression of a tree." [laughs]
JOËL: Sometimes, too, it's fun to do something that's relevant to the particular day. If there's something special happening that day, you get something relevant. I've done before, if it's on a Friday, say, "Everybody do your best Rebecca Black impression."
STEPHANIE: Yeah, also excellent.
JOËL: Because, you know, it's Friday.
STEPHANIE: Yeah, like, a little moment of collective celebration for the weekend. On that note, it's a Friday we're recording this episode. Shall we wrap up and look forward to the weekend?
JOËL: [laughter] Fun, fun, fun, fun.
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.
Amanda is a wife. A mother. A blogger. A Christian.
A charming, beautiful, bubbly, young woman who lives life to the fullest.
But Amanda is dying, with a secret she doesn’t want anyone to know.
She starts a blog detailing her cancer journey, and becomes an inspiration, touching and
captivating her local community as well as followers all over the world.
Until one day investigative producer Nancy gets an anonymous tip telling her to look at Amanda’s
blog, setting Nancy on an unimaginable road to uncover Amanda’s secret.
Award winning journalist Charlie Webster explores this unbelievable and bizarre, but
all-too-real tale, of a woman from San Jose, California whose secret ripped a family apart and
left a community in shock.
Scamanda is the true story of a woman whose own words held the key to her secret.
New episodes every Monday.
Follow Scamanda on Apple Podcasts, Spotify, or wherever you listen.
Amanda’s blog posts are read by actor Kendall Horn.