

The Bike Shed
thoughtbot
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.
Episodes
Mentioned books

Nov 9, 2021 • 41min
315: Emotions Are A Pendulum
Steph talks about starting a new project and identifying "focused" tests while Chris shares his latest strategy for managing flaky tests. They also ponder the squishy "it depends" side of software and respond to a listener question about testing all commits in a pull request.
This episode is brought to you by ScoutAPM. Give Scout a try for free today and Scout will donate $5 to the open source project of your choice when you deploy.
rspec-retry
Cassidy Williams - It Depends - GitHub Universe 2021
Say No To More Process
StandardRB
Become a Sponsor of The Bike Shed!
Transcript:
CHRIS: My new computer is due on the fourth. I'm so close.
STEPH: On the fourth?
CHRIS: On the fourth.
STEPH: That's so exciting.
CHRIS: And I'm very excited. But no, I don't want to upgrade any software on this computer anymore. Never again shall I update a piece of software on this computer.
STEPH: [laughs]
CHRIS: This is its final state. And then I will take its soul and move it into the new computer, and we'll go from there. [chuckles]
STEPH: Take its soul. [laughs]
CHRIS: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey.
STEPH: And I'm Steph Viccari.
CHRIS: And together, we're here to share a bit of what we learn along the way. So, Steph, what's new in your world?
STEPH: Hey, Chris. Let's see. It's been kind of a busy week. It's been a busy family week. Utah, my dog, hasn't been feeling well as you know because you and I have chatted off-mic about that a bit. So he is still recovering from something, I don't know what. He's still on most days his normal captain chaos self, but then other days, he's not feeling well. So I'm just keeping a close eye on him. And then I also got some other family illnesses going on. So it has been a busy family week for sure.
On the more technical project side, I am wrapping up my current project. So I have one more week, and then I will shift into a new project, which I'm very excited about. And you and I have chatted about this several times. So there's always just that interesting phase where you're trying to wrap up and hand things off and then accomplish last-minute wishlist items for a project before then you start with a new one. So I am currently in that phase.
CHRIS: How long were you on this project for?
STEPH: It'll be a total of I think eight months.
CHRIS: Eight months, that's healthy. That's a bunch. It's always interesting to be on a project for that long but then not longer. There were plenty of three and four-month projects that I did. And you can definitely get a large body of work done. You can look back at it and proudly stare at the code that you have written. But that length of time is always interesting to me because you end up really...for me, when I've had projects that went that long but then not longer, I always found that to be an interesting breaking point. How are you feeling moving on from it? Are you ready for something new? Are you sad to be moving on? Do you feel attached to things?
STEPH: It's always a mix. I'm definitely attached to the team, and then there are always lots of things that I'd still love to work on with that team. But then, I am also excited to start something new. That's why I love this role of consulting because then I get to hop around and see new projects and challenges and work with new people. I'm thinking seven to eight months might be a sweet spot for me in terms of the length of a project. Because I find that first month with a project, I'm really still ramping up, I'm getting comfortable, I'm getting in the groove, and I'm contributing within a short amount of time. But I still feel like that first month; I’m getting really comfortable with this new environment that I'm in. And so then I have that first month.
And then, at six months, I have more of heads-down time. And I get to really focus and work with a team. And then there's that transition period, and it's nice to know when that's coming up for several weeks, so then I have a couple of weeks to then start working on that transition phase. So eight months might be perfect because then it's like a month for onboarding, ramping up, getting comfortable. And then six months of focus, and then another month of just focusing on what needs to be transitioned so then I can transition off the team.
CHRIS: All right. Well, now we've defined it - eight months is the perfect length of a project.
STEPH: That's one of the things I like about the Boost team is because we typically have longer engagements. So that was one of the reasons when we were splitting up the teams in thoughtbot that I chose the Boost team because I was like, yeah, I like the six-month-plus project.
Speaking of that wishlist, there are little things that I've wanted to make improvements on but haven't really had time to do. There's one that's currently on my mind that I figured I'd share with you in case you have thoughts on it. But I am a big proponent of using the RSpec focus filter for when running tests. So that way, I can just prefix a context it block or describe block with F, and then RSpec I can just run all the tests. But RSpec will only run the tests that I've prefixed with that F focus command., and I love it.
But we are running into some challenges with it because right now, there's nothing that catches that in a pull request. So if you commit that focus filter on some of your tests, and then that gets pushed up, if someone doesn't notice it while reviewing your pull request, then that gets merged into main. And all of the tests are still green, but it's only a subset of the tests that are actually running. And so it's been on my mind that I'd love something that's going to notice that, that's going to catch it, something that is not just us humans doing our best but something that's automated that's going to notice it for us. And I have some thoughts. But I'm curious, have you run into something like this? Do you have a way that you avoid things like that from sneaking into the main branch?
CHRIS: Interestingly, I have not run into this particular problem with RSpec, and that's because of the way that I run RSpec tests. I almost never use the focus functionality where you actually change the code file to say, instead of it, it is now fit to focus that it.
I tend to lean into the functionality where RSpec you can pass it the line number just say, file: and then line number. And RSpec will automatically figure out which either spec or context block or entire file. And also, I have Vim stuff that allows me to do that very easily from the file. It's very rare that I would want to run more than one file.
So basically, with that, I have all of the flexibility I need. And it doesn't require any changes to the file. So that's almost always how I'm working in that mode. I really love that. And it makes me so sad when I go to JavaScript test runners because they don't have that.
That said, I've definitely felt a very similar thing with ESLint and ESLint yelling at me for having a console.log. And I'm like, ESLint, I'm working here. I got to debug some stuff, so if you could just calm down for a minute. And what I would like is a differentiation between these are checks that should only run in CI but definitely need to run in CI. And so I think an equivalent would be there's probably a RuboCop rule that says disallow fit or disallow any of the focus versions for RSpec. But I only want those to run in CI.
And this has been a pain point that I felt a bunch of times. And it's never been painful enough that I put in the effort to fix it. But I really dislike particularly that version of I'm in my editor, and I almost always want there to be no warnings within the editor. I love that TypeScript or ESLint, or other things can run within the editor and tell me what's going on. But I want them to be contextually aware. And that's the dream I've yet to get there.
STEPH: I like the idea of ESLint having a work mode where you're like, back off, I am in work mode right now. [chuckles] I understand that I won't commit this.
CHRIS: I'm working here. [laughter]
STEPH: And I like the idea of a RuboCop. So that's where my mind went initially is like, well, maybe there's a custom cop, or maybe there's an existing one, and I just haven't noticed it yet. But so I'm adding a rule that says, hey, if you do see an fcontext, fdescribe, ffit, something like that, please fail. Please let us know, so we don't merge this in. So that's on my wishlist, not my to-don't list. That one is on my to-do list.
CHRIS: I'm also intrigued, though, because the particular failure mode that you're describing is you take what is an entire spec suite, and instead, you focus down to one context block within a given file. So previously, there were 700 specs that ran, and now there are 12. And that's actually something that I would love for Circle or whatever platform you're running your tests on to be like, hey, just as a note, you had been slowly creeping up and had hit a high watermark of roughly 700 specs. And then today, we're down to 12. So either you did some aggressive grooming, or something's wrong. But a heuristic analysis of like, I know sometimes people delete specs, and that's a thing that's okay but probably not this many. So maybe something went wrong there.
STEPH: I feel like we're turning CI into this friend at the bar that's like, "Hey, you've had a couple of drinks. I just wanted to check in with you to make sure that you're good." [laughs]
CHRIS: Yes.
STEPH: "You've had 100 tests that were running and now only 50. Hey, friend, how are you? What's going on?"
CHRIS: "This doesn't sound like you. You're normally a little more level-headed." [laughs] And that's the CI that is my friend that keeps me honest. It's like, "Wait, you promised never to overspend anymore, and yet you're overspending." I'm like, "Thank you, CI. You're right; I did say I want the test to pass."
STEPH: [laughs] I love it. I'll keep you posted if I figure something out; if I either turn CI into that friend, that lets me know when my behavior has changed in a concerning way, and an intervention is needed. Or, more likely, I will see if there's a RuboCop or some other process that I can apply that will check for this, which I imagine will be fast. I mean, we're very mindful about ensuring our test suite doesn't slow down as we're running it. But I'm just thinking about this out loud. If we add that additional cop, I imagine that will be fast. So I don't think that's too much of an overhead to add to our CI process.
CHRIS: If you've already got RuboCop in there, I'm guessing the incremental cost of one additional cop is very small. But yeah, it is interesting. That general thing of I want CI to go fast; I definitely feel that feel. And we're slowly creeping up on the project I'm working on. I think we're at about somewhere between five to six minutes, but we've gotten there pretty quickly where not that long ago; it was only three minutes.
We're adding a lot of features specs, and so they are definitely accruing slowdowns in our CI. And they're worth it; I think, because they're so valuable. And they test the whole integration of everything, but it's a thing that I'm very closely watching. And I have a long list of things that I might pursue when I decide it's time for CI to get a haircut, as it were.
STEPH: I have a very hot tip for a way to speed up your test, and that is to check if any of your tests have a very long sleep in them. That came up recently [chuckles] this week where someone was working in a test and found some relic that had been added a while back that then wasn't caught. And I think it was a sleep 30. And they were like, "Hey, I just sped up our test by 30 seconds." I was like, ooh, we should grep now to see if there's anything else like that. [laughs]
CHRIS: Oh, I love the sentence we should grep now. [laughter] The correct response to this is to grep immediately. I thought you were going to go with the pro tip of you can just focus down to one context block. And then the specs will run so much faster because you're ignoring most of them, but we don't want to do that. The sleep, though, that's a pro tip. And that does feel like a thing that there could be a cop for, like, never sleep more than...frankly, let's try not to sleep at all but also, add a sleep in our specs. We can sleep in life; it's important, but anyway. [chuckles]
STEPH: [laughs] That was the second hot tip, and you got it.
CHRIS: Lots of hot tips. Well, I'm going to put this in the category of good idea, terrible idea. I won't call it a hot tip. It's a thing we're trying. So much as we have tried to build a spec suite that is consistent and deterministic and tells us only the truth, feature specs, even in our best efforts, still end up flaking from time to time. We'll have feature specs that fail, and then eventually, on a subsequent rerun, they will pass. And I am of the mindset that A, we should try and look into those and see if there is a real cause to it. But sometimes, just the machinery of feature specs, there's so much going on there. We've got the additional overhead of we're running it within a JavaScript context. There's just so much there that...let me say what I did, and then we can talk more about the context.
So there's a gem called RSpec::Retry. It comes from the wonderful folks over at NoRedInk, a well-known Elm shop for anyone out there in the Elm world. But RSpec::Retry does basically what it says in the name. If the spec fails, you can annotate specs. In our case, we've only enabled this for the feature specs. And you can tell it to retry, and you can say, "Retry up to this many times," and et cetera, et cetera. So I have enabled this for our feature specs. And I've only enabled it on CI. That's an important distinction. This does not run locally.
So if you run a feature spec and it fails locally, that's a good chance for us to intervene and look at whether or not there's some flakiness there. But on CI, I particularly don't want the case where we have a pull request, everything's great, and we merge that pull request, and then the subsequent rebuild, which again, as a note, I would rather that Circle not rebuild it because we've already built that one. But that is another topic that I have talked about in the past, and we'll probably talk about it again in the future.
But setting that aside, Circle will rebuild on the main branch when we merge in, and sometimes we'll see failures there. And that's where it's most painful. Like, this is now the deploy queue. This is trying to get this out into whatever environment we're deploying to. And it is very sad when that fails. And I have to go in and manually say, hey, rebuild. I know that this works because it just worked in the pull request, and it's the same commit hash. So I know deterministically for reasons that this should work. And then it does work on a rebuild.
So we introduced RSpec::Retry. We have wrapped it around our feature specs. And so now I believe we have three possible retries. So if it fails once, it'll try it again, and then it'll try it a third time. So far, we've seen each time that it has had to step in; it will pass on the subsequent run. But I don't know; there was some very gentle pushback or concerns; let’s call them when I introduced this pull request from another developer on the team, saying, "I don't know, though, I feel like this is something that we should solve at the root layer. The failures are a symptom of flaky tests, or inconsistency or et cetera, and so I'd rather not do this." And I said, "Yeah, I know. But I'm going to merge it," and then I merged it.
We had a better conversation about that. I didn't just broadly overrule. But I said, "I get it, but I don't see the obvious place to shore this up. I don't see where we're doing weird inconsistent things in our code. This is just, I think, inherent complexity of feature specs." So I did it, but yeah, good idea, terrible idea. What do you think, Steph? Maybe terrible is too strong of a word. Good idea, mediocre idea.
STEPH: I like the original branding. I like the good idea, terrible idea. Although you're right, that terrible is a very strong branding. So I am biased right now, so I'm going to lead in answering your question by stating that because our current project has that problem as well where we have these flaky tests. And it's one of those that, yes, we need to look at them. And we have fixed a large number of them, but there are still more of them.
And it becomes a question of are we actually doing something wrong here that then we need to fix? Or, like you said, is it just the nature of these features-specs? Some of them are going to occasionally fail. What reasonable improvements can we make to address this at the root cause? I'm interested enough that I haven't heard of RSpec::Retry that I want to check it out because when you add that, you annotate a test. When a test fails, does it run the entire build, or will it rerun just that test? Do you happen to know?
CHRIS: Just the test. So it's configured as in a round block on the feature specs. And so you tell it like, for any feature spec, it's like config.include for feature specs RSpec::Retry or whatever. So it's just going to rerun the one feature spec that failed when and if that happens. So it's very, very precise as well in that sense where when we have a failure merging into the main branch, I have to rebuild the whole thing. So that's five or six minutes plus whatever latency for me to notice it, et cetera, whereas this is two more seconds in our CI runtime. So that's great. But again, the question is, am I hiding? Am I dealing with the symptoms and not the root cause, et cetera?
STEPH: Is there a report that's provided at the end that does show these are the tests that failed and we had to rerun them?
CHRIS: I believe no-ish. You can configure it to output, but it's just going to be outputting to standard out, I believe. So along with the sea of green dots, you'll see had to retry this one. So it is visible, but it's not aggregated. And the particular thing is there's the JUnit reporter that we're using. So the XML common format for this is how long our tests took to run, and these ones passed and failed.
So Circle, as a particular example, has platform-level insights for that kind of stuff. And they can tell you these are your tests that fail most commonly. These are the tests that take the longest run, et cetera. I would love to get it integrated into that such that retried and then surface this to Circle. Circle could then surface it to us. But right now, I don't believe that's happening. So it is truly I will not see it unless I actively go search for it. To be truly honest, I'm probably not doing that.
STEPH: Yeah, that's a good, fair, honest answer. You mentioned earlier that if you want a test to retry, you have to annotate the test. Does that mean that you get to highlight specific tests that you're marking those to say, "Hey, I know that these are flaky. I'm okay with that. Please retry them." Or does it apply to all of them?
CHRIS: I think there are different ways that you can configure it. You could go the granular route of we know this is a flaky spec, so we're going to only put the retry logic around it. And that would be a normal RSpec annotation sort of tagging the spec, I think, is the terminology there. But we've configured it globally for all feature specs. So in a spec support file, we just say config.include Rspec::Retry where type is a feature. And so every feature spec now has the possibility to retry. If they pass on the first pass, which is the hope most of the time, then they will not be tried. But if they don't, if they fail, then they'll be retried up to three times or up to two additional times, I think is the total.
STEPH: Okay, cool. That's helpful. So then I think I have my answer. I really think it's a good idea to automate retrying tests that we have identified that are flaky. We've tried to address the root, and our resolution was this is fine. This happens sometimes. We don't have a great way to improve this, and we want to keep the test. So we're going to highlight that this test we want to retry. And then I'm going to say it’s not a great idea to turn it on for all of them just because then I have that same fear about you're now hiding any flaky tests that get introduced into the system. And nobody reasonably is going to go and read through to see which tests are going to get retried, so that part makes me nervous.
CHRIS: I like it. I think it's a balanced and reasonable set of good and terrible idea. Ooh, it's perfect. I don't think we've had a balanced answer on that yet.
STEPH: I don't think so.
CHRIS: This is a new outcome for this segment. I agree. Ideally, in my mind, it would be getting into that XML format, the output from the tests, so that we now have this artifact, we can see which ones are flaky and eventually apply effort there. What you're saying feels totally right of we should be more particular and granular. But at the same time, the failure mode and the thing that I'm trying, I want to keep deploys going. And I only want to stop deploys if something's really broken.
And if a spec retries, then I'm fine with it is where I've landed, particularly because we haven't had any real solutions where there was anything weird in our code. Like, there's just flakiness sometimes. As I say it, I feel like I'm just giving up. [laughs] And I can hear this tone of stuff's just hard sometimes, and so I've taken the easy way out. And I guess that's where I'm at right now. But I think what you're saying is a good, balanced answer here. I like it. I don't know if I'm going to do anything about it, but...[laughter]
STEPH: Well, going back to when I was saying that I'm biased, our team is feeling this pain because we have flaky tests. And we're creating tickets, and we're trying to do all the right things. We create a ticket. We have that. So it's public. So people know it's been acknowledged. If someone's working on it, we let the team know; hey, I'm working on this. So we're not duplicating efforts. And so, we are trying to address all of them. But then some of them don't feel like a great investment of our time trying to improve.
So that's what I really do like about the RSpec::Retry is then you can still have a resolution. Because it's either right now your resolution is to fix it or to change the code, so then maybe you can test it in a different way. There's not really a good medium step there. And so the retry feels like an additional good outcome to add to your tool bag to say, hey, I've triaged this, and this feels reasonable that we want to retry this.
But then there's also that concern of we don't want to hide all of these flaky tests from ourselves in case we have done it and there is an opportunity for us to improve it. So I think that's what I do really like about it because right now, for us, when a test fails, we have to rerun the entire build, and that's painful. So if tests are taking about 20 minutes right now, then one spec fails, and then you have to wait another 20 minutes.
CHRIS: I would have turned this on years ago with a 20-minute build time. [chuckles]
STEPH: [laughs] Yeah, you're not wrong. But also, I didn't actually know about RSpec::Retry until today. So that may be something that we introduce into our application or something that I bring up to the team to see if it's something that we want to add. But it is interesting that initial sort of ooh kind of feeling that the team will give you introducing because it feels bad. It feels wrong to be like, hey, we're just going to let these flaky tests live on, and we're going to automate retrying them to at least speed us up. And it's just a very interesting conversation around where we want to invest our time and between the risk and pay off.
And I had a similar experience this week where I had that conversation, but this one was more with myself where I was working through a particular issue where we have a state in the application where something weird was done in the past that led us to a weird state. And so someone raised a very good question where it's like, well, if what you're saying is technically an impossible state, we should make it impossible, like at the database layer. And I love that phrase. And yet, there was a part of me that was like, yes, but also doing that is not a trivial investment. And we're here because of a very weird thing that happened before.
It felt one of those interesting, like, do we want to pursue the more aggressive, like, let's make this impossible for the future? Or do we want to address it for now and see if it comes back up, and then we can invest more time in it? And I had a hard time walking myself through that because my initial response was, well, yeah, totally, we should make it impossible. But then I walked through all the steps that it would take to make that happen, and it was not very trivial.
And so it was one of those; it felt like the change that we ended up with was still an improvement. It was going to prevent users from seeing an error. It was still going to communicate that this state is an odd state for the application to be in. But it didn't go as far as to then add in all of the safety measures. And I felt good about it. But I had to convince myself to feel good about it.
CHRIS: What you're describing there, the whole thought sequence, really feels like the encapsulation of it depends. And that being part of the journey of learning how to do software development and what it means. And you actually shared a wonderful video with me yesterday, and it was Cassidy Williams at GitHub Universe. And it was her talking to her younger self, and just it depends, and it was so true. So we will include a link to that in the show note because that was a wonderful thing for you to share. And it really does encapsulate this thing. And from the outside, before I started doing software development, I'm like, it's cool. I'm going to learn how to sling code and fix the stuff and hack, and it'll be great, and obvious, and correct, and knowable. And now I'm like, oh man, squishy nonsense. That's all it is.
STEPH: [laughs]
CHRIS: Fun squishy, and I like it. It's so good. But it depends. Exactly that one where you're like, I know that there's a way to get to correctness here but is it worth the effort? And looping back to...I'm surprised at the stance that I've taken where I'm just like, yeah, I'm putting in RSpec::Retry. This feels like the right thing. I feel good about this decision. And so I've tried to poke at it a tiny bit.
And I think what matters to me deeply in a list of priorities is number one correctness. I care deeply that our system behaves correctly as intended and that we are able to verify that. I want to know if the system is not behaving correctly. And that's what we've talked about, like, if the test suite is green, I want to be able to deploy. I want to feel confident in that.
Flaky specs exist in this interesting space where if there is a real underlying issue, if we've architected our system in a way that causes this flakiness and that a user may ever experience that, then that is a broken system. That is an incorrect system, and I want to resolve that. But that's not the case with what we're experiencing. We're happy with the architecture of our system. And when we're resolving it, we're not even really resolving them. We're just rerunning manually at this point. We're just like, oh, that spec flaked. And there's nothing to do here because sometimes that just happens. So we're re-running manually. And so my belief is if I see all green, if the specs all pass, I know that I can deploy to production.
And so if occasionally a spec is going to flake and retrying it will make it pass (and I know that pass doesn't mean oh, this time it happened to pass; it's that is the correct outcome) and we have a false negative before, then I'm happy to instrument the system in a way that hides that from me because, at this point, it does feel like noise. I'm not doing anything else with the failures when we were looking at them more pointedly. I'm not resolving those flaky specs. There are no changes that we've made to the underlying system. And they don't represent a failure mode or an incorrectness that an end-user might see. So I honestly want to paper over and hide it from myself. And that's why I've chosen this. But you can see I need to defend my actions here because I feel weird. I feel a little off about this. But as I talk through it, that is the hierarchy. I care about correctness.
And then, the next thing I care about is maintaining the deployment pipeline. I want that to be as quick and as efficient as possible. And I've talked a bunch about explorations into the world of observability and trying to figure out how to do continuous deployment because I think that really encourages overall better engineering outcomes. And so first is correctness. Second is velocity. And flaky specs impact velocity heavily, but they don't actually impact correctness in the particular mode that we're experiencing them here. They definitely can. But in this case, as I look at the code, I'm like, nah, that was just noise in the system. That was just too much complexity stacked up in trying to run a feature spec that simulates a browser and a user clicking in JavaScript and all this stuff and the things. But again, [laughs] here I am. I am very defensive about this apparently.
STEPH: Well, I can certainly relate because I was defending my answer to myself earlier. And it is really interesting what you're pointing out. I like how you appreciate correctness and then velocity, that those are the two things that you're going after. And flaky tests often don't highlight an incorrect system. It is highlighting that maybe our code or our tests are not as performant as we would like them to be, but the behavior is correct. So I think that's a really important thing to recognize.
The part where I get squishy is where we have encountered on this project some flaky tests that did highlight that we had incorrect behavior, and there's only been maybe one or two. It was rare that it happened, but it at least has happened once or twice where it highlighted something to us that when tests were run...I think there's a whole lot of context. I won't get into it. But essentially, when tests were being run in a particular way that made them look like a flaky test, it was actually telling us something truthful about the system, that something was behaving in a way that we didn't want it to behave. So that's why I still like that triage that you have to go through.
But I also agree that if you're trying to get out at a deploy, you don't want to have to deal with flaky tests. There's a time to eat your vegetables, and I don't know if it's when you've got a deploy that needs to go out. That might not be the right time to be like, oh, we've got a flaky test. We should really address this. It's like, yes; you should note to yourself, hey, have a couple of vegetables tomorrow, make a ticket, and address that flaky test but not right now. That's not the time. So I think you've struck a good balance. But I also do like the idea of annotating specific tests instead of just retrying all of them, so you don't hide anything from yourself.
CHRIS: Yeah. And now that I'm saying it and now that I'm circling back around, what I'm saying is true of everything we've done so far. But it is possible that now this new mode that the system behaves in where it will essentially hide flaky specs on CI means that any new flaky regressions, as it were, will be hidden from us.
And thus far, almost all or I think all of the flakiness that we've seen has basically been related to timeouts. So a different way to solve this would potentially be to up the Capybara wait time. So there are occasionally times where the system's churning through, and the various layers of the feature specs just take a little bit longer. And so they miss...I forget what it is, but it's like two seconds right now or something like that. And I can just bump that up and say it's 10 seconds. And that's a mode that if eventually, the system ends in the state that we want, I'm happy to wait a little longer to see that, and that's fine.
But there are...to name some of the ways that flaky tests can actually highlight truly incorrect things; race conditions are a pretty common one where this behaves fine most of the time. But if the background job happens to succeed before the subsequent request happens, then you'll go to the page. That's a thing that a real user may experience, and in fact, it might even be more likely in production because production has differential performance characteristics on your background jobs versus your actual application. And so that's the sort of thing that would definitely be worth keeping in mind.
Additionally, if there are order issues within your spec suite if the randomize...I think actually RSpec::Retry wouldn't fix this, though, because it's going to retry within the same order. So that's a case that I think would be still highlighted. It would fail three times and then move on. But those we should definitely deal with. That's a test-related thing. But the first one, race conditions, that's totally a thing. They come up all the time. And I think I've potentially hidden that from myself now. And so, I might need to lock back what I said earlier because I feel like it's been true thus far that that has not been the failure mode, but it could be moving forward. And so I really want to find out if we got flaky specs. I don't know; I feel like I've said enough about this. So I'm going to stop saying anything new. [laughs] Do you have any other thoughts on this topic?
STEPH: Our emotions are a pendulum. We swing hard one way, and then we have to wait till we come back and settle in the middle. But there's that initial passion play where you're really frustrated by something, and then you swing, and you settle back towards something that's a little more neutral.
CHRIS: I don't trust anyone who pretends like their opinions never change. It doesn't feel like a good way to be.
STEPH: Oh, I hope that...Do people say that? I hope that's not true. I hope we are all changing our opinions as we get more information.
CHRIS: Me too.
Mid-roll Ad
And now a quick break to hear from today's sponsor, Scout APM.
Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more.
Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform.
See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed.
CHRIS: Well, shifting only ever so slightly because it turns out it's a very related question, but we have a listener question. As always, thank you so much to everyone who sends in listener questions. We really appreciate them. And today's question comes from Mikhail, and he writes in, "Regarding the discussion in Episode 311 on requiring commits merged to be tested, I have a question on how you view multi commit PRs. Do you think all the commits in a PR should be tested or only the last one? If you test all commits in a PR, do you have any good tips on setups for that? Would you want all commits to pass all tests? For one, it helps a lot when using Git bisect. It is also a question of keeping the history clean and understandable.
As a background on the project I currently work on, we have the opinion that all commits should be tested and working. We have now decided on single commit PRs only since this is the only way that we can currently get the setup reasonably on our CI. I would like to sometimes make PRs with more than one commit since I want to make commits as small as possible. In order to do that, we would have to find a way to make sure all commits in the PR are tested. There seems to be some hacky ways to accomplish this, but there is not much talk about it. Also, we are strict in requiring a linear history in all our projects. Kind regards, Mikhail." So, Steph, what do you think?
STEPH: I remember reading this question when it came in. And I have an experience this week that is relevant to this mainly because I had seen this question, and I was thinking about it. And off the cuff, I haven't really thought about this. I haven't been very concerned about ensuring every single commit passes because I want to ensure that, ultimately, the final commit that I have is going in.
But I also rarely have more than one commit in a PR. So that's often my default mode. There are a couple of times that I'll have two, maybe three commits, but I think that's pretty rare for me. I'll typically have just one commit. So I haven't thought about this heavily. And it's not something that frankly I've been concerned about or that I've run into issues with.
From their perspective about using Git bisect, I could see how that could be troublesome, like if you're looking at a commit and you realize there's a particular commit that's already merged and that fails. The other area that I could think of where this could be problematic is if you're trying to roll back to a specific commit. And if you accidentally roll back to a commit that is technically broken, but you didn't know that because it was not the final commit as was getting tested on CI, that could happen. I haven't seen that happen. I haven't experienced it. So while that does seem like a legitimate concern, it's also one that I frankly just haven't had.
But because I read this question from this person earlier this week, I actually thought about it when I was crafting a PR that had several commits in it, which is kind of unusual for me since I'm usually one or two commits in a PR. But for this one, I had several because we use standard RB in our project to handle all the formatting. And right now, we have one of those standard to-do files because we added it to the project. But there are still a number of manual fixes that need to be applied.
So we just have this list of files that still need to be formatted. And as someone touches that file, we will format it, and then we'll take it out of that to-do list. So then standard RB will include it as it's linting all of our files. And I decided to do that for all of our spec files. Because I was like, well, this was the safest chunk of files to format that will require the least amount of review from folks. So I just want to address all of them in one go. But I separated the more interesting changes into different commits just to make others aware of, like, hey, this is something standard RB wants.
And it was interesting enough that I thought I would point it out. So my first commit removed all the files from that to-do list, but then my other commits are the ones that made actual changes to some of those files that needed to be corrected. So technically, one or two of my middle commits didn't pass the standard RB linting. But because CI was only running that final commit, it didn't notice that.
And I thought about this question, and so I intentionally went back and made sure each of those commits were correct at that point in time. And I feel good about that. But I still don't feel the need to add more process around ensuring each commit is going to be green. I think I would lean more in favor of let's keep our PR small to one or two commits. But I don't know; it’s something I haven't really run into. It's an interesting question. How about you? What are your experiences, or what are your thoughts on this, Chris?
CHRIS: When this question came through, I thought it was such an interesting example of considering the cost of process changes. And to once again reference one of our favorite blog posts by German Velasco, the Say No to More Process post, which we will, of course, link in the show notes. This is such a great example of there was likely a small amount of pain that was felt at one point where someone tried to run git bisect. They ran into a troublesome commit, and they were like, oh no, this happened. We need to add processes, add automation, add control to make sure this never happens again.
Personally, I run git bisect very rarely. When I do, it's always a heroic moment just to get it started and to even know which is the good and which is the bad. It's always a thing anyway. So it would be sad if I ran into one of these commits. But I think this is a pretty rare outcome. I think in the particular case that you're talking about, there's probably a way to actually tease that apart. I think it sounds like you fixed those commits knowing this, maybe because you just put it in your head. But the idea that the process that this team is working on has been changed such that they only now allow single commit PRs feels like too much process in my mind. I think I'm probably 80%, maybe 90% of the time; it’s only a single commit in a PR for me.
But occasionally, I really value having the ability to break it out into discrete steps, like these are all logically grouped in one changeset that I want to send through. But they're discrete steps that I want to break apart so that the team can more easily review it so that we have granular separation, and I can highlight this as a reference. That's often something that I'll do is I want this commit to standalone because I want it to be referenced later on. I don't want to just fold it into the broader context in which it happened, but it's pretty rare. And so to say that we can't do that feels like we're adding process where it may not be worth it, where the cost of that process change is too high relative to the value that we're getting, which is speculatively being able to run git bisect and not hit something problematic in the future.
There's also the more purist, dogmatic view of well, all commits should be passing, of course. Yeah, I totally agree with that. But what's it worth to you? How much are you willing to spend to achieve that goal? I care deeply about the correctness of my system but only the current correctness. I don't care about historical correctness as much, some. I think I'm diminishing this more than I mean to. But really back to that core question of yes, this thing has value, but is it worth the cost that we have to pay in terms of process, in terms of automation and maintenance of that automation over time, et cetera or whatever the outcome is? Is it worth that cost? And in this case, for me, this would not be worth the cost. And I would not want to adopt a workflow that says we can only ever have single commit PRs, or all commits must be run on CI or any of those variants.
STEPH: This is an interesting situation where I very much agree with everything you're saying. But I actually feel like what Mikhail wants in this world; I want it too. I think it's correct in the way that I do want all the commits to pass, and I do want to know that. And I think since I do fall into the default, like you mentioned, 80%, 90% of my PRs are one commit. I just already have that. And the fact that they're enforcing that with their team is interesting. And I'm trying to think through why that feels cumbersome to enforce that.
And I'm with you where I'll maybe have a refactor commit or something that goes before. And it's like, well, what's wrong with splitting that out into a separate PR? What's the pain point of that? And I think the pain point is the fact that one, you have two PRs that are stacked on each other. So you have the first one that you need to get reviewed, and then the second one; there’s that bit of having to hop between the two if there's some shared context that someone can't just easily review in one pull request.
But then there's also, as we just mentioned, there's CI that has to run. And so now it's running on both of them, even though maybe that's a good thing because it's running on both commits. I like the idea that every commit is tested, and every commit is green. But I actually feel like it's some of our other processes that make it cumbersome and hard to get there. And if CI did run on every commit, I think it would be ideal, but then we are increasing our CI time by running it on every commit.
And then it comes down to essentially what you said, what's the risk? So if we do merge in a commit that doesn't work or has something that's failing about it but then the next commit after that fixes it, what's the risk that we're going to roll back to that one specific commit that was broken? If that's a high risk for you and your team, then adding this process is probably the really wise thing to do because you want to make sure the app doesn't go down for users. That's incredibly important. If that's not a high risk for your team, then I wouldn't add the process.
CHRIS: Yeah, I totally agree. And to clarify my stances, for me, this change, this process change would not be worth the trade-off. I love the idea. I love the goal of it. But it is not worth the process change, and that's partly because I haven't particularly felt the pain. CI is not an inexhaustible resource I have learned. I'm actually somewhat proud our very small team that is working on the project that we're working on; we just recently ran out of our CI budget, and Circle was like, "Hey, we got to charge you more." And I was like, "Cool, do that." But it was like, there is cost both in terms of the time, clock time, and each PR running and all of those. We have to consider all of these different things.
And hopefully, we did a useful job of framing the conversation, because as always, it depends, but it depends on what. And in this case, there's a good outcome that we want to get to, but there's an associated cost. And for any individual team, how you weigh the positive of the outcome versus how you weigh the cost will alter the decision that you make. But that's I think, critically, the thing that we have to consider.
I've also noticed I've seen this conversation play out within teams where one individual may acutely feel the pain, and therefore they're anchored in that side. And the cost is irrelevant to them because they're like, I feel this pain so acutely, but other people on the team aren't working in that part of the codebase or aren't dealing with bug triage in the same way that that other developer is. And so, even within a team, there may be different levels of how you measure that. And being able to have meaningful conversations around that and productively come to a group decision and own that and move forward with that is the hard work but the important work that we have to do.
STEPH: Yeah. I think that's a great summary; it depends. On that note, shall we wrap up?
CHRIS: Let's wrap up. The show notes for this episode can be found at bikeshed.fm.
STEPH: This show is produced and edited by Mandy Moore.
CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes, as it really helps other folks find the show.
STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari.
CHRIS: And I'm @christoomey
STEPH: Or you can reach us at hosts@bikeshed.fm via email.
CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week.
All: Byeeeeeeeeee!
Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.Sponsored By:Scout: Scout APM is leading-edge application performance monitoring designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise-platform feature bloat.
With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve performance abnormalities -- like N+1 queries, slow database queries, memory bloat, and more.
Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them.
Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform.
See for yourself why developers worldwide call Scout their best friend and try our error monitoring and APM free for 14-days, no credit card needed!
And as an added bonus for Bikeshed listeners: Scout will donate $5 to the open-source project of your choice when you deploy.
Learn more at scoutapm.com/bikeshed.Support The Bike Shed

Oct 26, 2021 • 41min
314: Communication, Testing, and Accountability
Chris regains several of his developer merit badges and embarks on a perilous CSRF (Cross-Site Request Forgery) adventure. Steph shares highlights from Plucky, a management training course, including ways we can "click" and "break apart" from our current role, and how to have hard conversations.
They also discuss how software development processes change at different team sizes, processes that break down as teams grow, and processes that are resilient at any team size.
This episode is brought to you by ScoutAPM. Give Scout a try for free today and Scout will donate $5 to the open source project of your choice when you deploy.
The Nightmare Before Christmas - What's This
Giant Robots Smashing into other Giant Robots - Plucky with Jen Dary
Plucky
Services are Not a Silver Bullet
Become a Sponsor of The Bike Shed!
Transcript:
STEPH: Boom. I'm recording. Magic is happening. [singing] What's this? What's this? It's a Bike Shed episode. What's this? What's this?
CHRIS: You did that on the mic. [laughter] So you just started recording too, so it's not like you're like, "Oh, I forgot I was recording."
STEPH: Oh, I didn't have a finishing line that rhymes with shed.
CHRIS: Head, dead, bread, spread.
STEPH: [singing] Is TDD dead? I don't know. [laughs]
CHRIS: Cool. I liked it.
STEPH: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Steph Viccari.
CHRIS: And I'm Chris Toomey.
STEPH: And together, we're here to share a bit of what we've learned along the way. Hey, Chris, what's new in your world?
CHRIS: What's new? I had a fun experience over the past week or two of regaining some of my developer merit badges, which is always enjoyable. So one was I had to configure AWS, specifically S3 and IAM such that I could upload files to an S3 bucket, which seems like one of those things that a developer should be able to do, and it's just not that hard. And, man, I failed so many times, and I stared at the screen. And the ARNs I think that's another acronym that I had to try and figure out what it means and fight against. Anyway, I got there. So that's one merit badge earned. I really hope [laughs] I correctly and securely configured access to an S3 bucket such that we could upload files in our Rails app. Cool, neat.
Moving on, the next merit badge that I went for was restoring the sea of green dots. Our RSpec output had gathered some noise. There was a whole bunch of noise across a variety of things. There were some dev tools that were dumping some stuff in there. And there was something related to apparition, which is the...I want to say it's the Capybara feature spec driver that we're using now, which sits on top of ChromeDriver or something like that. I don't really understand the details, but it was complaining about something. And I found a fix, and then I fixed it and whatnot. But it was one of those. I did this on a Saturday because I was just like, you know what? This will be cathartic and healing. And then I got to the sea of green dots, and I was so happy to get to it.
STEPH: This is me...I'm giving you a round of applause.
CHRIS: Well, thank you. Arguable whether it delivered any real value to users, but again, this was Saturday effort, so I was allowed to indulge my fastidious caretaker of the code role.
STEPH: Sorry, before we move on to more serious, can we pause to talk about developer merit badges? I really, really want cute felt badges that we can...I mean, I can't design them. I don't have the talent. But I think between us and other folks, we could design amazing merit badges, and then people could collect those. I'm very much in love with that idea.
CHRIS: I love the idea. I am now certain that if we were to really pursue this, that we would fall into the deepest of bike sheds as we try and define well; what are all the merit badges? And what are the different levels?
STEPH: [laughs]
CHRIS: And how many do you need to collect before you can get to what are the different...There are just so many different taxonomies that we could introduce, and, oh man, I could spend a couple of weeks on that.
STEPH: [laughs] It has a very strong Pokémon vibe too of you got to catch them all.
CHRIS: Absolutely.
STEPH: Okay. All right. We won't digress into bikeshedding merit badges, but I'm still very, very interested in that idea.
CHRIS: Indeed. If anyone out there in the listener space wants to just make these, that would be great. This is the way that I avoid bikeshedding now is I just say I'm not allowed to make these decisions or even think about it. But if these happened into the world, I would be happy about that.
STEPH: Oh, I just remembered we do have something similar at thoughtbot. They're not physical where you can hold them, but I think we've talked about turning them into physical badges. But we have our internal tool hub that we used to track our schedules. And one of the fun Ralphapalooza events that we had, a team came up with the idea of introducing badges in the tool hub, so then you could award people badges. You could give people badges. And it's very cute. So they could probably help us with the taxonomy. They've probably already figured out a number of badges we could get started with.
CHRIS: And of course, this is where my brain went initially to like, oh, what would the taxonomy be? But I think that's how this goes bad. And if we just keep it in the this is cute and fun, and what are all the possible merit badges, but they're all equal, and the points are made up anyway, and then it's just a fun thing, then I'm like, I'm super into this. Let's do that. Have you used a regular expression to parse HTML? Congratulations, you get a merit badge. Have you not used regular expressions to parse HTML? You get a different merit badge. [chuckles]
STEPH: [laughs] I feel very positive that I could be chief of cute and fun. I could manage that department.
CHRIS: Yes, that feels like definitely a role that you could really excel at. But shifting around ever so slightly, I did run into a fun bug this week. And it was a mystery tour of, I'm going to say, sadness and then eventual learning and understanding, and I think we've come to a better place. But I want to tell a story, take us on a quick tour of the adventure that I went through.
So we recently saw a handful of exceptions come through in our exception monitoring service and then piped into Slack, where we see those around CSRF token expiry. So this occasionally happens in a Rails app. The CSRF token that was on the page gets rotated. And therefore, when someone...if they have an older version of the page open and they try and submit a form or something like that, then CSRF protection is going to kick in. And you do get some false negatives there or some cases where like, nope, this is actually a fine user, this is not hacking, this is nothing bad. It's just that that user had a tab open or something like that.
I'll be honest; I want to understand better the timeline of expiry and how Rails expires those and whatnot. But it's one of those things; it’s deep enough in Rails that I trust that they are doing a very reasonable thing. And I think the failures that we're seeing that's part of the game. And so, mostly, we wanted to add a nicer handling around that. So thankfully, Inertia actually has a really wonderful page in their docs about handling Cross-Site Request Forgery expiration token, this whole thing. This is a particular failure mode that your app might have. And so it's nice to be able to provide a nicer user experience.
And so what we ended up doing is if we catch that exception, we have a rescue_from in our application controller that will instead of having this be a 500 and just a full, like, something went wrong error page, we instead respond in an Inertia-like way to basically show a flash message that says, "This page has expired. Please refresh the page to continue." And if the user just refreshes the page, then they will get a new CSRF token. And from there, everything is going to be fine. So it's not ideal. But it is, I think, both secure and now a nicer user experience.
STEPH: Yeah, that sounds really nice. When they refresh the page, do they lose all that form data? I'm curious how painful of a flow that is for the user.
CHRIS: Currently, yes. Inertia actually has a really nice feature for remembering form data. If you've ever been on GitHub and you're filling in a box, and then you go away to a different tab, and you come back, and it's still there, and you're happy about that, it's that sort of thing. So we could configure that. At this point, we don't have...most of our forms are pretty small. So this is not something that we opted to do proactive management around. But that is definitely something that we could add but not something that's default or anything like that.
STEPH: Cool. Yeah, that makes sense. I was just curious because yeah, either small form doesn't really matter, or also, this may be just a small enough error that only a handful of people are experiencing it that it's also just not that big of a deal.
CHRIS: Yes, this definitely should be an edge case. And we've also recently been working on functionality to log folks out after a period of inactivity, which would also, I think, obviate this in a different way. So all total, this shouldn't be a big deal. And this was basically a quick, little snippet of code that we thought we could just drop in, and everything would be great because it shouldn't happen much.
But then I was testing out a different feature on staging, and everything I tried to do was popping up this little alert flash message that was like, "Hey, your page is expired." And I was like, that seems bad. And then I realized literally every action, any non-GET request, was getting this response that the CSRF token didn't match. And I was like, well, this seems bad. Luckily, it was only on staging and hadn't made it to production.
But it had made it to staging, which meant it had gotten through CI, which was very concerning because we have a pretty robust set of feature specs at this point. We built up a bunch of fakes for all of the external data systems that we're interacting with. And we're really putting the app through its paces and trying to do so in a very production-like way. And so I was like, this is such a deep fundamental breakage. I don't know what's going on here. And so I started to investigate.
And it turns out that in a recent commit, I had started using Axios, which is a little wrapper around the Fetch API. They may not actually use the Fetch API under the hood, but it allows you to have a nicer interface to make XHRs. And we implicitly had that in our package already by virtue of Inertia. Inertia uses it under the hood, but I wanted to make it explicit because now I was using it directly. So I figured that's cool. I will yarn add Axios, and then I will continue on with my day. And I worked on my feature and everything was great. And then I pushed it up into a pull request, and everything was great, and CI passed. And I got it onto staging, and everything was very sad.
So then I started on the adventure of like, what is going on here? It turns out that somewhere between version 0.21.1 of Axios and 0.23.0, which there's a bunch of things about those version numbers that make me uncomfortable but here we are, somehow the behavior where you can configure the XSRF header name, which is what they're calling it on their side, the configuration stopped working. And so our override that says this is what our CSRF or XSRF token should be called when it's sent back up to the server in a header that was getting lost. And so they were falling back to their default name, Axios was. And, therefore, Rails was like, "There's no CSRF token here. So this is going to be a no for me. I'm going to reject all of the requests."
So the fix was relatively easy to roll back and to pin the version of Axios to the previous version that we had been using. I didn't actually intend to upgrade it. I just intended to make it an explicit dependency. But by doing that, I accidentally upgraded it. I don't love that there was this pretty deep breakage in that. I haven't done the good work of trying to open an issue. I still want to scan through and see if there is an open issue or a conversation around this before I start making any noise. But I think if I don't find anything, this is the sort of thing that should be reported because I can't imagine I'm the only one running into this.
Likewise, I was very sad that my test suite did not find this. Turns out in Rails, CSRF protection is just turned off in test mode, which may be overall makes sense. But for feature specs, in particular, I definitely want to have it. And so, it was nice that I was able to find the relevant configuration. And we introduced an RSpec configuration that says, "If it's a feature spec, save off the existing configuration and enable CSRF. And then after the spec, go back to whatever the previous was."
So now all feature specs run with CSRF. And I did make sure to push up that as a singular change to CI, and CI was very unhappy with me. Many, many features-specs failed, which was good. That was what we were going for. They failed for the right reason because things were fundamentally broken. And then, I was able to update the package-lock or the package.json on the yarn lock, pin the version, fix everything.
But man, there was this period of like, oh man, the app is broken in such a fundamental way. Users just can't do stuff anymore. They can view anything, but they couldn't change any data. And it just snuck through CI. And that feeling is the worst feeling. We had, at this point, built up a lot of trust in our test suite. It was really telling us when stuff was wrong, and if it was green, I felt very good merging. And suddenly, this just really shook me to my core on that front.
STEPH: I love these journeys that you take us on. I mean, they're painful for you, and I am sorry to hear that. But I love these journeys that you take us on. [chuckles]
CHRIS: I usually only take us on them when I've figured out the answer. And I'm like, all right, here's where we're at. It was rough for a little while, but now we are happy. And thankfully, the one configuration of saying, hey, Rails, also, please include this as part of our production like, configuration for test mode. So I feel better that moving forward, this breakage won't happen again.
STEPH: We should add that as another merit badge for telling a bug story. All right, I'm taking off my hat of chief of fun and cuteness. So this may not be terribly relevant to all the things that you just shared. But I am curious where you mentioned that with Axios because you'd specified the name of the token, and then that overriding behavior is what then broke. And so then that's what led to this whole adventure that you went on. I'm curious, why did y'all customize the name of that token?
CHRIS: A, this is a great question. B, I'm not super sure. C, I think the reason is because we were trying to align to Rails. So we have a little middleware on the Rails side that will serialize the CSRF token into a cookie. And then that cookie value gets read by Axios and sent back up as a header on the request. So this is the way that with Inertia CSRF just kind of works and is good. And it's different than Rails' normal. We put a hidden input into any form. And so Rails holistically knows about both sides of that, and everything works fine. But now I have to manually round trip the CSRF token.
And Axio's default configuration is a header name X-XSRF-TOKEN, and we needed X-CSRF-TOKEN because that's what Rails is looking for. I probably could have configured it the other way on the Rails side. But one way or another, I had to get Rails and Axios to come to an agreement, to meet at a table, and to agree to collectively protect the app. And so I had to mediate that discussion, and that's what ended us here.
STEPH: A meeting of the minds. [chuckles] Cool, cool, cool. Yeah, that makes sense. I was just curious because then that would have changed the whole journey. But yeah, that is super interesting. And I definitely resonate with the idea of when you've really invested in your test suite, and you trust it that then when it doesn't catch something that obviously breaks the application, then that feels like something worth prioritizing and digging into and then figuring out how to bring back that parity.
I don't know that I've turned on enable CSRF for feature spec. So I'm also very interested in looking at that configuration and considering if I need that for any of my future client projects if that's something that I need to remember for the future because that's very niche but good to know about.
CHRIS: I feel like this only really comes up if you're working in the...it's called the odd middle ground that Inertia ends up occupying. If you're in a traditional Rails app that is generating HTML server-side, forms are generated. They got the CSRF token inlined there in a hidden input. And then when you post that form, it's coming back up. The names automatically are going to match. You don't need to worry about it. And it's probably fine to not have it included in test mode.
And if you're at the other end of the spectrum and you've got API interaction, and that's the way you're doing everything, then you have a different auth mechanism and cookies, and whatnot just don't apply in the same way. And so it won't really matter on that side but for a different reason. And it's only because we're in this interesting middle ground, which, again, I really love. And it's the thing that I love about Inertia. But this is a rare case where it's like, oh, we do have to bring the two sides to meet in the middle. And this is a case where, unfortunately, due to a very subtle breakage on a minor release of...a package that we're using silently broke so, yeah.
But yeah, thankfully, everything is back to working. And again, we've been able to enhance the test suite in that little way that I feel confident again because this won't sneak in another time. We have coverage around this. We're good to go. So while I was very scared when this initially happened, I feel better now. I'm happy to go into the weekend feeling better about this. But that's my story. What's new in your world?
STEPH: So I feel like I've been having one of those weeks where I have less code adventures. In fact, it's one of those days where I went to thoughtbot's daily sync...because we often have our client daily syncs, but then we still have a thoughtbot sync as well. And I went to the group, and I was like, I get to write code today. It's going to be a great day. All the other things I'm doing are also interesting, but I get particularly excited when I get some maker's time and get to write some code.
So I feel like I've had less coding adventures recently and more hiring and process-related adventures. And specifically, I just completed the Plucky Manager Training, which is a program that's founded and led by Jen Dary, who was recently on thoughbot's podcast, The Giant Robots Smashing Into Other Giant Robots. I'll be sure to include a link in the show notes for anyone that's interested.
CHRIS: I believe this was the third time she was on. It's at least the second, possibly the third. And all of them are great listens, just as an aside, so we should include links to all of them.
STEPH: Yes, I think she's one of the rare guests that has been on the show three times. And I think I've only listened to the first couple minutes of that episode. But I think they talk about the fact that this is her third episode, which is really, really cool. And I'm still frankly synthesizing all the information and the ideas that I've collected from the course.
But I do have a few quick takes that I'm interested in sharing with you. So the first one is my cohort...we were the Panda Cohort, so go, Pandas. And some of the things that we talked about were…, and I think that this may have been the first day. So it was three days, and it was three hours for those three days. And they're spread out over a couple of weeks, which is really nice because then you show up for those three hours of the class, but then you leave with some ideas and some things to experiment with. You get a week to then try out an experiment and then come back to class next time and talk about this is how it went; it went to wonderful, or it went terrible. And you get to share that with others and work through it.
And in the first class, we talked about coaching versus managing, which I found just a helpful definition to review. So managing is more direct, and telling someone what to do while coaching is encouraging someone to determine their own path and find their own solution. And I find that as a team lead at thoughtbot, I'm very often more in that coaching space than I am in that managing space. I think it's frankly pretty rare that I actually need to put on a manager's hat. And I often feel like I'm wearing my coaching hat instead.
And some of the other things we talked about one of them is what is work? Which is a fun question to ask. And Jen had an analogy for this speaking about imagine that you have a plastic Easter egg. So it's got two sides, and side one is all the skills and desires and things that you're fulfilled by. And side two is a company that needs those skills. And it's great when those line up and click together, like when you take a job or get a promotion. Have you ever played...do you know what I'm talking about? Those little plastic Easter eggs. Have you ever played with those as a kid?
CHRIS: Yes, certainly.
STEPH: [laughs] I realize I just launched into that analogy. [chuckles] And then Jen goes on to say that's totally normal for then those sides to unclick. And Jen continues to say that it's totally normal for them to unclick. So maybe the company changes direction, the company is acquired. You've fallen out of love with something that you do about your job, or you have kids, and that has changed the things that you are fulfilled by and what you're looking for. And that's not necessarily bad. So it can be like, hey, you are working on x now, and you're not fulfilled by that anymore. But then another company comes along and says, "Hey, we're working on this, and you are fulfilled by that." So then another click happens.
And essentially, it's a nice analogy to represent someone's career path and the ways that we are going to shift and re-prioritize what we're interested in. But it's also a really nice way to help it feel less personal because both sides are allowed to change. The company can change. You, as an employee, can change. And then you can look for that next click that is going to match up with a company that meets your skills and things that help you feel fulfilled.
One of the other topics that we talked about are hard conversations, which I love that we dug into this one because that's certainly one that I struggle with or...I mean, we all get that feeling if you have to confront someone if you have to have that uncomfortable discussion with someone. It is a very hard thing to do. And so we had some very honest conversations around what is a hard conversation? What does that represent? And essentially, they represent that there is stalled progress and something can be improved.
So Jen likens a hard conversation to a tool. It's something that you can use to then help something move forward again if something feels stalled or if there's something that needs to change. And during those hard conversations, you may not get to the resolution that you're looking for. So you may be looking for a specific outcome. But you also have another person that needs time to respond and to take in everything that you have said and process that information.
So when you have a hard conversation, you may actually only move forward an inch. So if you had a lofty goal of we're going to talk and then we're going to have this hard conversation, and we're going to get to this space...But instead, you actually just make incremental progress. Like, okay, at least this person is now aware of this concern. That might be your win for the hard conversation versus actually tackling; how are we going to address it? I just want them to be aware of this concern.
And it's a very vulnerable conversation, and they often take time before you can get to that ideal resolution. But essentially, the idea is get in the game, start the conversation, and then have follow-up conversations for that hard conversation. And I really appreciated that framing because I often will think of hard conversations of oh, we have to have this hard conversation and get to this specific outcome. But if you shift the goal line to be like, no, I really just need to at least make this person aware of a concern, that makes it a lot more approachable. And then also probably yields more fruitful outcomes because that gives the other person time to think about what you've shared to also come to the table with their own ideas and then work together to then get to that ideal resolution.
CHRIS: I like that framing a lot. I can definitely see the case where you, as someone who has recognized something that needs to change (perhaps you're a manager),lineup you've now thought about that a good bit; you've observed it, but the individual that you're bringing that to this may be novel. This may be a surprise for them. And so if you come into that interaction both about to share this information but then also trying to resolve it and trying to get to I need you to internalize it, and I need you to fundamentally change your behavior as a result of this conversation we're going to have, that's quite possibly not a realistic outcome. And if you're trying for that, it might inherently lead to just a bad outcome because that individual is not in a position to do that. But they are potentially ready to hear it. And so you can just achieve step one and then later have step two. So I like that a lot.
STEPH: Yeah, in general, I found the course incredibly helpful, very insightful. It was also really nice to hear from other managers that are facing similar problems or perhaps novel problems and then getting to weigh in and help each other. So it's a wonderful course. I'll be sure to include a link in the show notes for anyone that is interested. And I'll probably come back with some more insights from the class because it's really...we just wrapped up. So I'm sure I still have some ideas that will percolate over time, and I want to come back and share those with the group.
Mid-roll Ad
And now a quick break to hear from today's sponsor, Scout APM.
Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more.
Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform.
See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed.
STEPH: Pivoting just a bit, we have a listener question that I'm excited to dive into. This question comes from the one and only, the Edward Loveall, fellow thoughtboter. And Edward wrote in, "How does the process of software development change at different team sizes? What's a process that breaks down soon after the team starts growing? What's a process that is resilient at all sizes? And by process, I mean anything that involves other people including organizing tasks, code review, deployment, or anything else that isn't you alone writing code in a vacuum."
I'm really excited about this question because I think there's a lot here. And there's actually one part that I'm struggling with a bit, so I'm curious to see what you think, Chris, about it. But I'm going to start off with saying that I think there are a number of management processes that definitely break down as a team grows. But in the spirit of Edward's question, I'm going to focus more on the software development process and how those might need to change and what starts to break as your team grows.
So starting off with processes that break after the team starts growing, this one, frankly, what really starts to break is not a process specifically, but it's the lack of process that really starts to become visible and painful. So, how do we track work? Before, maybe the product manager or someone would just send you a message and say, "Hey, can you work on this?" or "Hey, can you fix this thing?" And how does code need to be reviewed before being merged? Does it need to be reviewed? Are people just merging as they get stuff done? How are deploys performed? Oh, we have a super urgent production fix that needs to go out, and the only person that knows how to deploy is out sick today? Cool. That's the type of process that I think that really breaks down, or at least you start to notice when the team starts to grow. What are your thoughts?
CHRIS: I definitely feel that first one very strongly. We're feeling it right now on the team, which is still very small. There are only three developers working on the project, and then we have a product manager. And each week, we're slowly iterating, and tweaking, and honing, and trying to introduce just enough process in terms of how we define the work to be done, communicate the status of it, all of that fun stuff.
We started with Trello. And we just had a board with some columns, and then we had more columns, and then we got rid of a few of them. And then we recently added a Power-Up to the Trello board, which allows for epics. So there are cards which are epics which tie to sub cards. And I'm staring at it, and I'm like, how long until we're Jira? How long can I hold out here and not be Jira?
But it does feel like we're slowly iterating towards a more useful process for this team rather than process for process' sake, which I feel like is a really useful distinction. There's also a question of like, what can be known or what can be adequately measured and whatnot versus what can't be? So we've talked many a time on the show about estimation and velocity and trying to track that and the pitfalls inherent with that. And so there's, in my mind, two different camps. There's the process we want to avoid. And again, to reference German Velasco's wonderful blog post, Say No To More Process.
And I really feel like there is a tendency often when things go wrong to then try and paper over that with process. Oh, this team didn't use the design system. So we need to write ESLint rules to make sure you can't import from the directories that aren't the thing. And it's like, we can do that, and I've definitely done that. And I will do that again in the future. But I always have the lens of do we need this? Is it worth the trade-off, the cost, the overhead, the complexity that it's bringing in?
But definitely, organizing and communicating tasks is one of the ones that becomes really difficult. The more people that are working on something, the more you need probably more than one person staying out in front of them and trying to define the next bit of work that needs to be done after that.
Code review feels like it probably should stay similar, with the exception that I lose the ability to review all code at some point. Right now, I'm trying to review every single PR that goes through or close to it. At some point, I'm just going to have to give up on that. But for now, that's my goal. But fundamentally, code review, I think, will hopefully take the same shape.
Deployment, similarly, like, I've talked about the merge queue thing. I want to get a little bit of process in there but not too much. There is definitely some necessity for change. But I definitely want to resist the urge to change everything and to just say, like, slowly over time; we’re going to have to be a big Byzantine organization with lots of rules and standard operating procedures and all of that.
I've heard anecdotally, and I don't know if this is true, so maybe someone out there on the internet can correct me if I'm wrong, but my understanding is that at Google, they’re pretty tight in terms of what languages and frameworks can be used and what processes, and workflows, and build tools and all of that whereas Facebook, as a counterpoint, is relatively lax. Obviously, React is used very heavily on the core web application. But there's some flexibility in terms of different languages and frameworks and things for sub-projects or small individual teams having a little bit more autonomy. And I think that's a really interesting thing of are you one large, cohesive, organized company or do you try to act like a bunch of small disparate but roughly connected teams that share good ideas but can work independently? And that changes how I would think about this question.
STEPH: I really like how you're describing the addition of process. It sounds like a just-in-time process. So as you're learning that something needs to be added, then that's when you look for answers. And then you sprinkle on a bit of process that everyone agrees that feels very helpful within also the right to review and see if that still makes sense for the team.
There's one additional area where I think the lack of process really shines through in addition to the number of ways that you've mentioned is also onboarding. So if you have a very small team and you are onboarding, it's likely that...Chris, you can let me know if I'm wrong, but when someone's joining the team, there's probably a good chance that they get to pair with you at some point, or they even get welcomed by you to the team. And then, they get an overview of the product and the codebase. And there's probably this really nice session where they get to ask you questions, and then they have that onboarding session. Does that sound about right?
CHRIS: Yes. But I would go so far as to say it's not just a day or a session, but it's probably a couple of days. So yes, and.
STEPH: That's even better. And with some of the smaller teams that I've seen, that onboarding process is where they are pairing with that lead person on the team. And that's going well until suddenly that lead person can't pair with everybody. And nobody has really thought about how to streamline that onboarding or how to coach or teach someone else to be a really good onboarding pair.
And I have strong feelings about this area because we often focus so much on hiring, but then we drop the ball when it comes to onboarding that new, wonderful colleague that we've worked so hard to recruit. And at the end of that day, someone's going to reach out to them and say, "Hey, how was your first day?" And it makes a big difference for that person's retention as to how those first couple of days ago.
So I think onboarding is another really important part that when you're a smaller team, you probably don't need much process because you have more of that personable onboarding experience. But as the team grows, there needs to be more of a process to help other teammates join the team.
CHRIS: It's interesting. I think I totally agree with you that over time, there is a necessity to be more intentional and to have a little bit more structure in the process. And I don't think you're saying this, but I just want to make sure we are saying the thing that I think we believe, which is that shouldn't replace the human that helps you onboard.
Like, I still like the idea that everybody gets a pair for some amount of time when they start at a new company. And you're working together on a feature, or you're working together on bug fixes. You're shipping to production as soon as possible. But you're not doing that based on some guides in a wiki. You're doing that with another human that's helping you. There should also be guides, and a wiki, and documentation, and formalization as the organization grows but not in place of having another person that you get to talk to.
STEPH: We're just going to send you a little yellow rubber duck and then with a little Post-It note that says, "Good luck [laughs] with your onboarding process." Definitely. I agree with everything you said. It does not replace that human element where there's someone that's helping you onboard. I just see that onboarding is one of those things that gets forgotten, or we often point someone to a README which I do think is great because then it is battle-testing our README. But then there still needs to be someone that is readily there to say, "Hey, how's it going? What are you struggling with? Can I pair with you?" There still has to be that human element that is helping guide you through the process.
And I think smaller teams may forget that they actually need to assign somebody to you to make sure that you have someone that you know. Like, hey, this is who I can reach out to with all my questions. Because they're probably not going to be comfortable posting in the company channel at that point or a larger communication to say, "Hey, I'm stuck on something."
CHRIS: There's one other area that comes to mind, or I guess it's more of an anecdote that I have heard, but it speaks back to GitHub's early, early days. And they were somewhat famous for being very flat in terms of the organization and very self-organized, and everybody's figuring it out, and you're working on the thing that's most important in your mind. And for a long time, this was a celebrated facet of the company and a thing that they talked about rather publicly.
And then I think there was this collective recognition, and maybe they reached a tipping point where that just didn't work anymore. Or maybe it actually hadn't been working for a bit, and there was just the collective realization of that. But it was interesting to watch from the outside as GitHub added more formalization, more structure, more managers, and hierarchy, and career ladders, and things of that nature. And I think there's a way to do all of those things in a complicated, overloaded, heavy way.
But I think a different version of it is...like, you were using the word coaching earlier. Having formal structures within your organization to encourage people on their career path, to help them grow, to have structure around that, I think is a really difficult thing to get right. But I think it is critical, and I think just not having it can't be the answer past a certain probably pretty small size. So that is an interesting one where I think you do need to introduce some process and formalization around how you think about the group of people and how they work together within your organization.
STEPH: I agree. I think where some folks may see a lack of hierarchy; others feel a lack of support. And adding levels of management should really be focused on the outcome is that we're helping people feel supported. So even getting feedback as you're adding those different levels of management, like, hey, did we make your life better? Did we make your life worse? I think that's a great question for management to ask as they're exploring a less flat structure.
CHRIS: So, Steph, I have a question for you now on a variant of this topic. In general, we seem to be fans of having a codebase. Probably a Rails app that’s got a database behind it, and that's where you put the data. Everybody commits to that same repository. It's all kind of one collected thing. And often, organizations grow to a certain size, and they're like, this is untenable. We cannot have this many people working on this same codebase. So we shall do the logical thing, which is we will break it up into small pieces. And those pieces will communicate over HTTP, and it will be great because then our teams can be separate from each other and can manage their little piece of the world. What do you think about that? Is there truth there? Is it not true at all? What do you think?
STEPH: All right, so your team is getting too big, and to the point that you feel like you need to split it out so then you can have small teams, and they can all work independently on different parts and services of the codebase. I don't love the idea. I'm trying to think through because I feel like there's a lot of nuance here. But I don't love the idea that that's the driving force as to why are we making the change?
And that is often a question that comes to mind whenever we are making a big change, either architecture or process-related is like, what's driving this? And then how are we going to measure it? And if we are driving it just because we have a large team, let's talk more. Why are people blocked? Why can't people work together? What's preventing people from being able to contribute to the same codebase? Are people blocked for a long time because they're having to wait on someone else to complete that work? I have a lot of questions that I don't know if I can fully answer your question. But my instinct is to say let's not break up the architecture just because our team grew in size.
CHRIS: Yeah, I think I definitely agree with that. There's probably a breaking point where it's just too many individuals, and there'll be too much contention. But I think resisting that or at least naming that as like, okay, that's what we're saying but is that really what's true? Or are we actually feeling that this system is so deeply coupled that there's no way to change some small piece of the code without impacting other parts of it?
Like, is the CSS completely untenable because we're just using global class names, and it's leaking everywhere? Okay, do we need a different solution there? And then it's actually fine. We don't need to have different services that have their own different style sheets. We just need a different approach to CSS. That's a particularly easy one to go for because there's inherently a global namespace there. But the same thing is true in a lot of different contexts. So services are a way to break things apart and enforce those boundaries. But if inherently coupling is your problem, then you're just going to be coupled over HTTP, and I think it's going to be difficult.
There's a wonderful blog post by Josh Clayton, which I think does a better job than I'm doing in this moment of highlighting some of the questions I would want to ask. The blog post is titled Services are Not a Silver Bullet. And so Josh goes through and enumerates a bunch of the different versions of the story that he's heard throughout the years of well, we need to go to services because x, because our test suite is slow because pull requests are constantly having merge conflicts and whatnot, because the code is very deeply coupled and any change here affects everything else. And a fix over here broke something over there. This is no good. And so he does a really good job of presenting alternatives or at least questions that you can ask to say, like, is this the problem, or is this a symptom? And we need to address the more underlying cause.
And so I think there is a point where you just can't have 1,000 people trying to commit to the same Rails codebase. That feels like it's maybe too big. But it takes a while to get to 1,000 people. And there will be times where extracting a service makes sense or integrating with an external service that exists. Like, I've talked about Stripe before as my canonical like, yeah, it's actually deeply intertwined with the data model, but they're just dealing with such a distinct complexity set over there. And they have such expertise on that that I'm happy to accept the overhead of the fact that that service lives outside of my core application, and I need to deal with synchronizing state and all of that. I will take on that complexity, but it's not worth it for everything, and it's not a silver bullet. Again, to reference the name of Josh’s blog post there, Services are Not a Silver Bullet.
And so, coming back to Edward's original question, I would say that having a monolithic codebase works for a really long time, but there is probably a breaking point somewhere well along, but fight it for as long as you can. I think.
STEPH: I really like how you touched on coupling because it really helps ask those questions to get to the heart of what are the pain points that you are feeling? And it is less of a decision that is based on people and process but more if you're going to split out a portion of your architecture. It is in response to an actual business need and a business value versus some other pain points that you're trying to fix.
A particular example might be like maybe you have a portion of your application that really just needs to spend a lot of time crunching data. And it's really not as specific to your application; it's something that can happen on its own. And then it's beneficial to move that outside so it can scale and relate it to the work that it needs to perform versus keeping it in-house with the application.
I do want to circle back to another question that Edward included which is what's a process that is resilient at all sizes? And the ones that really come to mind for me...and these are a bit amorphous intentionally because it will look different for each company. But three areas that are very resilient at all sizes, whether you are 1 to 2 employees versus you've got hundreds or thousands it's communication, testing, and accountability.
So communication, where are we headed, and how do we know what we're working on? For testing, it's how do we test our changes? Do we write tests? Do we use QA? Do we have a staging environment? What does that look like? What's our parity between staging and production? And then how do we know what's in progress, and how do we know when it's done? Those are three core areas that, regardless of your team size,,I think are very crucial to the team success. What do you think? What are some of the processes that are resilient at all sizes?
CHRIS: I actually really like the list that you just provided. That is a wonderful trifecta, and I think it will take you very far, so probably not much to add from me. But I guess on that note, should we wrap up?
STEPH: Let's wrap up.
CHRIS: The show notes for this episode can be found at bikeshed.fm.
STEPH: This show is produced and edited by Mandy Moore.
CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes, as it really helps other folks find the show.
STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari.
CHRIS: And I'm @christoomey
STEPH: Or you can reach us at hosts@bikeshed.fm via email.
CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week.
All: Byeeeeeeeeeee!
Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.Sponsored By:Scout: Give Scout a try for free today and Scout will donate $5 to the open source project of your choice when you deploy.Support The Bike Shed

Oct 19, 2021 • 42min
313: Forty-Seven Percent
Steph talks about binging a few Things Worth Learning podcast episodes and particularly enjoyed an episode that featured one of thoughtbot's design directors, Sameera Kapila. Sam shared her expertise about management and inclusion, and Steph shares her favorite parts.
Chris shares the story of a surprising error and the resulting journey through database transactions and Sidekiq that eventually resolved the issue. He also shares some follow up on the broken build and the merging process changes they introduced (spoiler, the process changes have been rolled back).
Leading Inclusively, with Sameera Kapila - Things Worth Learning Podcast
How to Skim a Pull Request
Isolator
after_commit_everywhere
time_for_a_boolean
Transcript:
STEPH: Oh man, I'm about to stop eating my pop-tart. I'll put it away. It's within distance. I'm going to eat it.
CHRIS: Your high-fat content unfrosted pop-tart.
STEPH: You know, surprise Sunday twist: it has icing on it.
CHRIS: Steph, who even are you?
STEPH: [laughs]
CHRIS: There are a few canonical anchor facts that one knows about other people, and when one of those...
STEPH: I like to keep everyone, including myself, on their toes.
CHRIS: Or you've just secretly accepted that the icing adds another textural flavor adventure component. It's just better with icing.
STEPH: All right, all right, all right. There's a complicated answer to this. And the complicated [chuckles] answer to this is that the more organic ingredients that I recognize when reading about pop-tarts are by a particular company, and they all have frosting on them. And the more generic pop-tarts that don't have frosting on them, I don't know how to pronounce a lot of those ingredients. So I'm like, no, but okay, I still eat them. But I prefer the ingredients I can pronounce. So I either go with the ingredients I can't pronounce or have a little bit of frosting on my pop-tart. And I'm going with the non-cancer route for today.
CHRIS: For today, in this moment, and accepting the frosting. Okay, all right. Well, that is complicated. [laughs] It's tricky out there.
Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey.
STEPH: And I'm Steph Viccari.
CHRIS: And together we're here to share a bit of what we've learned along the way. So, Steph, what's new in your world?
STEPH: Hey, Chris. So the weather, I'm going to talk about the weather for a little bit. [chuckles] It's been almost non-stop rain for the past several days, which is fine. I'm sure it's great for plant life. But it's really hard on my dog Utah because then we can't go outside for our normal walks and playtime. Although he is my four-legged water baby because he absolutely loves water, and puddles, and playing in the rain. So he's very fine with going outside and playing for a long time. But then I have to essentially give him a full-on bath before I want to bring him back in.
So not wanting to have to give him a bath each time, in the spirit of improvising, we started finding more indoor games to play. And I've started teaching him to play hide and seek. And he's not great at it mainly because he will only stay until I'm out of eyesight, and then he will come and find me. And so I have to be really, really fast at finding a hiding spot to like dash around a corner or hide behind the door. But I think he enjoys it because he will find me and then he seems very excited. And we go back, and we play again. And so I just have to work on teaching him to wait a bit longer so I can find better hiding spots.
CHRIS: When you said that, at first, I was like, how did you teach him to hide? But I realize he's only playing the seek part of the game, and you're only playing the hide part of the game.
STEPH: [laughs]
CHRIS: I'm just so used to you exchange roles back and forth. First, you hide, then you seek, and then you switch it up. That would be a lot to get your dog to be like, now I'm going to secretly hide.
STEPH: [laughs] I'd be very impressed. Yes, we have very distinct roles in this game. I am the one that always counts and hides. But he's a very good seeker. So that's been fun. We just got to work on getting a little better at it.
But on a more tech-related note, one of the design directors at thoughtbot, Sameera Kapila, who also goes by Sam, was a guest on the podcast Things Worth Learning, which is hosted by Matt Stauffer. And Matt is also the host of The Five-Minute Geek Show and The Laravel Podcast. And in the show Things Worth Learning, Matt meets with individuals that are excited to share something that they're deeply passionate about; maybe it's tech, maybe it's not. And I've binged a couple of those episodes.
And I really like how you can choose between the podcast format or the YouTube format. So then you can really watch the conversation unfold, which I know you and I a couple of times have thought it would be fun if people could see us because there are so many facial emotions and gestures that go along with conversations. So it was really delightful.
And speaking of delightful, Sam shared her expertise about management and inclusion. And I definitely recommend listening to the episode because I can't share everything that Sam shared. But a couple of the topics that Sam mentioned that I really enjoyed and would love to chat about, so the first one is about helping someone, in this case, someone that you manage that comes to you with a concern.
So there's often a presumption that just because someone comes to you with a concern or an issue that they've experienced at work, that they're the ones that will also want to work to address that concern, and that's often not true. It can be true; maybe that person wants to be involved. But they're often coming to you in the leadership or management role to say, "Hey, I've had this issue," and they really want help with that instead of walking away with homework for it. Because then that trains people to essentially be in this mindset of well, if I bring up this concern, then I'm going to be the one that has to address it, even if I'm the one that's most negatively impacted by this. And addressing this concern could be actively harmful to me.
And she shared a really great real-world example from her own experience where her and another co-worker had noticed a concern about the hiring process. And her and that co-worker got together, and they talked about the concerns. They even rehearsed for the meeting because they were trained by the tech industry to say, "Hey, if you bring up a concern, you're going to be responsible for addressing and then resolving that concern."
And so they had that meeting with the person in leadership. And they were pretty nervous about how it was going to go. And that person in leadership said to them, "Thank you both so much for sharing that. That must have been such a burden. And this is my responsibility to fix. And here are what my next steps are." And that was amazing because it allowed Sam and the other person to go back to client work. And they also received follow-up conversations about how that issue was being addressed. So there was even that feedback loop as to how things were going to change.
And I have a personal example that...I really resonated with the example that Sam provided because I remember there are different teams that I've been a part of, where often I was one of the few women engineers on the team. And so we often have conversations about how do we get more women engineers into the company? And they're wonderful conversations.
But there's a part of me that always felt resentful about, like, why am I here? Why am I the one fixing this? I understand I have some more insight and expertise, and experience in this area. But I was also frustrated by the fact that I was the one that was in that meeting often with other women, and it felt like our responsibility to fix this. And I used to feel bad about feeling resentful towards that. Because I was like, shouldn't I want to help other people? And I do. But Sam's example really helped remind me and clarify that yes, just because there's a concern doesn't necessarily mean you should be the one to address it. And it really takes everybody involved, or it takes leadership to step up and address that concern.
CHRIS: Oh, that's really interesting the way Sam is framing that and describing the situation of not having any problem that you bring in be now your work to solve. Like, oh, I found the issue, and now we've got to go do this. But the idea that you can bring something to light and then be able to walk away from it.
And the particular thing that you were saying that if your interaction is always that when you reference something when you bring in a concern that then your manager works with you to figure out how you can solve it, then you get this mental block of like, well, do I even want to say anything? Because I don't want to try and deal with big, amorphous unclear issues. So maybe I just won't even say anything.
And so this as a way to make sure that there's room for all of the conversation is a really interesting framing that I hadn't really thought about, frankly, but it's very interesting. I haven't seen this interview either. So I'm definitely excited to give this a look because Sam is wonderful. And the topic that you're describing here sounds fantastic as well.
STEPH: Yeah. There was an important moment for me where...one of my managers is Matt Sumner, who's been on the show. And when Matt was my manager, at one point, we were having a one on one, and we would often go for walks for our one on one. And I mentioned something about "I have this concern, or I have this problem, but I don't really know how to fix it. So I'm not sure I'm ready to talk about it." And Matt, in his delightful way, was like, "We can still talk about it. You don't have to have an answer or a solution." I'm like, "Yeah, but I feel like I should be able to fix it. Like, if you have a concern, or if you have something that you want to gripe about, then you should come to the table with solutions for it." And Matt was like, "No, you don't need to do that at all. We can totally gripe about stuff or talk about concerns and then either figure out the solutions together or go to other people for ideas."
And that was really important to me because, like you'd mentioned, otherwise, it felt like this mental block where then it feels like you can't air out some of the things that you're worried about or have concerns about because then you think you're the only one responsible. And you may not be able to come up with the best solution. You may need other people to then help you strategize and come up with ideas. And I just love, love, love that part of Sam's discussion.
And oh, there was one other part about the conversation. Well, there are lots of parts that were amazing. But another one in particular that blew my mind is about Comic Sans, the font, the font that everyone loves to hate. [chuckles] And I learned that it's one of the most legible fonts for kids. And it's one of the more accessible fonts for people with dyslexia. And it's actually recommended...I think there are still more academic studies that need to be done to really classify fonts that are best for people that have dyslexia.
But Comic Sans is recommended by The British Dyslexia Association and the Dyslexia Association of Ireland. And there are some other really great posts that talk about the benefits of using a font like Comic Sans because the typeface has long ascenders and descenders and generous letter spacing and asymmetrical lowercase b and d to then help distinguish those letters. And I just thought that was so cool. This font that everybody wants to rip apart because it seems whimsical, unprofessional gets overused. There are lots of reasons, I suppose. [laughs] But there's a really big benefit to it, and it can help others. And I just found that very whimsical in itself.
CHRIS: I love the idea that there are multiple levels of knowing about Comic Sans. First, you're just like, I don't even know the name, but it's that comic book-looking font. And then obviously, the next step is to be like Comic Sans? How could you ever use that? It's an atrocity. And then it's like, but actually, Comic Sans has some things going for it. And it is a really interesting consideration and something that you wouldn't necessarily think of. But then once you learn it, you're like, okay. Man, I wonder how many other things in the world have this interesting shape to them? Hmm.
STEPH: Do you know the history behind Comic Sans?
CHRIS: I do not.
STEPH: I read about it fairly recently, but I'm probably going to botch some of the details. But I believe it was designed or created by Vincent Connare. And it was created for Microsoft. And Vincent was working on a project where I think there was a dog that was essentially going to have these bubbles that would then show you different parts of the application and walk you through the different features. And the dog had a very comic book feel to the character.
And so then Vincent designed a font to go along with that comic book character, this dog and came up with Comic Sans. I don't think the dog actually launched with that particular font. But since the font was still developed, it was released as part of the available fonts. And there we go, there is the birth of Comic Sans. And then it just received so much love and ire all throughout history. [chuckles]
CHRIS: There's something that you said there that I want to loop back on when you were talking about chatting with Matt Sumner and saying, "Here's this thing, but I don't know how to solve it. So I don't even want to bring it up." I really liked the framing that you gave and the fact that Matt was like, "No, no, we can still talk about it. We can at least explore this thing, have a conversation." I think that's really wonderful.
There's a very similar thing that I experience a lot when doing code review, particularly when I'm in more of a leadership role within a team, which is I often want to highlight something that feels a little bit off to me in the code, but I may not have a specific solution. Like, I may see a variable name, or I may see a controller action that feels like it's the wrong shape or something. And I'll often name it but explicitly say, "I actually don't have a better idea here. So feel free to continue on with this, but I want to name it. So in case that sparks something in you, if you were also feeling some incongruousness, maybe it's worth you spending another minute to think about it, but I want to make sure my comment isn't blocking or otherwise making you feel uncomfortable."
If I just come to you and I'm like, "This feels wrong," and that's all I say, that to me is unacceptable code review. Because now I want all of my code review feedback to be very actionable, it’s either here's the thing that I feel strongly I think we should definitely change this. If you disagree, let's have a conversation. But yeah, this one definitely needs to change. Here's the thing that, like, I don't know, maybe we could break this into two lines and split it up. But if you don't like that, that's fine. Do whatever. And so then it's I've given the person my thoughts but given them clarity and a free rein to do whatever they want with that information.
And then there are ones where I'm like, I don't even know what I think we should do here, but I think something. But if you don't have any ideas...like, I don't have any ideas specifically. If you don't have any ideas, it's fine. We'll continue on with this and maybe revisit it down the road. But I want to make sure each of those different tiers is actionable for the other person, and I'm not just giving them homework or something to be sad about because that would be bad code review.
STEPH: I'm just imagining a PR comment that says, "I don't know what we should do here. But I don't think this is it," [laughs] and that just creating sadness. That's so interesting to me because I have flip-flopped with that opinion in regards to there are times that I very much resonate and do what you just said where I will point out to someone where I'm like, "I'm not sure why, but I just have concerns about this. And I don't know if you also ran into anything that was weird about this and would like to talk about it. I don't have any really great ideas, so I think this is good for now. And we should keep moving forward, so we're not blocked on it," but just wanted to, as you mentioned, highlight it in case it sparks something for the other person or for someone else that's reviewing the code.
And then there are other times where I'll look at something, and I'm like, "Yeah, it's not great. There's something that feels brittle or potentially maybe hard to maintain or things like that. But I don't have a better idea." And I don't comment on it because I'm like, I don't want to distract that person or block them. And I do think it's good enough, and I don't have anything to add to the conversation, so I just leave it out. So it's interesting to me where is that line of when I feel like it's important enough to comment to then potentially spark some conversation versus just letting it go so then I don't add any distraction to their work?
CHRIS: I think it's when the spidey-sense gets past 47%. It's a very specific number. I do the same thing where there's something, and I'm like, you know what? I can't even clearly express what about this makes me feel something off, and so I won't even comment on it, and I agree. And then there are things that trip past some magical line in the sand. And I'm like, you know what? I think I'm going to say something here, but I don't even have a recommendation. And then there's a whole spectrum of the nature of code review and, again, 47% being the specific number.
STEPH: There's actually a thoughtbot blog post that correlates nicely to that concept of spidey sense. It's written by Mike Burns, and it's titled How to Skim a Pull Request. But essentially, grabbing from one of the lines here is where Mike presents an unexplained, incomplete, and arbitrarily grouped list of keywords that will cause us thoughtboters to read your code with more care and suspicion. [laughs] That feels perfectly aligned with that idea of spidey sense, spidey-sense 101. I'll be sure to include a link in the show notes. Or, you know, 40%.
CHRIS: I think it was 47%. It's a very precise number. [chuckles]
STEPH: Very precise nonsensical number. Got it. [laughs]
CHRIS: If I'm making up fake statistics, I'm not going to have them round to an even 10. [laughter]
STEPH: Makes it seem more legit somehow.
CHRIS: Exactly.
STEPH: But that's really the novelties that I wanted to chat about.
Mid-roll Ad
And now a quick break to hear from today's sponsor, Scout APM.
Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more.
Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform.
See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed.
STEPH: What's new in your world?
CHRIS: I have some follow up on a recent topic that we talked about. So we had a kerfuffle which I described where we had a branch that got merged and the rebase some stuff got out of hand. And so we introduced some process, the protected branch configuration within GitHub that required the branches to be up-to-date before they can be merged and CI to be passing. And everybody was happy. It was like, this is great.
Turns out it was never turned on. That's actually the day I was like, man; this is really straightforward. There's been no annoyance here. And then I got to the point where it was like; this seems weird because we just merged a lot of things in rapid succession.
I went and checked, and it turns out what I thought was the name of the branch protection rule in GitHub's UI is, in fact, a regular expression pattern. It might not be a full regular expression but like a wildcard pattern for the branch name to match to, and so it's specific.
I created this rule, and in small, gray text underneath, it said, "This applies to zero branches." I missed that the first time but then the second time going back, I was like, oh, I actually wanted it to apply to more than zero branches. So I went back in and changed that. It's a great example of very subtle UI that just slipped past me.
STEPH: I was going to say in your defense, the very subtle gray font to say, "This applies to zero," feels tricky.
CHRIS: That...also, going through the work of creating this thing and if that results in zero branches that would match, maybe that's the thing to emphasize on creation. I would love that. Because in my case, I was trying very specifically to target an existing branch. There is the ability to say, "Oh, any bugfix-* named branch," if you're using branch naming strategies like that, you can use this for that sort of thing. So it may be that currently, there are no branches with that name. But in my case, I was just like, please, main, anytime anything is happening on main, that is what we want to do. I just needed to put the word main there. But anyway, once I actually turned it on, insufferable, absolutely not, cannot survive in this world.
We have a relatively small team. There are three of us, and not everyone is even full-time, and my time is pulled in a lot of different directions. So I'm actually not pushing as much code as I might otherwise. Even with that, nope, absolutely not. Our CI is like; I don't know, five-ish minutes per run. Turns out, especially Monday mornings, we have a volley of things that will have been reviewed and trickled in through Friday afternoon. And then there's a bunch of work we want to land Monday morning. And then, just at any point, it turns out, yes, this was untenable. So we have turned it off.
I would like to revisit this down the road and introduce the MergeQueue functionality, so the idea of being able to say, "Yeah, you just name when you want something to go in, and then the system will manage the annoying finicky work there." But for now, I had to give up on my dream of everything running on CI, on a feature branch, before it gets merged.
STEPH: Ooph, that phrase, "I had to give up on my dream," that breaks my heart for you. [laughs]
CHRIS: I may be going a little bit fanciful with my language but, like, a little.
STEPH: [laughs]
CHRIS: I liked this thing. I want to exist in that world. But it is not feasible given the current state of the world. And that will only get worse over time, is my expectation. So I get to revisit this when I have the time to more thoroughly figure a thing out. But for now, I don't know, merge whatever; it will be fun.
STEPH: There's a small part of me that feels a little reassured that it was a terrible time, although I hate that it was a terrible time. But I have felt that pain on so many other projects where I am constantly waiting, and I'm constantly checking to be like, can I merge? Can I merge? Can I merge? And then I can merge, but then someone beats me to it. And I'm like, oh, then I got to restart. And I got to wait, and I'm constantly checking. So that feels like it helps validate my experience. [chuckles]
I am excited for that MergeQueue. I would be super excited to try that out and hear about how it goes just because that seems more like the dream where you can just say, hey, I want this PR to go whenever it can go. Just take care of it. I want it to be rebased, whatever the flow is, and have it be merged, so I don't ever have to check on it again.
CHRIS: But once we configured this, there was a new thing that appeared in the GitHub UI, which was auto-merge. And so that was a button where I could say like, "Hey, merge this whenever CI passes," which was a nice upgrade, but it didn't have the additional logic of and rebase as necessary. Or the more subtle logic of like, you don't actually want to rebase where you have five different branches that are all trying to merge, and they keep rebasing. You want to have the idea of a queue, and so you get in line. And you rebase when it's your turn, and then you run the CI. And you try and be as smart as possible about that.
If anyone at GitHub is listening, I would love if you all threw this into your platform, and then you could ping Slack if anything went wrong. But otherwise, there are, like I said, existing tools. At some point, I will probably, I don't know, over a long weekend or something like that, sit down with a large cup of coffee and explore these. But today is not that day.
STEPH: I'm excited to hear about that day.
CHRIS: So that is a tale of woe and sadness. But luckily, I get to balance it out with a tale of happiness and good outcomes. So that's good. The happiness and good outcome story does start with trouble, as they always do. So we had a bug that occurred in the application where something was supposed to have happened. And then there was an email that needed to go out to tell the user that this thing had happened. And the bug popped up within AppSignal and said something was nil that shouldn't have been nil.
Particularly, we're using a gem called Time For a Boolean, which is by Caleb Hearth. And he's a former thoughtboter and maintains this wonderful gem that instead of having a Boolean for like, is this thing approved, or is it paid? Or is it processed? You use a timestamp. And then this gem gives you nice Boolean-like methods on top of that timestamp. Because it turns out, very often just having the Boolean of like, this was paid, it turns out you really want to know when it was paid. That would be a really useful piece of information. And so, while you're still in Postgres land, it's nice to be able to reach for this and have the affordances of the Boolean-like interface but also have the timestamp where available.
So anyway, the email was trying to process but that timestamp...let's pretend that it was paid as the one that matters here so paid at was nil, which was very concerning. Because this was the email that's like, hey, that thing was processed. Or let's say it was processed, actually, because that's closer to what it was. Hey, this thing was processed, and here's an email notification to tell you that. But the process timestamp was nil. I was like, oh no. Oh no. And so when I saw this pop up, I was like, this is very bad. Everything is very bad. Oh goodness.
Turns out what had happened was...because I very quickly chased after this, looked in the background job queue, looked in Sidekiq's UI, and the job was gone. So it had been processed. I was like, wait a minute, how? How did this fix itself? Like, that's not the kind of bug that resolves itself, except, in this case, it was. This was an interaction that I'd run into many times before. Sidekiq was immediately processing the job. But the job was being enqueued from within the context of a database transaction. And the database transaction had not been committed yet. But Sidekiq was already off to the races trying to process.
So the record that was being worked on, the database record, had local changes within the context of that transaction, but that hadn't been committed. Sidekiq then reads that record from the database, but it's now out of sync because that tiny bit of Sidekiq is apparently very fast off to the races immediately. And so there's just this tiny little bit of time that can occur. And this is also a fun one where this isn't going to happen every time. It's only going to happen sometimes. Like, if the queue had a couple of other things in it, Sidekiq probably would have not gotten to this until the database transaction had fully closed.
So the failure mode here is super annoying. But the solution is pretty easy. You just have to make sure that you enqueue outside of the database transaction. But I'm going to be honest, that's difficult to always do right.
STEPH: That's a gnarly bug or something to investigate that I don't think I have run into before. Could you talk a little bit more about enqueueing the job outside the database transaction?
CHRIS: Sure. And I think I've talked about this on a previous episode a while back because I have run into this one a few times. But I think it is sufficiently rare; like, you need almost a perfect storm because the database transaction is going to close very quickly. Sidekiq needs to be all that much more speedy in picking up the job in order for this to happen.
But basically, the idea is within some processing logic that we have in our system; we find a record, we do some work. And then we need to update that record to assign this timestamp or whatever it is. And then we also want to inform the user, so we're going to enqueue a job to send the email notification. But for all of the database work, we are wrapping it in a transaction because we want it to either succeed or fail atomically. So there are three different records that we need to update. We want all of them to be updated or none of them to be updated. So, therefore, we wrap it in a transaction.
And the way we had written, this was to also enqueue the job from within the transaction. That wasn't something we were actively intentionally doing because those are different systems. It doesn't really mean anything. But we were still within the block of ApplicationRecord.transaction do. We're now inside of that block. We're doing all of the record updates. And then the last piece of work that we want to think about is enqueueing the job to send the email.
The problem is if we're still within that database transaction if it's yet to be committed, then when Sidekiq picks up that job to run it, it will see the prior state of the world. And it's only if the Sidekiq job waits a little bit that then the database transaction will have been committed. The record is now updated and available to be read by Sidekiq in the correct updated state.
And so there's this tiny little bit of inconsistency that can happen. It's basically because Sidekiq is going out to Redis, which is a distinct system. It doesn't have any knowledge of the database transaction at play. That's why I sometimes consider using a Postgres-backed background job system because then actually the job can be as part of the database transaction.
STEPH: Cool. That's helpful. That makes a lot of sense the way you explained the whole you're actually enqueueing the job from inside that transaction. I'm curious, that prompts another question. In the case where you mentioned you're using a transaction because you want to make sure that if something fails to update so, everything gets updated together, in the event that something does fail to update because you were previously enqueueing that job from the transaction, does that mean that the update could have failed but that email would still have gone out?
CHRIS: That does not. And the reason for that is because we're within dry-monad world. And so dry-monad will implicitly capture the ActiveRecord rollback, which I think is an exception that gets raised or somehow...But basically, if that database transaction fails for any reason and ends up getting rolled back, then dry-monads will not continue processing through the rest of the sequential operation. And so, therefore, even if we move the enqueuing of the email outside of the database transaction, the sequential nature of that processing and the dry-monad stuff that we have in play will handle that. And I think that would more generally be true because I think Rails raises an exception on rollback. Not certain there. But I know in our case, we're fine on that. And we have actually explicitly checked7 for that sort of thing.
STEPH: So I meant a slightly different question because that makes sense to me everything that you just said where if it's outside of the transaction, then that sequential order won't fire because of that ActiveRecord migration error. But when you have the enqueuing inside of the transaction because then that's going to be inside of the sequential order, maybe before the rollback error gets raised. Does that make sense?
CHRIS: Yes. I think what you're asking is basically like, do we make sure to not send the job if the rest of the stuff didn't succeed?
STEPH: I'm just wondering from a transaction perspective, actually. If you have a transaction wrapped block and then you have in there, like, update this record, send email, end block, let's say update...well, I guess it's going raise because you've got probably like an update bank. Okay, so then yeah, you won't get to the next line. Got it. Got it. Got it. I just had to walk myself through that because I forgot that you probably...I have to visualize [laughs] as to what that code probably looks like. All right, that answered my question.
CHRIS: Okay. So back up to the top level then, this is the problem that we have. And looking through the codebase, we actually have it in a bunch of different places. So the solution in any one of those cases is to just take the line of code where we're saying enqueue UserMailer.deliver_later take that line of code, move it outside of the database transaction, and make sure it only happens if the database transaction succeeds. That's very easy to do in one case.
But my concern was this is a very easy failure mode to end up in. And this is a very easy incorrect version of the code to write. As far as I can tell, we never want to write the code where this is happening inside of the transaction because it has this failure mode. But how do we enforce that? That was the thing that came to mind. So I immediately did a quick look of like, is there a RuboCop thing I can do here or something?
And I actually found something even more specific, which was so exciting to find. It's a gem called Isolator. And its job is to detect non-atomic interactions within database transactions. And so it's fantastic. I was like, wait, really? Is this going to do the thing? And so I just installed the gem, configured it where I wanted, and then ran the test suite. And it showed me every place throughout the app right now where we were doing this pattern of behavior like enqueueing work from within a database transaction, which was great.
STEPH: Ooh, that's really nifty. I kind of want to install that and just run it on my current client's codebase and see what I find.
CHRIS: This feels like something like strong migrations where it's like, yeah, this is great. I kind of want to have this as part of my core toolset now. This one feels even perhaps slightly more so because sometimes I look at strong migrations, and I'm like, no, no, no, strong migrations, I get why you would say that, but for reasons, this is actually fine. And they have configurations within it to say, like, no, this is okay. Isolator feels like it's always telling me something I want to know. So this, very quickly, I'm like, I think this might be part of my toolset moving forward on every single app forever.
And actually, there's another gem that I used. It's made by the same team. So this is from the folks over at Evil Martians, which is another Rails consultancy out there in the world. And the Isolator gem is one thing that they've produced. And then I think the same author of it who is an Evil Martian's employee created the after_commit_everywhere gem.
So after_commit is one of Rails' ActiveRecord callbacks. But in this case, it allows you to use it everywhere, as the name implies. And so rather than actually having to take that line of code out of the database transaction block, which is naturally where we would write it because that's how we think about the code and how we want to express it, you can just use this after_commit method, wrap the call in that, so it's after_commit, and then a block. So either braces or do..end. That enqueueing of the email now just gets wrapped in that. And so what that does is it says, "Defer this until after the transaction commits. If the transaction does not commit, if we roll it back, then don't run it."
And what was nice is the actual code change when I finally submitted all of this was add the gem to the gem file. And then everywhere that we're doing the wrong thing, which running the test suite told me, I just went in, and I wrapped that line in after_commit and a block. And it was such a nice, clean...like, I didn't have to move the code around or actually shift the lines, which was my first attempt at this. I was able to just annotate each of those lines and say, "You're special, you're special, you're special," And then I'm done. And again, the first gem told me every case where I needed to do that. It's like, well, this is a wonderful little outcome here.
STEPH: That's really nice, yeah, how you can make the changes and then, like you said, re-run the test or re-run that gem, and it lets you know what else still needs to be updated. I'm intrigued where you mentioned you didn't have to move any lines, though. Maybe I just need to look at the gem and see it, but I'm still envisioning that you have your transaction do block. And then you're doing some things; you're updating records, and then you have your end. And then after that, it's when you want to enqueue the email. And with this after_commit, you actually added that method call inside of the transaction but then wrapped the call to Sidekiq to send the email inside of that block.
CHRIS: Correct. Yeah. So it's basically like saying, "Here's almost an anonymous function." If you think about a Ruby block in that nomenclature, you're saying, like, here's some work to do when and if the transaction succeeds. And so it meant that I was able to keep the code in the way that we as humans would talk about it but deal with the murky details, and edge cases of database transactions, and Sidekiq, and whatnot. Sort of just handle it by saying like...it almost feels like an annotation or a decoration or something like that. But it was this, in my mind, almost like a perfect melding of I don't want to think about this. Oh, cool. Okay, here's a quick, easy way to deal with it but to not have to fundamentally change how I write the code.
STEPH: Interesting. So I like all the things you're saying. I'll be honest, I'm not totally sold, and I'm trying to think of why. I think the benefits...one, as you mentioned, it's something you don't have to think about or at least signals to others that hey, maybe you should think about this to the extent that you use after_commit. And so that way, you don't have these asynchronous events taking place inside the transaction. So I like that visibility and communication to the rest of the team. Putting it inside of the transaction feels interesting. I don't know why; I feel a little weird about this. [laughs] I'm bringing my true self.
CHRIS: That's fair. So if we're being honest, I solved this first by finding the Isolator gem. Well, I solved it first by just doing it manually. I went through the app, and I found all the places. And I was like, you know what? I'm worried that the next person authoring code like this, it's so easy to fall into this trap. Like, this is such a subtle little thing that our brains are not thinking about. And so I had first fixed it, and so I had a diff that involved moving lots of lines of code, every instance of this moved from being in the database transaction out of it. And that was fine. I was fine with that as a solution. But it was a little bit noisy because I was moving a bunch of lines.
So then I brought in the Isolator gem. I actually reset that, and I went back to before I had made the fix, ran the test just to make sure Isolator was actually finding every instance. They did; that was great. So I was like, all right, cool. This is better because now I have this thing that will tell anyone when this happens. So I'm very happy about that. Because frankly, this is some hard-earned knowledge that I had to read Sidekiq and remember how database transactions work and convince myself of what was going on here and finally come to what I believe the solution is.
And now Isolator is just like, cool, that's encapsulated. And it gives a very nice failure message in the test suite. So it's like, excellent. I really like this. But still looking at it, the diff, the amount of code that I had to change, it's like, well, naturally, this is how we want to write this code, but for reasons, we can't. And it's appeasing the computer more than it's appeasing the reader or the author of the code.
And so then I happen to be reading through the Isolator gem's README, and they mention the after_commit_everywhere gem. And I was like, oh, that's interesting. So one more time, I reset. And then I really tried fixing it with after_commit. And the look of the diff there felt nice to me because the lines got a little more on them, but they didn't move. And so it's like, this is how we naturally would have authored it, and now it works correctly. And I liked that.
But I understand your hesitation because you're like, but the thing is, it's wrong. And so you've made the wrong not wrong anymore, but you didn't...and so I get your hesitation. I still like the fancy version.
STEPH: Yeah, I think you just helped me figure out my grumpiness with it or why I'm not totally sold on it. And it was in regards to adding a dependency to avoid a noisy diff is the oversimplified version that I was processing or the reason that I was a bit grumpy about adding this other gem for that. But then you also just brought a lot of other really good reasons.
One thing that you said that I do really like is adding tools that help us author code in a more natural style, the way that we want to highlight this process, and how this application does work, and how this business logic flows. So given in that light, that makes me feel better about it. But yeah, I think that was my initial grumpiness. I was like, it’ll be a noisy diff. It's okay.
CHRIS: I think I definitely share your hesitation, or you're like, hmm, that's an interesting reason to bring more code into the application. But at the same time, I think the counterpoint that comes to mind for me is we're using Ruby because of its expressiveness; at least, that's why I'm using Ruby. I really want the code that I write to be as close as possible to the thing that I would say to another human about like, oh okay, when a user signs up for the application, we need to create a record in our system, and then we need to send them an email. And then we need to do this other thing. And so, the closer that our code is to those words that I would use to describe to another human, the happier I am.
And I will put in some pretty significant effort to hold that line as long as the code can also be correct. And so, the Isolator gem here does a great job of enforcing that correctness. And then after_commit allows me to still maintain that expressiveness and not have to think about the murky details as much or not have to reshape my code to match the murky realities of different persistence engines.
But I do agree. I think it's a good thing to look at and ask, like, is it worth it? Are you sure? And in this case, I will say, "Yeah, I think so," but with that amount of certainty in my voice, [chuckles] which is not a ton.
STEPH: I think this is going back to my days of working with dependency bot PRs where every time there was an upgrade for a gem, I always ask, what do you do here? [chuckles] Do we need to upgrade you? Can we just remove you from the codebase? So I'm fairly...I don't know, resistant is a strong word. I'm skeptical of when we're adding stuff in, and I just want to question the value that it's adding.
But I want to circle back to something that you said, and that is hard-earned knowledge. And that part I understand so much where when you have gone through a fair amount of work to uncover an issue, and then you want to make sure that others don't have to go through that. This is a really nice way to highlight; hey, there's something that's tricky about computers and software here, and we need to watch out for that. And I want to help you lookout for that. Versus this is just inherit information where this needs to happen outside or after that transaction. And so that makes a really nice entry point where someone can look to say, "Why did we add this gem?" And then there's a commit message that goes with it that explains this is why we use this after_commit gem because we're specifically looking to avoid this type of bug. And I love that.
CHRIS: Yeah, I think more lines of git commit message than diff on this one. So yeah, I wrote a short novel describing all of the features, describing the different pieces that are coming together. And then it's actually a +28 -6 diff. So it's a very small code change. But yeah, lots of story captured there.
STEPH: And if you had just moved the lines, you could still have that commit message. But it's not likely that someone's going to look up that git commit change or that message that went along with it because they're not going to know to blame that one. But if they look at that particular edition of after_commit, they're more likely to find that historical context. So long story short, I think you have walked me through my initial grumpiness and provided some really good ways to avoid that really tricky failure mode for other developers.
CHRIS: Well, thank you. I'm getting Steph's seal of approval starting from grumpy places. [laughs] I feel good. All right.
STEPH: I'll have some special Stephanie's approval stickers designed and printed for you.
CHRIS: I hope you're not joking because I very much want a yellow heart that says, "Steph-approved."
STEPH: [laughs]
CHRIS: And I can put it on PRs, and I can put it on the wall. [laughs]
STEPH: Well, now I have to find a sticker designer and make a...well, it's just a yellow heart. I can probably handle this. I'm going to use Comic Sans. That will be the approved part. [laughs] Yellow hearts and Comic Sans for everybody.
CHRIS: Well, with that absolutely fantastic call back to earlier parts of the episode, shall we wrap up?
STEPH: Let's wrap up.
CHRIS: The show notes for this episode can be found at bikeshed.fm.
STEPH: This show is produced and edited by Mandy Moore.
CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes, as it really helps other folks find the show.
STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari.
CHRIS: And I'm @christoomey
STEPH: Or you can reach us at hosts@bikeshed.fm via email.
CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week.
All: Byeeeeeeee!
Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.Sponsored By:Scout: Scout APM is leading-edge application performance monitoring designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise-platform feature bloat.
With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve performance abnormalities -- like N+1 queries, slow database queries, memory bloat, and more.
Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them.
Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform.
See for yourself why developers worldwide call Scout their best friend and try our error monitoring and APM free for 14-days, no credit card needed!
And as an added bonus for Bikeshed listeners: Scout will donate $5 to the open-source project of your choice when you deploy.
Learn more at scoutapm.com/bikeshed.Support The Bike Shed

Oct 12, 2021 • 39min
312: Spooky Stories
Chris evaluates the pros and cons between using Sidekiq or Active Job with Sidekiq. He sees exceptions everywhere.
Steph talks about an SSL error that she encountered recently. It's officially spooky season, y'all!
sidekiq-symbols
Transcript:
CHRIS: Additional radiation just makes Spider-Man more powerful.
STEPH: [laughs] Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Steph Viccari.
CHRIS: And I'm Chris Toomey.
STEPH: And together, we're here to share a bit of what we've learned along the way. Hey, Chris, what's new in your world?
CHRIS: Fall is in the air. It's one of those, like, came out of nowhere. I knew it was coming. I knew it was going to happen. But now it's time for pumpkin beer and pumpkin spice lattes, and exclusively watching the movie Hocus Pocus for the next month or so or some variation of those themes. But unrelated to that, I did a thing that I do once, let's call it every year or so, where I had to make the evaluation between Sidekiq or Active Job with Sidekiq, as the actual implementation as the background job engine that is running. And I just keep running through this same cycle.
To highlight it, Active Job is the background job system within Rails. It is a nice abstraction that allows you to connect to any of a number of them, so I think Delayed Job is one. Sidekiq is one. Resque is probably another. I'm sure there's a bunch of others. But historically, I've almost always used Sidekiq. Every project I've worked on has used Sidekiq. But the question is do you use Active Job with the adapter set to Sidekiq and then you're sort of living in both worlds, or do you lean in entirely and you use Sidekiq? And so that would mean that your jobs are defined to include Sidekiq::Worker because that's the actual thing that provides the magic as opposed to inheriting from Application Job. And then do you accept all of the trade-offs therein? And every time I go back and forth. And I'm like, well, but I want this feature, but I don't want that feature. But I want these things. So I've made a decision, but I want to talk ever so briefly through the decision points that were part of it. Have you done this back and forth? Are you familiar with the annoying choice that exists here?
STEPH: It's been a while since I've had the opportunity to make that choice. I'm usually joining projects where that decision has already been made. So I can't think of a recent time that I've thought through it. And my current project is using that combination of where we are using Active Job and Sidekiq.
CHRIS: So I think there's even a middle ground there where that was the configuration that I'd set up on the project that I'm working on. But you can exist in both worlds. And you can selectively opt for certain background jobs to be fully Sidekiq. And if you do that, then instead of saying, "Perform_later," You say, "Perform_async." And there are a couple of other configurations. It gives you access to the full Sidekiq API. And you can do things like hey, Sidekiq, here's the maximum number of retries or a handful of other things. But then you have to trade away a bunch of the niceties that Active Job gives.
So as an example, one thing that Active Job provides that's really nice is the use of GlobalID. So GlobalID is a feature that they added to Rails a while back. And it's a way to uniquely identify a given record within your system such that when you say perform_later, you can say, InvitationMailer.perform_later and then pass it a user record so like an instance of a user model. And what will happen in the background is that gets serialized, but instead of serializing the whole user object because we don't actually want that, it will do the GlobalID magic. And so it'll turn into, I think it's GID:// so almost like a URL. But then it'll be, I think, your application name/model name down the road. And the Perform method actually gets invoked via the background system. Then you will just get handed that user record back, but it's not the same instance of the user record. It sort of freezes and thaws it. It's really nice. It's a wonderful little feature. Sidekiq wants nothing to do with that.
STEPH: I'm so glad that you highlighted that feature because that was on my mind; I think this week where I was reviewing...somebody had made the comment where they were concerned about passing a record to a job and saying how that wouldn't play nicely with Sidekiq. And in the back of my mind, I'm like, yeah, that's right. But then I was also I'm pretty sure this got addressed, though. And I couldn't recall specifically if it was a Sidekiq enhancement or if it was a Rails enhancement. So you just cleared something up for me that I had not had time to confirm myself. So thanks.
CHRIS: Well, to be clear, this works if you are using Active Job with Sidekiq as the adapter, but not if you are using a true Sidekiq worker. So if you opt-out of the Active Job flow, then you have to say, "Perform_async," and if you pass it a record, that's not going to work out particularly nicely.
The other similar thing is that Sidekiq does not allow the use of keyword args, which, I'm going, to be honest, I really like keyword arguments, especially for background jobs or shuttling data through your system. And there's almost a lazy evaluation. I want some nicety to make sure that when I am putting something into a background job that I'm actually using the correct call signature, essentially passing the correct data in the correct shape. Am I passing a record, or am I passing the ID? Am I passing a list of options or a single option? Those sort of trade-offs that are really easy to subtly get wrong.
I came around on this one because I realized although Active Job does support keyword arguments, the way it does that is it just has a JSON serialization format for them. So a keyword argument turns into a positional array with an associated hash that allows for the lookup or whatever. Basically, again, they handle the details. You get to use keyword args, which is great, with the exception that when you're actually calling perform_later, that method perform_later is a method missing type magic method. So it does not actually check the keyword arguments at that point. You're basically just passing an options hash as opposed to true keyword arguments that would error because they don't match up. And so when I figured that out, I was like, oh, never mind. This doesn't actually do the thing that I care about. It's a little bit nicer in terms of the signature of the method when you're defining your background job itself, but it doesn't actually do any logical checking. It doesn't give me any safety or robustness within my system. So I don't care about that.
I did find a project called sidekiq-symbols, which does some things under the hood to how Sidekiq serializes and deserializes jobs, which I think gives largely the same behavior as Active Job. So I can now define my Sidekiq jobs with keyword arguments. Things will work. I can't use GlobalID. That's still out. But that's fine. I can do a little helper method that basically does the same thing as GlobalID or at least close approximation. But sidekiq-symbols lets me have keyword arg-like signatures in my methods; basically, it is. But again, it doesn't actually do any check-in when I'm enqueueing a job, and I am sad about that.
STEPH: Yeah, that's another interesting distinction. And I'm unsurprisingly with you that I would favor having keyword args and having that additional safety in place. Okay, so I've been keeping track. And so far, it sounds like we have two points because I'm doing a little scorecard here between Active Job and Sidekiq. And we have two points in favor of Active Job because they offer a GlobalID, which then allows us to pass in a record, and then it takes care of the serialization for us. And then also, keyword args, which I agree with you that's a really nice feature to have in place as well. So I'm curious, so it sounded like you're leaning towards Active Job, but I don't want to spoil the ending.
CHRIS: Yes, I could see why that's what you would be taking away from the conversation thus far. So again, just to reiterate, Active Job and Sidekiq with this sidekiq-symbols extension they both support keyword args, kind of. They support defining your job with keyword args and then enqueueing a job passing something that looks like keyword args. But it ends up...nobody's actually checking anything, so it's mostly like a syntactic nicety as opposed to any sort of correctness, which is still nicer, but it's not the thing that I actually want. Either way, nobody supports it, so it is not available to me. Therefore, it is not a consideration point.
The GlobalID thing is nice, but it is really, again, it's a nicety more than anything. I have gone, and I'm leaning in the direction of full Sidekiq and Sidekiq everywhere as opposed to Active Job in most cases, but then Sidekiq when we need it. And that's because Sidekiq just has a lot more power and a lot more functionality. So, in particular, Sidekiq has a feature which allows you to say...it's a block that you put at the top of your Sidekiq job that says retries exhausted or something. I think Sidekiq retries exhausted is the actual full name of that at that point, which is really unfortunate in my mind, but anyway, I'll deal. At that point, you know that Sidekiq has exhausted all of the retries, and you can treat it as failed.
I'm going, to be honest, I went on a quest to find a way to say, hey, I'm going to put some work into the background. It's really important for me to know if this work succeeds or if it fails. It's very easy to know if it succeeds because that just happens in-line in the method. But we can have an exception raised at basically any point; Sidekiq does a great job of catching those, of retrying, of having fundamental mechanisms there. But this is the best that I can get for this job failed. And so Active Job, as far as I can tell, does not have anything for this in order to say, yep, we are done. We are not going to keep working on this. This work has failed. It is dead.
Dead is; actually, I think the more correct term for where we're at because failed is a temporary state, and then you retry after a failure. Whereas dead is, this has gone through all of its retries, and it will never be run again. Therefore, we should treat this as not having run. And in my case, the thing that I want to do is inform the user that this operation that we were trying to do on their behalf has not succeeded, will not succeed. And please reach out or otherwise deal with the fact that we were unable to do the thing that they asked us to do. That feels like a really important thing for me to be able to do, to be able to communicate back to my users.
This is one of those situations where I'm looking at the available options, and I'm like, I feel like I can't be the only one who wants to know when something goes wrong. This feels like a thing that's important. But this is the best example that I've found, the Sidekiq retries exhausted block. And unfortunately, when I'm using it, it gets yielded the Sidekiq JSON blob deserialized, so it's like Ruby hash. But it's still like this blob of data. It's not the same data that gets passed into perform. And so, as a result, when I want to look up the record that was associated with it, I have to do this nested dig into the available hash of data. And it just feels like this is not a well-paved path. This is not something that is a deeply thought about or recommended use case. But again, I don't feel like I'm doing something weird here. Am I doing something weird, Steph, wanting to tell my users when I was unable to do the thing they asked me to do? [chuckles]
STEPH: That feels like a very rhetorical question. [laughs]
CHRIS: It does. I apologize. I'm leading the witness. But in your sincere heart of hearts, what do you think?
STEPH: No, that certainly doesn't sound weird. I'm actually thinking back to some of the jobs that cause me stress in regards to knowing when they failed and then having that communication of knowing that we've exhausted all the retries. And, of course, knowing when those retries are exhausted is incredibly helpful.
I am intrigued, though,, because you're highlighting that Active Job doesn't have the same option around setting the retry. And I'm trying to recall exactly how it's set. But I feel like I have set the retry count for Active Job. And maybe, as you mentioned before, that's because it's an abstraction, or I'm not sure if Active Job actually has that native support. So I feel a little confused there where I think my default instinct would have been Active Job does have that retry capability. But it sounds like you've discovered otherwise.
CHRIS: I'm not actually sure what Active Jobs core retry logic or option looks like. So fundamentally, as far as I understand it, Active Job is an abstraction. And under the hood, you're always connecting an adapter. So it's either going to be Sidekiq, or Resque, or Delayed Job, or other. And each of those systems, whichever system you have as the adapter, is the one that's actually going to be managing retries. And so I know Sidekiq happens to have as a default 25 retries. And that spans, I think it's a two-week exponential back off. And Sidekiq has some very robust logic that they have implemented as the way retries exist within Sidekiq. I'm not sure what that would look like if you're trying to express it abstractly because it is slightly different.
I know there was some good work that was done on Sidekiq to allow the Sidekiq options that's a method at the top level of the job, even if it's an Active Job job to express the retries. So that may be what you've seen, or there may be truly an abstraction that exists within Active Job, and then each adapter needs to know how to handle retries. But frankly, the what can Sidekiq do that Active Job can't? There's a whole bunch of stuff around limiting when you would retry limiting, enqueuing a job if there already exists one, when and how do those records get locked. There's a whole bunch of stuff.
Sidekiq has a lot of power under the hood. And so if we want to be leaning into that, that's why I'm leaning towards let's just be Sidekiq all the time. Let's become Sidekiq experts. Let's accept that as a deep architectural decision within the app as opposed to just relying on the abstraction. Because fundamentally, if we're just using Active Job, we're not going to have access to the full power of Sidekiq or whatever the underlying system is, so sort of that decision that I'm making, but I don't know specifically around the retries.
STEPH: Okay, thanks. That's really helpful. It's been a while since I've had to make this decision. I'm really enjoying you sharing your adventure because I'm trying to think what's the risk? If you don't use Active Job, what are the trade-offs? And you'd mentioned some of them around the GlobalID and keyword args, which are some niceties. But overall, if you don't go with the abstraction, if you lean into Sidekiq, the risk is then you want to migrate to a different enqueuing service. And something that we talk about is mitigating that risk, so then you can swap it out. That's also something I have never done or encountered where we've had to make that change. And it feels like a very low risk in my mind.
CHRIS: Sidekiq feels like the thing you would migrate to, not a thing you would migrate from. It feels like it is the most powerful. And if anything, I expect at some point we'll be upgrading to Sidekiq pro or enterprise or whatever the higher versions that you pay for, but you get more features there. So in that sense, that is the calculation. That's the risk trade-off in my mind is that we're leaning into this technology and coupling ourselves more closely to it.
But I don't see that as one that will reassess in the same way that people talk about Active Record and it being an ORM. And it's like, oh, we're abstracting the database underneath, and I'm like, no, I'm not. I'm always using Postgres. Please do not take Postgres. I'm not going to switch over to MySQL next week. That's totally fine if you start on MySQL. It's unlikely you're going to port over to Postgres. We may port to an entirely…like it's a Cassandra column store with a Kafka queue, I don't know, something weird down the road. But it's not going to be swapping out Postgres for MySQL or vice versa. Like you said, that's probably not a change that's going to happen. But that I think is the consideration.
The other consideration I have in my mind is Active Job is the abstraction that exists within Rails. And so I can treat it as the lowest common denominator, and folks joining the project, it's nice to have that familiarity. So perform_later is the method on the Active Job jobs, and it has a certain shape to it. People may be familiar with that. Mailers will automatically use Active Job just implicitly under the hood. And so there's a familiarity, a discoverability. It's just kind of up the middle choice. And so if I can stick with that, I think there's a nicety there. But in this case, I think I'm choosing I would like the power and consistency on the Sidekiq side, and so I'm leaning into that.
STEPH: Yeah, that makes a lot of sense to me. And I liked the other example you provided around things that were not likely to swap out and Postgres, MySQL, your database being one of them. And in favor of an example that I do have for something that...I do enjoy wrapping. It's not something that I adhere to strictly, but I do enjoy it when I have the space to make this choice. So I do enjoy wrapping HTTPClients, not just because then I can swap it out for a different HTTPClient, which frankly, that's also rare that I do that. Once I choose an HTTPClient, I'm probably pretty happy, and I don't need to swap it out.
But I really like being able to extend to the API specifically if they don't handle error responses in a way that I would like to or if they raise, and then I want to change the API to have a more thoughtful interface and where I don't have to rescue those errors. But instead, I can interact with this object that then represents an error state. So that was just one example that came to mind for things that I do enjoy having an abstraction around and not just so I can swap it out because that feels like a very low risk, but more frankly, so I can extend the API.
CHRIS: I definitely share the I almost always wrap APIs, or I try and hide whatever the implementation detail whether it be HTTPParty, or Faraday or whatever it is that I'm using and trying to hide that deeply within the system. And then I have whatever API client that we define. And that's what we're interacting with. It's interesting that you bring up errors and exceptions there because that's the one other thing that has caused me this...what I'm describing now seems perhaps like, oh, here's just a list of pros and cons, a simple decision was made, and there we are.
This represents some real soul searching on my part, if we will. And one of the last things that I ran into that was just so frustrating is that Sidekiq is explicitly built around the idea of exceptions; Sidekiq retries if there is an exception raised in the job, otherwise, it treats it as success, and that's it. That is the entirety of it. That is the story. But if you raise an exception in a job, then you can't test that job because now it's raising an exception. You can't test retries or this retry exhausted block that I'm trying to lean into. I'm like, I want to put that in a feature spec and say, oh, this job goes in the background, but it's in a failure state, and therefore, the user sees the failure message. Sorry, I can't do that because the only way to actually fail a job is via an exception.
And I've actually gone to some links in this application to try to introduce more structured data flow. I've talked a bunch about the command objects and the dry-monads and all those things. And I've really loved them where I've gotten to use them. But then I run into one of these edge cases where Sidekiq is like, no, no, no, you can't do that. And so now I have parts of my system that very purposefully return data as opposed to raising an exception. And I just have to turn around and directly raise that failure as an exception, and it just feels less expressive.
I actually just ran into the identical thing with Pundit. They have a little bit better control over it; I can choose whether or not I want the raising version or not. But I see exceptions everywhere, and I want a little more discrete data flow. [chuckles] That is my dream. So anyway, I chose Sidekiq is the summary here. And slowly, we're going to migrate entirely to Sidekiq. And I'm going to be totally fine with it. And I'm done griping now.
STEPH: This is your own little October Halloween movie, that I see exceptions everywhere.
CHRIS: They're so spooky.
STEPH: [laughs] That's cool about Pundit. I'm not sure I knew that, that you get to essentially turn on or off that exception flow behavior. On one hand, I'm like, that's nice. You get the option. On the other hand, I'm like, well, let's just not do it. Let's just never raise on people. But at least they give people options; that seems really cool.
CHRIS: They do give the option. I think you can choose different strategies there. And also, if we're being honest, I'm newer to Pundit. And I used a different thing, which was to get the Policy Object and ask it a question. I wanted to ask, is this enabled or not? Can a user do this or not? That should not raise an exception. I'm just asking a question. We're just being real chill about this. I just want to know some information. Let's flow some data through our system. We don't need exceptions for that.
STEPH: Why are you yelling at me? I just have a question. [laughs]
CHRIS: Yeah. I figured out how to be easy on that front. Sidekiq apparently has no be easy mode, but that's fine. You know what? We're going to make it work, and it's going to be fine. But it is interesting deciding which of these facets of the system that I'm building do I really care about? Which are the ones where I'm like, whatever, just pick something, and we'll move forward, it's not a big deal? Versus, we're actually going to be doing a lot of work in the background. This is the thing that I care about deeply. I want to know about failure and success. I want to really understand that and have a robust answer to what our architecture looks like there.
Similarly, Pundit for authorization. I believe that authorization will be a critical aspect of our system. It's typically a pretty important thing. But for us, I think we're going to have different types of users who can log in and see different subsets of data and having a consistent and concrete way that we have chosen to implement that we are able to test, that we're able to verify. I think that's another core competency within the app. But you only get to have so many of those. You can only be really good at a couple of things. And so I'm in that place where I'm like, which are our top five when I say are the things that I care a lot about? And then which are the things where I'm like, I don't know, whatever, just run with it?
STEPH: Just a little bit ago, I came so close to singing because you said the I want to know phrase again. And that, I'm realizing, [laughs] is a trigger for me and a song where I want to sing. I held it back this time.
CHRIS: It's smart. You got to learn anytime you sing on mic that is part of the permanent record.
STEPH: Edward Loveall at thoughtbot, since I sang in a recent episode, did the delightful thing where then he grabbed that clip of where you talk a little bit, and then I sing and then encouraged everyone to go listen to it. And in which I responded, like, I would highly recommend that you save your ears and don't listen to it. But yes, singing on the mic is a thing. I do it from time to time. I can't hold it back.
CHRIS: We all do. But since it doesn't seem that you're going to sing in this moment, I think I can probably wrap up my Odyssey of choosing between Sidekiq and Active Job. I hope those details were useful to anyone other than me. It was an adventure, so I figured I'd share it. But yeah, that about wraps it up on my side.
Mid-roll Ad
And now a quick break to hear from today's sponsor, Scout APM.
Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more.
Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform.
See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed.
STEPH: So, I would love to talk about an SSL error that I encountered recently. So one of the important processes in our application is sending data to another system. And while sending data to that other system, we started seeing the following error that the read "Certificate verify failed." And then in parens, it states, "Unable to get local issuer certificate." So upon seeing that error, I initially thought, okay, something is wrong with their SSL certificate or their SSL configuration. And that's not something that I have control over and can fix. So we should reach out and let them know to take a look at their SSL config.
But it turns out that their team already knew about the issue. They had recently updated or renewed their SSL cert, and they saw our messages were no longer being processed, and they were reaching out to us for help. So at that point, I'm still pretty sure that it's related to something on their end, and it's not something that I can really fix on our end. But we can help them troubleshoot. Maybe there's a workaround that we can add to still get messages processing while they're looking into their SSL config. It seemed like they still just needed help. So it was something that was still worth diving into.
So going back to the first error, I want to talk a little bit about it because I realized that I understand SSL just enough, just the surface to get by as a developer. But then, every time that I run into a specific error with it, then I really have to refresh my understanding as to what could be wrong, so then I can troubleshoot more effectively.
So for anyone that could use a refresher on that certificate verification process, when your browser or your server is connecting to a site that uses SSL, then your browser server, whichever one you're using, is going to download that site certificate and verify a couple of things. So it's going to check does the certificate contain the domain name of the website? So essentially, you gave us a certificate. Is this your certificate? Does it match the site that we're connecting to? Is this cert issued by a trusted certificate authority? So did someone that we trust give you this certificate? And is the cert still valid, or has it expired? So that part is pretty straightforward.
The second part, "Unable to get local issuer certificate," so that's the part I was less certain about. And I took this to mean that they had passed two of those three checks that their cert included the site's name, and it had not expired. But for some reason, we aren't able to determine if their cert was issued by someone that we should trust.
So following that journey, my next question was, so what are they giving us? So this is a tool that I don't get to use very often, but I reached for OpenSSL and, specifically, the s_client command, which connects to a specified domain and prints all certificates in the certificate chain. You may already know this, but the certificate chain is basically a fancy way of saying, show me all the certificates necessary to prove your site certificate was authorized by a trusted certificate authority.
CHRIS: I did not know that.
STEPH: Okay, I honestly didn't either. [laughs]
CHRIS: I liked that you thought I would, though. So thank you, but no. [chuckles]
STEPH: Yeah, it's one of those areas of SSL where I know just enough. But that was something that was new to me. I thought there was a site certificate, and I didn't realize that there is this chain of certificates that has to be honored.
So going back and looking through that output of the certificate chain, that's what highlighted to me that their server was giving us their certificate and saying, hey, you should trust our site certificate. It's legit because it was authorized by, let's say, XYZ certificate. And so if it were a proper certificate chain, then they would give us that XYZ cert. And essentially, we can use this chain of certificates to get back to a trusted authority that then everybody knows that we can trust. However, they weren't actually giving us a reference certificate; they were giving us something else. So essentially, they were saying, "Hey, look at our certificate and look at this very trustworthy reference that we have." But they're actually failing to give us that reference.
So to bring it all home, we can download that intermediate certificate that they reference; that is something that is publicly accessible. That's why we're able to then verify each certificate that's provided in that chain. We could go and download that intermediate certificate from that certificate authority. We could combine that with their site-specific certificate, include that in our request to their system, and then complete the certificate chain. And boom, we're back in business. But it was quite a journey.
CHRIS: That is quite the journey. And yeah, I definitely knew very little of that, although everything you're saying makes sense. And I have a bunch of cubbyholes in my brain for SSL knowledge. And the words you said all fit into the spaces that I have in my brain, but I didn't know a bunch of those pieces. So thank you for sharing that.
SSL and cryptography, more generally or password hashing or things like that, occupy this special place in my brain where I'm both really interested in them. And I will occasionally research them. If I see a blog article, I'll be like, oh yeah, I want to read more about this password hashing. And what's a Salt? And what's a Pepper? And what are we doing there? And what is BCrypt versus SCrypt? What are all these things? This is cool. And almost the arms race on the two sides of how do we demonstrate trust in a secure manner on the internet?
But at the same time, I am not allowed to do anything with this information. I outsource this as much as humanly possible because it's one of those things that you just should not do yourself and SSL perhaps even more so. So I have configured aspects of my password hashing. But I 100% just lean on the fact that Let's Encrypt exists in the world. And prior to that, it was a little more work. But frankly, earlier on in my career, I wasn't dealing with the SSL parts of things. But I'm so grateful to Let's Encrypt as a project that exists.
And now, on almost every platform that I work with, there's just a checkbox for please do the SSL work for me, make it good, make it work, and then I will be happy. And I'm so glad that that organization exists and really pushed the envelope also. I forget what it was, but it was only like three years ago where SSL was not actually nearly as common as it is now. And now it is pervasive and everywhere. And all of the sites have it, and so that is a wonderful thing. But I don't actually know much. I know that I should have it. I must have it. I should force it. That's true. So I push that out…
STEPH: Hello.
CHRIS: Are you trying to get me to sing? [chuckles]
STEPH: [laughs] No, but I did want to know if you get the reference, the Salt-N-Pepa.
CHRIS: Push It Real Good the song? Yeah, okay.
STEPH: Yeah, you got it. [chuckles]
CHRIS: I will just say the lyrics. I shall not sing the lyrics. I would say that, though, that yes, yes, they do that.
STEPH: Thank you for acknowledging my very terrible reference. Circling back just a little bit too in regards to...I'm with you; this is a world that is not one that I am very deeply technical in and something that I learned a fair amount while troubleshooting this particular SSL error. And it was very interesting. But there's also that concern where it's like, that was interesting. And we worked around the issue, but this also feels very fragile.
So we still haven't fixed it on their end where they are sending the wrong certificate. So then that's why we had to do more investigative work, and then download the certificate that they meant to send us, and then send back a complete certificate chain so that we don't have this error anymore. But should they change anything about their certificate, should they renew anything like that, then suddenly, we're going to break again. And then, the next developer is going to have to go through the same journey. And this wasn't a light journey. This was a good half-day journey to figure out what was going on and to spend the time, and then to also get that fix out to production. So it's a meaningful task that I don't want anyone else to have to go through.
But we are relying on someone else updating their configuration. So, on one hand, we're in a good spot until they are able to update. But on the other hand, I wrote a heck of a commit message for the next person just describing like, friend, just grab some coffee if we're going to chat. It's a very small code change, but you need to know the scoop. So should you need to replicate this because they've changed something, or if this happens…because we work with a number of systems that we send data to. So if someone else should run into a similar issue, they will understand some of the troubleshooting techniques that I used and be able to look up that chain and find out if there's a missing cert or something else they need to provide. So it feels like a win, but I'm also nervous for future selves, future developers.
So there's another approach that I haven't mentioned yet, but it was often a top recommendation for when dealing with SSL errors. And specifically, it was turning off SSL verification. And I saw that, and I was like, well, that won't work. I'm definitely sending sensitive, important data. And I need to verify that who I'm sending this to is really the person that I want to send this data to. So that was not an option for me. But it made me very nervous how often that was an approach that people would recommend and be like, oh, it's okay, just turn off SSL. You'll be fine. Like, don't worry about it.
CHRIS: I feel like this so perfectly fits into the...some of our work is finding the information and connecting the pieces together and making it work. But some of it is that heuristic sense, that voice in the back of your head that is like, wait, I'm sorry, what? You want me to just turn off the security perimeter and hope that the velociraptors won't come in? That doesn't seem like it's going to end well. I get that that's an easy option that we have available to us right now and will solve the immediate problem but then let's play this out. There are four or five Jurassic Park movies now that tell the story of that. So let's be careful.
STEPH: It always ends super well, though, right? Like, it's totally fine. [laughs]
CHRIS: [laughs] Exclusively. Although it's funny that you mentioned OpenSSL no verify because just this past week, I used that very same configuration. I think it was okay in my case; I’m pretty sure. But it is interesting because when I saw it, I was like, oh no, can't do that. Certainly not that. Don't turn off the security feature. That's the wrong way to deal with the issue.
But in the particular case that I'm working with, I'm using Redis, Heroku Redis, in particular, in a Heroku configuration. And the nature of how Heroku configures the Redis instances and the connectivity to our app into our dyno...I forget why. I read an article. They wrote it; Heroku wrote it. I trust them; they’re good. I've outsourced my trust to people that I do trust. The trust chain actually maps really well to the certificate trust chain. I trust that Heroku has taken security deeply seriously. And for some reason, their configuration of Redis requires that I turn on OpenSSL no verify mode. So I'm using this now both in Sidekiq, and then we're using our Redis instance for our Rails cache as well.
So in both cases, I said, "It's fine. Don't worry about it." I used the Don't worry about it configuration. And I didn't love it but I think it's okay. And partly, I'm trying to say this into the internet radio right now just in case anyone's listening who's like, no, no, no, you can't do that. That's bad. So I'm willing to be deeply wrong on the internet in favor of someone telling me and then I get to get out in front of it. But I think it's fine. Pretty sure it's fine. It should be fine.
STEPH: I love love love that you gave a very visual example of velociraptors, and then you're like, oh, but I turned it off. [laughs] So I'm going to start sending you a velociraptor gif each day.
CHRIS: I hope you do. I hope the internet holds you accountable to that.
STEPH: [laughs]
CHRIS: And I really look forward to [laughs] moving forward because that's a great way to start the day. Well, it doesn't need to start the day, but I look forward to them.
STEPH: [laughs] I am really intrigued because I'm with you. Like you said, there are certain entities that are in our trust chain where it's like, hey, you are running this for us, and so I do have faith and trust in you that you wouldn't steer me wrong and provide a bad recommendation. Someone on Stack Overflow telling me to turn off SSL verify uh; that’s not my trust chain. Heroku or someone else telling me I'm going to take it a little more seriously. And so I'm also interested in hearing from...what'd you say? You're speaking into the internet phone. [laughs] What'd you say?
CHRIS: I think I said internet radio. But yeah, in a way. I mean, we're recording over Skype right now. So in a manner of speaking, we're on the internet phone to make our internet radio show.
STEPH: [laughs] Oh goodness, the internet radio. I'm also intrigued to hear if other people are like, oh, no, no, no. Yeah, that sounds like an interesting scenario. Because I would think you'd still want your connection to...you said it's for Redis. So you still want that connection to be verified. But then if Redis itself can't have a specific...yeah, we're testing the boundaries of my SSL knowledge here as to how the heck you would even establish that SSL connection or the verification process.
CHRIS: Me too. And it also exists in an interesting space where Heroku is rather clear in their documentation about this. And it was a surprising claim when I saw it. And so, I don't expect them to be flippant about a thing that is important. Like, if they're like, "No, no, no, it is okay. You can turn off the security thing, don't worry." I trust that they're not just like, oh, we didn't think about it too much. But we figured why not? It's not a big deal. I'm sure that they have thought about it deeply because it is an important thing.
And so in a weird way, my trust of them and the severity of what this thing represents, I'm like, oh yeah, I super trust that because you're not going to get a major thing wrong. You might get a minor, small, subtle thing wrong. But this is a pretty major configuration change. As I say it, I'm now getting more worried. I'm now like, I feel fine about this. This doesn't seem like a problem at all. But then I keep saying stuff, and I'm like, oh no. That's why I love having a podcast; I find out things about myself as I talk into a microphone to you.
STEPH: We come here to share our deep, dark developer secrets.
Chris: Spooky developer therapy.
STEPH: But just to clarify, even though you've turned off the SSL verify, you're still connecting over SSL.
CHRIS: Yes, I believe that's the case. And if I'm remembering, I think the nature of how this works is they're using a self-signed certificate because of shared infrastructure or something, something that made sense when I read it. But it was the idea that they are doing a self-signed certificate. Therefore, to what you were talking about earlier, there isn't the certificate authority in the chain of those because it's self-signed. And so, they are not a trusted certificate authority. Therefore, that certificate that they have generated would not be trusted. But it does still allow for the SSL handshake and then communication to happen over SSL. It's just that fundamental question of trust. I'm saying, in this case, for reasons, it's okay. Trust me that I trust them. We're good. Which, again, I don't feel great about, but I think yes, it is still SSL, but it is a self-signed certificate. So we have to make this configuration change.
STEPH: Yeah, all of that makes sense. And it certainly sounds like you have been very thoughtful about that change and put in some investigative work. So on that note, I have a very unrelated bad joke for you.
CHRIS: I'm very excited.
STEPH: All right, here we go. All right, so what do you call an alligator wearing a vest?
CHRIS: I don't know. What do you call an alligator wearing a vest?
STEPH: An investigator.
[laughter]
On that note, shall we wrap up?
CHRIS: Oh, let's wrap up. We should also include a link in the show notes to the episode where you told the joke about the elephant hiding in the trees because that's one of my favorite jokes. You slayed me with that one. [laughs] But on that note, yes, let us wrap up. The show notes for this episode can be found at bikeshed.fm.
STEPH: This show is produced and edited by Mandy Moore.
CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes,,as it really helps other folks find the show.
STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari.
CHRIS: And I'm @christoomey
STEPH: Or you can reach us at hosts@bikeshed.fm via email.
CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week.
All: Byeeeeeeeeee!!!
Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.Support The Bike Shed

Oct 5, 2021 • 38min
311: Marketing Matters
Longtime listener and friend of the show, Gio Lodi, released a book y'all should check out and Chris and Steph ruminate on a listener question about tension around marketing in open-source.
Say No To More Process, Say Yes To Trust by German Velasco
Test-Driven Development in Swift with SwiftUI and Combine by Gio Lodi
Transcript:
CHRIS: Our golden roads.
STEPH: All right. I am also golden.
CHRIS: [vocalization]
STEPH: Oh, I haven't listened to that episode where I just broke out in song in the middle. Oh, you're about to add the [vocalization] [chuckles].
CHRIS: I don't know why, though. Oh, golden roads, Golden Arches.
STEPH: Golden Arches, yeah.
CHRIS: Man, I did not know that my brain was doing that, but my brain definitely connected those without telling me about it.
STEPH: [laughs]
CHRIS: It's weird. People talk often about the theory that phones are listening, and then you get targeted ads based on what you said. But I'm almost certain it's actually the algorithms have figured out how to do the same intuitive leaps that your brain does. And so you'll smell something and not make the nine steps in between, but your brain will start singing a song from your childhood. And you're like, what is going on? Oh, right, because when I was watching Jurassic Park that one time, we were eating this type of chicken, and therefore when I smell paprika, Jurassic Park theme song. I got it, of course.
STEPH: [laughs]
CHRIS: And I think that's actually what's happening with the phones. That's my guess is that you went to a site, and the phones are like, cool, I got it, adjacent to that is this other thing, totally. Because I don't think the phones are listening. Occasionally, I think the phones are listening, but mostly, I don't think the phones are listening.
STEPH: I definitely think the phones are listening.
CHRIS: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey.
STEPH: And I'm Steph Viccari.
CHRIS: And together, we're here to share a bit of what we've learned along the way. So, Steph, what's new in your world?
STEPH: Hey. So we have a bit of exciting news where we received an email from Gio Lodi, who is a listener of The Bike Shed. And Gio sent an email sharing with us some really exciting news that they have published a book on Test-Driven Development in Swift. And they acknowledge us in the acknowledgments of the book. Specifically, the acknowledgment says, "I also want to thank Chris Toomey and Steph Viccari, who keep sharing ideas on testing week after week on The Bike Shed Podcast." And that's just incredible. I'm so blown away, and I feel officially very famous.
CHRIS: This is how you know you're famous when you're in the acknowledgments of a book. But yeah, Gio is a longtime listener and friend of the show. He's written in many times and given us great tips, and pointers, and questions, and things. And I’ve so appreciated Gio’s voice in the community. And it's so wonderful, frankly, to hear that he has gotten value out of the show and us talking about testing. Because I always feel like I'm just regurgitating things that I've heard other people saying about testing and maybe one or two hard-learned truths that I've found. But it's really wonderful. And thank you so much, Gio. And best of luck for anyone out there who is doing Swift development and cares about testing or test-driven development, which I really think everybody should. Go check out that book.
STEPH: I must admit my Swift skills are incredibly rusty, really non-existent at this point. It's been so long since I've been in that world. But I went ahead and purchased a copy just because I think it's really cool. And I suspect there are a lot of testing conversations that, regardless of the specific code examples, still translate. At least, that's the goal that you and I have when we're having these testing conversations. Even if they're not specific to a language, we can still talk about testing paradigms and strategies. So I purchased a copy. I'm really looking forward to reading it.
And just to change things up a bit, we're going to start off with a listener question today. So this listener question comes from someone very close to the show. It comes from Thom Obarski. Hi, Thom. And Thom wrote in, "So I heard on a recent podcast I was editing some tension around marketing and open source. Specifically, a little perturbed at ReactJS that not only were people still dependent on a handful of big companies for their frameworks, but they also seem to be implying that the cachet of Facebook and having developer mindshare was not allowing smaller but potentially better solutions to shine through. In your opinion, how much does marketing play in the success of an open-source project framework rather than actually being the best tool for the job?" So a really thoughtful question. Thanks, Thom. Chris, I'm going to kick it over to you. What are your thoughts about this question?
CHRIS: Yeah, this is a super interesting one. And thank you so much, Thom, although I'm not sure that you're listening at this point. But we'll send you a note that we are replying to your question. And when I saw this one come through, it was interesting. I really love the kernel of the discussion here, but it is, again, very difficult to tease apart the bits. I think that the way the question was framed is like, oh, there's this bad thing that it's this big company that has this big name, and they're getting by on that. But really, there are these other great frameworks that exist, and they should get more of the mindshare.
And honestly, I'm not sure. I think marketing is a critically important aspect of the work that we do both in open source and, frankly, everywhere. And I'm going to clarify what I mean by that because I think it can take different shapes. But in terms of open-source, Facebook has poured a ton of energy and effort and, frankly, work into React as a framework. And they're also battle testing it on facebook.com, a giant website that gets tons of traffic, that sees various use cases, that has all permissions in there. They're really putting it through the wringer in that way.
And so there is a ton of value just in terms of this large organization working on and using this framework in the same way that GitHub and using Rails is a thing that is deeply valuable to us as a community. So I think having a large organization associated with something can actually be deeply valuable in terms of what it produces as an outcome for us as consumers of that open-source framework.
I think the other idea of sort of the meritocracy of the better framework should win out is, I don't know, it's like a Field of Dreams. Like, if you build it, they will come. It turns out I don't believe that that's actually true. And I think selling is a critical part of everything. And so if I think back to DHH's original video from so many years ago of like, I'm going to make a blog in 15 minutes; look at how much I'm not doing. That was a fantastic sales pitch for this new framework. And he was able to gain a ton of attention by virtue of making this really great sales pitch that sold on the merits of it. But that was marketing. He did the work of marketing there.
And I actually think about it in terms of a pull request. So I'm in a small organization. We're in a private repo. There's still marketing. There's still sales to be done there. I have to communicate to someone else the changes that I'm making, why it's valuable to the system, why they should support this change, this code coming into the codebase. And so I think that sort of communication is as critical to the whole conversation. And so the same thing happens at the level of open source.
I would love for the best framework to always win, but we also need large communities with Stack Overflow answers and community-supported plugins and things like that. And so it's a really difficult thing to treat marketing as just other, this different, separate thing when, in fact, I think they're all intertwined. And marketing is critically important, and having a giant organization behind something can actually have negative aspects. But I think overall; it really is useful in a lot of cases. Those are some initial thoughts. What do you think, Steph?
STEPH: Yeah, those are some great initial thoughts. I really agree with what you said. And I also like how you brought in the comparison of pull requests and how sales is still part of our job as developers, maybe not in the more traditional sense but in the way that we are marketing and communicating with the team. And circling back to what you were saying earlier about a bit how this is phrased, I think I typically agree that there's nothing nefarious that's afoot in regards to just because a larger company is sponsoring an open-source project or they are the ones responsible for it, I don't think there's anything necessarily bad about that.
And I agree with the other points that you made where it is helpful that these teams have essentially cultivated a framework or a project that is working for their team, that is helping their company, and then they have decided to open source it. And then, they have the time and energy that they can continue to invest in that project. And it is battle-tested because they are using it for their own projects as well. So it seems pretty natural that a lot of us then would gravitate towards these larger, more heavily supported projects and frameworks. Because then that's going to make our job easier and also give us more trust that we can turn to them when we do need help or have issues.
Or, like you mentioned, when we need to look up documentation, we know that that's going to be there versus some of the other smaller projects. They may also be wonderful projects. But if they are someone that's doing this in their spare time just on the weekends and yet I'm looking for something that I need to be incredibly reliable, then it probably makes sense for me to go with something that is supported by a team that's getting essentially paid to work on that project, at least that they're backed by a larger company. Versus if I'm going with a smaller project where someone is doing some wonderful work, but realistically, they're also doing it more on the weekends or in their spare time. So boiling it down, it’s similar to what you just said where marketing plays a very big part in open source, and the projects and frameworks that we adopt, and the things that we use. And I don't think that's necessarily a bad thing.
CHRIS: Yeah. I think, if anything, it's possibly a double-edged sword. Part of the question was around does React get to benefit just by the cachet of Facebook? But Facebook, as a larger organization sometimes that's a positive thing. Sometimes there's ire that is directed at Facebook as an organization.
And as a similar example, my experience with Google and Microsoft as large organizations, particularly backing open-source efforts, has almost sort of swapped over time, where originally, Microsoft there was almost nothing of Microsoft's open-source efforts that I was using. And I saw them as this very different shape of a company that I probably wouldn't be that interested in. And then they have deeply invested in things like GitHub, and VS Code, and TypeScript, and tons of projects that suddenly I'm like, oh, actually, a lot of what I use in the world is coming from Microsoft. That's really interesting.
And at the same time, Google has kind of gone in the opposite direction for me. And I've seen some of their movements switch from like, oh Google the underdog to now they're such a large company. And so the idea that the cachet, as the question phrase, of a company is just this uniformly positive thing and that it's perhaps an unfair benefit I don't see that as actually true.
But actually, as a more pointed example of this, I recently chose Svelte over React, and that was a conscious choice. And I went back and forth on it a few times, if we're being honest, because Svelte is a much smaller community. It does not have the large organizational backing that React or other frameworks do. And there was a certain marketing effort that was necessary to raise it into my visibility and then for me to be convinced that there is enough there, that there is a team that will maintain it, and that there are reasons to choose that and continue with it. And I've been very happy with it as a choice.
But I was very conscious in that choice that I'm choosing something that doesn't have that large organizational backing. Because there's a nicety there of like, I trust that Facebook will probably keep investing in React because it is the fundamental technology of the front end of their platform. So yeah, it's not going to go anywhere. But I made the choice of going with Svelte. So it's an example of where the large organization didn't win out in my particular case. So I think marketing is a part of the work, a part of the conversation. It's part of communication. And so I am less negative on it, I think, than the question perhaps was framed, but as always, it depends.
STEPH: Yeah, I'm trying to think of a scenario where I would be concerned about the fact that I'm using open source that's backed by a specific large company or corporation. And the main scenario I can think of is what happens when you conflict or if you have values that conflict with a company that is sponsoring that project? So if you are using an open-source project, but then the main community or the company that then works on that project does something that you really disagree with, then what do you do? How do you feel about that situation? Do you continue to use that open-source project? Do you try to use a different open-source project?
And I had that conversation frankly with myself recently, thinking through what to do in that situation and how to view it. And I realize this may not be how everybody views it, and it's not appropriate for all situations. But I do typically look at open-source projects as more than who they are backed by, but the community that's actively working on that project and who it benefits. So even if there is one particular group that is doing something that I don't agree with, that doesn't necessarily mean that wholesale I no longer want to be a part of this community. It just means that I still want to be a part, but I still want to share my concerns that I think a part of our community is going in a direction that I don't agree with or I don't think is a good direction.
That's, I guess, how I reason with myself; even if an open-source project is backed by someone that I don't agree with, either one, you can walk away. That seems very complicated, depending on your dependencies. Or two, you find ways to then push back on those values if you feel that the community is headed in a direction that you don't agree with. And that all depends on how comfortable you are and how much power you feel like you have in that situation to express your opinion. So it's a complicated space.
CHRIS: Yeah, that is a super subtle edge case of all of this. And I think I aligned with what you said of trying to view an open-source project as more generally the community that's behind it as opposed to even if there's a strong, singular organization behind it. But that said, that's definitely a part of it. And again, it's a double-edged sword. It's not just, oh, giant company; this is great. That giant company now has to consider this.
And I think in the case of Facebook and React, that is a wonderful hiring channel for them. Now all the people that use React anywhere are like, "Oh man, I could go work at Facebook on React? That's exciting." That's a thing that's a marketing tool from a hiring perspective for them. But it cuts both ways because suddenly, if the mindshare moves in a different direction, or if Facebook as an organization does something complicated, then React as a community can start to shift away. Maybe you don't move the current project off of it, but perhaps you don't start the next one with it. And so, there are trade-offs and considerations in all directions. And again, it depends.
STEPH: Yeah. I think overall, the thing that doesn't depend is marketing matters. It is a real part of the ecosystem, and it will influence our decisions. And so, just circling back to Thom's question, I think it does play a vital role in the choices that we make.
CHRIS: Way to stick the landing.
STEPH: Thanks.
Mid-roll Ad
And now a quick break to hear from today's sponsor, Scout APM.
Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more.
Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform.
See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed.
STEPH: Changing topics just a bit, what's new in your world?
CHRIS: Well, we had what I would call a mini perfect storm this week. We broke the build but in a pretty solid way. And it was a little bit difficult to get it back under control. And it has pushed me ever so slightly forward in my desire to have a fully optimized CI and deploy pipeline. Mostly, I mean that in terms of ratcheting. I'm not actually going to do anything beyond a very small set of configurations.
But to describe the context, we use pull requests because that's the way that we communicate. We do code reviews, all that fun stuff. And so there was a particular branch that had a good amount of changes, and then something got merged. And this other pull request was approved. And that person then clicked the rebase and merge button, which I have configured the repository, so that merge commits are not allowed because I'm not interested in that malarkey in our history. But merge commits or rebase and merge. I like that that makes sense.
In this particular case, we ran into the very small, subtle edge case of if you click the rebase and merge button, GitHub is now producing a new commit that did not exist before, a new version of the code. So they're taking your changes, and they are rebasing them onto the current main branch. And then they're attempting to merge that in. And A, that was allowed. B, the CI configuration did not require that to be in a passing state. And so basically, in doing that rebase and merge, it produced an artifact in the build that made it fail. And then attempting to unwind that was very complicated.
So basically, the rebase produced...there were duplicate changes within a given file. So Git didn't see it as a conflict because the change was made in two different parts of the file, but those were conflicting changes. So Git was like, this seems like it's fine. I can merge this, no problem. But it turns out from a functional perspective; it did not work. The build failed. And so now our main branch was failing and then trying to unwind that it just was surprisingly difficult to unwind that. And it really highlighted the importance of keeping the main branch green, keeping the build always passing. And so, I configured a few things in response to this. There is a branch protection rule that you can enable.
And let me actually pull up the specific configuration that I set up. So I now have enabled require status checks to pass before merging, which, if we're being honest, I thought that was the default. It turns out it was not the default. So we are now requiring status checks to pass before merging. I'm fully aware of the awkward, painful like, oh no, the build is failing but also, we have a bug. We need to deploy this. We must get something merged in.
So hopefully, if and when that situation presents itself, I will turn this off or somehow otherwise work around it. But for now, I would prefer to have this as a yeah; this is definitely a configuration we want. So require status checks to pass before merging and then require branches to be up to date before merging. So the button that does the rebase and merge, I don't want that to actually do a rebase on GitHub. I want the branch to already be up to date. Basically, I only ever want fast-forward merges on our main branch. So all code should be ahead of main, and we are simply updating what main points at. We are not creating new code. That code has run on CI, that version of the code specifically. We are fully rebased and up to date on top of main, and that's how we're going.
STEPH: All of that is super interesting. I have a question about the workflow. I want to make sure I'm understanding it correctly. So let's say that I have issued a PR, and then someone else has merged into the main branch. So now my PR is behind me, and I don't have that latest commit. With the new configuration, can I still use the rebase and merge, or will I need to rebase locally and then push up my branch before I can merge into main but at least using the GitHub UI?
CHRIS: I believe that you would be forced to rebase locally, force push, and then CI would rebuild, and that's what it is. So I think that's what require branches to be up to date before merging means. So that's my hope. That is the intention here. I do realize that's complicated. So this requirement, which I like, because again, I really want the idea that no, no, no, we, the developers, are in charge of that final state. That final state should always run as part of a build of CI on our pull request/branch before going into main. So no code should be new. There should be no new commits that have never been tested before going into main. That's my strong belief. I want that world. I realize that's...I don't know. Maybe I'm getting pedantic, or I'm a micromanager of the Git history or whatever. I'm fine with any of those insults that people want to lob at me. That's fine. But that's what I feel.
That said, this is a nuisance. I'm fully aware of that. And so imagine the situation where we got a couple of different things that have been in flight. People have been working on different...say there are three pull requests that are all coming to completion at the same time. Then you start to go to merge something, and you realize, oh no, somebody else just merged. So you rebase, and then you wait for CI to build. And just as the CI is completing, somebody else merges something, and you're like, ah, come on. And so then you have to one more time rebase, push, wait for the build to be green. So I get that that is not an ideal situation.
Right now, our team is three developers. So there are a few enough of us that I feel like this is okay. We can manage this via human intervention and just deal with the occasional weight. But in the back of my mind, of course, I want to find a better solution to this. So what I've been exploring…there's a handful of different utilities that I'm looking at, but they are basically merged queues as an idea. So there are three that I'm looking at, or maybe just two, but there's mergify.io, which is a hosted solution that does this sort of thing. And then Shopify has a merge queue implementation that they're running.
So the idea with this is when you as a developer are ready to merge something, you add a label to it. And when you add that label, there's some GitHub Action or otherwise some workflow in the background that sees that this has happened and now adds it to a merge queue. So it knows all of the different things that might want to be merged. And this is especially important as the team grows so that you don't get that contention. You can just say, "Yes, I would like my changes to go out into production." And so, when you label it, it then goes into this merge queue. And the background system is now going to take care of any necessary rebases. It's going to sequence them, so it's not just constantly churning all of the branches. It's waiting because it knows the order that they're ideally going to go out in.
If CI fails for any of them because rebasing suddenly, you're in an inconsistent state; if your build fails, then it will kick you out of the merge queue. It will let you know. So it will send you a notification in some manner and say, "Hey, hey, hey, you got to come look at this again. You've been kicked out of the merge queue. You're not going to production." But ideally, it adds that layer of automation to, frankly, this nuisance of having to keep things up to date and always wanting code to be run on CI and on a pull request before it gets into main. Then the ideal version is when it does actually merge your code, it pings you in Slack or something like that to say, "Hey, your changes just went out to production." Because the other thing I'm hoping for is a continuous deployment.
STEPH: The idea of a merge queue sounds really interesting. I've never worked with a process like that. And one of the benefits I can see is if I know I'm ready for something to go like if I'm waiting on a green build and I'm like, hey, as soon as this is green, I'd really like for it to get merged. Then currently, I'm checking in on it, so I will restart the build. And then, every so often, I'm going back to say, "Okay, are you green? Are you green? Can I emerge?" But if I have a merge queue, I can say, "Hey, merge queue, when this is green, please go and merge it for me." If I'm understanding the behavior correctly, that sounds really nifty.
CHRIS: I think that's a distinct but useful aspect of this is the idea that when you as a developer decide this PR is ready to go, you don't need to wait for either the current build or any subsequent builds. If there are rebases that need to happen, you basically say, "I think this code's good to go. We've gotten the necessary approvals. We've got the buy-in and the teams into this code." So cool, I now market as good. And you can walk away from it, and you will be notified either if it fails to get merged or if it successfully gets merged and deployed. So yes, that dream of like, you don't have to sit there watching the pot boil anymore.
STEPH: Yeah, that sounds nice. I do have to ask you a question. And this is related to one of the blog posts that you and I love deeply and reference fairly frequently. And it's the one that's written by German Velasco about Say No to More Process, and Say Yes to Trust. And I'm wondering, based on the pain that you felt from this new commit, going into main and breaking the main build, how do you feel about that balance of we spent time investigating this issue, and it may or may not happen again, and we're also looking into these new processes to avoid this from happening? I'm curious what your thought process is there because it seems like it's a fair amount of work to invest in the new process, but maybe that's justified based on the pain that you felt from having to fix the build previously.
CHRIS: Oh, I love the question. I love the subtle pushback here. I love this frame of mind. I really love that blog post. German writes incredible blog posts. And this is one that I just keep coming back to. In this particular case, when this situation occurred, we had a very brief...well, it wasn't even that brief because actually unwinding the situation was surprisingly painful, and we had some changes that we really wanted to get out, but now the build was broken. And so that churn and slowdown of our build pipeline and of our ability to actually get changes out to production was enough pain that we're like, okay, cool.
And then the other thing is we actually all were in agreement that this is the way we want things to work anyway, that idea that things should be rebased and tested on CI as part of a pull request. And then we're essentially only doing fast-forward merges on the main branch, or we're fast forward merging main into this new change. That's the workflow that we wanted. So this configuration was really just adding a little bit of software control to the thing that we wanted. So it was an existing process in our minds. This is the thing we were trying to do. It's just kind of hard to keep up with, frankly. But it turns out GitHub can manage it for us and enforce the process that we wanted. So it wasn't a new process per se. It was new automation to help us hold ourselves to the process that we had chosen.
And again, it's minimally painful for the team given the size that we're at now, but I am looking out to the future. And to be clear, this is one of the many things that fall on the list of; man, I would love to have some time to do this, but this is obviously not a priority right now. So I'm not allowed to do this. This is explicitly on the not allowed to touch list, but someday. I'm very excited about this because this does fundamentally introduce some additional work in the pipeline, and I don't want that.
Like you said, is this process worth it for the very small set of times that it's going to have a bad outcome? But in my mind, the better version, that down the road version where we have a merge queue, is actually a better version overall, even with just a tiny team of three developers that are maybe never even conflicting in our merges, except for this one standout time that happens once every three months or whatever. This is still nicer. I want to just be able to label a pull request and walk away and have it do the thing that we have decided as a team that we want. So that's the dream.
STEPH: Oh, I love that phrasing, to label a pull request and be able to walk away. Going back to our marketing, that really sells that merge queue to me. [laughs]
Mid-roll Ad
And now we're going to take a quick break to tell you about today's sponsor, Orbit. Orbit is mission control for community builders. Orbit offers data analytics, reporting, and insights across all the places your community exists in a single location. Orbit's origins are in the open-source and developer relations communities. And that continues today with an active open-source culture in an accessible and documented API.
With thousands of communities currently relying on Orbit, they are rapidly growing their engineering team. The company is entirely remote-first with team members around the world. You can work from home, from an Orbit outpost in San Francisco or Paris, or find yourself a coworking spot in your city.
The tech stack of the main orbit app is Ruby on Rails with JavaScript on the front end. If you're looking for your next role with an empathetic product-driven team that prides itself on work-life balance, professional development, and giving back to the larger community, then consider checking out the Orbit careers page for more information. Bonus points if working in a Ruby codebase with a Ruby-oriented team gives you a lot of joy. Find out more at orbit.love/weloveruby.
CHRIS: To be clear, and this is to borrow on some of Charity Majors' comments around continuous deployment and whatnot, is a developer should stay very close to the code if they are merging it. Because if we're doing continuous deployment, that's going to go out to production. If anything's going to happen, I want that individual to be aware. So ideally, there's another set of optimizations that I need to make on top of this. So we've got the merge queue, and that'll be great. Really excited about that.
But if we're going to lean into this, I want to optimize our CI pipeline and our deployment pipeline as much as possible such that even in the worst case where there's three different builds that are fighting for contention and trying to get out, the longest any developer might go between labeling a pull request and saying, "This is good to go," and it getting out to production, again, even if they're contending with other PRs, is say 10, 15 minutes, something like that.
I want Slack to notify them and them to then re-engage and keep an eye on things, see if any errors pop up, anything like that that they might need to respond to. Because they're the one that's got the context on the code at that point, and that context is decaying. The minute you've just merged a pull request and you're walking away from that code, the next day, you're like, what did I work on? I don't remember that at all. That code doesn't exist anymore in my brain. And so,,, staying close to that context is incredibly important.
So there's a handful of optimizations that I've looked at in terms of the CircleCI build. I've talked about my not rebuilding when it actually gets fast-forward merged because we've already done that build on the pull request. I'm being somewhat pointed in saying this has to build on a pull request. So if it did just build on a pull request, let's not rebuild it on main because it's identically the same commit. CircleCI, I'm looking at you. Give me a config button for that, please. I would really love that config button.
But there are a couple of other things that I've looked at. There's RSpec::Retry from NoRedInk, which will allow for some retry semantics. Because it will be really frustrating if your build breaks and you fall out of the merge queue. So let's try a little bit of retry logic on there, particularly around feature specs, because that's where this might happen.
There's Knapsack Pro which is a really interesting thing that I've looked at, which does parallelization of your RSpec test suite. But it does it in a different way than say Circle does. It actually runs a build queue, and each test gets sent over, and they have build agents on their side. And it's an interesting approach. I'm intrigued. I think it could use some nice speed-ups. There's esbuild on the Heroku side so that our assets build so much more quickly. There are lots of things. I want to make it very fast. But again, this is on the not allowed to do it list. [laughs]
STEPH: I love how most of the world has a to-do list, and you have this not-allowed to-do list that you're adding items to. And I'm really curious what all is on the not allowed to touch lists or not allowed to-do list. [laughs]
CHRIS: I think this might be inherent to being a developer is like when I see a problem, I want to fix it. I want to optimize it. I want to tweak it. I want to make it so that that never happens again. But plenty of things...coming back to German's post of Say No to More Process, some things shouldn't be fixed, or the cost of fixing is so much higher than the cost of just letting it happen again and dealing with it manually at that moment.
And so I think my inherent nature as a developer there's a voice in my head that is like, fix everything that's broken. And I'm like, sorry. Sorry, brain, I do not have that kind of time. And so I have to be really choosy about where the time goes. And this extends to the team as well. We need to be intentional around what we're building. Actually, there's a feeling that I've been feeling more acutely than ever, but it's the idea of this trade-off or optimization between speed and getting features out into the world and laying the right fundamentals. We're still very early on in this project, and I want to make sure we're thinking about things intentionally.
I've been on so many projects where it's many years after it started and when I ask someone, "Hey, why do your background jobs work that way? That's a little weird." And they're like, "Yeah, that was just a thing that happened, and then it never changed. And then, we copied it and duplicated, and that pattern just got reinforced deeply within the app. And at this point, it would cost too much to change." I've seen that thing play out so many times at so many different organizations that I'm overwhelmed with that knowledge in the back of my head. And I'm like, okay, I got to get it just right.
But I can't take the time that is necessary to get it, quote, unquote, "Just right." I do not have that kind of time. I got to ship some features. And this tension is sort of the name of the game. It's the thing I've been doing for my entire career. But now, given the role that I have with a very early-stage startup, I've never felt it more acutely. I've never had to be equally as concerned with both sides of that. Both matter all the more now than they ever have before, and so I'm kind of existing in that space.
STEPH: I really like that phrasing of that space because that deeply resonates with me as well. And that not allowed to-do list I have a similar list. For me, it's just called a wishlist. And so it's a wishlist that I will revisit every so often, but honestly, most things on there don't get done. And then I'll clear it out every so often when I feel it's not likely that I'm going to get to it. And then I'll just start fresh. So I also have a similar this is what I would like to do if I had the time.
And I agree that there's this inclination to automate as well. As soon as we have to do something that felt painful once, then we feel like, oh, we should automate it. And that's a conversation that I often have with myself is at what point is the cost of automation worthwhile versus should we just do this manually until we get to that point? So I love those nuanced conversations around when is the right time to invest further in this, and what is the impact? And what is the cost of it? And what are the trade-offs? And making that decision isn't always clear. And so I think that's why I really enjoy these conversations because it's not a clear rubric as to like, this is when you invest, and this is when you don't.
But I do feel like being a consultant has helped me hone those skills because I am jumping around to different teams, and I'm recognizing they didn't do this thing. Maybe they didn't address this or invest in it, and it's working for them. There are some oddities. Like you said, maybe I'll ask, "Why is this? It seems a little funky. What's the history?" And they'll be like, "Yeah, it was built in a hurry, but it works. And so there hasn't been any churn. We don't have any issues with it, so we have just left it." And that has helped reinforce the idea that just because something could be improved doesn't mean it's worthwhile to improve it.
Circling back to your original quest where you are looking to improve the process for merging and ensuring that CI stays green, I do like that you highlighted the fact that we do need to just be able to override settings. So that's something that has happened recently this week for me and my client work where we have had PRs that didn't have a green build because we have some flaky tests that we are actively working on. But we recognize that they're flaky, and we don't want that to block us. I'm still shipping work. So I really appreciate the consideration where we want to optimize so that everyone has an easy merging experience. We know things are green. It's trustworthy. But then we also have the ability to still say, "No, I am confident that I know what I'm doing here, and I want to merge it anyways, but thank you for the warning."
CHRIS: And the constant pendulum swing of over-correcting in various directions I've experienced that. And as you said, in the back of my mind, I'm like, oh, I know that this setting I'm going to need a way to turn this setting off. So I want to make sure that, most importantly, I'm not the only one on the team who can turn that off because the day that I am away on vacation and the build is broken, and we have a critical bug that we need to fix, somebody else needs to be able to do that. So that's sort of the story in my head.
At the same time, though, I've worked on so many teams where they're like, oh yeah, the build has been broken for seven weeks. We have a ticket in the backlog to fix that. And it's like, no, the build has to not be broken for that long. And so I agree with what you were saying of consulting has so usefully helped me hone where I fall on these various spectrums. But I do worry that I'm just constantly over-correcting in one direction or the other. I'm never actually at an optimum. I am just constantly whatever the most recent thing was, which is really impacting my thinking on this. And I try to not do that, but it's hard.
STEPH: Oh yeah. I'm totally biased towards my most recent experiences, and whatever has caused me the most pain or success recently. I'm definitely skewed in that direction.
CHRIS: Yeah, I definitely have the recency bias, and I try to have a holistic view of all of the things I've seen. There's actually a particular one that I don't want to pat myself on the back for because it's not a good thing. But currently, our test suite, when it runs, there's just a bunch of noise. There's a bunch of other stuff that gets printed out, like a bunch of it. And I'm reminded of a tweet from Kevin Newton, a friend of the show, and I just pulled it up here. "Oh, the lengths I will go to avoid warnings in my terminal, especially in the middle of my green dots. Don't touch my dots." It's a beautiful beauty. He actually has a handful about the green dots. And I feel this feel.
When I run my test suite, I just want a sea of green dots. That's all I want to see. But right now, our test suite is just noise. It's so much noise. And I am very proud of...I feel like this is a growth moment for me where I've been like, you know what? That is not the thing to fix today. We can deal with some noise amongst the green dots for now. Someday, I'm just going to lose it, and I'm going to fix it, and it's going to come back to green dots. [chuckles]
STEPH: That sounds like such a wonderful children's book or Dr. Seuss. Oh, the importance of green dots or, oh, the places green dots will take you.
CHRIS: Don't touch my dots. [laughter]
STEPH: Okay. Maybe a slightly aggressive Dr. Seuss, but I still really like it.
CHRIS: A little more, yeah.
STEPH: On that note of our love of green dots, shall we wrap up?
CHRIS: Let's wrap up. The show notes for this episode can be found at bikeshed.fm.
STEPH: This show is produced and edited by Mandy Moore.
CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes, as it really helps other folks find the show.
STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari.
CHRIS: And I'm @christoomey
STEPH: Or you can reach us at hosts@bikeshed.fm via email.
CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week.
All: Byeeeeeee!!!
Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.Sponsored By:Scout: Scout APM is leading-edge application performance monitoring designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise-platform feature bloat.
With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve performance abnormalities -- like N+1 queries, slow database queries, memory bloat, and more.
Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them.
Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform.
See for yourself why developers worldwide call Scout their best friend and try our error monitoring and APM free for 14-days, no credit card needed!
And as an added bonus for Bikeshed listeners: Scout will donate $5 to the open-source project of your choice when you deploy.
Learn more at scoutapm.com/bikeshed.Orbit: Orbit is mission control for community builders. Orbit offers data analytics, reporting, and insights across all the places your community exists in a single location. Orbit’s origins are in the open-source and developer relations communities, and that continues today with an active open-source culture and an accessible and documented API.
With thousands of communities currently relying on Orbit, they are rapidly growing their engineering team. The company is entirely remote-first with team members around the world. You can work from home, from an Orbit “outpost” in San Francisco or Paris, or find yourself a co-working spot in your city.
The tech stack of the main Orbit app is Ruby on Rails with JavaScript on the frontend. If you are looking for your next role with an empathetic, product-driven team that prides itself on work-life balance, professional development, and giving back to the larger community then consider checking out the Orbit careers page for more information. Bonus points if working in a Ruby codebase with a Ruby-oriented team gives you a lot of joy.
Find out more at orbit.love/weloveruby.Support The Bike Shed

Sep 28, 2021 • 39min
310: Schedule Shut Down, Complete
Chris talks feature flags featuring Flipper (Say that 3x fast!), and Steph talks reducing stress by a) having a work shutdown ritual and b) the fact that thoughtbot is experimenting with half-day Fridays. (Fri-yay?)
Flipper
Drastically Reduce Stress with a Work Shutdown Ritual
Iceland's Journey to a Short Working Week
Burnout: The Secret to Unlocking the Stress Cycle
Transcript:
STEPH: Hey, do you know that we could have an in-person recording at the end of October?
CHRIS: I do. Yes, I'm planning. That is in the back of my head. I guess I hadn't said that to you yet. But I'm glad that we have separately had the same conversation, and we've got to figure that out, although I don't know how to do noise cancellation and whatnot in the room. [laughs] How do we...we'll have to figure it out. Like, put a blanket in between us but so that we can see across it, but it absorbs sound in the middle. It's weird. I don't know how to do stuff. Just thinking out loud here.
STEPH: We'll just be in the same place but still different rooms. So it'll feel no different.
[laughter]
Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Steph Viccari.
CHRIS: And I'm Chris Toomey.
STEPH: And together, we're here to share a bit of what we've learned along the way. Hey, Chris, what's new in your world?
CHRIS: Feature flags. Feature flags are an old favorite, but they have become new again in the application that I'm working on. We had a new feature that we were building out. But we assumed correctly that it would be nice to be able to break it apart into smaller pieces and sort of deliver it incrementally but not necessarily want to expose that to our end users. And so, we opted with that ticket to bring along the feature flag system.
So we've introduced Flipper, in particular, which is a wonderful gem; it does the job. We're using the ActiveRecord adapter. All that kind of makes sense, happy about that. And so now we have feature flags. But it was one of those mindset shifts where the minute we got feature flags, I was like, yes, okay, everything behind a feature flag. And we've been leaning into that more and more, and it really is so nice and so freeing, and so absolutely loving it so far.
STEPH: I'm intrigued. You said, "Everything behind a feature flag." Like, is it really everything or? Yeah, tell me more.
CHRIS: Not everything. But at this point, we're still very early on in this application, so there are fundamental facets of the platform, different areas of what users can do. And so the actual stuff that works and is wired up is pretty minimal, but we want to have a little more surface area built out in the app for demo purposes, for conversations that are happening, et cetera.
And so, we built out a bunch of new pages to represent functionality. And so there are sidebar links, and then the actual page itself, and routing, and all of the things that are associated with that, and so all of those have come in. I think there are five new top-level nav sections of the platform that are all introduced behind a feature flag right now. And then there's some new functionality within existing pages that we've put behind feature flags. So it's not truly every line of code, but it's basically the entry point to all new major features we're putting behind a feature flag.
STEPH: Okay, cool. I'm curious. How are you finding that in terms of does it feel manageable? Do you feel like anybody can go into the UI and then turn on feature flags for demos and feel confident that they know what they're turning on and off?
CHRIS: We haven't gotten to that self-serve place. At this point, the dev team is managing the feature flags. So on production, we have an internal group configured within Flipper. So we can say, "Ship this feature for all internal users so that we can do testing." So there is a handful of us that all have accounts on production. And then on staging, we have a couple of representative users that we've been just turning everything on for so that we know via staging we can act as that user and then see the application with all of the bells and whistles.
Down the road, I think we're going to get more intentional with it, particularly the idea of a demo account. That's something that we want to lean into. And for that user, we'll probably be turning on certain subsets of the feature flags. I think we'll get a little more granular in how we think about that. For now, we're not as detailed in it, but I think that is something that we want to expand as we move forward.
STEPH: Nice. Yeah, I was curious because feature flags came up in our recent retro with the client team because we've gotten to a point where our feature flags feel complex enough that it's becoming challenging and not just from the complexity of the feature flags but also from the UI perspective. Where it feels challenging for users to understand how to turn a feature on, exactly what that impacts, and making sure that then they're not changing developer-focused feature flags, so those are the feature flags that we're using to ship a change but then not turn it on until we're ready. It is user-facing, but it's something that should be managed more by developers as to when we turn it on or off. So I was curious to hear that's going for you because that's something that we are looking into.
And funnily enough, you asked me recently, "Why aren't y'all using Flipper?" And I didn't have a great answer for you. And that question came up again where we looked at each other, and we're like, okay, we know there was a really good reason we didn't use Flipper when we first had this discussion. But none of us can remember, or at least the people in that conversation couldn't remember. So now we're asking ourselves the question of we've made it this far. Is it time to bring in Flipper or another service? Because we're getting to the point that we're starting to build too much of our own feature flag system.
CHRIS: So did you uncover an answer, or are you all just agreeing that the question makes sense?
STEPH: Agreeing that the question makes sense. [laughs]
CHRIS: That's the first step on a long journey to switching from internal tooling to somebody else managing that for you.
STEPH: Yeah, because none of us could remember exactly. But it was funny because I was like, am I just forgetting something here when you asked me that? So I felt validated that others were like, "Oh yeah, I remember that conversation. But I too can't recall why we didn't want to use Flipper in the moment or a similar service."
CHRIS: I'll definitely be interested to hear if you do end up trying to migrate off to another system or find a different approach there or if you do stick with the current configuration that you have. Because those projects they're the sort of sneaky ones that it's like, oh, we've been actually relying on this for a while. It's a core part of our infrastructure, and how we do the work, and the process, and how we deploy. That's a lot. And so, to switch that out in-flight becomes really difficult. It's one of those things where the longer it goes on, the harder it is to make that change. But at some point, you sometimes make the decision to make it. So I will be very interested to hear if you do make that decision and then, if so, what that changeover process looks like.
STEPH: Yeah, totally. I'll be sure to keep you up to date as we make any progress or decisions around feature flags.
CHRIS: But yeah, your questions around management and communication of it that is a thing that's in the back of my mind. We're still early enough in our usage of it, and just broadly, how we're working, we haven't really felt that pain yet, but I expect it's coming very soon. And in particular, we have functionality now that is merged and is part of the codebase but isn't fully deployed or fully released rather. That's probably the correct word. We have not fully released this functionality, and we don't have a system right now for tracking that.
So I'm thinking right now we're using Trello for product management. I'm thinking we want another column that is not entirely done but is tracking the feature flags that are currently in flight and just use that as a place to gather communication. Do we feel like this is ready? Let's dial this up to 50%, or let's enable it for this beta group or whatever it is to sort of be able to communicate that. And then ideally, also as a way to track these are the ones that are active right now. You know what? We feel like this one's ready. So do the code change so that we no longer use the feature flag, and then we can actually turn it off. Currently, I feel like I can defer that for a little while, but it is something that's in the back of my mind.
And then, of course, I nerd sniped myself, and I was like, all right, how do I grep the codebase for all the feature flags that we're using? Okay. There are a couple of different patterns as to how we're using…You know what? I think I actually need an AST-based parser here, and I need to use the Visitor...You know what? Never mind. Stop it. Stop it. [laughs] It was one of those where I was like...I was doing this not during actual work hours. It was just a question in my mind, and then I started to poke at it. I was like, oh, this could be fun. And then I was like, no, no, no, stop it. You need to go read a book or something. Calm down.
STEPH: As part of the optimization around our feature flag system that we've created, we've added a few enhancements, which I think is also one of the reasons we're starting to question how far we want to go in this direction. One of them is we want a very easy way to track what's turned on and what's turned off for an environment. So we have a task that will easily check, or it prints out a really nice list of these are all your flags, and this is the state that they're in. And by using the system that we have, we have one file that represents...well, you mentioned migration because we're migrating from the old system to this new one. So it's still a little bit in that space of where we haven't fully moved over. So now, moving over to a third thing like Flipper will be even more interesting because of that.
But the current system, we have a file that lists all the feature flags and a really nice description that goes with it, which I know is supported by Flipper and other services as well. But having that one file does make it nice where you can just scan through there and see what's in use. I really think it's the UI and the challenges that the users are facing and understanding what a feature flag does, and which ones they should turn off, and which ones they shouldn't touch that that's the point where we started questioning okay, we need to improve the UI.
But to improve the UI, do we really want to fully embrace our current system and make those improvements, or is now that time that we should consider moving to something else? Because Flipper already has a really nice UI. I think there is a free tier and a paid tier with Flipper, and the paid tier has a UI that ships.
CHRIS: There's definitely a distinct thing, Flipper Cloud, which is their hosted enterprise-y solution, and that's the paid offering. But Flipper just the core gem there's also Flipper web, I want to say is what it is, or Flipper UI. And I think it's an engine that you mount within your Rails app and that displays a UI so that you can manage things, add groups and teams. So we're definitely using that. I've got my eye on Flipper Cloud, but I have some fundamental questions around I like to keep my data in the system, and so this is an external other thing. And what's the synchronization? I haven't really even looked into it like that. But I love that Flipper exists within our application.
One of the niceties that Flipper Cloud does have is an audit history, which I think is interesting just to understand over time who changed what for what reasons? It's got the ability to roll back and maintain versions and whatnot. So there are some things in it that definitely look very interesting to me. But for now, the open-source, free version of Flipper plus Flipper UI has been plenty for us.
STEPH: That's cool. I didn't know about the audit feature.
CHRIS: Yeah. It definitely feels like one of those niceties to have for a more enterprise offering. So I could see myself talking me into it at some point but not quite yet. On that note though, so feature flags we introduced a week and a half, something like that, ago, and we've been leaning into them more and more. But as part of that, or in the back of my mind, I've wanted to go to continuous deployment.
So we had our first official retro this week. The project is growing up. We're becoming a lot of things. We used retro to talk about continuous deployment, all of these things that feel very real. Just to highlight it, retro is super important. And the fact that we haven't had one until now is mainly because up till now, it’s been primarily myself and another developer. So we've been having essentially one-on-ones but not a more formal retro that involves others.
At this point, we now have myself and two other developers that are working on the project, as well as someone who's stepped into the role of product manager. So we now have communication collaboration. How are we doing the work? How are we shipping features and communicating about bugs and all of that? So now felt like the right time to start having that more formal process. So now, every two weeks, we're going to have a retro, and hopefully, through that, retro will do the magic that retro can do at its best which is help us get better at all the things that we're doing.
But yeah, one of the core things in this particular one was talking about moving to continuous deployment. And so I am super excited to get there because I think, much like test-driven development, it's one of those situations where continuous deployment puts a lot of pressure on the development process. Everything that is being merged needs to be ready to go out into production. And honestly, I love that as a constraint because that will change how you build things. It means that you need to be a little more cautious. You can put something behind a feature flag to protect it. You decouple the idea of merging and deploying from releasing. And I like that distinction.
I think that's a really meaningful distinction because it makes you think about what's the entry point to this feature within the codebase? And it's, I think, actually really nice to have fewer and more intentional entry points into various bits of functionality such that if you actually want to shut it off in production, you can do that. That's more straightforward. I think it encourages an intentional coupling, maybe not a perfect decoupling but an intentional coupling within the system.
So I'm very excited to explore it. I think feature flags are going to be critical for it, and I think also observability, and monitoring, and logging, and all those things. We need to get really good at them so that if anything does go wrong when we just merge and deploy, we want to know if anything goes wrong as quickly as possible. But overall, I'm super excited about all of the other niceties that fall out of it.
STEPH: [singing] I wanna know what's turned on, and I want you to show me. Is that the song you're singing to Flipper? [laughs]
CHRIS: [laughs]
STEPH: Sorry, friends. I just had to go there.
CHRIS: That was just in your head. You had that, and you needed to get it out. I appreciate it. [laughter] Again, I got Flipper UI, so that's not the question I'm asking. I think that's the question you have in your heart.
STEPH: [laughs]
Mid-roll Ad
And now we're going to take a quick break to tell you about today's sponsor, Orbit. Orbit is mission control for community builders. Orbit offers data analytics, reporting, and insights across all the places your community exists in a single location. Orbit's origins are in the open-source and developer relations communities. And that continues today with an active open-source culture in an accessible and documented API.
With thousands of communities currently relying on Orbit, they are rapidly growing their engineering team. The company is entirely remote-first with team members around the world. You can work from home, from an Orbit outpost in San Francisco or Paris, or find yourself a coworking spot in your city.
The tech stack of the main orbit app is Ruby on Rails with JavaScript on the front end. If you're looking for your next role with an empathetic product-driven team that prides itself on work-life balance, professional development, and giving back to the larger community, then consider checking out the Orbit careers page for more information. Bonus points if working in a Ruby codebase with a Ruby-oriented team gives you a lot of joy. Find out more at orbit.love/weloveruby.
STEPH: That's funny about the CI deployment adding pressure to the development process because you're absolutely right. But I see it as such a positive and improvement that I don't really think about the pressure that it's adding. And I just think, yes, this is awesome, and I want this to happen and if there are steps that we have to take in that direction.
It dawned on me that what you said is very true, but I've just never really thought about it from that perspective about the pressure. Because I think the thing that does add more pressure for me is figuring out what can I deploy, or do I need to cherry-pick commits? What does that look like? And going through that whole cycle and stress is more stressful to me than figuring out how do we get to continuous deployments and making sure that everything is in a safe space to be deployed?
CHRIS: That's the dream. I'm going to see if I can live it. I'll let you know how it goes. But yeah, that's a bit of what's up in my world. What else is going on in your world other than some lovely singing?
STEPH: Oh, there's always lots of singing. It's been an interesting week. It's been a mix of some hiring work. Specifically, we are helping our client team build their development team. So we have been helping them implement a hiring process. And then also going through technical interviews and then going through different stages of that interview process. And that's been really nice. I haven't done that specifically for a client team where I helped them build a hiring pipeline from scratch and then also conduct those interviews.
And one thing that stood out to me is that rotations are really important to me and specifically that we don't ask for volunteers. So as we were having candidates come through and then they were ready to schedule an interview, then we are reaching out to the rest of the development team and saying, "Hey, we have this person. They're going to be scheduled at this time. Who's available? Who's interested? I'm looking for volunteers." And that puts pressure on people, especially someone that may be more empathetic to feel the need to volunteer. So then you can end up having more people volunteer than others.
So we've established a rotation to make sure that doesn't happen, and people are assigned as it becomes their next turn to conduct an interview. So that's been a lot of fun to refine that process and essentially make it easier. So the rest of the development team doesn't have to think about the hiring. But it still has an easy way of just saying, "Hey," and tapping someone to say, "Hey, it's your turn to run an interview."
The other thing I've been working out is figuring out how to measure an experiment. So we at thoughtbot are running an experiment where we're looking to address some of the concerns around sustainability and people feeling burned out. And so we have introduced half-day Fridays, more specifically 3.5 Fridays, as our half-day Fridays just to help everybody be certain about what a half-day looks like.
And then also, you can choose your half-day. Everybody works different schedules. We're across different time zones, so just to make sure it's really clear for folks and that they understand that they don't need to work more than those hours, and then they should have that additional downtime. And that's been amazing. This is the second Friday of the experiment, and we're doing this for nine Fridays straight.
And one of the questions that came up was, well, how do we know we did a good thing? How do we know that we helped people in terms of sustainability or addressing some of the feelings that they're having around burnout? And so I've collaborated with a couple of other thoughtboters to think through of a way to measure it. It turns out helping someone measure their wellness is incredibly complex. And so we went for a fairly simple approach where we're using an anonymous survey with a number of questions.
And those questions aren't really meant to stand up to scientific scrutiny but more to figure out how the team is feeling at the time that they fill out the survey and then also to understand how the reduced weekly hours have impacted their schedule. And are people working extra hours to then accommodate the fact that we now have these half Fridays? So do you feel pressured that because you can't work a full day on Friday that you are now working an extra hour or two Monday through Thursday to accommodate that time off? So that survey just went out today.
And one of the really interesting parts (I just haven't had to create content for a survey in a while.) was making sure that I'm not introducing leading questions or phrasing things in a very positive or negative light since that is a bias that then people will pick up on. So instead of saying, "I find it easy to focus at work," and then having like a multiple choice of true, always, never, that kind of thing, instead rephrasing the question to be, "Are you able to focus during work hours?" And then you have a scale there.
Or instead of asking someone how much energy they have, maybe it's something like, "Do you experience fatigue during the day?" Or instead of asking someone, "Are you stressed at work?" because that can have a more negative connotation. It may lead someone to feel more negatively as they are assessing that question. Then you can say, "How do you feel when you're at work?" And then you can provide those answers of I'm stressed, slightly stressed, neutral, slightly relaxed, and relaxed.
So it generated some interesting conversations around the importance of how we phrase questions and how we collect feedback. And I really enjoyed that process, and I'm really looking forward to seeing what folks have to say. And we're going to have three surveys total. So we have one that's early on in the experiment since we're only two Fridays in. We'll have one middle experiment survey go out, and then we'll have one at the end once we're done. And then hopefully, everybody's responses will then help us understand how the experiment went and then make a decision going forward.
I'll be honest; I’m really hoping that this becomes a trend and something that we stick with. It is a professional goal of mine to slowly reduce the hours that I work each week or quickly; it doesn't have to be slowly. But I really like the four-day workweek. It's something that I haven't done, but I've been reading about it a fair amount lately. I feel like I've been seeing more studies conducted recently becoming published, and it's just very interesting to me.
I had some similar concerns of how am I still going to be productive? My to-do list hasn't changed, but my hours are changing. So how am I still going to get everything done? And does it make sense for me to still get paid the same amount of money if I'm only working four out of the five days? And I had lots of questions around that, and the studies have been very enlightening and very positive in the outcome of a reduced workweek, not just for the individuals but for the companies as well.
CHRIS: It's such an interesting space and exploration. The way that you're framing the survey sounds really great. It sounds like you're trying to be really intentional around the questions that you're asking and not being leading and whatnot. That said, it is one of the historically hard problems trying to quantify this and trying to actually boil it down.
And there are so many different axes even that you're measuring on. Is it just increased employee happiness? Is it retention that you're talking about? Is it overall revenue? There are so many different things, and it's very tricky. I'm super interested to hear the results when you get those. So you're doing what sounds like more of a qualitative study like, how are you feeling? As opposed to a more quantitative sort of thing, is that right?
STEPH: Yes, it's more in the realm of how are you feeling? And are you working extra hours, or are you truly taking the time off?
CHRIS: Yeah, I think it's really hard to take something like this and try and get it into the quantitative space, even though like, oh yeah, if we could have a number, if it used to be two and now it's four, fantastic. We've doubled whatever that measure is. I don't know what the unit would be on this arbitrary number I made up. But again, that's the hard thing and probably not feasible at all. And so it makes sense the approach that you're taking. But it's super difficult. So I'm very interested to hear how that goes.
More generally, the four-day workweek thing is such a nice idea. We should do that more. I'm trying to think how long I did that. So during the period that I was working freelance, I think there were probably at least five months where I did just a true four-day workweek. Fridays were my own. It was fantastic. Granted, I recorded the podcast with you. But that day was mine to shape as I wanted.
And I found it was a really nice decompression period having that for a number of weeks in a row. And just getting to take care of personal stuff that I hadn't been and just having that extra little bit of space and time. And it really was wonderful. Now I'm working full five days a week, and my Fridays aren't even investment days, so I don't know what I'm doing over here.
But I agree. I really like that idea, and I think it's a wonderful thing. And it's, I don't know, sort of the promise of this whole capitalism adventure we're supposed to go on, increasing productivity. And wasn't this the promise the whole time, everybody, so I am intrigued to see it being explored more, to see it being discussed. And what you're talking about of it's not just good for the employees, but it's also great for the companies. You're getting people that are more engaged on the days that they're working, which feels very true to me.
Like, on a great day, I can do some amazing work. On a terrible day, I can do mediocre to bad work. It is totally possible for me to do something that is actively detrimental. Like, I introduce a bug that is going to impact a bunch of customers. And the remediation of that is going to take many more hours. That is totally a realistic thing. I think we often think of productivity in terms of are you at zero or some amount more than zero? But there is definitely another side of that. And so the cost of being not at your best is extremely high in my mind. And so anything we can do to improve that.
STEPH: There's a recent study from a non-profit company called Autonomy that published some research called Going Public: Iceland's Journey to a Shorter Working Week. It's very interesting. And a number of people in my social circle have shared it. And that's one of the reasons that I came across it. And they commented in there that one of the reasons...I hope I'm getting this right, but we'll link to it in case I've gotten it a bit wrong.
But one of the reasons that Iceland was interested or open to this idea of moving workers to a shorter workweek is because they were struggling with productivity and where people were working a lot of hours, but it still felt like their productivity was dropping. So then Autonomy ran this study to help figure out are there ways to improve productivity? Will shortening a workweek actually lead to higher productivity?
And there was a statement in there that I really liked where it talks about the more hours that we work; we’re actually lowering our per hour productivity which rings so true for me. Because I am one of those individuals where I'm very stubborn, and so if I'm stuck on something, I will put so many hours into trying to figure it out. But at some point, I have to just walk away, and if I do, I will solve it that much faster. But if I just try to use hours as my way to chip away at a problem, then that's not going to solve it. And my ability to solve that problem takes exponentially more time than if I had just walked away and then come back to the problem fresh and engaged.
And some of the case studies I admired the way that they tackled the problem. They would essentially pay the company. So the company could reduce the hours for certain employees so then they could run the experiment. So if they reduced employees to say 32 hours but the company didn't actually want to stop working at 32 hours and they wanted to keep going, so then they brought in other people to work the remaining eight hours. Then as part of that study, they would pay the company to help them stay at their current level of productivity or current level of hours. This way, they could conduct the study. And I thought that was a really neat idea.
I do have lots of questions still around the approach itself because it is how do you reduce your to-do list, essentially? So just because you dropped to a four-day workweek. So essentially, you have to just say less stuff gets done. Or, as these case studies promise, they're saying you're actually going to be more productive. So you will still continue to get a lot of your work done. I'm curious about that. I'd like to track my own productivity and see if I feel similarly.
And then also, who is this for? Is this for everybody? Does everybody get to move to a four-day workweek? Is this for certain companies? Is it for certain jobs? Ideally, this is for everybody because there are so many health benefits to this, but I'm just intrigued as to who this is for, who it impacts, how can we make it available for everyone? And is the dream real that I can work four days a week and still feel as productive, if not more productive, and healthier, and happier as I do when working five days a week?
Mid-roll Ad
And now a quick break to hear from today's sponsor, Scout APM.
Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more.
Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform.
See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed.
CHRIS: I remember there was an extended period where working remote was this unique benefit that some organizations had. They had adopted that mode. They were async, and remote, and all of these wonderful things. And it became this really interesting selling point for those companies. Now the pandemic obviously pushed public opinion and everything on that in a pretty significant way such that it's a much more common thing. And so, as a result, I think it's less of a differentiator now. It used to be a way to help with recruiting.
I wonder if there are organizations that are willing to take this, try it out, see that they are still close to as productive. But if it means that hiring is twice as easy, that is absolutely...especially if it is able to double your ability to hire, that is incredibly valuable or retention similarly. If you can increase retention or if you can make it easier to hire, the value of that is so, so high.
And it's interesting in my mind because there's sort of a gold rush on that. That's only true for as long as a four-day workweek is a unique benefit of working at the organization. If this is actually the direction that everything's going and eventually everyone's going to settle to that, then if you wait too long to get there, then you're going to miss all the benefits. You're going to miss that particular benefit of it.
And so I do wonder, would it be advantageous to organizations...I'm thinking about this now. Maybe this is the thing I have to do. But would it be advantageous to be that organization as early on as possible and try to get ahead of the curve and use that to hire more easily, retain more easily? Now that I say it all out loud, I'm sold. All right. I got to do this.
STEPH: Yeah, I think that's a great comparison of where people are going to start to look for those types of benefits. And so, if you are one of the early adopters and you have the four-day workweek or a reduced workweek in general, then people will gravitate towards that benefit. And it's something that people can use to really help with hiring and retention. And yeah, I love it.
You are CTO. So you have influence within your company that you could push for the four-day workweek if you think that's what you want to do. And I would be really intrigued to hear how that goes and how you feel if you...well, you've done it before where you've worked four days a week. So applying that to your current situation, how does that feel?
CHRIS: Now you're actually holding me accountable to the things that I randomly said in passing. But it's interesting. So we're so early stage, and there's so much small work to do. There's all…oh, got to set up a website. We've got to do this. We've got to build that integration. There's just kind of scrambling to be done.
And so there's a certain version in my mind that maybe we're in a period of time where additional hours are actually useful. There's a cost to them. Let's be clear about that. And so how long that will remain true, I'm not sure. I could see a point perhaps down the road where we achieve a little bit closer to steady-state maybe, who knows? It depends on how fast growth is and et cetera, a lot of other things.
So I'm not sure that I would actually lead with this experiment myself, given where the organization is at right now. But I could see an organization that's at a little bit more of a steady-state, that's growing more incrementally, that is trying to think really hard about things like hiring and retention. If those were bigger questions in my mind, then I think I would be considering this more pointedly. But for now, I'm like, I kind of just got to do a bunch of stuff. And so my brain is telling me a different story, but it is interesting. I want to interrogate that and be like, brain, why is that the story you have there, huh? Huh?
STEPH: I really appreciate what you're saying, though, because that makes sense to me. I understand when you are in that earlier stage, there's enough to do that that feels correct. Versus that added benefit of having a reduced workweek does benefit or could benefit larger companies who are looking to hire more heavily, or they're also concerned about retention or just helping their people address feelings of burnout. So I really appreciate that perspective because that also rings true.
So along this whole conversation around wellness and how we can help people work more sustainable hours, there's a particular book that I've read that I've been really excited to share and chat with you about. It's called Burnout: The Secret to Unlocking the Stress Cycle. It's written by two sisters, Emily and Amelia Nagoski. And they really talk through the impact that stress has on us and then ways to work through that.
And specifically, they talk about completing the stress cycle. And I found this incredibly useful for me because I have had weeks where I have just worked hard Monday through Friday. I've gotten to the end of my day Friday, and I'm like, great, I'm done. I've made it. I can just relax. And I walk away from work, and I can't relax. And I'm just like, I feel sick. I feel not good.
Like, I thought I would walk away from work, and I would just suddenly feel this halo of relaxation, and everything would be wonderful. But instead, I just feel a bit ill, and I've never understood that until I was reading their book about completing the stress cycle. Have you ever had moments like that?
CHRIS: It has definitely happened to me at various points, yes.
STEPH: That makes me feel better because I haven't really chatted about this with someone. So until I read this book and I was like, oh, maybe this is a thing, and it's not just me, and this is something that people are experiencing. So to speak more about completing the stress cycle, they really highlight that stress and feelings, capital F feelings, can cause physiological symptoms. And so it's not just something that we are mentally processing, but we are physically processing the stress that we feel.
And there's a really big difference between stressors and stress. So a stressor could be something like an unmeetable deadline. It could be family. It could be money concerns. It could be your morning commute, anything that increases your stress level. And during that, there's a very physical process that happens to your body anytime there's a perceived threat. And it's really helpful to us because it's frankly what triggers our fight, flight, or freeze response. And our bodies receive a rush of adrenaline and cortisol, which essentially, if we're using that flight response, that's going to help us run. And a number of the processes in our system will essentially go into a state of hibernation because everything in our body is very focused on helping us run or do the thing that we think is going to save our life in that moment.
The problem is our body doesn't know the difference between what's more of a mental threat versus what is a truly physical threat. So this is the difference between your stress and your stressors. So in more of a physical threat, if there's a lion that you are running from, that is the stressor, but then the stress is everything that you still feel after you have run from that lion.
So you encounter a lion, you run. You make it back to your group of people where you are safe, and you celebrate, and you dance, and you hug. And that is completing the stress cycle because you are essentially processing all of that stress. And you are telling your body in a body-focused language that I am safe now, and everything is fine. So you can move back, and anything that was in a hibernation state, all of that dump of adrenaline and cortisol can be worked out of your system, and everything can go back to a normal state.
Most of us aren't encountering lions, but we do encounter jerks in meetings or really stressful commutes. And whenever we have survived that meeting, or we've gotten through our commute to the other side, we don't have that moment of celebration where we really let our body know that hey, we've made it through that moment of stress, and we are away from that stressor, and we can actually process everything.
So if you're interested in this, the book's really great. It talks about ways that you can process that stress and how important it is to do so. Otherwise, it will literally build up in your system, and it can make you sick. And it will manifest in ways that will let us know that we haven't dealt with that stress.
And one of the top methods that they recommend is exercise and movement. That's a really great way to let your body know that you are no longer in an unsafe state, and your body can start to relax. There's also a lot of other great ways. Art is a really big one. It could be hugging someone. It could be calling someone that you love. There are a number of ways that you can process it. But I hadn't recognized how important it is that once you have removed yourself from a stressor, that doesn't necessarily just mean you're done, and you can relax. You actually have to go through that physical process, and then you can relax.
So I started incorporating that more into my day that when I'm done with work, I always find something to do, and it's typically to go for a walk, or it's go for a run. And I have found that now I really haven't felt that ill-feeling where I'm trying to relax, but I just feel sick. Saying that out loud, I feel like I'm a mess on Fridays. [chuckles]
CHRIS: I feel like you're human. It was interesting when you asked the question at the beginning. You were like, "Is this a thing that other people experience?" And my answer was certainly, yes; I have experienced this. I think there's something about me that I think is useful where I don't think I'm special at all on any axis whatsoever. And so whenever there's something that's going on, I'm like, I assume that this is just normal human behavior, which is useful because most of the time it is.
And this is the sort of thing where if I'm having a negative experience, I will look to the external world to be like, I'm sure other people have experienced this, and let me pull that in. And I've found that really useful for myself to just be like, I’m not special. There's nothing particularly special about me. So let me go look from the entirety of the internet where people have almost certainly talked about this. And I've not read the book that you're describing here, but it does sound like it does a great job of describing this.
There is a blog post that I found that has stayed in the back of my mind and informed a little bit of my day-to-day approach to this sort of thing which is a blog post by Cal Newport, who I think at this point we've mentioned him a handful of times on the show. But the title of the post is Drastically Reduce Stress with a Work Shutdown Ritual. And it's this very interesting little post where he talks about at the end of your day; you want to close the book on it. I think this is especially pointed now that many of us are working from home. For me, this is a new thing. And so, I've been very intentional with trying to put walks at the beginning and end of my day.
But in this particular blog post, he describes a routine that he does where he tidies things up and makes his list for the next day. And then he has a particular phrase that he says, which is "schedule shut down, complete." And it's a sort of nonsense phrase. It doesn't even quite make sense grammatically, but it's his phrase that he internalized, and somehow this became his almost mantra for the end of the day.
And now when he does it, that's like his all right, okay, turned off the brain, and now I can walk away. I know that I've said the phrase, and I only say the phrase when I have properly set things up. And so it's this weird structure that he's built in his mind. But it totally works to quiet those voices that are like, yeah, but what about…Do we think about…Do we complete…And he's got now this magic phrase that he can say. And so I've really loved that.
For myself, I haven't gotten quite to that level, but I've definitely built the here's how I wind down at the end of the day. Here's what I do with lists and what I do so that I can ideally walk away comfortably. Again, this is one of those situations where I sound like I know what I'm doing or have my act together. This is aspirational me.
Day-to-day me is a hot mess like everybody else. [laughs] And this is just what I...when I do this, I feel better. Most of the time, I don't do this because I forget it, or because I'm busy, or because I'm stressed, [chuckles], and so I don't do the thing that reduces stress, you know, human stuff. But I really enjoyed that post.
STEPH: I haven't heard that one. I like a lot of Cal Newport's work, but I haven't read that particular blog post. Yeah, I think the idea of completing the stress cycle has helped me tremendously because by giving it a name like completing the stress cycle has been really helpful for me because working out is important to me. It's something that I enjoy, but it's also one of those things that's easy to get bumped. It is part of my wellness routine. And so, if I'm really busy, then I will bump it from the list. And then it's something that then doesn't get addressed.
But recognizing that this is also important to my productivity, not to just this general idea of wellness, has really helped me recenter how important this is and to make sure that I recognize hey, it's been a stressful day. I need to get up and move. That is a very important part of my day. It is not just part of an exercise routine, but this is something that I need to do to close out my day to then make sure I have a great day tomorrow.
So bringing it back, it's been a week that's been filled with a lot of discussions around burnout and then ways that we can measure it and then also address it. And I've really enjoyed reading this book. So I'll be sure to drop a link in the show notes. On that note, shall we wrap up?
CHRIS: Schedule shut down, complete. The show notes for this episode can be found at bikeshed.fm.
STEPH: This show is produced and edited by Mandy Moore.
CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes, as it really helps other folks find the show.
STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari.
CHRIS: And I'm @christoomey
STEPH: Or you can reach us at hosts@bikeshed.fm via email.
CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week.
All: Byeeeeeeeeeee!!!
Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.Sponsored By:Orbit: Orbit is mission control for community builders. Orbit offers data analytics, reporting, and insights across all the places your community exists in a single location. Orbit’s origins are in the open-source and developer relations communities, and that continues today with an active open-source culture and an accessible and documented API.
With thousands of communities currently relying on Orbit, they are rapidly growing their engineering team. The company is entirely remote-first with team members around the world. You can work from home, from an Orbit “outpost” in San Francisco or Paris, or find yourself a co-working spot in your city.
The tech stack of the main Orbit app is Ruby on Rails with JavaScript on the frontend. If you are looking for your next role with an empathetic, product-driven team that prides itself on work-life balance, professional development, and giving back to the larger community then consider checking out the Orbit careers page for more information. Bonus points if working in a Ruby codebase with a Ruby-oriented team gives you a lot of joy.
Find out more at orbit.love/weloveruby.Scout: Scout APM is leading-edge application performance monitoring designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise-platform feature bloat.
With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve performance abnormalities -- like N+1 queries, slow database queries, memory bloat, and more.
Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them.
Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform.
See for yourself why developers worldwide call Scout their best friend and try our error monitoring and APM free for 14-days, no credit card needed!
And as an added bonus for Bikeshed listeners: Scout will donate $5 to the open-source project of your choice when you deploy.
Learn more at scoutapm.com/bikeshed.Support The Bike Shed

Sep 21, 2021 • 35min
309: Naming the Change
Steph talks about a new GitHub feature and Twitter account (@RubyCards) she's really excited about and Chris talks about his new job as a CTO of a startup and shifting away from writing code regularly.
GitHub
RubyCards
Resilient Management
The Manager's Path
Transcript:
CHRIS: Oh God, my computer is so stupid slow. I need a new computer.
STEPH: Come on, little computer, you can do it. You know you could just buy a new one. You don't have to wait for the fancy-schmancy M1.
CHRIS: I want to wait for the fancy. I want it so bad.
STEPH: [laughs]
CHRIS: Do you know how long I've had this computer? And if I can hold out one more month, I want the fancy stuff. I've waited this long. Why would I give in now when I'm right on the cusp of victory?
STEPH: One more month. I'm going to send you...as a kid, did you ever make those construction…
CHRIS: Oh yeah.
STEPH: They look like chain links bow construction paper. So we would make those for a countdown to special days. I'm going to send you one that's all crumpled and folded in the mail. It would be delightful. And you'll be able to snip off a little chain each day as your countdown to your new fancy-schmancy. [laughs]
CHRIS: I love it.
Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey.
STEPH: And I'm Steph Viccari.
CHRIS: And together, we're here to share a bit of what we've learned along the way. So, Steph, what's new in your world?
STEPH: Hey. Well, I just got back from vacation. So getting back to work is what's new in my world. And vacation is nice. I miss it already. But it's also nice to be back, and see everybody, and see what they've been up to.
CHRIS: I've heard wonderful things about vacation.
STEPH: Yeah. Have you had one recently? I know you've been quite busy.
CHRIS: I have. I think it's hard to tell, especially because everything just kind of blends together these days. But I think I took off a few days recently. I haven't had an extended vacation since much earlier on in the summer, I think. And so I think I'm due for one of those sometime in the not too distant future. But it's one of those things where you got to plan it. And you got to think ahead, and I haven't been doing that of late really with anything. So kind of living for the moment, but that's not how you take a vacation. So I got to rethink some strategies here. [chuckles]
STEPH: Yeah, I've been trying to schedule more vacation time just further out. Because then if I don't want to take it, like if I decide that I don't want the staycation or I don't need the day off, then I can just change my mind, and that's pretty easy to do. But I'm like you; if I don't plan it, then I don't feel like I have the energy to plan a vacation, and then it just doesn't happen. So I know that's one thing that I've been doing.
I've also been mentoring or coaching others, just checking in with them to say, "Hey, when's your next vacation? Have you scheduled any days off? Do you want to schedule a day off next month?" And saying that to other people has also been a very helpful reminder to me to do so.
CHRIS: Oh, I like that a lot as a recurring one-on-one question of, so what can you tell me about vacation? What do you got in the works there? Because that's the most important thing, [chuckles] which it kind of is. It's the way that we keep doing the work that we do.
STEPH: And I think so many people just haven't been taking a vacation. I mean, in 2020, we were all locked in and going through a pandemic, so then a lot of people weren't taking those breaks. And so part of it is just reminding people that even if you can't go somewhere, still please take some downtime and just know that you can step away from work and should step away from work.
But for us, we did go somewhere. So we went out to Seattle, which I've never...I've been out to the West Coast, but it's more like I've been out to L.A., Santa Monica. But this time, we went to the Northwest region. We went to Seattle, and we explored and did a lot of hiking and camping around the Northern Cascades and then Mount Rainier. And both of those are amazing. And I've never flown with camping gear, but that went really well. It worked out nice. We had an Airbnb every so often just for showers and having a roof over your head. That's really nice. But for most of the trip, we did a lot of camping and hiking.
CHRIS: That sounds like an awesome trip.
STEPH: Yeah, it was really cool. I'd love to go back to the Olympic National Park because there are just so many national parks that are around Seattle and in Washington that we couldn't begin to do it all. But Olympic National Park is still on my list. And I'm really grateful to have also seen the Northern Cascades and Mount Rainier.
But switching gears a bit, I have something that I'm really excited to share with you because I don't think you've seen it yet. I'm excited to find out if you have. But it's a new GitHub feature that came out, I think about a month ago, but there doesn't seem to have been much fanfare from GitHub about announcing this new feature. And I happened to find out through Twitter because someone else found it, and then they were really excited. And so now I think it's really gaining some more traction. But it still seems like one of those sneaky feature releases, but it's really cool.
So GitHub has added the ability to open up a web-based editor that allows you to view the source code for a repo, view it in syntax, highlighting, make a code change, and commit the change. And it's free for everybody. And there's a couple of ways to get there, but I'll pause there. Have you seen this yet? Have you interacted with it?
CHRIS: I think I've seen it and poked around ever so gently with it. I want to say this is GitHub Codespaces. Is that the name of this feature?
STEPH: Yep. That's it?
CHRIS: Yes. I poked around with it just a tiny bit, and I'm very excited about it. But it's very much in the like, huh, okay, cool; I’ll look at that someday down the road and figure out what I want to do with it. But have you actually dug into it particularly deeply?
STEPH: I used it to make a change for a personal project, just because I wanted to see the whole flow. So I went to a personal project, and there are two ways that you can open it up for anyone that hasn't seen this yet. So you can either press the period button that's on your keyboard, and that will open it up, or you can just alter the URL. So instead of github.com, replace that .com with .dev, and then that will also open up the browser.
And so I made a change to a personal project, and it worked really well, and it commits the change to main. And it was nice. It was easy. In my case, I was just making a change to make a change. I think I actually went to an older project where I was still using the underscore target to force users that when they clicked on a link that it opened a new tab, and I was like, perfect. This is a good thing to just change. And I could do it from my iPad. I didn't have to be at my computer. And it was really nifty. I was very impressed with it.
And they also mentioned that it's very easy to integrate your own VS Code settings and environment. I'm not a heavy VS Code user, so I haven't tried that. But I've heard really positive things about how easy it is to sync your settings between your local VS Code and then GitHub's editor. But overall, it was really easy to use.
CHRIS: That's super cool. My very limited understanding of it is like GitHub has had the ability to edit files and things like that for a while. But it was very much like a simple web editor where it's a big text box that happens to contain the code. And they've added some stuff for like browsing with syntax highlighting and even some context-aware show usage and things like that. But as far as I understand it, this is like a whole VS Code instance in the cloud that is running it.
And then I think what you're saying about you can have your VS Code settings in there, but even your project settings and the ability to run the tests, I'm not sure where the edges of it are. But my understanding with Codespaces it's like this is how your team can develop. Everyone gets one of these Codespaces. You're developing in the cloud. But it does VS Code remote sync type stuff. I'm very intrigued to see where it goes and that idea of...obviously, I like Vim. That's the thing that's probably known and true about me. So I will probably be one of the later adopters of this.
But the idea of being able to bottle up the development environment for your projects and have those settings, and the ability to run the test and all of that packaged up as part of the repository, and then allow people to run with that, especially in the cloud, and be able to carry that with them as they move around, that's really intriguing. And the idea of having this very easy on-ramp, especially for open-source projects and things like that. If you want people to be able to contribute easily but with the linting, and the configuration, and the settings, and all the stuff, well, now you can have that packaged up. And that is very interesting to me.
So I'm super intrigued to see where it goes. Again, I will probably be one of the later adopters of this platform for reasons. But I am super interested, and I continue to like...the work with VS Code is so interesting in the way it keeps expanding out and the language server stuff and now the Codespaces stuff. And it's super interesting developments across the board.
STEPH: Yeah, I'm with you. I don't actually see this replacing my current development that I do day-to-day, but it's more generally nice to have access. So if I needed to make a change and I don't have my laptop or if it's just something small and I don't want to have to go through…I guess essentially, if I don't have my laptop, but I wanted to make a change, then I could do this realistically from something that doesn't have my full local dev setup.
I don't know if you have the ability to run tests. I didn't explore that far as to whether you can actually have access to run those types of commands or processes. I did see some additional notes while reading through GitHub's documentation about this new editor. And they included some notes that talk about how the editor runs entirely in your browser's sandbox. So it doesn't actually clone the repo, but instead, it loads your code by invoking the services API directly from the browser. So then your work is saved in the browser's local storage until you commit it, and then you can persist your changes by then committing it back to the repo.
And because there's no associated compute, you won't be able to build and run your code or use the integrated terminal. Ah, I think that actually answers the question about running tests. So only a subset of extensions can run in the web will appear in the extensions panel and can be installed. So this does impose certain limitations for particular programming languages and full functionality, things that we may need like running tests.
CHRIS: Interesting. That now puts it back more on the uncanny valley for me where it's like, oh, it's just VS Code, except it can't do a bunch of the stuff. So yeah, I'll probably be hanging out in Vim for a while. But again, I'm super interested to see where they can push this and what the browser platform allows, and then how they're able to leverage that and so on and so forth.
STEPH: There is one flow that I was testing out because I was reading someone else mentioned that not only can you use this for looking at source code and then changing that source code but also for a pull request. And so I went to a pull request and changed the URL to dev. And I do have the ability to make changes, but I'm not quite sure if I could commit my changes and if that would go to the branch or how that would work. It wasn't obvious to me how I could save my changes. But it was obvious to me that I could make changes. [laughs] So that part feels weird to me, and I will have to test that out. But I'm going to wait until I have my own PR before I start fooling around [laughs] so I don't ruin somebody else's PR.
CHRIS: Ideally, the worst case is you just push commit to a branch, and commits are reversible. You can throw them away. You can reset, and you can do all sorts of stuff. But I agree with you that maybe I'll do this on my home turf first before I start messing around with somebody's PR.
STEPH: That way, someone doesn't reach out to me and say, "Steph, what is this commit that I have on my PR?" And I'm like, "Oh, I'm just testing." [laughs] But that's something that I was excited to talk about and share with you. What's new in your world?
CHRIS: Well, what's new in my world? I think we've talked about this a little bit, but to give a little bit of context on what's new in my world, I joined a startup. I am now engineer number one. I'm also CTO, a very fancy title, but again, I'm the team of one, so count it as you will. But we do have some consultants working with us. So there is a small team that I am managing, and very quickly, I found myself shifting away from the code or having to balance that trade-off of maker versus manager time. Like, how much of the time am I actually coding and shipping features versus managing and communicating, and trying to figure out the work to be done and triaging the backlog? And all of those sorts of things.
I've also just been coding less, and I think that's a trend that will almost certainly continue, and I'm intrigued by that. And that's a thing that I want to poke at just a little bit. And then I've also noticed that my work has become much more reactive than it used to be, where there are lots of things in Slack. And there's stuff that I'm kind of the only person that can do certain things because I have certain access levels and yadda yadda. And I want to make sure other folks aren't blocked. So I'm trying to be as responsive as possible in those moments. But I'm also struggling with that that trade-off between reactive versus proactive.
My ideal version I think of the work is gather all of the information, all of the different permutations, and what are all the features we want? And then I think about them holistically, and then I respond once solidly as opposed to little one-off interactions and things like that. So there are just a lot of subtle differences. And I think there are trends that will continue. And so I'm trying to just take a step back, observe them from a distance and say, "How do I feel about these?"
But probably most interesting to me is the moving away from code. Have you noticed that at all in your work? Or is that something you've thought about, something you'd be interested in, opposed to? How do you feel about that space in the coding world?
STEPH: That is a wonderful question. It's one that I have wrestled with for a while because I really love my current position. I love being a team lead because I feel like there's this wonderful balance between where I get to code a lot of the time, but then I also get to learn how to be a manager, and help those around me, and provide some coaching or mentoring or just help people find the resources that they need essentially. And I really like that balance. That feels like the right balance to me, where I still get to grow in both areas.
But then, as you'd mentioned, it still feels like one tries to take over the other with time. Like you find that more responsibilities are growing as CTO of the company. And so you feel more responsible to do more of the managerial task or unblocking others and taking on that role, and then that reduces your time for coding.
And I often find myself in that space where I think it's just how I'm wired. I'm very interested and empathetic towards how people are doing and how they're feeling. So I'm always looking for ways to support others and to help unblock them and make sure that they're having a very positive experience with our project. And so then that may mean I'm coding less because then I'm more focused on that. But then, it's still also a very valid part of my job to code. So finding the right balance between those is frankly hard.
To answer your other question, I don't think I want to give that up. I've considered for myself if I'm going to head towards more of a manager path, and I'm going to reserve the right to change my mind. But currently, I still like maintaining most of my individual contributor status with a dash of management sprinkled in there and then some responsibilities for making sure that the team is doing well and that people are enjoying their work.
Along that line, as I've been having conversations with others around, tell me more about your job as a manager, and what does that look like? What responsibilities do you have? How much coding do you still get to do? There have been a couple of books that have been recommended to me that really help someone define are you interested in management? Is that a place that you see yourself going? This is really an honest look at what it means to be a manager. The fact that a lot of your fulfilling work isn't necessarily work that you get to produce, but it's actually helping someone else produce that work and then getting to see them succeed. That is your new fulfillment or a big part of it.
So you are losing that closeness of being a maker,, but instead, you are empowering someone else to be the maker, and then that becomes your win. And that becomes an indication of your success. Versus as an individual contributor, it's really easy to see our wins in a different light: how many tickets have we addressed? How many PRs have we reviewed? That type of work. So there is an interesting dichotomy there, and I can't remember the books off the top of my head, but I will find them and I'll add a link to them in the show notes.
CHRIS: Yeah, definitely interested to see the book recommendations. And generally, yeah, everything you're saying makes sense to me. I think I'm somewhat on the adventure right now. I very much intentionally chose this, and I want to lean into it and explore this facet of the work and doing more of the management and leading a team. But I have to accept that that comes with letting go of some of the individual contributor parts. And I was coding a bit over the weekend. I was just rediscovering the flow of that. And I was like, oh yeah, I really like this. Huh, that's interesting. What am I going to do with that? But I think, again, it's an exploration. And there are facets of both sides that I really like.
And I've spent a lot of time deeper in the individual contributor side. And I've explored the manager side somewhat but not quite as much. And so this is very much about that I want to push on those edges and try and find what feels true to me. So the moving away from code and then moving more into management, I think I like that overall. Although I know there's the small amount in the back of my head that I'm like, I know there's a cost there. That is a trade-off. And so do I find more time in my evenings and weekends to do personal coding projects and things like that just to have that enjoyable work for myself?
The maker versus manager stuff is interesting, though, where my day is now split up into smaller pieces. And even if I'm not coding, there's still writing up docs, or there are things that still require structured blocks of time. And my day is now just sprinkled with other things. And so trying to find that heads down of I want to just do the work right now, and I want to think hard about something is just fundamentally harder to do with more meetings and things speckled throughout the day. So that's one that I think I just don't like overall. But it's sort of a trade-off inherent to the situation.
So I think there's also a version of trying to be intentional about that and saying, you know what? I need some heads-down time. And so Tuesday and Thursday afternoons those are going to be mine. I'm going to wall those off on my calendar and try and protect that time so that whatever necessary heads-down work that I need to do this week fits into those blocks of time and then fit the rest of things around that. But I think I have to make that intentional choice to do that.
Mid-roll Ad
And now we're going to take a quick break to tell you about today's sponsor, Orbit. Orbit is mission control for community builders. Orbit offers data analytics, reporting, and insights across all the places your community exists in a single location. Orbit's origins are in the open-source and developer relations communities. And that continues today with an active open-source culture in an accessible and documented API.
With thousands of communities currently relying on Orbit, they are rapidly growing their engineering team. The company is entirely remote-first with team members around the world. You can work from home, from an Orbit outpost in San Francisco or Paris, or find yourself a coworking spot in your city.
The tech stack of the main orbit app is Ruby on Rails with JavaScript on the front end. If you're looking for your next role with an empathetic product-driven team that prides itself on work-life balance, professional development, and giving back to the larger community, then consider checking out the Orbit careers page for more information. Bonus points if working in a Ruby codebase with a Ruby-oriented team gives you a lot of joy. Find out more at orbit.love/weloveruby.
STEPH: Your mention of having more meetings really resonates with me. And it also made me think of a recent episode of a new TV show I just started watching. Have you seen the TV show called Schmigadoon!?
CHRIS: I have indeed.
STEPH: Okay. We need to have a whole conversation about Schmigadoon! in an upcoming episode. I'm very excited about this show. It's delightful. [laughs] There's a particular line that Keegan-Michael Key says that I just love so much where he says that he became a surgeon because he wanted to help people without talking to people. And I was like, oh, that's a developer. [laughs] I'm the same way. And I really enjoyed that. Although I do like talking to people but still, it just made me think about when you're talking about more meetings and then increasing the amount of talking that needs to be done as you progress into more of a management role.
Also, circling back, I really like what you said earlier about you're noticing the changes that are happening. You're letting those changes happen, and then you're reflecting on how you feel about it. I really like that approach. Do you think that's working well for you? Does it feel too loose because then you don't feel in control enough of those changes? Or do you actually feel like that's a really good way to explore a new role and then find out if you like those changes?
CHRIS: Now that you are restating it back to me, I'm like, oh yeah, I guess that is a good way to do things. But to clarify, I'm not doing nothing with it. I am trying to proactively, where I can, structure my days and do things like that or recognize that right now, I'm probably not the right person to be moving code along. And so I'm saying okay, that is true. And I'm actively choosing to not pick up the bigger pieces of work or to pair with someone else so that they can then run with it but not having me being the person that owns it. So it's not completely letting it happen, but it is almost like meditation to invoke that idea of I'm observing that I'm having these thoughts, and I'm just going to let them go. And it's more about the thinking and the response to it.
So I'm trying to name the thing and be like, oh, this is interesting that this is happening. And I'm noticing an immediate visceral reaction to it where it's like, you're taking away my coding? And I'm like, well, hey, it's not them, it's you; you chose to do this. But let's just spend a minute there. That's okay. How do we feel about this? And so it's trying to not have it be a purely reactive response to it but have it be a more intentional, more thoughtful, and more observing, and then giving it a little bit of time to ruminate and then see a little bit more what I think.
And also, some of it is purposefully pushing myself out of my comfort zone. I think I'm happy, and I do a reasonable job when I'm the person moving the code along. But I also have really enjoyed being at the edge of an engineering team and working with sales or working with other groups and facilitating the work that's happening. And so, if I explore that a little bit more, what's that going to look like for me?
So this period of my career, I'm very intentionally trying to do stuff that I'm like, well, this is a little bit different for me, or this is stretching a little bit, but that is the goal. And I hope good things will come out of it across the board. But it may be that I find like, you know what? Actually, I really miss coding, and I need to find a way to restructure that. And I have seen examples of individuals who are even in CEO positions that are like, no, no, no, I still make some time to code.
Like Amir, the founder of Todoist talks regularly about the fact that he is a CEO who still codes. And that organization has a very particular approach to work. And they're very much about async remote, et cetera. So having these blocks of times and being intentional about how they work. So it's not surprising that he's been able to do that and a purposeful thing that he's structured. I don't think that will make sense for me immediately. But I could see a version down the road where I'm like, this is who I am. I need to get this thing back. But for now, I'm purposefully letting it happen and seeing how I feel from there.
Also, as I'm saying all of this, it sounds like I'm totally on top of this and really thinking it through. I'm like, no, no, no, this is in the moment. I'm noticing some stuff and being like, oh, okay, well, that's interesting. And some of it I intentionally chose. Again, intentionally chose to get out of my comfort zone. So I think I'm just actively out of my comfort zone right now and saying things about it. And then I think I'm telling the story of how I want to respond to it moving forward but not necessarily perfectly achieving that goal immediately.
STEPH: I think that's a nice representation of essentially how you and I have processed things. We've highlighted before that you and I...it's funny, I just made the joke about not talking to people, but it's how I actually process stuff. And the best is when I'm talking out loud to somebody else. And so it totally makes sense that as you were noticing this and reflecting on it, that then this is another way that you are then processing those changes and reflecting on it and thinking through is this a good change? Is it something that I'm going to enjoy? Or am I really going to miss my street coding creds? I need to get back to the editor.
CHRIS: I just need that precious flow state that comes from drinking some Mountain Dew and coding for hours.
STEPH: Do you drink Mountain Dew?
CHRIS: No, I gave it up years ago.
STEPH: [laughs]
CHRIS: I don't drink soda broadly. But if I'm going to drink soda, it's going to be Mountain Dew because if we're going to do it, let's do this thing. I'm pretty sure that stuff is like thermonuclear, but that's fine.
STEPH: [laughs] That's funny. I know we've had this conversation before also around Pop-Tarts where you're like, hey, if I'm going to have a Pop-Tart, I'm going to have the sugariest (Is that a word - sugariest?) Pop-Tart possible.
CHRIS: To be clear, that means it has icing on it because some people in the world, namely you, would prefer the ones without icing. Although we recently learned that the ones without icing have a higher fat and calorie content, so I don't know. The world's murky. I wish it were all just clear, and we could just work with it. But it turns out even Pop-Tarts icing versus not is not a simple question.
STEPH: It's a very simple question. You just need to be on the right side, which is the non-frosted side. [laughs] I can simplify this for you because fat is delicious. Fat trumps sugar; that’s my stance. That's my hot take.
CHRIS: I'm saying both, a little from column A, a little from column B. You got yourself a stew.
STEPH: [laughs] You got a fat sugar stew.
CHRIS: Yeah. That was in Arrested Development. All right, we're veering way off course now. [laughter] To bring it back, what you were highlighting of I'm definitely someone who thinks through stuff by talking out loud, and so it's been wonderful. I've learned so much about myself while talking to you on this podcast. I'll say something, and I'll be like, wait, I actually believe that thing I just said. This is fantastic. Now I can move forward with the knowledge that I've just gained for myself by talking about it on a podcast. So highly recommended: everybody should get a podcast.
STEPH: Plus one. I also have a very real, maybe silly, follow-up question for you as we are, like you just said, exploring the things that we believe or not. My question for you is part of the transition to management and moving away from coding. Isere some fear in the back of your mind where you're like, if I stopped coding, I'm going to lose this skill?
CHRIS: Honestly, no. And I feel kind of bad saying that because I feel like I should say, "Yeah, I feel like it'll fade away and whatnot." But I think I have an aptitude and an interest towards this work. And if I were to ignore it for two years, then frankly, I also know myself. And I'm still going to keep an eye on everything for a while. So I think I'll be aware of what's going on and maybe just haven't spent as much time with it.
But I think if I need to two years from now, I'm like, all right, I got to rebuild my coding muscle. I'll skip a couple of JavaScript frameworks, which will be nice, and I'll be on to the 15th iteration that's new now. But I hope that I could revisit that not trivially, not with no effort. It's the wonderful nature of coding. It's one of the things that I love about it so much is that there are blog posts and YouTube tutorials. And it's so individually discoverable that I'm not really worried about that aspect.
My concern, if anything, isn't so much that I'm going to lose my skills or not be able to code anymore; it’s that I really enjoy coding. It's a practice that I find very enjoyable. A workweek is enjoyable when it contains big blocks of me putting on my headphones, listening to music, and digging into a problem, and then coding and producing a solution. And those tiny little feedback loops of test-driven development or running something and then going to the browser and clicking around like that, there's a directness there that has always really worked well for me.
And so the more I'm abstracted away from that sort of thing, and the more of my work is I'm helping a team, and I'm directing strategy, or whatever it is, that just feels so indirect. And so I'm very interested to find out how I respond to that sort of thing. I've definitely enjoyed it in the past, and so that's why I'm intentionally leaning into it.
But I know that I'm giving up a part of the work that I really love, and giving up is too strong of a word as well. I'm going to find what shape makes sense moving forward. And I expect I'll still be pairing with the other developers on the team and helping to define architecture and things like that. So it's not like it's 100% gone. But for now, I think the world where most of my week was spent coding is no longer the case. And so just naming that and being intentional about it. And yeah, that's the game.
STEPH: Cool. Yeah, that makes a lot of sense. I was mainly interested in that question because that is a question that I've asked myself from time to time that I think I do have that worry that if I step away from coding for too long, then it won't be easy to jump back into. And I've talked myself out of that many times because I don't think it's true for all the reasons that you just said. But it is something that I have considered as like, well, if I take this leap of faith into this other direction, how easy is it for me to get back if I decide to change my mind and go back to being more of an individual contributor?
And one other thing that weighs on me as I'm splitting my time between two areas that I really want to grow…So I'm constantly trying to grow as a developer. I'm also trying to grow as a manager, and I don't want to do a bad job at either. I want to do a great job at both, and that's frankly not always possible. And at times, I have to make trade-offs with myself around okay, I'm going to focus a little heavier this day or this week on being a really great manager or focus a little bit more on being a developer and to pick and choose those topics. And then that sometimes means doing like B+ work in one area, and that's really hard for me. I'm an A-work person. So even downgrading to a B+ level of effort is challenging. But I have found that that's a really great space to be because then I'm doing well in both areas, not perfect, but doing well enough. And often, that's really what counts is that we're doing well enough and still pursuing growth in the areas that are important to us.
CHRIS: Yeah, I think that intentional switching back and forth between them is the space that I'm in. I expect my work will remain very technical, and I hope that that's true. And I think to a certain extent; I get to shape it and determine that. And so how much of it is strategy and planning and things like that? Versus how much of it is helping the team with architecture and defining processes as to how we code, and what are our standards, and what are our languages and frameworks and all of that? I expect I'm still going to be involved in the latter. And again, I think to a certain extent; I get to choose that.
So I am actually interested to see the shape that both naturally the organization needs out of the role that I'm in. But also, what sort of back pressure I can apply and be like, but this is how I want it to be. Is there room for that, or is there not? And it's all an experiment, and we're going to find out. But personally, for me, I'm going to keep reading Twitter and blog posts every day, and I'm probably going to code on the weekends and things.
So the idea of my coding muscle atrophying, I don't know, that one doesn't feel true. But we'll see what I have to say a year from now or after what that looks like. But I expect...this has been true of me for so long, even when I had an entirely different career that I was just reading blogs and other things all the time because this is a thing that deeply interests me. So we will see.
STEPH: Yeah, I'm excited to hear how it goes. And I think there's something to be said for the fact that you are also a CTO that's very close to the work that's being done. So being someone that is very involved in the technical decisions and the code that's being written but then also taking on more of the management responsibilities. And that feels more of a shift where you still have a lot of your coding skills.
And you are writing code day-to-day at least based on what you're saying, but then you are also acquiring a lot of these management skills to go along with it. Versus if someone were going into management and maybe they're at a really large company and then they are very far away from the development team. And they're focused on higher-level themes and discussions, at least that's my guess. But I'm very excited to hear more about your updates and how this experiment is going and to find out who is the true Chris?
CHRIS: Who's the true Chris? That feels complicated. I feel like I contain multitudes. But yeah, you know what? I'm excited to find out as well. Let's see what's going on there. But yeah, so that's a grand summary of the things that are going on in my head. And I expect these are topics that will be continuing to evolve for me. So I think we'll probably have more conversations like this in the future but also some tech stuff. Because like I said, I don't know, I can't stop.
Mid-roll Ad
And now a quick break to hear from today's sponsor, Scout APM.
Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more.
Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform.
See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed.
STEPH: Yeah, that's actually the perfect segue as we were talking earlier about just ways that we're looking to grow as developers. And I saw something that I really enjoyed, and it's published by another thoughtboter. Their name is Matheus Richard. And Matheus runs a Twitter account that's called @RubyCards. And I don't recall the exact cadence, but every so often, Matheus will share a new snippet of either Ruby or Rails code and then will often present the information as a question.
So I'll give you an example, but the highlight is that it teaches you something, either about Ruby or Rails. Maybe you already knew it, maybe you didn't. But it's a really nice exercise to think through okay, I'm reading this code. What do I think it's going to return? And then respond to this poll and then see how other people did as well. Because once the poll closes, then Matheus shares the actual answer for the question.
So one example that I saw recently highlights Ruby's endless method definition, which was introduced in Ruby 3. So that would be something like def, and then let's say the method name is message. And then you have closing, but empty parenthes equals a string of "Hello, World." And so then the question is if you call that method message, what would that return? And then the poll often has options around; it would return "Hello World," or it's going to return a syntax error. It's going to return nil. And then it highlights, well, because of Ruby's endless method definition, this would return "Hello, World."
And then I also saw a new method that I hadn't used before that's defined in Ruby's Hash class that's called store. And so you can use it calling it on a Hash. So if you have your hash equals and then curly brackets, let's say foo is equal to an integer of zero, then you can call hash.store and then pass in two arguments. The first argument's going to be the key. The second argument is the value. And then, that would essentially be the same syntax that we use for assigning a value to a hash. But I just hadn't actually seen the method store before.
So there are fun snippets of Ruby or Rails code. A little bit of a brain teaser helps you think through how that code works, what it's going to execute, what it's going to return. And I really enjoy it. I'll be sure to include a link to it in the show notes so other people can check it out.
CHRIS: Oh, that sounds fun. I hadn't seen that, but I will definitely be following. That's the word on Twitter, right? You have subscribing, subscribe and follow, smash that like button, all of the things. I will do all of the things that we do here on the internet. But I do like that model of the question and answer, and it's slightly more engaging than just sharing the information. So yeah, super interested to see that.
STEPH: Yeah, I like the format of here's some code, and then we're going to ask you what does it return? So that way, you get a moment to think it through. Because if I read something and it just shows me the answer, my brain just doesn't absorb it. And I'm like, okay, that makes sense, and my brain quickly moves on. But if I actually have to think about it and then respond with my answer, then it'll likely stick with me a lot longer. At least we'll find out; that’s the dream.
On that note, shall we wrap up?
CHRIS: Let's wrap up. The show notes for this episode can be found at bikeshed.fm.
STEPH: This show is produced and edited by Mandy Moore.
CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes,; maybe as it really helps other folks find the show.
STEPH: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed or reach me on Twitter @SViccari.
CHRIS: And I'm @christoomey
STEPH: Or you can reach us at hosts@bikeshed.fm via email.
CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week.
All: Byeeeeeeeeeee!
Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.Sponsored By:Orbit: Orbit is mission control for community builders. Orbit offers data analytics, reporting, and insights across all the places your community exists in a single location. Orbit’s origins are in the open-source and developer relations communities, and that continues today with an active open-source culture and an accessible and documented API.
With thousands of communities currently relying on Orbit, they are rapidly growing their engineering team. The company is entirely remote-first with team members around the world. You can work from home, from an Orbit “outpost” in San Francisco or Paris, or find yourself a co-working spot in your city.
The tech stack of the main Orbit app is Ruby on Rails with JavaScript on the frontend. If you are looking for your next role with an empathetic, product-driven team that prides itself on work-life balance, professional development, and giving back to the larger community then consider checking out the Orbit careers page for more information. Bonus points if working in a Ruby codebase with a Ruby-oriented team gives you a lot of joy.
Find out more at orbit.love/weloveruby.Scout: Scout APM is leading-edge application performance monitoring designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise-platform feature bloat.
With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve performance abnormalities -- like N+1 queries, slow database queries, memory bloat, and more.
Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them.
Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform.
See for yourself why developers worldwide call Scout their best friend and try our error monitoring and APM free for 14-days, no credit card needed!
And as an added bonus for Bikeshed listeners: Scout will donate $5 to the open-source project of your choice when you deploy.
Learn more at scoutapm.com/bikeshed.Support The Bike Shed

Sep 14, 2021 • 48min
308: That’s Picante
You know what really grinds Chris' gears? (Spoiler Alert: It's Single-Page Applications.)
Steph needs some consulting help. So much to do, so little time.
Sarah Drasner tweet about shared element transitions
Article about Page Transitions API
Svelte Crossfade layout demo
Svelte Crossfade tutorial page (Note - click "Show Me" on the bottom left)
Transcript:
CHRIS: I have restarted my recording, and we are now recording. And we are off on the golden roads. Isn't software fun?
STEPH: Podcast battle. Here we go!
Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Steph Viccari.
CHRIS: And I'm Chris Toomey.
STEPH: And together, we're here to share a bit of what we've learned along the way. Hey, Chris, happy Friday. How's your week been?
CHRIS: Happy Friday to you as well. My week's been good with the exception of right before we started this recording, I had one of those experiences. You know the thing where software is bad and software is just terrible overall? I had one of those. And very briefly to describe it, I started recording, but I could hear some feedback in my headphones. So I was like, oh no, is that feedback going to show up on the final recording? Which I really hope it doesn't. Spoiler alert - listener, if I sound off, sorry about that. But so I stopped recording and then I went to go listen to the file, and I have our audio software configured to record directly to the desktop. And it does that normally quite well. But for some reason, the file wasn't there. But I remember this recently because I ran into it another time.
For some reason, this is Finder failing me. So the thing that shows me the files in a graphical format, at least on my operating system. Although I think it also messes up in the terminal maybe. That feels like it shouldn't be true, but maybe it is. Anyway, I had to kill all Finder from the terminal to aggressively restart that process. And then suddenly, Finder was like, oh yeah, there's totally files there, absolutely. They were there the whole time. Why do you even ask?
And I know that state management is a hard problem, I am aware. I have felt this pain. I have been the person who has introduced some bugs related to it, but that's not where I want to experience it. Finder is one of those applications that I want to just implicitly trust, never question whether or not it's just sneakily telling me that there are files that are not there or vice versa. So anyway, software.
STEPH: I'm worried for your OS. I feel like there's a theme lately [chuckles] in the struggles of your computer.
CHRIS: On a related note, I had to turn off transparency in my terminal because it was making my computer get very hot. [chuckles]
STEPH: Oh no, you're not a hacker any more.
CHRIS: I'm not. [chuckles] I just have a weird screen that's just dark. And jellybeans is my color scheme, so there's that going on. That's in Vim specifically. Pure is my prompt. That's a lovely little prompt. But lots of Day-Glo colors on just a black background, not the cool hacker transparency. I have lost some street cred.
STEPH: What is your prompt? What did you say it is?
CHRIS: Pure.
STEPH: Pure, I don't know that one.
CHRIS: It is by Sindre Sorhus; I think is his name. That's his Twitter handle, GitHub name. He is a prolific open-source creator in the Node world, particularly. But he created this...I think it's a Bash and a Zsh prompt. It might be for others as well. It's got a bunch of features. It's pretty fast. It's minimal. It got me to stop messing around with my prompt, which was mostly what I was going for. And it has a nice benefit that occasionally now I'll be pairing with someone, and I'll be like, "Your prompt looks like my prompt. Everything is familiar. This is great."
STEPH: Well, if you get back in the waters of messing around with your prompts again, I'm using Starship. And I hadn't heard of Pure before, but I really like Starship. That's been my new favorite.
CHRIS: Wow.
STEPH: Wow.
CHRIS: I mean, on the one hand…
STEPH: You're welcome. [laughs]
CHRIS: On the one hand, thank you. On the other hand, again, let me lead in with the goal was to stop messing around with my prompt. So you're like, oh, cool. Here's another prompt for you, though. [chuckles]
STEPH: [laughs] But my goal is to nerd snipe you into trying more things because it's fun.
CHRIS: I don't know if you know this, but I am impervious to nerd sniping.
STEPH: [laughs]
CHRIS: So try as you might, I shall remain steady in my course of action.
STEPH: Are we playing two truths and a lie? Is that what we're doing today? [laughs]
CHRIS: Nah, just one lie. It's easier. Everybody wins one lie.
STEPH: [laughs]
CHRIS: But anyway, in other news, we're going to do a segment called this really grinds my gears. That's today's segment, which is much like when I do a good idea, terrible idea. But this is one that I'm sure I've talked about before. But there's been some stuff that I saw moving around on the internet as one does, and it got these ideas back into my head. And it's around the phrase single-page application. I am not a fan of that phrase or SPA as the initialism. Thank you, Edward Loveall, for teaching me the difference between an initialism and an acronym. I really hope I'm getting it right, by the way, [laughs] SPA as people call them these days.
I feel weird because of how much I care about this thing, how much I care about this idea, and how much whenever I hear this acronym, I get a little bit unhappy. And so there's a part of it that's I really do think our words shape our thinking. And I think single-page application has some deeply problematic ideas. Most notably, I think one of the most important things about building web applications is the URL. And those are different pages, at least in my head. I don't know of a different way to think about this.
But if you are not emphasizing the URL and the fact that the URL is a way to address different pages or resources within your application, then you are throwing away one of the greatest advancements that humankind has made, in my mind. I care a lot about URLs; it turns out. And it's not inherent to an SPA that you will not be thinking about URLs. But again, in that idea that our words shape our thinking, by calling it an SPA, by leaning into that idea, I think you are starting down a path that leads to bad outcomes. I'm going to pause there because I'm getting kind of ranty. I got more to say on the topic. But what do you think?
STEPH: Yeah, these are hot takes. I'm into it. I'm pretty sure that I know why URLs are so important to you and more of your feelings around why they're important. But would you dive in a bit deeper as to why you really cherish URLs, and why they're so important, and why they're one of the greatest advancements of humanity?
CHRIS: [laughs] It sounds lofty when you say it back to me, but yeah. It's interesting that as you put into a question, it is a little bit hard to name. So there are certain aspects that are somewhat obvious. I love the idea that I can bookmark or share a given resource or representation of a resource very simply. Like the URL, it's this known thing. We can put hyperlinks in a document. It's this shared way to communicate, frankly, very complex things.
And when I think of a URL, it's not just the domain and the path, but it's also any query parameters. So if you imagine faceted search on a website, you can be like, oh, filter down to these and only ones that are more than $10, and only ones that have a future start date and all those kinds of nuance. If you serialize that into the URL as part of the query param, then that even more nuanced view of this resource is shareable is bookmarkable is revisitable.
I end up making Alfred Workflows that take advantage of the fact that, like, oh, I can look at this URL scheme, and I can see where different parts are interpolated. And so I can navigate directly to any given thing so fast. And that's deeply valuable, and it just falls naturally out of the idea that we have URLs. And so to not deeply embrace that, to not really wrap your arms around it and give that idea a big hug feels weird to me.
STEPH: Yeah, I agree. I remember we've had this conversation in the past, and it really frustrates me when I can't share specific resources with folks because I don't know how to link to it. So then I can send you a link to the application itself to the top URL. But then I have to tell you how to find the information that I thought was really helpful. And that feels like a step backward.
CHRIS: Yeah. That ability to say, "Follow this link, and then it will be obvious," versus "Go to this page, click on this thing, click on the dropdown, click on this other thing." Like, that's just a fundamentally different experience. So one of the things that I saw that got me thinking about this was I saw folks referring to single-page applications but then contrasting them with MPAs, which are multiple-page applications.
STEPH: So the normal application? [laughs]
CHRIS: And I was like, whoa, whoa, everybody. You mean like a website or a web app? As much as I was angry at the first initialism, this second one's really getting me going. But it really does speak to what are we doing? What are we trying to build? And as with anything, you could treat this as a binary as just like there are two options. There are either websites which, yeah, those have got a bunch of URLs, and that's all the stuff. And then there are web apps, and they're different. And it's a bundle of JavaScript that comes down, boots up on the client, and then it's an app thing. And who cares about URLs? I think very few people would actually fall in that camp.
So I don't really believe that there is a dichotomy here. I think, as always, it's a continuum; it’s a spectrum. But leaning into the nomenclature of single-page application, I think pushes you more towards that latter end of the spectrum. I think there are other things that fall out of it. Like, I believe deeply in having the server know more, have more of the logic, own more of the logic, own more authorization and routing, and all of those things because really great stuff falls out of that. And that one has more of a trade-off, I'd say.
But I won't name any names, but there is a multiple billion-dollar company whose website I had to interact with recently. And you land on their page on their marketing site. And then, if you click log in, it navigates you to the application, so a separate domain or a separate subdomain, the application subdomain, and the login page there. And the login page renders, and then I go to fill in my username and password. Like, my mouse makes it all the way to click on the little box or whatever I'm doing if I'm using keyboard things. But I have enough time to actually start to interact with this page.
And then suddenly, it rips away, and it actually just renders the authenticated application because it turns out I was already logged in. But behind the scenes, they're doing some JWT dance around that they're checking; oh no, no, you're already logged in, so never mind. We don't need to show you the login page, but I was already on the login page.
And my feeling is this sort of brittle UI; this sort of inconsistency erodes my trust in that application, particularly when I'm on the login page. That is a page that matters. I don't believe that they're doing anything fundamentally insecure. But I do have the question in my head now. I'm like, wait, what's going on there, everybody? Is it fine? Was that okay? Or if you see something that you shouldn't see and then suddenly it's ripped away from you, if you see half of a layout that's rendered on a page and then suddenly you see, no, no, no, you actually don't have access to that page, that experience erodes my trust.
And so, I would rather wait for the server to fully resolve, determine what's going to happen, and then we get a response that is holistically consistent. You either have access, or you don't, that sort of thing. Give me a loading indicator; give me those sorts of things. I'm fine with that. But don't render half of a layout and then redirect me back away.
STEPH: I feel like that's one of the problems with knowing too much because most people are not going to pick up on a lot of the things that you're noticing and caring deeply about where they would just see like, oh, I was logged in and be like, huh, okay, that was a little weird, but I'm in and just continue on. Versus other folks who work very closely to this who may recognize and say, "That was weird." And the fact that you asked me to log in, but then I was already logged in, did you actually log me in correctly? What's happening? And then it makes you nervous.
CHRIS: Maybe. Probably. But I wonder…the way you just said that sounds like another dichotomy. And I would say it's probably more of a continuum of an average not terribly tech-savvy user would still have a feeling of huh, that was weird. And that's enough. That's a little tickle in the back of your brain. It's like, huh, that was weird.
And if that happens enough times or if you've seen someone who uses an application and uses it consistently, if that application is reasonably fast and somewhat intuitive and consistent, then they can move through it very quickly and very confidently. But if you have an app that half loads and then swaps you to another page and other things like that, it's very hard to move confidently through an application like that. I do think you're right in saying that I am over-indexed on this, and I probably care more than the average person, but I do care a lot.
I do think one of the reasons that I think this happens is mobile applications came along, and they showed us a different experience that can happen and also desktop apps for some amount of time this was true. But I think iOS apps, in particular really great ones, have super high fidelity interactions. And so you're like, you're looking at a list view, and then you click on the cell for that list view. And there's this animated transition where the title floats up to the top and grows just a little bit. And the icon that was in the corner moves up to the corner, and it gets a little bigger. And it's this animated transition to the detailed view for that item. And then if you go back, it sort of deanimates back down.
And that very consistent experience is kind of lovely when you get it right, but it's really, really hard. And people, I think, have tried to bring that to the web, but it's been such a struggle. And it necessitates client-side routing and some other things, or it's probably easiest to do if you have those sorts of technologies at play, but it's been a struggle. I can't think of an application that I think really pulls that off. And I think the trade-offs have been very costly.
On the one positive note, there was a tweet that I saw by Sarah Drasner that was talking about smooth and simple page transitions with the shared element transition API. So this is a new API that I think is hoping to bring some of this functionality to the web platform natively so that web applications can provide that higher fidelity experience. Exactly how it'll work whether or not it requires embracing more of the single-page application, client-side routing, et cetera, I'm not sure on that. But it is a glimmer of hope because I think this is one of the things that drives folks in this direction. And if we have a better answer to it, then maybe we can start to rethink the conversation.
STEPH: So I think you just said shared element transitions. I don't know what that is. Can you talk more about that?
CHRIS: I can try, or I can make a guess. So my understanding is that would be that sort of experience where you have a version of a certain piece of content on the page. And then, as you transition to a new page, that piece of content is still represented on the new page, but perhaps the font size is larger, or it's expanded, or the box around it has grown or something like that. And so on mobile, you'll often see that animate change. On the web, you'll often see the one page is just completely replaced with the other. And so it's a way to have continuity between, say, a detailed view, and then when you click on an item in it, that item sort of grows to become the new page. And now you're on the detail page from the list page prior.
There's actually a functionality in Svelte natively for this, which is really fancy; it's called crossfade. And so it allows you to say, "This item in the component hierarchy in the first state of the application is the same as this item in the second state of the application." And then, Svelte will take care of transitioning any of the properties that are necessary between those two.
So if you have a small circle that is green, and then in the next state of the application, it's a blue rectangle, it will interpolate between those two colors. It will interpolate the shape and grow and expand it. It will float it to its new location. There is a really great version of it in the Svelte tutorial showing a to-do list. And so it's got a list on the left, which is undone things, and a list on the right that is done things. And when you click on something to complete it, it will animate it, sort of fly across to the other list. And if you click on it to uncomplete, it will animate it and fly back.
And what's great is within Svelte because they have this crossfade as a native idea; all you need to say is like, "It was on this list, now it's on this list." And as long as it's identifiable, Svelte handles that crossfade and all the animations. So it's that kind of high-fidelity experience that I think we want. And that leads us to somewhat more complex applications, and I totally get that. I want those experiences as well. But I want to ask some questions, and I want to do away with the phrasing single-page application entirely. I don't want to say that anymore. I want to say URLs are one honking good idea. Let's have more of those.
And also, just to name it, Inertia is a framework that allows me to build using some of the newer technologies but not have to give up on URLs, give up on server-side logic as the primary thing. So I will continue to shout my deep affection for Inertia in this moment once again.
STEPH: Cool. Thanks. That was really helpful. That does sound really neat. So in the ideal world, we have URLs. We also have high fidelity and cool interactions and transitions on our pages. We don't have to give it a fancy name like single-page application or then multi-page application. I do wonder, with our grumpiness or our complaint about the URLs, is that fair to call it grumpy?
CHRIS: It's fair to call it grumpy, although you don’t need to loop yourself in with me. I'm the grump today.
STEPH: [laughs]
CHRIS: You're welcome to come along for the ride if you'd like. And I'm trying to find a positive way to talk about it. But yeah, it's my grumpytude.
STEPH: Well, I do feel similarly where I really value URLs, and I value the ability to bookmark and share, like you said earlier. And I do wonder if there is a way to still have that even if we don't have the URL. So one of the things that I do is I'll inspect the source code. And if I can find an ID that's for a particular header or section on the page, then I will link someone to a section of that page by then adding the ID into the URL, and that works. It's not always great because then I have to rely on that being there. But it's a fix, it's a workaround.
So I wonder if we could still have something like that, that as people are building content that can't be bookmarked or the URL doesn't change explicitly, or reference that content, to add more thoughtful bookmark links, essentially, or add an ID and then add a user-facing link that says, "Hey, if you want to link someone to this content, here you go." And under the hood, it's just an ID. But most people aren't going to know how to do that, so then you're helping people be able to reference content because we're used to URLs, so just thinking outside the box. I wonder if there are ways that we can still bookmark this content, share it with people. But it's okay if the URL isn't the only way that we can bookmark or reference that content.
CHRIS: It's interesting that you bring that up, so the anchor being the thing after the hash symbol in the URL. I actually use that a ton as well. I think I built a Chrome extension a while back to try what you're saying of I'll inspect the DOM. I did that enough times that I was like, what if the DOM were to just tell me if there were an ID here and I could click on a thing? Some people's blogs...I think the thoughtbot blog has this at this point. All headers are clickable. So they are hyperlinks that append that anchor to the URL.
So I wouldn't want to take that and use that functionality as our way to get back to URLs that are addressing resources because that's a way to then navigate even further, which I absolutely love, to a portion of the page. So thinking of Wikipedia, you're on an article, but it's a nice, long article. So you go down to the section, which is a third of the way down the page. And it's, again, a very big page, so you can link directly to that. And when someone opens that in their browser, the browsers know how to do this because it's part of the web platform, and it's wonderful.
So we've got domains, we've got paths, we've got anchors, we've got query params. I want to use them all. I want to embrace them. I want that to be top of mind. I want to really think about it and care about that as part of the interface to the application, even though most users like you said, are not thinking about the shape of a URL. But that addressability of content is a thing that even if people aren't thinking of it as a primary concern, I think they know it when they...it's one of those like, yeah, no, that app's great because I can bookmark anything, and I can get to anything, and I can share stuff with people.
And I do like the idea of making the ID-driven anchor deep links into a page more accessible to people because you and I would go into the DOM and slice it out. Your average web user may not be doing that, or that's much impossible to do on mobile, so yes, but only more so in my mind. [laughs] I don't want to take anchors and make them the way we do this. I want to just have all the URL stuff, please.
Mid-roll Ad
Now we're going to take a quick break to tell you about today's sponsor, Orbit. Orbit is mission control for community builders. Orbit offers data analytics, reporting, and insights across all the places your community exists in a single location. Orbit's origins are in the open-source and developer relations communities. And that continues today with an active open-source culture in an accessible and documented API.
With thousands of communities currently relying on Orbit, they are rapidly growing their engineering team. The company is entirely remote-first with team members around the world. You can work from home, from an Orbit outpost in San Francisco or Paris, or find yourself a coworking spot in your city. The tech stack of the main orbit app is Ruby on Rails with JavaScript on the front end.
If you're looking for your next role with an empathetic product-driven team that prides itself on work-life balance, professional development, and giving back to the larger community, then consider checking out the Orbit careers page for more information. Bonus points if working in a Ruby codebase with a Ruby-oriented team gives you a lot of joy. Find out more at orbit.love/weloveruby.
STEPH: I have a confession from earlier when you were talking about the examples for those transitions. And you were describing where you take an action, and then the page does a certain motion to let you know that new content is coming onto the page and the old content is fading away. And I was like, oh, like a page reload? We're just reimplementing a page reload? [laughs] That's what we have?
CHRIS: You have a fancy, though.
STEPH: Fancy, okay. [laughs] But that felt a little sassy. And then you provided the other really great example with the to-do list. So what are some good examples of a SPA? Do you have any in mind? I think there are some use cases where...so Google Maps, that's the one that comes to mind for me where URLs feel less important. Are there other applications that fit that mold in your mind?
CHRIS: Well, so again, it's sort of getting at the nomenclature, and how much does the acronym actually inform what we're thinking about? But taking Google Maps as an example, or Trello is a pretty canonical one in my mind, most people say those are single-page applications. And they are probably in terms of what the tech actually is, but there are other pages in those apps. There's a settings page, and there's a search page, and there's this and that. And there's like the board list in Trello.
And so when we think about Trello, there is the board view where you're seeing the lists, and you can move cards, and you can drag and drop and do all the fancy stuff. That is a very rich client-side application that happens to be one page of the Trello web app and that one being higher fidelity, that one being more stateful. Stateful is probably the thing that I would care about more than anything. And so for that page, I would be fine with the portion of the JavaScript that comes down to the client being a larger payload, being more complex, and probably having some client-side state management for that. But fundamentally, I would not want to implement those as a true client-side application, as a true SPA. And I think client-side routing is really the definition point for me on this.
So with Trello, I would probably build that as an Inertia-type application. But that one page, the board page, I'd be like, yeah, sorry, this is not going to be the normal Inertia thing. I'm going to have to be hitting JSON endpoints that are specifically built for this page. I'm going to have a Redux store that's local. I'm going to lean into all of that complex state management and do that within the client-side app but not use client-side routing for actual page-level transitions, the same being true for Google Maps. The page where you're looking at the map, and you can do all sorts of stuff, that's a big application. But it is one page within the broader website, if you will. And so, I still wouldn't want client-side routing if I can avoid it because I think that is where I run into the most problems.
And that thing I was talking about where I was on the login page for a second, and then I wasn't; I do not like that thing. So if I can avoid that thing, which I have now found a way to avoid it, and I don't feel like I'm trading off on that, I feel like it's just a better experience but still reserving the right to this part of the application is so complex. This is our Wiziwig drag and drop graphical editor thing, cool. That's going to have Redux. That's going to have client-side state management, all that stuff. But at no point does single-page application feel like the right way to describe the thing that we're building because I still want to think about it as holistically part of the full web app. Like the Trello board view is part of the Trello web app. And I want it all to feel the same and move around the same.
STEPH: Yeah, that makes sense. And it's funny, as you were mentioning this, I pulled up Google Maps because I definitely only interact with that heavy JavaScript portion, same for Trello. And I wasn't even thinking about the fact that there are settings. By the way, Google Maps does a lot. I don't use hardly any of this. But you make a great point. There's a lot here that still doesn't need such heavy JavaScript interaction and doesn't really fit that mold of where it needs to be a single-page app or even needs to have that amount of interactivity. And frankly, you may want URLs to be able to go specifically to these pages.
CHRIS: That actually is an interesting, perhaps counterpoint to what I'm saying. So if you do have that complex part of one of your applications and you still want URL addressability, maybe you need client-side routing, and so that becomes a really difficult thing to answer in my mind. And I don't necessarily have a great answer for that. I'm also preemptively preparing myself for anyone on the internet that's listening to this and loves the idea of single-page applications and feels like I'm just building a straw man here, and none of what I'm saying is actually real and whatnot.
And although I try to...I think we generally try and stay in the positive space of like what's good on the internet. This is a rare case where I'm like, these are things that are not great. And so I think in this particular case, leaning into things that I don't like is the way to properly capture this. And giant JavaScript bundles where the entirety of the application logic comes down in 15-megabyte download, even if you're on 3G on a train; I don't like that.
I don't like if we have flashes of a layout that they can get ripped away b; it’secause it turns out we actually aren't authorized to view that page, that sort of thing. So there are certain experiences from an end client perspective that I really don't like, and that's mostly what I take issue with. Oh, also, I care deeply about URLs, and if you don't use the URL, then I'm going to be sad. Those are my things.
Hopefully, that list is perhaps a better summary of it than like...I don't want it to seem like I'm just coming after SPA as a phrase or a way of thinking because that's not as real of a conversation. But those particular things that I just highlighted don't feel great. And so I would rather build applications that don't have those going on. And so if there's a way to do that that still fits any other mold or is called whatever, but largely what I see called an SPA often has those sorts of edge cases. And I do not like those edge cases.
STEPH: Yeah, I like how you're breaking it down where it's less of this whole thing like I can't get on board with any of it. You are focusing on the things that you do have concerns with. So there can be just more interesting, productive conversations around those concerns versus someone feels like they have to defend their view of the world.
I have found that I think I'm a bit unique in this area where when people have a really differing opinion than mine, that gets me really excited because then I want to know. Because if I believe very strongly in something and I just think this is the way and then someone very strongly says like, "No, that's not," I'm like, "Oh yeah. Okay, we should talk because I'm interested in why you would have such a different opinion than mine." And so, I typically find those conversations really interesting. As long as everybody's coming forward to be productive and kind, then I really enjoy those conversations.
CHRIS: That is, I think, an interesting frame that you have there. But I think I'm similar, and hopefully, my reframing there puts it in the way that can be a productive conversation starter as opposed to a person griping on a podcast. But with that said, that's probably enough of me griping on a podcast. [chuckles] So what's up in your world, Steph?
STEPH: Oh, there are a couple of things going on. So I am in that pre-vacation chaotic zone where I'm just trying to get everything done. And I heard someone refer to it recently as going into a superman or superwoman mode where you're just trying to do all the things before you go, which is totally unreasonable. So that has been interesting. And the name of the game this week has been delegate, delegate, delegate, and it seems to be going fairly well. [chuckles] So I'm very excited for the downtime that I'm about to have.
And some other news, some personal news, Utah, my dog, turns one. I'm very excited. I'm pretty sure we'll have a dog birthday party and everything. It's going to be a thing. I'll share pictures on Twitter, I promise.
CHRIS: So he's basically out of the puppy phase then.
STEPH: Yeah, the definition for being a puppy seems to be if you're a year or younger, so he will not be an adult. Teenager? I don't know. [laughs]
CHRIS: What about according to your lived experience?
STEPH: He has calmed down a good bit.
CHRIS: Okay, that's good.
STEPH: He has gotten so much better. Back when we first got him, I swear I couldn't get 15 minutes of focus where he just needed all the attention. Or it was either constant playtime, or I had to put him in his kennel since we're using that. That was the only way I was really ever getting maker’s time. And now he will just lounge on the couch for like an hour or two at a time. It's glorious. And so he has definitely calmed down, and he is maturing, becoming such a big boy.
CHRIS: Well, that is wonderful. Astute listeners, if you go back to previous episodes over the past year, you can certainly find little bits of Utah sprinkled throughout, subtle sounds in the background.
STEPH: He is definitely an important part of the show. And in some other news, I have a question for you. I'm in need of some consulting help, and I would love to run something by you and get your thoughts. So specifically, the project that I'm working on, we are always in a state where there's too much to do. And even though we have a fairly large team, I want to say there's probably somewhere between 7 and 10 of us. And so, even though we have a fairly...for thoughtbot, that's a large team to have on one project. So even though there's a fair number of us, there's always too much to do. Everything always feels like it's urgent. I can't remember if I've told you this or not, but in fact, we had so many tickets marked as high priority that we had to introduce another status to then indicate they're really, really high, and that is called Picante. [chuckles]
CHRIS: Well, the first part of that is complicated; the actual word that you chose, though, fantastic.
STEPH: I think that was CTO Joe Ferris. I think he's the one that came up with Picante. So that's a thing that we have, and that really represents like, the app is down. So something major is happening. That's like a PagerDuty alert when we get to that status where people can't access a page or access the application. So there's always a lot to juggle, and it feels a lot like priority whiplash in terms that you are working on something that is important, but then you suddenly get dragged away to something else. And then you have to build context on it and get that done. And then you go back to the thing that you're working on.
And that's a really draining experience to constantly be in that mode where you're having to pivot from one type of work to the other. And so my question to you (And I'll be happy to fill in some details and answer questions.) is how do you calm things down? When you're in that state where everything feels so urgent and busy, and there's too much to do, how do you start to chip away at calming things down where then you feel like you're in a good state of making progress versus you feel like you're just always putting out fires or adding a band-aid to something? Yeah, that's where I’m at. What thoughts might you have, or what questions do you have?
CHRIS: Cool. I'm glad you brought an easy question that I can just very quickly answer, and we'll just run with that. It is frankly...what you're describing is a nuanced outcome of any number of possible inputs. And frankly, some of them may just be like; this is just the nature of the thing. Like, we could talk about adding more people to the project, but the mythical man-month and that idea that you can't just throw additional humans at the work and suddenly have that makes sense because now you have to coordinate between those humans. And there's that wonderful image of two people; there's one line of communication. Three people, suddenly there are a lot more lines of communication. Four people, wow. The exponential increase as you add new people to a network graph, that whole idea.
And so I think one of the first questions I would ask is, and again, this is probably not either/or. But if you would try and categorize it, is it just a question of there's just a ton of work to do and we're just not getting it done as quickly as we would want? Or is it that things are broken, that we're having to fix things, that there are constant tweaks and updates, that the system doesn't support the types of changes that we want, so any little thing that we want to do actually takes longer? Is it the system resisting, or is it just that there's too much to do? If you were to try and put it into one camp or the other.
STEPH: It is both, my friend. It is both of those camps. [chuckles]
CHRIS: Cool. That makes it way easier.
STEPH: Totally. [laughs] To add some more context to that, it is both where the system is resistant to change. So we are trying to make improvements as we go but then also being respectful of the fact if it is something that we need to move quickly on, it doesn't feel great where you never really get to go back and address the system in a way that feels like it's going to help you later. But then, frankly, it's one of those tools that we can use. So if we are in the state where there's too much to do, and the system is resisting us, we can continue to punt on that, and we can address things as we go.
But then, at some point, as we keep having work that has slowed down because we haven't addressed the underlying issues, then we can start to have that conversation around okay; we’ve done this twice now. This is the third time that this is going to take a lot longer than it should because we haven't really fixed this. Now we should talk about slowing things down so we can address this underlying issue first and then, from now on, pay the tax upfront. So from now on, it's going to be easier, but then we pay that tax now. So it is a helpful tool. It's something that we can essentially defer that tax to a later point. But then we just have to have those conversations later on when things are painful. Or it often leads to scope creep is another way that that creeps up.
So we take on a ticket that we think, okay, this is fairly straightforward; I don't think there's too much here. But then we're suddenly getting into the codebase, and we realize, oh, this is a lot more work. And suddenly, a ticket will become an epic, and you really have one ticket that's spiraled or grown into five or six tickets. And then suddenly, you have a person that's really leading like a mini project in terms of the scope of the work that they are doing.
So then that manifests in some interesting ways where then you have the person that feels a bit like a silo because they are the ones that are making all these big changes and working on this mini-project. And then there's the other one where there's a lot to do. There are a lot of customers, and there's a lot of customization for these customers. So then there are folks that are working really hard to keep the customers happy to give them what they need. And that's where we have too much to do. And we're prioritizing aggressively and trying to make sure that we're always working on the top priority. So like you said, it's super easy stuff.
CHRIS: Yeah. To say it sincerely and realistically, you're just playing the game on hard mode right now. I don't think there is any singular or even multiple easy answers to this. I think one question I would have particularly as you started to talk about that, there are multiple customers each with individualized needs, so that's one of many surface areas that I might look t say, "Can we sort of choke things off there?"
So I've often been in organizations where there is this constant cycle of the sales team is going out. They're demoing against an InVision mock. They're selling things that don't exist. They're making promises that are ungrounded and, frankly, technically infeasible or incredibly complicated, but it's part of the deal. They just sold it, and now we have to implement it as a team. I've been on teams where that was just a continuing theme. And so the engineering team was just like, "We can never catch up because the goalpost just keeps moving."
And so to whatever degree that might be true in this case, if there are ten different customers and each of them right now feels like they have an open line to make feature requests or other things like that, I would try to have the conversation of like, we've got to cut that off right now because we're struggling. We're not making the forward progress that we need to, and so we need to buy ourselves some time. And so that's one area that I would look at.
Another would be scope, anywhere that you can, go into an aggressive scope cutting mode. And so things like, well, we could build our own modal dialogue for this, but we could also use alert just like the JavaScript alert API. And what are all of the versions of that where we can say, "This is not going to be as nice, and as refined, and as fitting with the brand and feel and polish of the website. But ways that we can make an application that will be robust, that will work well on all of the devices that our users might be using but saves us a bunch of development time"? That's definitely something that I would look to.
What you described about refactoring is interesting. So I agree with we're not in a position where we can just gently refactor as we find any little mess. We have to be somewhat ruthless in our prioritization there. But like you said, when you get to that third time that a thing is working way harder, then take the time to do it. But really, like just every facet of the work, you just have to be a little better. If you're an individual developer and you're feeling stuck, raise your hand all the earlier because that being stuck, we don't have spare cycles right now. We need everybody to be working at maximum efficiency. And so if you've hit a wall, then raise your hand and grab somebody else, get a pair, rubber duck, whatever it is that will help you get unstuck. Because we're in a position where we need everybody moving as fast as they can.
But also to say all of those aren't free. Every one of those where you're just like, yeah, do it the best you can. Dial it up to 11 on every front. That's going to drain the team, and so we have to also be mindful of that. This can't be forever. And so maybe it is bringing some new people onto the team or trying to restructure things so that we can have smaller communication channels. So it's only four people working together on this portion of the application, and therefore their communication lines are a bit simpler. That's one way that we can maybe save a little bit. But yeah, none of these are free. And so, we also need to be mindful that we can't just try harder forever. [laughs] That's a way to burn out the team. But what you're describing is like the perfect storm of every facet of this is difficult, and there's no singular answer.
There's the theory of constraints (I think I'm saying that right.) where it's like, what's the part of our process that is introducing the most slowdowns? And so you go, and you tackle that. So if you imagine a website and the app is slow is the report that you're getting, and you're like, okay, what does that mean? And you instrument it, and you log some stuff out. And you're like, all right, turns out we have tons of N+1s. So frankly, everything else doesn't matter. I don't care if we've got a 3 megabyte JavaScript bundle right now; the 45 N+1s on the dashboard that's the thing that we need to tackle. So you start, and you focus on that.
And now you've removed that constraint. And suddenly, the three megabyte JavaScript bundle is the new thing that is the most complicated. So you're like, okay, cool, let's look into tree shaking or whatever it is, but you move from one focus to another. And so that's another thing that could come to play here is like, which part of this is introducing the most pain? Is it feature churn? Is it unrealistic sales expectations? Is it developers getting stuck? And find the first of those and tackle it. But yeah, this is hard.
STEPH: Yeah, it is. That's all really helpful, though. And then, I can share some of the things that we are experimenting with right now and then provide an update on how it's going. And one of the things that we're trying; I think it's similar to the theory of constraints. I'm not familiar with that, but based on the way you described it, I think they're related.
One of the things that we are trying is breaking the group into smaller teams because there are between 7 and 10 of us. And so, trying to jump from one issue to the next you may have to really level up on different portions of the application to be able to make an impact. And there are areas that we really need infrastructure improvements and then essentially paving the way for other people to be able to move more quickly. We do have to prioritize some of that work as well.
So if we break up into smaller teams, it addresses a couple of areas, or at least that's the goal is to address a couple of areas. One is we avoid having silos so that people aren't a bottleneck, or they're the only ones that are really running this mini-project and the only one that has context. Because then when that person realizes the scope has grown, bringing somebody on to help feels painful because then you're in an urgent state, but now you have to spend time leveling someone else up just so that they can help you, and that's tough.
So the goal is that by having smaller teams, we will reduce that from happening because at least everything that feels like a small project...and by feels like a small project, I mean if we have more than one ticket that's associated with the same theme, that's going to start hinting at maybe this is more than just one ticket itself, and it might actually belong to an epic. Or there's a theme here, and maybe we should have two people working on this. And breaking people into groups, then we can focus on some people are focused more on the day-to-day activity. Some people are focused on another important portion of the codebase as we have what may be extracted. I'm going to say this, but we're going to move on, maybe extracted into its own service. [laughs] I know that's a hot one for us, so I'm just going to say it.
CHRIS: I told you I can't be nerd sniped. This is fine. Let's continue on. [laughs]
STEPH: [laughs] And then a small group can also focus on some of those infrastructure improvements that I was alluding to. So smaller teams is something that we are trying.
We are also doing a really great job. I've been really happy and just proud of the team where folks are constantly reaching out to each other to say, "Hey, I'm done with my ticket. Who can I help?" So instead of immediately going to the backlog and grabbing the next thing. Because we recognize that because of this structure where some people are some silos, they have their own little mini backlog, which we are working to remove that to make sure everything is properly prioritized instead of getting assigned to one particular person. But we are reaching out to each other to say, "Hey, what can I do to help? What do you need to get done with your work before I go pick something else up?"
The other two things that come to mind is who's setting the deadlines? I think you touched on this one as well. It's just understanding why is it urgent? Does it need to be urgent? What is the deadline? Is this something that internally we are driving? Is this something that was communicated without talking to the rest of the team? Is this just a really demanding customer? Are they setting unrealistic expectations? But having more communication around what is the sense of urgency? What happens if we miss this deadline? What happens if we don't get to this for a week, a month? What does that look like?
And then also, my favorite are retros because then we can vote on what feels like the highest priority in terms of pain points or run these types of experiments like the smaller teams. So those are the current strategies that we have. And I'm very interested to see how they turn out because it is a tough way. Like you said, it's challenge mode, and it is going to burn people out. And it does make people feel fatigued when they have to jump from one priority to the next. So I'm very interested. It's a very interesting problem to me too. It just feels like something that I imagine a lot of teams may be facing. So I'm really excited if anybody else is facing a similar issue or has gone through a similar challenge mode; I’d love to hear how your team tackled it.
CHRIS: Yeah, I'm super interested to hear the outcome of those experiments. As a slightly pointed question there, is there any semi-formal version of tracking the experiments? And is it just retro to retro that you're using for feedback on that? I've often been on teams where we have retro. We come up with it, and we're like, oh, this is a pain point. All right, let's try this. And then two weeks later, we're like, oh, did anyone actually do that? And then we just forget. And it's one of those things that I've tried to come up with better ways to actually manage, make slightly more explicit the experiments, and then have a timeline, have an almost scientific process of what's the hypothesis? What's the procedure? What are the results? Write up an executive summary. How'd it go?
STEPH: We are currently using retro, but I like that idea of having something that's a bit more concrete. So we have action items. And typically, going through retro, I tend to revisit the action items first as a way to kick off retro. So then that highlights what did we do? What did we not do? What do we not want to do anymore? What needs to roll over to the current iteration? And I think that could be just a way that we chat about this. We try something new, and we see how it's going each week in retro. But I do like the idea of stating upfront this is what we're looking to achieve because I think that's not captured in the retro action item. We have the thing that we're doing, but we haven't captured this is what we hope to achieve by taking this experiment on.
Mid-roll Ad
And now a quick break to hear from today's sponsor, Scout APM.
Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more.
Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform.
See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed.
STEPH: As for the other thing that you mentioned, I do have an idea for that because a former client that I worked with where we had experiments or things that we wanted to do, we were using Trello. And so we would often take those action items…or it was even more of a theme. It wasn't something that could be one-and-done. It was more of a daily reminder of, hey; we are trying this new thing. And so, we want to remind you each day to embrace this experiment and this practice. And so we would turn it into a Trello ticket, and then we would just leave it at the top of the board. So then, each day, as we were walking the board, it was a nice reminder to be like, hey, this is an ongoing experiment. Don't forget to do this.
CHRIS: I do like the idea of bringing it into a stand-up potentially as like that's just a recurring point that we all have. So we can sort of revisit it, keep it top of mind, and discard it at some point if it's not useful. And if we're saying we're doing a thing, then let's do the thing and see how it goes. So yeah, very interested to hear the outcomes of the experiment and also the meta experiment framework that you're going to build here. Very interested to hear more about that.
And just to say it again, this sounds like your perfect storm is not quite right because it doesn't sound like there's a ton of organizational dysfunction here. It sounds like this is just like, nah, it's hard. The code's not in perfect shape, but no code is. And there's just a lot of work to be done. And there are priorities because frankly, sometimes in the world, there are priorities, and you're sort of at the intersection of that.
And I've been in plenty of teams where it was hard because of humans. In fact, that's often the reason of we're sort of making up problems, or we're poorly communicating or things like that. But it sounds like you're in the like, nope, this is just hard. And so, in a way, it sounds like you're thinking about it like, I don't know, it's kind of the challenge that I signed up for. Like, if we can win this, then there's going to be some good learnings that come out of that, and we're going to be all the better. And so, I wish you all the best of luck on that and would love to hear more about it in the future.
STEPH: Thank you. And yeah, it has been such an interesting project with so many different challenges. And as you've mentioned, that is one area that is going really well where the people are wonderful. Everybody is doing their best and working hard. So that is not one of the competing challenges. And it is one of those; it’s hard. There are a lot of external factors that are influencing the priority of our work. And then also, some external areas that we don't have control over that are forcing some of those deadlines where customers need something and not because they're being fussy, but they are themselves reacting to external deadlines that they don't have control over.
So it is one of those where the people are great, and the challenges are just real, and we're working through them together. But it's also hard. But it's helpful chatting through all the different challenges with you. So I appreciate all of your thoughts on the matter. And I'll report some updates once I have some more information.
On that note, shall we wrap up?
CHRIS: Let's wrap up.
STEPH: The show notes for this episode can be found at bikeshed.fm.
CHRIS: This show is produced and edited by Mandy Moore.
STEPH: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or a review in iTunes as it helps other people find the show.
CHRIS: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed on Twitter. And I'm @christoomey.
STEPH: And I'm @SViccari.
CHRIS: Or you can email us at hosts@bikeshed.fm.
STEPH: Thanks so much for listening to The Bike Shed, and we'll see you next week.
All: Byeeeeeeee!
Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.Sponsored By:Orbit: Orbit is mission control for community builders. Orbit offers data analytics, reporting, and insights across all the places your community exists in a single location. Orbit’s origins are in the open-source and developer relations communities, and that continues today with an active open-source culture and an accessible and documented API.
With thousands of communities currently relying on Orbit, they are rapidly growing their engineering team. The company is entirely remote-first with team members around the world. You can work from home, from an Orbit “outpost” in San Francisco or Paris, or find yourself a co-working spot in your city.
The tech stack of the main Orbit app is Ruby on Rails with JavaScript on the frontend. If you are looking for your next role with an empathetic, product-driven team that prides itself on work-life balance, professional development, and giving back to the larger community then consider checking out the Orbit careers page for more information. Bonus points if working in a Ruby codebase with a Ruby-oriented team gives you a lot of joy.
Find out more at orbit.love/weloveruby.Scout: Scout APM is leading-edge application performance monitoring designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise-platform feature bloat.
With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve performance abnormalities -- like N+1 queries, slow database queries, memory bloat, and more.
Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them.
Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform.
See for yourself why developers worldwide call Scout their best friend and try our error monitoring and APM free for 14-days, no credit card needed!
And as an added bonus for Bikeshed listeners: Scout will donate $5 to the open-source project of your choice when you deploy.
Learn more at scoutapm.com/bikeshed.Support The Bike Shed

Sep 7, 2021 • 37min
307: Walking Contradictions
On this episode, Chris talks about testing external services and dissects a tweet on refinements for Result. Steph talks about thoughbot's recent improvement to their feature flag system.
Links:
refinements For Result
Faking External Services in Tests with Adapters by German Velasco
Testing Interaction with 3rd-party APIs
Transcript:
CHRIS: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey.
STEPH: And I'm Steph Viccari.
CHRIS: And together, we're here to share a bit of what we've learned along the way. So, Steph, what's new with you?
STEPH: Hey, Chris. Well, today is Summit Day at thoughtbot, and it's the day where all the bots gather, and we hang out, and we chat, and we play games. And it's a lot of fun. We're actually taking more of a respite this year just because life has been taxing. And so we decided to give people more of the day off. So we still had some fun events, but most of it is everybody gets a chill day. Do something that brings you joy is the theme of the day.
But we had Lightning Talks, which is my favorite thing that we do on Summit Day because I realize that I just work with the coolest people, and they have such interesting things to talk about. And we had such a variety of topics. So one of them, Alex Chen taught us acronyms in K-pop. And Sam Kapila, our resident foodie, taught us about a variety of spices. And one of my favorite talks was by Akshith Yellapragada, and it's the top 10 best limo entrances by The Bachelor, and it was phenomenal. And I really want to share some stuff that I learned with you.
CHRIS: The Bachelor like the TV show?
STEPH: Yeah, like the TV show. Are you familiar with it? Have you seen it before?
CHRIS: I am familiar with it. I know it exists. I know that there's a spinoff, The Bachelorette. And I believe we have now exhausted my information on the matter.
STEPH: [laughs] That's fair. For anyone that hasn't seen the show, the show revolves around a single person. For the bachelor, it's a single bachelor who dates a number of people over several weeks, and then they narrow down the people. There are elimination rounds, and the whole goal is for them to find their true love. So each week, someone is eliminated, and I think the show ends with a marriage proposal. So it's a wild show. It's something. [chuckles]
And in Akshith's talk, I learned some really fun terminology. The first one is the Crown, and this is actually an important building block because we're going to get to the rest of the terminology that uses this word, so we got to start here. So the first one is the Crown, and this is the person that everyone's competing for. So they're the star of the show. They're the one that everybody is hoping to fall in love with or will fall in love with them so they get a marriage proposal.
So then the other stuff that I've learned is all about the entrance because again, we're talking about the top 10 best entrances. And one of them is the sidecar entrance. So this is where the player, because yes, this is totally a game, has someone assist them in meeting the crown. So it could be like a family member, maybe it's like your grandma.
And then there's TOT, T-O-T, which is short for Trick Or Treat. And this person exits the limo wearing a costume. So it's someone wearing a shark costume. There was someone wearing a sloth costume where they really dedicated to the role, and they climbed a tree and hung from a branch. I don't know for how long but for long enough to really vibe with the role.
And then there's the Kringle, and this person brings a prop or a present to the Crown. And there's the Grandy, and this player arrives in something other than a limo. So the example that Akshith provided is someone arrived in a motorized cupcake.
CHRIS: Was the cupcake edible?
STEPH: I don't think so, fair question. [laughs]
CHRIS: So really just like a go-kart that looked like a cupcake, not really a motorized cupcake, if I'm going to meet pedantic about the thing, [chuckles] which I think is my job.
STEPH: Yes, it is a motorized non-edible cupcake, but that seems like something a next player should do. They should really up the game, and they should bring an edible motorized cupcake.
CHRIS: Yeah, because you get the visual novelty, but then you layer on top of it that it's actually something that you can now eat, and it's a double win.
STEPH: Ooh, and then you're a Grandy, and you're a Kringle because you arrived in something other than a limo, and it's a present.
CHRIS: I love how you have so deeply internalized this now that you're like, ooh, okay. I can remix here. I'm going to bring together the pieces. Yeah, all right. Yeah, this all makes sense.
STEPH: Yeah, it was a lot of fun. Those are most of my notes for today. I have some tech stuff too, but this felt like the most important thing to start the show with.
CHRIS: We use the phrase tech talk and nonsense to describe the show often, but I think nonsense and tech talk is the correct orientation.
STEPH: [chuckles]
CHRIS: Correct in terms of importance and chronological order, and whatnot. But yeah.
STEPH: I love that we start with a bit of nonsense. So I do have some tech stuff. But first, before I share any of that, what's going on in your world?
CHRIS: I'm sure there's plenty of nonsense in my world, but at the top of my list is some tech stuff. So someone on Twitter, Adam Lassek, reached out and he suggested related to the conversation and the back and forth that I've been having with myself around some of the data structures within the app that I'm building…So I've talked about the dry-monads result object, and there's this success and failure. And I wanted to introduce this new method called bimap, but I wanted to do it in a reasonable way. So I wrapped, and then I wrapped, and I wrapped things.
As an aside, former colleague and friend of the show, Joel Oliveira, sent a wonderful tweet which was a reference to the SNL video where they make a taco and put it inside of a pizza and put it inside of a bag. And that was his joke about it, which I really liked. That was an excellent reference. But in this case, Adam Lassek reached out and suggested if I'm that squeamish about monkey patching, which I am, have I considered refinements? And so he sent an image of a code sample, which is so kind of him to send that much detail over, but it was interesting because I know of refinements in Ruby. I know of that as an alternative to monkey patching, a more refined way, but a safer way, a more controlled way to alter code, but I've not actually used them.
STEPH: I'm not familiar with refinements. What is that?
CHRIS: Refinements are a way...so similar to monkey patching, where you say like, I'm going to reopen this class or this module and define a new method or redefine a method or do something like that, a refinement is a way to do that in a scoped manner. So I'll be honest, I'm not super familiar with them. I think I came into Ruby at a time where the community was moving away from monkey patching. And the dogmatic swing of the pendulum was like, that's a bad thing to do. And so even the refinements were introduced, as far as I understand it, to be a more controlled way to do it. So it's not just like, hey, cool. This module is redefined now in your app in a magical way that's really hard to figure out and hard for folks to debug refinements. You have to explicitly opt into within a certain lexical scope.
I'll be honest; I know that at the headline level. I don't actually know the ramifications or where and when you can use them and how you can. But I know that that was the idea is refinements are a way to do monkey patching but in a more controlled, more understandable manner, and so the code sample that Adam shared does that. And it's very interesting. As I'm looking at it, I'm like, okay, that's cool because I think it'll be a little bit safer.
But at the end of the day, my concern wasn't safety in this case because I was introducing a method that would be new, that would be additive to the API of this module that I'm working with, and so that I think of as a relatively safe operation. My hesitation was more around how does someone figure it out if they're working with this? And particularly, the name of the method that I was introducing was bimap so, B-I-M-A-P. And if someone sees that in our codebase and is like, "Bimap, where is this coming from?" Well, this is one of those dry-monad result objects. And they go to the code, and they try and look it up in the docs, and they're just not going to find anything.
And I can imagine losing a lot of time to try and chase that down. There are ways to figure it out. There's the method in Ruby, which is a wonderful trick for chasing things down. Or if you grep the codebase, you'd find it. But I think I'm possibly over-indexed on worrying about that lost time, that moment. But I've lost that time so many times in my life where I'm like, I can't grep for this. I can't Google for this. And so I have so strongly moved in the direction of being like, everything should be grepable, everything should be googleable. Those are the two of the things that I believe about software. I think I believe a bunch of stuff.
STEPH: I think we have a full episode that talks about what we believe in software.
CHRIS: I believe we do.
STEPH: Cool. Thanks. Yeah, I have not heard of refinements. That sounds really interesting. I really like that bit about everything should be grepable, and everything should be googleable, googling everything. I kind of agree with that one. We live in a world where we're always doing bespoke things so that one feels a little bit harder that we're always going to be able to Google it. But then that encourages people to constantly publish the bespoke work that they're doing so then others can benefit from that work. But the grepable, I absolutely agree with that one. It's so frustrating where I see a method, but I cannot find its definition. And then having the ways to figure out where that method is defined to then find its definition is crucial.
CHRIS: Yeah, it's interesting. I definitely feel that way very strongly. And it's in such stark contrast to Rails. Rails is like, hey, don't worry. There's going to be a lot of methods. You don't need to worry about where they come from, or why they exist, or what they are, or what they do. Well, probably what they do. But all of the magic inflections on database tables,, and suddenly you have methods named after every column. That's both very magical and hard to grep for or impossible to grep for, but it also leaks the entire structure of your database into your application in a way that I've always felt a little bit complicated about. And so explicitness, grepability, those are things that I care about.
There's another one, delegates in Rails, that I sometimes pause around using especially when it's like delegates 19 methods to user prefix user. And so you end up with methods that are like username. And that's a delegation to the user object to get the name method off of it, but it creates the method user_name. And you're never going to be able to grep for that. And it saves like a little bit of code, definitely, but it saves this very obvious, very knowable code. So this one I actually shy away from using delegates in most cases, and I'll just write out the methods manually because sometimes I like to hear the clackety of my keyboard. There's a reason I have a clackety keyboard.
STEPH: You want to get your money's worth. You want to clackety as much as possible. Yeah, I'm also not a fan of delegates. This may be a lie, but I don't know that I've actually ever used it. I've worked with it, but I can't think of a time that I've implemented delegates. Maybe that's a lie, but I'm going to say it anyways because that feels true, at least in the last couple of years.
CHRIS: I feel like that could be true for the last couple of years. I would be surprised if you have never even added to a delegates line. Because that's the thing, you can just keep shoveling stuff into them as well. So I would put money on you having used it at some point and then just forgotten about it. But who knows, maybe not.
STEPH: This is where we play two truths and a lie and that one's my lie. [laughs] Yeah, that's also fair about adding to it because if that's already defined and it's easier to add to it, I don't know. Who knows what past Stephanie has done, probably some wild stuff.
CHRIS: It's unknowable at this point. It's lost to the sands of time. But looping back to the core thing of this refinement and the module, I think I'm leaning in the direction of doing that and unwinding my wrapping and wrapping layer thing. Because obviously, as I talked about...I think it was the previous episode or maybe two episodes ago. There was conceptual complexity to the additional wrapping layer. Even as I was fully in the context of working on that, I was still getting myself confused in either triple wrapping or then unwrapping too much or whatever. And these are the concerns with this type of code. So moving away from that feels better, having just a single layer of context wrapping around a given value.
And then the other thing it's actually just a lot less code, and it's less prone to error, I think. That's my hope. I have to look into exactly how refinements get used, but I noticed in a couple of places that sometimes we were wrapping with this local value object that gave us the bimap method, and sometimes we were forgetting to. And so, I could see that being a very subtle, easy way to introduce failures into the app that would be hard to catch just by looking at it.
So I think having a more global refinement...although I think that's sort of a contradiction, a global refinement because I think refinements are meant to be local. But anyway, I'm going to look into it because it's a much more concise code sample than what I have. Yeah, I'm going to poke at that a little bit. But it was an interesting exploration of some different things. And then it forced me to consider why am I so resistant to monkey patching at this point, especially in this particular case where I think it's okay-ish?
STEPH: That's a good question. Do you have any insights? I am also resistant to monkey patching. I feel that pain and also that timidness of diving into that space. But I'm curious, have you figured out any other reasons that you really prefer to avoid it?
CHRIS: I think this one falls into that sort of...what's the word? Like tribal knowledge of we've been burned by it in the past and therefore we build almost a...religious is too strong of a word but that sort of cultural belief. This is a thing that we do not do because of the bad things that we've experienced in the past. And there are a lot of things that fall into that experiential negative space.
So with monkey patching, things that I know we can run into is if I introduced this bimap method, but I introduce it subtly differently than the library will eventually, then they could eventually introduce it themselves. And suddenly, I have this fork of my code expects it to work this way, but you've now implemented it that way. I no longer can upgrade. This is a critical piece of infrastructure in my app. I've just painted myself into a corner by doing this. Whereas if I do this wrapping layer, that's my code. I own that. It's not going to be a problem in that same way.
There's also the subtlety, the grepability that sort of thing is a concern in my mind. Like, is this our code? Is this their code? Is this an engine? Being able to find code within a codebase, I think, is a critical thing. And so that's a part of the hesitation. I also know longer ago prototypes...I want to say Prototype JS was the name of the project, but it was one that was just like, yeah, JavaScript doesn't have enough stuff in the standard library. So we're just going to override everything and add all of these wonderful methods sort of in the way that Active Support does, which is an interesting comparison.
But the JavaScript community definitely moved away from Prototype. And now JavaScript is a language or the standard runtime that's available in most JavaScript engines. It has a lot of the methods, but there are conflicts, and stuff gets weird, and it's all complicated. But again, as I thought of it, Active Support is a complete contradiction to everything I'm saying. Active Support just adds whatever to anything, 2.days.ago. Why does the number 2 have a days method? Because it's great, that's why. But I'm just a walking contradiction, I guess.
STEPH: Everything you said really resonates with me. And I'm just trying to reason with myself like yes, Active Support uses a lot of this, a lot of metaprogramming, and adds everything it wants to. So why does that feel okay? And I wonder if it comes down to one is more almost like an agreed standard. It's built by a team, and it's maintained by a team, and then it's used by a large number of people, and then you get that feedback. Or maybe it's not even just a team, but it's a larger community versus if it's internal to your software team, maybe that doesn't feel like a big enough group or if it just needs...Rails is also documented. So maybe that's part of it, too, is if you are going to dive into that space, it's easy to discover, and it's well-documented as if you are building an open-source project that other people are going to use. Like, you designed for the intent of people to use this pattern that you've introduced, then perhaps that's when it starts to feel okay. ,
But the experiences I have had is where people basically will add some dynamic programming or monkey patch an existing feature. And then that's very hard to find and has surprising results, or it gets outdated. So I guess it comes down to who are you designing for? Are you designing for more of an open-source community, or you're at least designing for the people behind you that are going to be using this? Or is this a one-off adventure that you have chosen for yourself and future developers to discover? [chuckles]
CHRIS: Yeah, I think that's a good summary, although I'm open to the fact that I exist in a state of contradiction. I'm also fine with that, to be clear. [chuckles] But I think what you said is true, and I think there is subtlety and nuance and reasons that it's okay in one context and less okay in others. And that idea of just like, I don't know, this is one of those things that I got in my head that I've done the thinking a long time ago to decide this is a thing I don't do.
So now, in order to override that, I would have to do so much thinking. I would have to be like, all right, well, my brain tells me, no, but I'm going to go reread everything about monkey patching right now to convince myself that it's okay or to fully get the context and the subtlety and the nuance. And so sometimes we have to rely on that heuristic knowledge of monkey patching, nope, don't do that. That's not a thing, but other stuff is fine. And well, Active Support is fine because it's Rails. But it is interesting to observe contradictions and be like, huh, look at me go. All right. Well, moving on.
STEPH: It's our lizard brain that's saying, "Hey, there's danger here." [laughs]
CHRIS: Exactly.
STEPH: I rather like living in a world of contradictions, or at least I find it that I'm drawn to them. And maybe that's also one of the things that I really like about consulting is because then I join all these different teams, and I hear all these different opinions. So as I'm forming these opinions around something like tests are great, I really like tests, and then someone's like, "I really hate tests." I'm like, "Cool. Let's talk. I want to understand why you don't like this thing that I think is wonderful because then I'm really interested." So I find that I'm often really drawn to contradictions as I like hearing opinions that are very different than mine and finding out why people have a different opinion than mine.
CHRIS: Yeah, the world is full of contradictions. So it's, I think, at least a useful way to exist in the world, to be open to them and to enjoy exploring them. But yeah, I'll update in future weeks if I do end up going the refinements route. I'll let you know if anything interesting falls out of that.
And now we're going to take a quick break to tell you about today's sponsor, Orbit. Orbit is mission control for community builders. Orbit offers data analytics, reporting, and insights across all the places your community exists in a single location. Orbit's origins are in the open-source and developer relations communities. And that continues today with an active open source culture in an accessible and documented API.
With thousands of communities currently relying on Orbit, they are rapidly growing their engineering team. The company is entirely remote-first with team members around the world. You can work from home, from an Orbit outpost in San Francisco or Paris, or find yourself a coworking spot in your city
The tech stack of the main orbit app is Ruby on Rails with JavaScript on the front end. If you're looking for your next role with an empathetic product-driven team that prides itself on work-life balance, professional development, and giving back to the larger community, then consider checking out the Orbit careers page for more information. Bonus points if working in a Ruby codebase with a Ruby-oriented team gives you a lot of joy. Find out more at orbit.love/weloveruby.
STEPH: So we made a recent improvement to our feature flag system, which I'm really excited about, that we have found a way to improve that workflow because it felt really great that we're...well, okay, I should say that with a caveat. It felt really great that we're using feature flags to ensure that the main branch is always in a deployable state. But it did not feel great around how tedious it was becoming to add all of the feature flags specifically because each time we're adding a feature flag, we're having to add a migration. So we're having to run a migration, add the feature flag column, and then we can interact with that feature flag. And that part's okay. It was more removing that feature flag once we're done with it, that that part was starting to feel tedious because then that's becoming a two-deploy process.
So one change is to remove the code that's relying on that feature flag. And then the second deploy was to actually drop that column because we wanted it to be safe to make sure that the code wasn't trying to reference a database column that didn't exist anymore, which is what happened at one point at first when we weren't doing the two-deploy process.
So the improvement that Chris White came up with is where we're now using a Postgres JSONB column. And it's here that we actually have a feature flag YAML file. And we can have the name of the feature flag. We have a description of the purpose of the feature flag. And we have an enabled property on there, so then we can turn it on and off. The benefit of this is now we don't have to do that two-deploy process. And we also don't have to run a migration for when we're adding a new feature flag. So we can add it to the feature flag file, we can load it in, and then we can set that property to say, "Yes, this is enabled," or "No, it's not." And that has just simplified our feature flag process.
One tricky bit that I believe the team ran into is around enabling this with Active Admin because Active Admin was just relying on those database columns to then turn something on or off. But then we've added some methods that work well with Active Admin that then say, "Read from here when you're checking to see if something is enabled," or "Look at this list to see which feature flags can be turned on and off." So it's been a really nice improvement, and everybody on the team seems to be in favor of the ways that we've improved this. So it's been really nice. So I wanted to come back and bring an update on how we've simplified our feature flag system.
CHRIS: That definitely sounds like a nice improvement, the ability to just more regularly iterate around that or taking away the pain, any pain associated with using feature flags. Because they are such a nice thing to have, but there's that overhead. Then you start to have that voice in your head that's like, do I really need a feature flag for this? Could I just sneak this one in? And we always regret that.
I had a similar thing this week where I wrote some code. I didn't quite write as many tests as I should have. And it was wildly broken, just like all of the connection points through everything were broken. But then it pushed me in an interesting direction where I was like, well, what I'm going to do is write an integrated test. It was basically an event coming in from a webhook that then enqueued a job, which did a thing, which then spit out an email. But it was broken at like three layers, and I was very embarrassed, if we're being honest. But, I don't know, I was just having a low energy afternoon, and I did not write the test, which I know I'm supposed to do.
So similarly, any pain that we can take out of these things that we're supposed to do, any way that we can pave the happy path, I'm all about those. I'm intrigued because I think we've talked about this before, but it sounds like you guys have a very home-grown feature flag system. Is that true?
STEPH: We do.
CHRIS: Is there something about it that makes it unique to your situation, or was it just like that's what happened? Someone early on was like, "We need feature flags. I can just do the simplest thing that works," and then that's where you're at now or?
STEPH: You're asking a very good question. And I'm trying to recall what led us to the state that we're in because I feel like we had this same discussion several episodes back when we were introducing the home-grown feature flag system. And I was like, there are reasons, but I didn't really dive into those reasons because it felt very custom to the application. But now I've forgotten what those reasons were. So I think you ask a great question where it'd be worth revisiting to confirm that yes, there's a reason for this home-grown version versus using something like Flipper.
CHRIS: I'm glad I'm at least consistent over time in the questions that I ask and the heuristics that I have. This does feel like one of those things. It's not quite like crypto where I'd be like, we can never write our own crypto. But a feature flag system, I would be really intrigued if there are things that they are just workflows or functionality that you really need that are not supported by any of the existing solutions that are out there. I think audit trails is an interesting one. I think Flipper has a hosted product at this point that does that, but the local version wouldn't necessarily. So maybe that's a thing that you want to get. Again, I'd just be really interested. It sounds like the current state of the world that you have is enabled or disabled; just broadly, that's it. Those are the two states for any given flag. Is that true?
STEPH: It is. There's nothing complex with the flags in that nature. And then we use naming to indicate if something is more for beta, so if it's a change that we're making to the codebase, but it's a feature flag that we plan on removing, versus maybe it's a feature flag for enterprise customers.
CHRIS: Oh, interesting. I wouldn't think of using a feature flag in that context where it's going to be like a persistent, long-lived; this is conditional logic around some state or some property of the viewer. I think of feature flags as a way to gate code conditionally based on a point in time. And the reason I asked about the enabled-disabled basically like the Boolean state for your flags is when I've worked with feature flags in the past, I've liked having the ability to say, for this user or these users, or this group of users, which we've named this is our beta list…and it's the ten people that just really love the product and are happy to bump into some rough edges. And so we'll put things on for them first or even like percentages, so roll it out to 10% and then 50% and so on. And I think the larger an application and user base gets, the more that sort of thing starts to feel right.
STEPH: Yeah, we certainly have some complexity around where each customer can really specify which features that they want. And then the features also differ a bit for each customer. So we are in a world where we're pretty customized or configurable for different customers. And whether that's something that we could simplify, that would certainly be a good question or something to pursue.
But part of this also feels like our decision may have been based around what the system was already doing, and we're looking for ways to make slow improvements versus trying to redesign the whole thing. Because initially, the way we were customizing all of these different features for customers was in a YAML file. And that part was painful because then, anytime we wanted to make a change, it required a deploy. So the introduction of feature flags is really to get away from having to deploy to then make a small change like that.
But now that we're in the space that we can easily configure that change and do that on the fly and not have to issue a deploy, I think we're now in a good space to reassess. And the team may have some really good answers. Perhaps I'm just not recalling as to why we've chosen the more home-grown feature flags. But yeah, I'll visit that topic and report back. Because I've been coasting along on our new system and enjoying it, but you're asking some really good questions.
CHRIS: I mean, as an aside, if you're coasting along and really enjoying it, then maybe you don't need to ask any questions. It's still interesting. I would be intrigued to know. But if it's not causing you any pain, then you probably shouldn't change it. Because frankly, changing out the feature flag system is going to be non-trivial, I'm pretty sure. You could feature flag the feature flag system, and then you can transition from one to the other. You need a third feature flag system for that. But anyway, I digress. [chuckles]
STEPH: You referenced crypto earlier. So I think I like the feature flag, the feature flag system. We should have some crypto flags in there somewhere. I think that's a thing too. But I think the main goal if I'm looking into changing it would be, circling back to what we were talking about earlier, is discoverability, so having a home-grown feature flag system. How easy is it for…if nobody was around on the team and there was someone new working with it, how easy would it be for them to turn something on or off? And if that's easy, then that's great. Then I think we've got a great home-grown system. If that's challenging, then I definitely think it's worth reassessing.
And now a quick break to hear from today's sponsor, Scout APM.
Scout APM is leading-edge application performance monitoring that's designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise platform feature bloat. With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve those performance abnormalities like N+1 queries, slow database queries, memory bloat, and much more.
Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them. Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform.
See for yourself why developers call Scout their best friend and try our error monitoring and APM free for 14 days; no credit card needed. And as an added-on bonus for Bike Shed listeners, Scout will donate $5 to the open-source project of your choice when you deploy. Learn more at scoutapm.com/bikeshed. That's scoutapm.com/bikeshed.
CHRIS: One of the things that's been interesting working lately in the app that I'm building is thinking about testing. We have a number of interactions with third-party services. Frankly, a lot of the app is that at this point. We have a handful of different external data providers systems that we're interacting with, webhooks and flows and things like that. And so we had to make that decision that you always have to make in these sorts of situations which is, how are we going to test this?
And there's a wonderful blog post on the thoughtbot blog called Faking External Services in Tests with Adapters. It's by the one and only German Velasco. And it is a beautiful summary of the different approaches that you can take, but it really dials into one, which is the adapter pattern. There's also a weekly iteration episode on Upcase with Joël Quenneville, which discusses a little bit more of an exploration of the different options. There are sort of a handful of different options that we can consider your whereas the blog post by German talks specifically about the adapters approach.
But to talk about them briefly, there's one where you can go all the way outside your app, spin up a fake service. Typically, we would do this with Capybara Discoball, which is a wonderfully named project. But it allows you to spin up a little Sinatra app type thing such that your web application is still making quote, unquote "real HTTP requests." This external service is going to catch that and respond with whatever canned data or structured responses that you want.
But you still have the ability in that to, say, tell it to create data beforehand or be in a certain state or respond with certain data or have any stateful persistence. So if you create a record in that external system, and then later you query for it, that system can do that. But it has the complexities of now, your test suite is running different systems. And do you have thread-safety or all that kind of stuff? So that's a particularly complex end of the spectrum. At the lowest end would be stubbing and mocking. You just take whatever external clients you have, and you're mocking the API calls in them. That's the lowest end. And that's the one, especially for feature specs, those I try and avoid. Then there's a middle ground of like WebMock or VCR, those sort of things where you're saying whenever you see an HTTP request that looks like this, respond in this way. You record the cassettes, all that kind of stuff.
And then there's the one that we've settled on, which is the adapters. So the client that we've introduced in our local codebase to interact with any of these third-party systems internally has a class attribute, a cattr_accessor in the Rails parlance, I believe. And that allows us to switch out the backend. And so we have a real HTTP backend, and that's the one that actually runs in production and a test in-memory backend. And that in-memory backend can implement whatever logic. We're ending up with one of them almost recreating this external service, sort of re-coding some of their inconsistencies or oddities but also features and whatnot.
But it feels like it has struck just the right balance, and it allows our feature specs to be very rich, very real. We start up the world, and we say, "Hey, external service be in this state." And then I'm going to go visit the page. I'm going to see the data. But we are almost making real HTTP requests. It's very close. It's always an interesting choice to make here. I'm very happy with the one that we've made, but it's still not perfect. There are always going to be trade-offs between the different options here. But it's always interesting revisiting this and being like, which one am I going to choose today?
STEPH: I feel like my natural progression when testing external services; I always start with WebMock, and then I progress to using adapters. And then from there, I go to actually replacing the HTTP service that is receiving and then returning a response, like you mentioned to Capybara Discoball earlier. So I can certainly see what you like about the adapter pattern. You mentioned that you're coding some of the inconsistencies. That feels very real. I'm curious if you have an example of how you've had to manage that recently.
CHRIS: A specific example would be the external API responds with certain error codes or error structures. So it's an error. It has a status of a number and then a reason, or sometimes instead of a key that is reason; it’s the message. So it's like, oh, okay, I see that in this endpoint, you respond with reason, and then this endpoint you respond with message. So now, do I encode that into my fake? I guess I do. So my adapter now implements things like that. There are cases where it's inconsistency where I'm like, well, this is the way they behave. So I would like our test suite to exist in the context of that because then our app is getting exercise in a real way.
But in some cases, it's like little bits of logic validation that an external system might do if that's an important part of the flow. The app that we're building has a lot of forms and a lot of data validation and things like that. And so, we want to make sure that we have robust handling around that robust messaging to the user so that it's very clear what they need to do and how they need to respond to things. And so putting in little bits of that like, oh, that's how you format a phone number, okay, cool. Our fake will also format phone numbers in that way, things like that.
STEPH: Every time the topic of testing external services comes up, I really, really want VCR to be the answer. I really like the idea of being able to validate that...because you'd mentioned that we're programming the expected return from this other service. And it's very easy to get out of sync with those actual responses. And then we don't really have a great way to stay up to date other than we wait for production or staging environment to fail. And then we realize something has changed, and we have to go and update either our mock or our adapter. And maybe that doesn't happen often if you're working with an external service that is very good about broadcasting when they have a breaking change.
But if you're working with a less stable endpoint, then I always want VCR to really work. But it's just one of those areas where I'm like, yes, that's the thing that I want. I want this idea where I can rerun my tests in a way that they actually hit that service and record the response. But then I have felt pain [chuckles] from working with VCR and how it's configured, and how people have used it. It's one of those where I don't blame the library. I like the library. But the way people have implemented it and test I have felt a lot of pain from that.
CHRIS: Yeah, I definitely agree with that. It feels like it's nice if you can push the mocking all the way out to that layer. Because like right now, our codebase has code in it that is subtly changing the behavior for a test, and I don't like that. It's only the swapping out of the adapter, so it's a very minimal thing. And we try and push all logic away from that such that the test adapter is as similar as possible to the real production situation. But it's enough difference that I agree I would like if VCR would just like, I catch the HTTP requests, and I respond with the same thing and sometimes we can pass through.
I do think one of the fundamental limitations, or at least very hard to get right things, would be sequential requests. So I post to this endpoint in the external service, which creates some data. And then later, when I make a GET request to their endpoint, I should get back that data that I just created. That's, I guess, doable because you can have sequential requests, have cassettes that are first this request, then that request, then that request. And it knows that, like scope them to a given spec. But that feels extra difficult. And it does, again to your comment, the maintainers of that project do a wonderful job, but it's a really hard target to hit.
STEPH: Well, and one of the other hard requirements with using a tool like VCR is then that external service really needs that sandbox staging environment that you can use. So that way you can create this data, you can rerun your test. So they're actually going to hit this real environment. They're going to create this data and that not have any harmful effects. And then you can record fetching that data. So it requires a lot of pieces to fall into place for it to work well. But then I was just thinking as you're talking about adapters, I'm like, yeah, I love the adapter pattern. I've really enjoyed that one for testing as well. But then I immediately start to think, oh, well, what happens when it gets out of sync, and how do we know that it got out of sync? And I don't have a great answer to that.
CHRIS: Production blows up, obviously.
STEPH: Production blows up, and then we go update our adapter. That's very calm. [laughs]
CHRIS: It would be great if CI could more proactively catch that or...yeah, I agree. I would love if VCR would work because that facet of it is so attractive. But [chuckles] I've never gotten to walk exclusively the happy path with VCR. So here we are. This is a classic case of here's four options as to how we can think about this hard and important thing that we do in our codebases, and they all have trade-offs much like everything else in software.
STEPH: I'm going to add this to my developer bucket list to live in a world where I can easily validate if an external API has changed or not and then also have tests that know when something has broken before production does.
CHRIS: Ooph, dare to dream. I like it.
STEPH: I'm a dreamer.
CHRIS: I want to live in that world. Well, with that wonderful dream to take us out, should we wrap up?
STEPH: Let's wrap up. The show notes for this episode can be found at bikeshed.fm.
CHRIS: This show is produced and edited by Mandy Moore.
STEPH: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or a review in iTunes as it helps other people find the show.
CHRIS: If you have any feedback for this or any of our other episodes, you can reach us at @_bikeshed on Twitter. And I'm @christoomey.
STEPH: And I'm @SViccari.
CHRIS: Or you can email us at hosts@bikeshed.fm.
STEPH: Thanks so much for listening to The Bike Shed, and we'll see you next week.
All: Byeeeeeeeee.
Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.Sponsored By:Orbit: Orbit is mission control for community builders. Orbit offers data analytics, reporting, and insights across all the places your community exists in a single location. Orbit’s origins are in the open-source and developer relations communities, and that continues today with an active open-source culture and an accessible and documented API.
With thousands of communities currently relying on Orbit, they are rapidly growing their engineering team. The company is entirely remote-first with team members around the world. You can work from home, from an Orbit “outpost” in San Francisco or Paris, or find yourself a co-working spot in your city.
The tech stack of the main Orbit app is Ruby on Rails with JavaScript on the frontend. If you are looking for your next role with an empathetic, product-driven team that prides itself on work-life balance, professional development, and giving back to the larger community then consider checking out the Orbit careers page for more information. Bonus points if working in a Ruby codebase with a Ruby-oriented team gives you a lot of joy.
Find out more at orbit.love/weloveruby.Scout: Scout APM is leading-edge application performance monitoring designed to help Rails developers quickly find and fix performance issues without having to deal with the headache or overhead of enterprise-platform feature bloat.
With a developer-centric UI and tracing logic that ties bottlenecks to source code, you can quickly pinpoint and resolve performance abnormalities -- like N+1 queries, slow database queries, memory bloat, and more.
Scout's real-time alerting and weekly digest emails let you rest easy knowing Scout's on watch and resolving performance issues before your customers ever see them.
Scout has also launched its new error monitoring feature add-on for Python applications. Now you can connect your error reporting and application monitoring data on one platform.
See for yourself why developers worldwide call Scout their best friend and try our error monitoring and APM free for 14-days, no credit card needed!
And as an added bonus for Bikeshed listeners: Scout will donate $5 to the open-source project of your choice when you deploy.
Learn more at scoutapm.com/bikeshed.Support The Bike Shed

Aug 31, 2021 • 45min
306: If You Want To Go Far, Go Together
In this episode, Steph and Chris talk about things they've changed their minds about over the course of their careers as software developers. Steph talks about as it turns out, arm chair rests are good, feature flags and comments are also good, she's changed her mind about how teams structure the work that each person is doing at once, and believes strongly in representation in the field.
Chris is not a fan up upgrading his operating system and when he first started out, he gravitated towards learning dynamic languages, and since then, much prefers functional languages, static typing or more broadly, static analysis. He also no longer believes in the 10x engineer, and also very much believes that URLs matter on the internet. So basically, don't call them single-page applications; call them client-side applications instead!
Arq
Karabiner-Elements
Kent C. Dodd’s Epic React Course
The Art of Code Comments by Sarah Drasner
Gary Bernhardt: Functional Core, Imperative Shell
Steph's Standing Desk - curved top - 55x28
Transcript:
CHRIS: I still have dreams that I missed an entire semester of math class, and now it's time for the final. I don't know that I'm ever going to grow out of that.
STEPH: That's wild.
CHRIS: You don't experience that? It's a mixture of I'm in elementary school, but it's a college final. Like, the physical school that I'm in is my elementary school, but it's a calculus college course that I missed. And now it's time for the final, and I won't graduate college as a result. But it's also high school at the same time. Just every part of education sort of melded together into this nightmare scenario. Do you not experience that? I thought this was normal.
STEPH: [chuckles] Not in a very long time, not since I was in college. But I'm imagining this very cute, young Chris showing up with a backpack to the calculus final like, "Oh no." [laughs]
CHRIS: Yeah, pretty much, yeah. I really thought I would grow out of it at some point. But it shows...I think it manifests when I have anxiety about something else in the world, and then I have a math terror dream.
STEPH: That's your stress sign. That's your terror dream.
CHRIS: Apparently.
STEPH: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Steph Viccari.
CHRIS: And I'm Chris Toomey.
STEPH: And together, we're here to share a bit of what we've learned along the way. Hey, Chris, how's your week going?
CHRIS: Oh, it's going fine. Yeah, I'll go with fine. I had to upgrade my operating system. Enough things had stopped working or seemed to be pestering me about it regularly, which normally I'm going to ignore that for as long as I can. That's sort of where I'm at in the world these days. Like, I don't want to upgrade because I don't know what's going to break and whatnot, but then things had broken already.
Text messages were no longer showing up on my computer. And it turns out that the primary way that I interact with text messages is by replying to them through my computer. I don't want to type on my phone, that's not a thing. I'm already grumpy enough about text messages, to begin with, that I will regularly respond switching to email, and then I'll go off from there. But yeah, they stopped working, it stopped connecting.
And then I got this really weird message from Apple when I tried to sign in. And I was like, I feel like I should at least try to upgrade to the new operating system, which I think has been out for a long time, and I've just been ignoring it. But then I had the added problem of I didn't have enough space on my computer to install it, which I tried once before.
So I downloaded the installer, but the installer downloader doesn't check whether or not you have enough space to do the install. So it's just like, hey, so you know how you didn't have enough space? Well, we took up the remainder of it, and now you can't do anything about it. And the installer is hidden somewhere in the computer. So at one point, it just went away, and then suddenly had a lot of space on my computer. But finally, I decided to bite the bullet.
I found a bunch of caches on my computer. So there was a cache for my backup utility, which is called Arq, A-R-Q, which was a lot of space. It was like 20 gigs or something like that. So it was like, sorry, you have no more cache. I'm pretty sure my computer's going to light on fire the next time it tries to do a backup because it has no cache to rely on, and it's got to try a lot harder, pull a lot more data down. I don't know what it does, but whatever. It's going to do that.
And then, I found the more general application caches on the computer. Spotify had like six gigs of cache. Well, what are you doing? Aren't you streaming from the internet? Stop it. That's not okay. That is not acceptable. Yarn had three gigs. I was like, what is everybody doing? And I busted all of these. I threw away everything, and my computer seems to be doing fine after the fact. So, were the caches even doing anything? I ask.
Anyway, so I upgraded, and then some stuff didn't work. And so then I had to find the versions to make stuff work. The particular one that stood out was Karabiner-Elements, which I used to make my mechanical keyboard do the right things for the function keys. That stopped working. And I tried to upgrade it to the newer version because I figured okay; they probably hopefully released a new version, but it failed in the upgrade process.
And it turns out the secret was I had to upgrade to an intermediate version. I was on 12.3, and I needed to go to 13.4. But in between, I had to go to 12.10. And if I went to 12.10, then the upgrade to 13...everything about it was everything that I hate about upgrading software. It's like, I just know it's working right now, and I feel like if I even just look at it wrong, this whole tower of software is going to fall over.
The worst thing, the thing that I have not been able to fix, is now I use iTerm as my terminal, my terminal emulator as it were. And I typically run with transparency mode on which some people look at and say, "Wow, that's a choice." And I say, "I kind of like it. I don't know; it makes me feel like a hacker or something." I don't know, whatever. [chuckles] Let me live my life. But for some reason, switching to Big Sur, the version of OS X that I'm on now, iTerm doesn't have transparency anymore. And I just haven't been bothered to fix it yet.
But, man, I got rambly. I clearly have some feelings about upgrading software.
STEPH: You have so many feelings. The fact that you kept going...People can't see me, but I'm just dying because of that whole story. [laughs]
CHRIS: I kind of felt like I had to get through it. I had to exorcise the demons, tell my tale, and then be done with it, which I think I'm at now.
STEPH: When I start laughing that hard, [laughs] I try to hide from the camera view because I want you to keep going for people to listen.
CHRIS: But what's fun is you bob and weave. You'll hide for a minute, and then you'll come back and be like, okay, I'm composed, never mind. And then you'll just fade off to the side again. So yeah, but I powered through. [laughs]
STEPH: Oh, all right, there is so much there. [laughs] Upgrading is the worst. I agree with that. That was actually something I ran into earlier this week. Well, it was a mix of where upgrading presented a problem and then upgrading something else resolved that problem. And so that was an adventure where I shared a tweet. I can link to it in the show notes as well.
But Ruby was just taking up 100%, a full core, just all the time, and I couldn't figure out why. I wasn't doing anything with Ruby. We weren't talking at the moment, but it was just turning up one of those 100% CPU or higher. And so then I did some searching. And I did find the resolution, which was to upgrade the Listen gem because there was something in the Listen gem that didn't fully support Big Sur. Is that the name of the thing that I am on?
CHRIS: That's the new one, yeah. I know because I've just upgraded to it. I have thoughts on the matter. [chuckles]
STEPH: Cool. [chuckles] Yeah, when I upgraded to Big Sur. But then someone had kindly marched in to fix it, then upgrading resolved that problem. And Ruby is back to a peaceful level as to the amount of process, the amount of CPU that it should be taking up. Transparency mode, I'm thumbs up on it. I like how you called that out, how that's a choice. And I'm with you on that choice, although I didn't realize that's broken. I guess I just hadn't...I guess I don't care deeply enough that I've tried to restore my transparency, but you're telling me to hold on.
CHRIS: We're going to get realer now in this moment. So I have a very old version of iTerm because it has a different way of going fullscreen than the default operating system level fullscreen. I really hate that it animates to fullscreen, and it doesn't quite fill the full screen. Like, it still had a border around it or something. So I have a very old version of iTerm that I've been running with forever, and I refuse to upgrade in any way as a result of I want to cling to this old version of things working. But as a result, I think I finally hit the end of the road on that. This is like years running now too.
I remember I kept it in a Dropbox folder so that each time I upgrade or get a new computer, I'm like, okay, good. I still have my old special version [chuckles] of iTerm. But I think that time is over and I got to find...I feel like there are new terminal emulators out there. It's like Alacritty and other stuff that people talk about. So maybe it's time for me to try and find something new as long as I can get that transparency because I want to feel like an uber lead hacksaw.
STEPH: You have such a brand of new-new that I'm now discovering that you are also a software hoarder, so you have both in your personality. [chuckles]
CHRIS: There was a period early on in my software career that was like, oh, I got to find all this stuff. I got to figure things out and configure it. And then I was like, wow, that's taking up a lot of my time, I should stop it. And I think since then, I haven't upgraded anything. If you go look at my .files, I don't know the last time I pushed to them, but it's been a while. I'm still doing things, of course, but not as much. I know the cost of it, and I know the cost of maintenance.
And really, this is an allegory for software overall. This isn't just about our local development environments, but entropy exists in software. Software does not exist at rest, and it will decay over time. And so the idea of we've worked with so many clients where they're like, yeah, we're on Ruby 1.8, and it's Rails 0.9. So okay, all right, well, we're going to have to deal with that, it turns out. We can't just keep ignoring that. So really, it's the same story played out but in my local hoarder cavern.
STEPH: There was a part of the saga, the story that you shared with the installer and that you don't have enough space, and it took up the rest of the space, and you can't do anything. I'm very nervous; what happened to your stuff, your space? How did that resolve? [chuckles]
CHRIS: I finally bit the bullet. And so I have a bunch of...I've tried a bunch of the different pieces of software that will visually analyze your disk space. So they crawl the whole directory starting from the very root of your computer, and it will be like, all right, applications has this much, and the library directory in your home directory has this much. Here are all of the different places that stuff might be hiding on your computer. And then you can visualize and be like, okay, that's where the most of it is.
Node modules, as an aside, we did not choose an efficient way to approach how to put code on my computer because Node modules take up a lot of space on my computer, but they're so spread out. Multiple times I've seen people share a version of rm -rf, and then it's some subshell that does find every Node modules directory underneath a code folder. So you can find every single Node module and just blow them away. That will regain you some space. But that was not the solution this time.
I've tried lots of piecemeal solutions over time. But eventually, the thing that got me there was just busting all of those caches. So I cleared the backup utility, Arq's cache. I cleared a bunch of them, Spotify Yarn, et cetera. And that cleared enough space for the installer to actually run. And then, once that was done, the installer program itself was no longer around, so I reclaimed that space. But it was this weird chicken and egg thing where I had to have enough space to complete the installation such that the installer could go away.
And now...actually, let me see what my hard drive looks like now. So somehow, according to the Macintosh hard drive info, I have 50 gigabytes of available space, which is really frustrating because there were a number of weeks where we went into a Bike Shed recording, and I was like, I have one gigabyte. I'm not safe right now because this audio is going to be more than that. And so I don't know how now I'm sitting at 50. I guess all those caches that I cleared and the installer being gone probably puts me in a good spot.
But anyway, I'm living in an upgraded, wonderful world. As an aside, Big Sur is ridiculously rounded and colorful and almost cartoonish. They're really leaning into the iOS vibes. And I'm not sure it's my personal aesthetic, but that's fine. I spend most of my time in the terminal anyway. But I think that's enough of me ranting about upgrading my operating system, which apparently I had a lot to say about. But what else is up in your world, Steph?
STEPH: I do appreciate the ranting, though. You're not often grumpy, and when you are, it's quite humorous. [laughs] I really enjoy the grumpiness. And it's often a painful process. So I appreciate all of that story.
Something that I really need to share with you and get off my chest is a couple; I don't know, x number of episodes back, you and I were talking about computer chairs. And I bragged about the fact that I have a computer chair that has no armrest, and I love it. I love my chairs like this, and it's wonderful. And I just think it's the best way to live.
And it turns out that that's bad because I happened to go see a massage therapist who's also very well-skilled in physical therapy and other areas. And they were talking to me about my desk setup. And I mentioned the fact that I get these typical headaches, and I have my chair, but there's no armrest. And they're like, "Oh, that would do it." I was like, "Why? I like my setup. What's wrong with it?" And they're like, "Well, if you don't have armrests, then your back is having to compensate and to hold up your arms and your shoulders all day. So while you're typing, you're using more muscles to then hold that. And then they eventually tighten and contract, and then that can cause headaches."
So in case, I have led anyone astray into having no armrest, they are apparently very important to not having headaches or having your back overworked to the point that you have headaches, which I'm a bit sad about. But on that front, I have ordered a new chair, and we'll see how it goes. I will have to assimilate into the world of chairs with armrests.
CHRIS: We welcome you with open armrests. [laughs] Sorry, I saw it, and then I went with it. Anyway, I'm realizing now I actually don't use the armrests on my chair per se. I actually end up putting my arms on the desk, which is probably not ideal either. I have a little wrist pad so that my wrists are brought up and so that I don't have the upward breaking of the wrist thing going on. I think that matters a lot. And then my arms are supported by the desk, but it is just right on the desk, and I wonder if that's worse. But I've never...I don't know, getting the armrests just right and then also having the wrist pad.
But I can't adjust my desk is probably the main problem. If I could bring my desk down a little bit, and if it were a thinner top, then I'd have more flexibility. The chair that I have is wonderful and has flexibility. The arms can go up and forward into the side and lumbar and this and that. And so I'm able to make the chair work to the desk. But I do wish I had more of an adjustable...ideally, like a stand-sit desk. But I haven't made that jump just yet.
STEPH: When you're ready to make that jump, I'm going to share with you where I bought my desk because I'm really happy with it. And it's also not nearly as expensive as most of the other desks that will go up and down.
CHRIS: Presumably, we can include it in the show notes as well so that we share it with everyone.
STEPH: Definitely, yeah.
CHRIS: Otherwise, that's just kind of mean. [laughs] You and I have a weird back channel that we talk about on the show, but they're not actually put in the show notes.
STEPH: We're not mean. We wouldn't do that. I love my desk. And it was from someone else. They're the ones that shared it with me, so I'm happy to pass it along because it has served me well. And yeah, I'm also not sure about how this is going to work with the chair and the armrest because I'm just worried they're going to be too wide, and they're not going to actually offer support. I have doubts. I have lots of doubts, but I'm willing to investigate. And we'll see how this goes because I would like for the headaches to stop.
CHRIS: Good luck on that front. That definitely seems like an indication of worth putting in some effort there.
STEPH: Agreed. I also have some other exciting news. Stephen Hanson at thoughtbot has organized a number of other thoughtboters to get together who are interested in really diving into leveling up, learning React, and specifically focusing on purchasing the Kent C. Dodd’s Epic React course. And it's for anyone that is comfortable writing code, whether you know React really well or if you're new to it. Everyone's welcome to join.
So we just kicked that off today where we're going to go through the course together and then meet every Friday. I think the cadence is probably three hours, three and a half hours every Friday, that then we're going to commit to working through the course together.
And I have to admit, I always nerd out a bit over how does someone build a course? Like, I'm really excited about the content as well, but I just want to know how did someone go about producing this content and then sharing it with everyone? And then what's their outline? How do they help people that are getting stuck because they can't be there in the same room? How do they record their videos?
So I'm really excited to see all the ways that Kent has crafted this workshop. And so far, there's so much content, but I'll have more to report as we really start to dive in. But I'm excited to revisit React because I haven't been in React land for at least a year and a half; it’s been a while. And so it's one of those areas that I know some bits, but a lot has also changed. And I would like to just revisit that world. So I'm really excited to dive into the course.
And so far, I really like the structure that Kent has taken with the curriculum where we're focusing first on what exactly is happening and all the effort that goes into if you wanted to actually write HTML and then layer on JavaScript on top of that. But then here's how React makes that easier for you. Here is how JSX makes it even easier on top of the React API. I really liked that. Here's some pain; feel a little bit of pain, let's get a little bit better. And then let's get even better on top of that. And that has been a really nice reminder and progression into the course.
CHRIS: I'm definitely a fan of the way you're describing it like, feel some pain, and then let's get better. But then, like, what's the hook? With any educational content, this is the sort of structure where there can be full education. But this is the thing that I feel very deeply about conference talks is my goal isn't to teach you everything if I'm giving a conference talk; it is just to get your attention just to say, "Here's the thing, here's why you might care." And starting from the problem, starting from the pain is always such a good way to do that. Because you know how this stuff is hard? What if I had an option that was easier? And then building from that totally makes sense.
I want to say that course, Kent's course was built in conjunction with the egghead team, egghead.io. And it's a distinctly branded course. But it was built on top of the framework in the platform that's there and all of that, and then some of the editing support. I don't know this for certain, but I think there was some teamwork there.
And I love just pushing forward the envelope of how we do educational content in the world of development because it is such an interesting world that has, frankly, such a need for ongoing development. The world is changing out from underneath us every two days. And therefore, having great educational content is so important. So yeah, definitely interested to hear how your experience goes both with the course and then also diving deeper into React.
Well, switching gears just a little bit, I had a topic that I wanted to dig into with you today. And so to give some context, the topic, the thing that we're going to be talking about today is what have we changed our mind about? So you and I have both done a little bit of thinking and tried to come up with some answers to this. The background, this was actually inspired by a tweet that I saw between Shawn Wang, aka "Swyx" on the internet, and Charity Majors, a recent guest here on this podcast.
And Charity is someone who is known for having strong opinions. But Shawn asked the question of what are some opinions that you've changed your mind about? And Charity actually had a wonderful list, which we'll link to her tweet thread where she shared some of her both technical and then also more personal ones, but really talking about the sort of evolution of thinking and the way someone's thoughts can change over time.
And I thought it was just such an interesting thing because, for most points in time, we experience someone's sort of snapshot of where are you at now? What do you believe to be true? But I think there's such an interesting story and sort of the arc there of what did you believe to be true that you don't anymore? What have you softened your beliefs on? What have you strengthened your beliefs on? So yeah, with that as the context, what have you changed your mind about, Steph?
STEPH: Yeah, this one really got me thinking, and I feel a little stumped on it. I have a few that I'm excited to share. But I'm very excited to hear your list to see if that also helps me reflect more on some of the things that I have changed my mind about. And I have found that there's only a couple maybe that I feel like I've really solidly changed my mind about. The others, I've either dialed up the strictness, or I've dialed it down. So the ones where I've really changed my mind about are feature flags and comments. Those are two of them. Well, there's a third one, but I'll get to that in a moment.
So starting with the first one, feature flags I was more in the camp where I very much appreciate feature flags, but I use them sparingly because then there is a tedious nature of introducing them and then having to clean them up, and then having to maintain two states of code. But now I've really seen the value of feature flags and how we can make sure that we have calm releases and ensuring that main is always in a deployable state. So feature flags is one for me. I'm very invested in having more of a robust feature flag system because I see the benefit to that.
The other one was comments. I used to be very rigid about comments are bad. We should never have comments in our code. They are just waiting to go out of date, and they're not going to be helpful. But I have since dialed down that strictness where I have certainly seen moments where comments do feel very helpful, and I can see how people use them. I still want to avoid them for the most part, but I am less strict now in regards to people who really find value in comments. I'm more open to that discussion. I want to understand what it is they find helpful about that comment, and if it is something that we can't capture with code or a test, where does that live?
CHRIS: Those are both interesting. Feature flags, for me, I think I actually was more strongly opposed in the beginning. Earlier on in my career, I saw them as added complexity, as noise. I often would encounter them left behind in a codebase. And so, I had this negative association with them. And I didn't see the value; I hadn't yet felt that pain. And over time, I've definitely shifted to where you're at where I'm like, I love feature flags. This is a critical tool in our toolset of how we actually…like you said, calm deploys, being able to always deploy main, making sure that we don't have long-running feature branches. There are so many benefits that come out of it that I'm now very strongly in favor of them. But it's interesting; I think I would say that I started in a more strongly opposed place. So that wasn't on my list, but it's an interesting one that you've brought up and probably one that I've moved more on.
Code comments, I think, actually started in my career being like, obviously, you comment your code. It's the thing that I read about and stuff. And slowly, over time, I think I've just dialed in on I don't think we should be doing that. There are, of course, going to be exceptions.
And actually, one of the things that I discovered about myself as I was trying to go through this exercise is there are very few things that I believe are black and white. If anything, that maybe is one of the things that I've leaned into over time. It's like, nothing is binary. Nothing is black and white. Everything is on a continuum or shades of gray. There are things that I believe a little more seriously. But there's almost nothing that I can be like, nope, absolutely I will not equivocate on this beyond how we interact with other humans and being reasonable, kind people. And in terms of software practices, not really. Comments, though, are one that I still am pretty strongly not going to lean into. So it's interesting that you're like, eh, I've kind of opened up to that one.
STEPH: There's a particular talk, The Art of Code Comments by Sarah Drasner, and that's the one that really shifted some of my opinions around comments, and then how we talk about them, and what benefits they can play. But I will admit, if I see a PR that has code comments, I still immediately have a negative reaction to that. And I want to have a conversation around why that comment was added and if we can remove it, and how we can remove it. But even with that negative perspective, I still find that I'm more open to that discussion versus before, where I would have been like, no, that's just unequivocally bad.
CHRIS: I do like that you always bring up that talk whenever we talk about comments. This is a great talk. And in the background, I just looked up Sarah's Twitter profile because every time you bring it up, then I mention that she has a still from the movie Labyrinth in her Twitter background, but she actually changed it. And so now that's not true anymore. It's now something from The Force Awakens. Well, it's actually a joke, but I'm still going to suggest that you watch the movie Labyrinth at some point. That's the thing that I feel actually kind of weird about. It's a weird movie.
STEPH: I'm going to take your suggestion, but not watch it. But thank you. [laughs] To share my truth today.
CHRIS: That's fair, that's fair.
STEPH: What are some of the things on your list?
CHRIS: Okay, I have a couple, some more on the technical. Let's lean into one of the technical ones. Early on, I started with dynamic languages. I think I started with Python primarily and a little bit of JavaScript. I eventually found my way to Ruby and felt very at home there. And then, I started to explore functional languages. And I started to lean into them really hard and felt that immutability and functional programming and true pure functional programming was the thing. It was the answer, and I just needed to figure out how to do it. And so I would say that is the belief that I have since changed my mind on and decided, you know what? Actually, it feels like a bit of a force fit. I have tried. And maybe for others, it is actually a really fantastic way to build software. But having worked with a number of other people in more functional contexts, I find that it is a bit of a force fit. It's a bit rough.
And in particular, of late, I've been working with Svelte as opposed to React, and React does sort of lean into the functional paradigm, especially with Hooks and all those sorts of things. And it's a little bit rough because it turns out UIs are these deeply mutable things. We're changing values or typing things in. There are actions that are changing the state over time, and having a system that just more directly models that feels very natural.
I still love functional programming for the more core of an application. So again, I reference this talk often, but Gary Bernhardt's Functional Core, Imperative Shell. Gary has really formed some of my thinkings on this. And now I've started to find the examples in the work that I'm doing of like, oh, okay, I see that pattern actually applied here. But much as I would love to use them, the functional languages I find just aren't quite landing for me. And additionally, the mutability, particularly in the front end right at the edge of the UI, is not quite as good of a fit.
STEPH: So I think that resonates with me although I do still get very excited about following more patterns that represent more immutable state just because I felt so much pain and found bugs from the fact that we have mutated state in surprising ways. I'm honestly not quite sure how I feel about it. I'm going to have to think on that one. That's a very interesting one that you've changed your mind on.
CHRIS: Yeah, similarly, my feelings are lukewarm, whereas before, they were stronger. I was like, oh, okay, I think I found something here. And then, in attempting to use it across a wide variety of applications, it just didn't quite feel right. I felt like I was swimming upstream sort of thing.
Actually, there is an interesting counterpoint. One thing that I have leaned into and definitely changed my mind on and embraced is static typing or, broadly, static analysis. But I think static typing being the most pointed version of that. Early on, like I said, I got my start in very dynamic languages in Ruby, and Python, and JavaScript. And so that dynamic duck typing runtime can be anything. We just make our systems respond to the messages, and all of that sounded great.
But it turns out I really love having a compiler that can tell me some truths about my program before it ever reaches runtime. And the idea that a typo can make it to production feels absurd at this point. And actually, as I'm working in Ruby, I'm like, man, I really got to go look at that whole Ruby typing thing we got going on. I don't know what the state of it is. I've looked at it in the past, and I need to revisit it soon. But like TypeScript, I've definitely embraced that very strongly. And I would not work without TypeScript in a JavaScript project at this point.
I've loved the work that I've done in Elm, although that also sort of blends into the functional stuff where it's like, it was a little bit noisy, though, I'll say that. But the type system and the fact that the compiler can give you so much rich information about your program, I would not trade that at this point. And I don't see myself going back on that front, which is an interesting place for me to be on of actually, I'm not that into the functional programming as the core way that I build my applications.
But I do like static typing. And I feel like functional programming and static typing actually go together incredibly well. And functional programming and, more imperative, whatever it is that I'm doing with my day-to-day life these days is a more interesting fit. But it is interesting to me to observe that sort of combination of opinions where I really like static typing, and having a compiler, and something that can tell me about my program before I get to runtime. But also saying that I don't quite want the functional programming thing, or at least not as the entire way that I modeled my application because I found it a bit difficult to work with. Because I think static typing or compilers and functional programming go really well together.
But I think generally, what I'm finding is a more middle ground dynamic optimization of a bunch of different things. And the answer is like, well, it depends which I guess if you've listened to the show before, you'll have heard those words said, so I guess it makes sense.
STEPH: Yeah. All of that makes sense to me. And I can see why you might have a favor for types or why that feels more valuable initially because that is giving us so much feedback right off the bat versus following a more functional paradigm is something that could feel like more of a force fit and doesn't provide that same immediate feedback. But it has a longer-term or a longer cycle of that reward system. So I can see why you might favor one over the other or why I myself would favor one over the other.
CHRIS: How do you feel about types?
STEPH: I'm a big fan, although I say that, but I work in Ruby. [laughs] I don't have them. But when I have worked with types, I very much enjoyed it because it makes me think more about the design of my code in a way that I don't as much with Ruby. And working with types has heavy influence than when I am working in Ruby and thinking about the design of my code. So I think working with types is a wonderful thing that, frankly, all of us should do as developers at some point because it is so influential. So I'm for types, but I'm not using types in my day-to-day.
Another thing that I have changed my mind about is how we structure the work that each person is doing. So I used to be more in the camp of everybody can work on their own very complicated piece of codebase, their own complicated feature. We can have a bunch of complicated things in the sprint, and everything will just be great; it’ll be fine. And we'll get a bunch of work done, and we'll ship it. And then we're an even more productive team.
And I very much disagree with that now where I have found where everybody is working in their own silo on a complicated feature has slowed down the progress of then being able to ship that feature. Because we often want to collaborate with someone, we need to collaborate with someone. Then the PR review process is tough if I really have no idea what you're working on, and I don't have a context that then when I look at your code, not only am I evaluating at the code level, but then I'm also trying to understand the feature and gain all of that context. And that's a heavy cost for me to have to pay to then pick all of that up and then for you to have to reintroduce me to what's happening. Or I might make the bigger mistake, and I may look at your code and just evaluate it from the code perspective but not really understand the feature, the value that's being delivered. And that doesn't feel useful.
And I have a recent example where that happened where someone was working on a very complicated feature that I didn't have any insight into. So then, when I was looking at the PR, it was easier for me to just look at the code and get feedback on that. But then it was probably a day or two later. It wasn't until then that I finally started asking, what are we building? Like, what purpose is this serving? And that opened up a much larger discussion where we realized what was being built didn't actually really deliver what we needed to deliver. So I no longer agree with the idea that everybody should be working on their own complicated features independently, and there should be some collaboration. And, you know, it's the buddy system; we all need a buddy.
CHRIS: Well, I like that one. I feel like I've shared similar ideas where it made sense. It was just the efficient thing to do, to split the work up and have everybody very independent. I also feel like earlier on in my career; I was more scared of Git conflicts and things like that or people interacting with the same parts of the code. And so in my mind, it made sense to really strongly separate like, oh, you shouldn't even be touching the controller for this. I'll handle the views, and you handle the controller; it'll be separate. And I care less about that now. And I think what you're saying of like, it's actually better if we have some shared context, and we understand what we're working on, and it's more of a collaborative process. Yeah, I like that one. I think I followed a similar arc, and I'm at a similar place now as well.
Interestingly, to go into another one of mine that I think you'll probably be most surprised by on my list is I think I used to believe in 10x engineers. I used to believe in the idea of that one developer just off in the corner fueled entirely by Mountain Dew that would just produce the perfect code. They would just solve it. Over the weekend, they would write the entire billing system, and it would be great. And I think it was predicated on the idea that the coding is the hard part, which I no longer believe. I think coding at its core is communication. It's taking this thing that we want to be true in the world and then communicating it to a computer but also ideally communicating it to our teammates, and to future versions of ourselves, such that we can revisit that code, we can maintain it over time, other people can add to or augment it.
And so the idea of this loner that can just do incredible volumes of work and have that be a good outcome that just doesn't make sense to me anymore. I've worked with incredibly talented developers, to be clear, folks that I was sort of in awe of. I've worked with people who have, I think, just truly photographic memories. They seem to remember every single bug that they've ever had and exactly where they can look it up. Or from the top of their head, they can just intuitively know, oh, this bug means this. Go look at this line of code. I'm like, how did you do that? How did you do that magic trick? And they're incredibly capable developers. But at the end of the day, the folks that I see being most impactful on a team are the folks that are able to communicate and collaborate most effectively and make the whole team more effective.
STEPH: Maybe it's the Mountain Dew; maybe that's actually the secret sauce here. That's what I'm missing from my life to take me into that status.
CHRIS: I'm now imagining Mountain Dew but in a more viscous form, like a barbecue sauce, but it's Mountain Dew flavored. That's the secret sauce because it's a very…anyway, moving on. [laughs]
STEPH: It's a terrible product. We should make it and sell it.
[laughter]
CHRIS: Career pivot, we now sell Mountain Dew sauce.
STEPH: [laughs]
CHRIS: But yeah, I do not believe in 10x engineers anymore. If anything, I believe that that is a huge warning sign if you have anyone that's behaving in something close to that space.
STEPH: Yeah, I'm super interested in that you've shared because I don't think...We've talked about 10xers, but we haven't talked about the fact that you used to think that they were more of a thing and that they existed. And now it's all I'm sorry, but it's all crap. [chuckles] That's super interesting to me. Do you remember what changed your mind? Do you remember that pivotal moment of where you were like, oh, maybe this is all bullshit?
CHRIS: I think it was just an amalgamation of experience over time. I've encountered people who fit the archetype. But if anything, I would say they're deeply problematic in teams. They're that individual who refuses to collaborate, who just goes off and heads down, writes a bunch of code, but then it doesn't integrate with the other pieces, or no one else knows how to use it, or they won't let anyone contribute to it. And yeah, I've seen that just be very, very problematic.
So the folks that most fit, I think the imagined version of this, actually end up, in my experience, leading things astray. And the folks that are actually most productive and really cause teams to improve in a drastic way behave very differently. They're much more collaborative; they’re much more engaged with the team. It's less about their individual contributions and it's more about building a system together, collaborating, communicating, engaging external stakeholders, et cetera, et cetera. It's all that stuff that matters. And so, it's very much in contrast to what the 10x engineer ethos is about. But there's no one day where suddenly this idea that I had in my head crumbled when I saw that behind the pile of Mountain Dew cans, there was nothing there. [laughs]
STEPH: It's all a mirage. [laughs] I do like what you just said around that there are very impressive people out there. And those impressive people often focus less on their individual contributions and more at a higher level around communication. And then they are the powerhouses that then is helping facilitate everybody else be their best and have high levels of individual contribution. Those are the ones that...I'm still not going to endorse a 10xer, but they are the ones who, to me, embody the idea of someone that is incredibly efficient and really good at their job.
CHRIS: There's an adage that comes to mind here that "If you want to go fast, go alone. If you want to go far, go together." And that does ring true to me. I think an individual can have their individual productivity be higher if they're working entirely on their own, if they understand every line of code because they wrote every single line of code if they know where every feature of the platform is integrated because they wrote the whole thing. But they're going to be fundamentally limited. And in order to do bigger, more complex things, fundamentally, we have to work as a team. And then the way you have to interact just fundamentally changes.
So I think it started from that, like, one person on their own I think can be individually more effective. But the minute you start to have a team, that one person acting on their own is actually dragging the team down because other people can't then work in that space, and that's a problem.
STEPH: I really like that adage that you just shared where, "If you want to go fast, go alone. If you want to go far, go together." And that touches on something else that I have really changed my mind about, and that's representation. And this is more specific to me. So when I joined engineering and became a web developer, and I joined a team, and I was the only female engineer on that team, my initial feelings were I am the only female engineer, and that is fine. We're all just a group of engineers. We're here to solve problems together. It really doesn't matter if there's anyone here on this team that's like me. It's fine if there's no one that I can see myself in that's in leadership because we're all just people, is what I was coming down to. And I've completely changed my mind and realized that that's not true.
And I've experienced this where I've worked on other engineering teams with female engineers, and it's fucking awesome, and it does make a difference. And then when I can see someone that I can see myself in, in a leadership position, that is also inspiring. So that is something that I went in where I think it was more of I was trying to shield myself from the idea that I am different from everybody else in this room, and that could be a problem. And instead, I just tried to neutralize it by saying it's not.
But I think representation is incredibly important. People are not just people. We all have very important social and racial, and cultural identities. And it's very important that we get to feel that we can express all of those identities and see people that represent those identities in spaces where we would like to go. That's a big one that I've changed my mind on.
CHRIS: Yeah, I certainly agree that representation certainly matters, and being able to bring your full authentic self to work and seeing others around you that reflect that. And frankly, having teams that are made up of people that represent the users of the software that we're building feels so critically important. And it's very interesting to hear about the arc that you've had on that where initially, you tried to downplay it, but then you found a little more truth in it. And so yeah, thank you for sharing.
STEPH: You're welcome. It feels good to say that, too, because that's something that I've admitted and realized on my own, that that is something that has changed and shifted. But it's nice to be able to share that here with you as we're going through the things that we've changed our mind about. What else is on your list?
CHRIS: Well, to round us off with one more very technical version because, of course, that's where I'm going to take us after a much deeper and more nuanced topic that you led us on, single-page applications. Broadly, I'm opposed to the name; that’s a side conversation. But, man, URLs matter on the internet. So don't call them single-page applications, but client-side applications or whatever. Broadly, the idea of a bundle of JavaScript, and so you send down an empty HTML document, and then you reference a bundle of JavaScript, which that thing boots up and it then makes a bunch of API requests to the backend, and then it starts to fill in the page.
I was convinced for a while that this is a reasonable and perhaps even necessary way to build software. We need APIs for our mobile apps anyway. So if we're doing that, then let's have that be the consistent way that we are accessing information. This is going to be fine; it's not a problem. And then eventually, we found some problems. So then we got GraphQL, and we tried to solve it that way. But overall…and I have spent a lot of time trying to make this thing work, trying to find a version of this that I'm happy with that I find the end outcome of the software to be as pleasant to work with from an end-user perspective as a server-driven application, and I can't find it.
And so, to be clear, I'm still doing client-rendered applications these days. But Inertia.js is the framework that I've leaned into that helps me bridge that gap. And the idea that the server owns routing, that the server owns statefulness, things like that, not having to think about client-side routing, not having to think about client-side state management, being able to use traditional auth mechanisms built into cookies, all of these familiar things that we've had. Leveraging the fact that the server is the more privileged in terms of the information it has access to, the more secure, the more powerful environment, all of these things feel right to me. And the nature of the application that I can build just feels more robust, more consistent, easier to evolve.
There were a lot of promises that I heard when we started building applications in these ways. And I just haven't seen an example or have not worked on an example, at least of an application that is built as a client-side bundle that boots up and does some stuff and had a good experience with that. So Inertia, as an aside, is my answer to this. And I continue to be extremely happy with that as a solution, as really a middle-ground solution. Because going all the way back to true HTML server-side rendering is limiting in other ways that I didn't like. But I find that Inertia really strikes an ideal balance in the middle there.
STEPH: I feel like I completely agree with everything you're saying. But I also feel like I have a developer secret to share where I really haven't worked on single-page applications, and I am okay with that. [laughs]
CHRIS: It's fine, skip it. Just go straight to Inertia. It's better.
STEPH: Cool, cool, cool. I am working on leveling up React, and then the plan is to go to Svelte and Inertia. So I'll just completely...I'll skip that. I'll skip that part of my career.
CHRIS: I actually want to back up just a little bit as I'm saying this because I really try to avoid being in a more negative space. And I think this space, this architecture for building applications, is complex, and there are things that will warrant it. So things like Google Maps, it makes sense to have a lot of Dynamic JavaScript and to be doing complex things on the client-side. Trello is another example of an application that that as a server-rendered thing, doesn't really make sense. And frankly, using a tool like Inertia wouldn't quite work there. That said, that is, in my mind, truly a single page within the broader application. So the Trello board page is a very, very complex stateful application, and I think modeling it as such makes sense. Google Maps, similar. But there's still the profile page, and the login page, and all of these other things.
I think routing is probably where it breaks down for me. I think client-side routing is the thing that I feel the most pain on. Because at the end of the day, the server still needs to know the answer. And if we do client-side routing, we end up with this duplication of logic across the client and the server-side. We end up with disagreements from time to time. We end up with the weird flashes of half-rendered layout, and then we go to the login page because we get an API response that is different. And so, I think that is probably the kernel of the thing that I struggle with. And, of course, it is possible to build great things using any of these technologies.
But I think my summary is I've really tried on that front, and I've just not been able to make the fidelity of application that I want using…primarily; I’d say it's client-side routing is the thing that I struggle with the most.
STEPH: Yeah, it sounds like you're saying there are very valid use cases for using a single-page app or following that structure. But we haven't really gotten there in terms of our web development expertise, where we've made that easier to maintain and easier to implement. And there's still enough pain points around it that even though it seems like a very valid idea and approach, it still feels painful enough that you actively avoid it until it feels like something that you have to then invest in at that point to then really deliver the user experience that you want to provide.
CHRIS: Yeah, I think that's an accurate summary. And I think adding on to that, I’m noticing it becoming more and more of the standard approach; this is the way we build applications, and I don't agree with that. That is probably the thing that is the kernel of what I don't believe in. I think actually server rendering is a great way to start, and then you can slowly augment or move more things into complex client-side behavior. But starting with this as the mode that we're building our applications just feels like a less stable foundation than I would want. So it's perhaps an architecture that you want to evolve to at some point as the complexity necessitates it, but I definitely wouldn't be starting there. Similar to service-oriented architecture, not going to start there. Client-side routing, I'm not going to start there.
STEPH: Ooph. I feel like I've been holding my breath this episode. I feel like this was a very interesting topic that has been challenging to reflect on what we believe and what we've changed our mind about.
CHRIS: I think it's perhaps more nuanced than a lot of our episodes where often we're saying this is what we did, and this is how we felt in the moment. And that can be very experiential and true. But this, yeah, we had to draw the line in the sand and say what do we believe? I similarly definitely feel more tension in this episode than other ones. But hopefully, it was useful. Hopefully, folks found some value in the things, and hearing our story, also, the idea that we have singular formed opinions. Hopefully, this episode has broken that idea in anyone's head. And we're all on a journey.
STEPH: I really like how this has prompted me to reflect on the things that I used to hold dear and really cherish or follow strictly to then reflect on what are things that I used to believe versus what I believe now? Because that transition often happens so seamlessly for me that I don't really stop to think about it to be like, oh, something just happened that is really changing how I approach things, how I build, how I work with teams. And I really like this reflection point to be like, oh, what did I used to believe, and what's different today? I'd like to keep this practice going and just try to track the things...I'll have to make a list of all the things I believe. That seems like an easy list. [laughs]
CHRIS: Just the easiest list to write.
STEPH: The easiest list to write. And then I'll just check in with it every so often, scratch stuff out, or update it with the things that have changed my mind about. This is the good idea, terrible idea where you go, "Stephanie, that's a terrible idea." [laughs]
CHRIS: I don't know, write it down on a list, and then look at it in six months and see if it sounds like a good idea, and then we'll be able to close the loop on the whole thing. But with that, should we wrap up?
STEPH: Let's wrap up. I've got a list to write.
CHRIS: The show notes for this episode can be found at bikeshed.fm.
STEPH: This show is produced and edited by Mandy Moore.
CHRIS: If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review on iTunes, as it really helps other folks find the show.
STEPH: If you have any feedback for this or any of our other episodes, you can reach us @bikeshedor reach me on Twitter @SViccari.
CHRIS: And I'm @christoomey.
STEPH: Or you can reach us at hosts@bikeshed.fm via email.
CHRIS: Thanks so much for listening to The Bike Shed, and we'll see you next week.
All: Byeeeeeeee!
Announcer: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.Support The Bike Shed