TopPodcast.com
Menu
  • Home
  • Top Charts
  • Top Networks
  • Top Apps
  • Top Independents
  • Top Podfluencers
  • Top Picks
    • Top Business Podcasts
    • Top True Crime Podcasts
    • Top Finance Podcasts
    • Top Comedy Podcasts
    • Top Music Podcasts
    • Top Womens Podcasts
    • Top Kids Podcasts
    • Top Sports Podcasts
    • Top News Podcasts
    • Top Tech Podcasts
    • Top Crypto Podcasts
    • Top Entrepreneurial Podcasts
    • Top Fantasy Sports Podcasts
    • Top Political Podcasts
    • Top Science Podcasts
    • Top Self Help Podcasts
    • Top Sports Betting Podcasts
    • Top Stocks Podcasts
  • Podcast News
  • About Us
  • Podcast Advertising
  • Contact
Not in our directory?
Add Show Here
Podcast Equipment
Center

toppodcastlogoOur TOPPODCAST Picks

  • Comedy
  • Crypto
  • Sports
  • News
  • Politics
  • True Crime
  • Business
  • Finance

Follow Us

toppodcastlogoStay Connected

    View Top 200 Chart
    Back to Rankings Page
    Software How-To

    The Bike Shed

    On The Bike Shed, hosts Joël Quenneville, Sally Hall, and Aji Slater discuss development experiences and challenges at thoughtbot with Ruby, Rails, JavaScript, and whatever else is drawing their attention, admiration, or ire this week.

    Advertise
    • Apple Podcasts
    • Google Play
    • Spotify

    Latest Episodes:
    359: Serializers Oct 25, 2022
    Show notes

    Chris Toomey is back! (For an episode.) He talks about what he's been up to since handing off the reins to Joël. He's been playing around with something at Sagewell that he enjoys. At the core of it? Serializers. Primalize gemDerek's talk on code reviewInertia.jsPhantom typesio-tsdry-rbparse don't validatevalue objectsbroader perspective on parsingEnumerable#tallyRubyConf miniwhere.missing Transcript: JOËL: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Joël Quenneville. And today, I'm joined by a very special guest, former host Chris Toomey. CHRIS: Hi, Joël. Thanks for having me. JOËL: And together, we're here to share a little bit of what we've learned along the way. So, Chris, what's new in your world? CHRIS: Being on this podcast is new in my world, or everything old is new again, or something along those lines. But, yeah, thank you so much for having me back. It's a pleasure. Although it's very odd, it feels somehow so different and yet very familiar. But yeah, more generally, what's new in my world? I think this was probably in development as I was winding down my time as a host here on The Bike Shed, but I don't know that I ever got a chance to talk about it. There has been a fun sort of deep-in-the-weeds technical thing that we've been playing around with at Sagewell that I've really enjoyed. So at the core of it, we have serializers. So we take some data structures in our Ruby on Rails code base, and we need to serialize them to JSON to send them to the front end. In our case, we're using Inertia, so it's not quite a JSON API, but it's fine to think about it in that way for the context of this discussion. And what we were finding is our front end has TypeScript. So we're writing Svelte, which is using TypeScript. And so we're stating or asserting that the types like, hey, we're going to get this data in from the back end, and it's going to have this shape to it. And we found that it was really hard to keep those in sync to keep, like, what does the user mean on the front end? What's the data that we're going to get? It's going to have a full name, which is a string, except sometimes that might be null. So how do we make sure that those are keeping up to date? And then we had a growing number of serializers on the back end and determining which serializer we were actually using, and it was just...it was a mess, to put it lightly. And so we had explored a couple of different options around it, and eventually, we found a library called Primalize. So Primalize is a Ruby library. It is for writing JSON serializers. But what's really interesting about it is it has a typing layer. It's like a type system sort of thing at play. So when you define a serializer in Primalize, instead of just saying, here are the fields; there is an ID, a name, et cetera, you say, there is an ID, and it is a string. There is a name, and it is a string, or an optional string, which is the even more interesting bit. You can say array. You can say object. You can say an enum of a couple of different values. And so we looked at that, and we said, ooh, this is very interesting. Astute listeners will know that this is probably useless in a Ruby system, which doesn't have types or a compilation step or anything like that. But what's really cool about this is when you use a Primalize serializer, as you're serializing an object, if there is ever a type mismatch, so the observed type at runtime and the authored type if those ever mismatch, then you can have some sort of notification happen. So in our case, we configured it to send a warning to Sentry to say, "Hey, you said the types were this, but we're actually seeing this other thing." Most often, it will be like an Optional, a null sneaking through, a nil sneaking through on the Ruby side. But what was really interesting is as we were squinting at this, we're like, huh, so now we're going to write all this type information. What if we could somehow get that type information down to the front end? So I had a long weekend, one weekend, and I went away, and I wrote a bunch of code that took all of those serializers, ran through them, and generated the associated TypeScript interfaces. And so now we have a build step that will essentially run that and assert that we're getting the same thing in CI as we have committed to the codebase. But now we have the generated serializer types on the front end that match to the used serializer on the back end, as well as the observed run-time types. So it's a combination of a true compilation step type system on the front end and a run-time type system on the back end, which has been very, very interesting. JOËL: I have a lot of thoughts here. CHRIS: I figured you would. [laughs] JOËL: But the first thing that came to mind is, as a consultant, there's a scenario with especially smaller startups that generally concerns me, and that is the CTO goes away for a weekend and writes a lot of code... CHRIS: [laughs] JOËL: And brings in a new system on Monday, which is exactly what you're describing here. How do you feel about the fact that you've done that? CHRIS: I wasn't ready to go this deep this early on in this episode. JOËL: [laughs] CHRIS: But honestly, that is a fantastic question. It's a thing that I have been truly not struggling with but really thinking about. We're going to go on a slight aside here, but I am finding it really difficult to engage with the actual day-to-day coding work that we're doing and to still stay close to the codebase and not be in the way. There's a pattern that I've seen happen a number of times now where I pick up a piece of work that is, you know, one of the tickets at the top of the backlog. I start to work on it. I get pulled into a meeting, then another meeting, then three more meetings. And suddenly, it's three days later. I haven't completed this piece of work that was defined to be the next most important piece of work. And suddenly, I'm blocking the team. JOËL: Hmmm. CHRIS: So I actually made a rule that I'm not allowed to own critical path work, which feels weird because it's like, I want to be engaged with that work. So the counterpoint to that is I'm now trying to schedule pairing sessions with each of the developers on the team once a week. And in that time, I can work on that sort of stuff with them, and they'll then own it and run with it. So it makes sure that I'm not blocking on those sorts of things, but I'm still connected to the core work that we're doing. But the other thing that you're describing of the CTO goes away for the weekend and then comes back with a new harebrained scheme; I'm very sensitive to that, having worked on; frankly, I think the same project. I can think of a project that you and I worked on where we experienced this. JOËL: I think we're thinking of the same project. CHRIS: So yes. Like, I'm scarred by that and, frankly, a handful of experiences of that nature. So we actually, I think, have a really healthy system in place at Sagewell for capturing, documenting, prioritizing this sort of other work, this developer-centric work. So this is the feature and bug work that gets prioritized and one list over here that is owned by our product manager. Separately, the dev team gets to say, here are the pain points. Here's the stuff that keeps breaking. Here are the things that I wish was better. Here is the observability hard-to-understand bits. And so we have a couple of different systems at play and recurring meetings and sort of unique ceremonies around that, and so this work was very much a fallout of that. It was actually a recurring topic that we kept trying a couple of different stabs at, and we never quite landed it. And then I showed up this one Monday morning, and I was like, "I found a thing; what do we think?" And then, critically, from there, I made sure I paired with other folks on the team as we pushed on the implementation. And then, actually, I mentioned Primalize, the library that we're using. We have now since deprecated Primalize within the app because we kept just adding to it so much that eventually, we're like, at this point, should we own this stuff? So we ended up rewriting the core bits of Primalize to better fit our use cases. And now we've actually removed Primalize, wonderful library. I highly recommend it to anyone who has that particular use case but then the additional type generation for the front end. Plus, we have some custom types within our app, Money being the most interesting one. We decided to model Money as our first-class consideration rather than just letting JavaScript have the sole idea of a number. But yes, in a very long-winded way, yes, I'm very sensitive to the thing you described. And I hope, in this case, I did not fall prey to the CTO goes away for the weekend and made a thing. JOËL: I think what I'm hearing is the key difference here is that you got buy-in from the team around this idea before you went out and implemented it. So you're not off doing your own things disconnected from the team and then imposing it from on high. The team already agreed this is the thing we want to do, and then you just did it for them. CHRIS: Largely, yes. Although I will say there are times that each developer on the team, myself included, have sort of gone away, come back with something, and said, "Hey, here's a WIP PR exploring an area." And there was actually...I'm forgetting what the context was, but there was one that happened recently that I introduced. I was like; I had to do this. And the team talked me out of it, and I ended up closing that PR. Someone else actually made a different PR that was an alternative implementation. I was like, no, that's better; we should absolutely do that. And I think that's really healthy. That's a hard thing to maintain but making sure that everyone feels like they've got a strong voice and that we're considering all of the different ways in which we might consider the work. Most critically, you know, how does this impact users at the end of the day? That's always the primary consideration. How do we make sure we build a robust, maintainable, observable system, all those sorts of things? And primarily, this work should go in that other direction, but I also don't want to stifle that creative spark of I got this thing in my head, and I had to explore it. Like, we shouldn't then need to never mind, throw away the work, put it into a ticket. Like, for as long as we can, that more organic, intuitive process if we can retain that, I like that. Critically, with the ability for everyone to tell me, "No, this is a bad idea. Stop it. What are you doing?" And that has happened recently. I mean, they were kinder about it, but they did talk me out of a bad idea. So here we are. JOËL: So you showed up on Monday morning, not with telling everyone, "Hey, I merged this thing over the weekend." You're showing up with a work-in-progress PR. CHRIS: Yes, definitely. I mean, everything goes through a PR, and everything has discussion and conversation around it. That's a strong, strong like Derek Prior's wonderful talk Building a Culture of Code Review. I forget the exact name of it. But it's one of my favorite talks in talking about the utility of code review as a way to share ideas and all of those wonderful things. So everything goes through code review, and particularly anything that is of that more exploratory architectural space. Often we'll say any one review from anyone on the team is sufficient to merge most things but something like that, I would want to say, "Hey, can everybody take a look at this? And if anyone has any reservations, then let's talk about it more." But if I or anyone else on the team for this sort of work gets everybody approving it, then cool, we're good to go. But yeah, code review critical, critical part of the process. JOËL: I'm curious about Primalize, the gem that you mentioned. It sounds like it's some kind of validation layer between some Ruby data structure and your serializers. CHRIS: It is the serializer, but in the process of serializing, it does run-time type validation, essentially. So as it's accessing, you know, you say first name. You have a user object. You pass it in, and you say, "Serializer, there's a first name, and it's a string." It will call the first name method on that user object. And then, it will check that it has the expected type, and if it doesn't, then, in our case, it sends to Sentry. We have configured it...it's actually interesting. In development and test mode, it will raise for a type mismatch, and in production mode, it will alert Sentry so you can configure that differently. But that ends up being really nice because these type mismatches end up being very loud early on. And it's surprisingly easy to maintain and ends up telling us a lot of truths about our system because, really, what we're doing is connecting data from many different systems and flowing it in and out. And all of the inputs and outputs from our system feel very meaningful to lock down in this way. But yeah, it's been an adventure. JOËL: It seems to me there could almost be two sets of types here, the inputs coming into Primalize from your Ruby data structures and then the outputs that are the actual serialized values. And so you might expect, let's say, an integer on the Ruby side, but maybe at the serialization level, you're serializing it to a string. Do you have that sort of conversion step as part of your serializers sometimes, or is the idea that everything's already the right type on the Ruby side, and then we just, like, to JSON it at the end? CHRIS: Yep. Primalize, I think, probably works a little closer to what you're describing. They have the idea of coercions. So within Primalize, there is the concept of a timestamp; that is one of the types that is available. But a timestamp is sort of the union of a date, a time, or I think they might let through a string; I'm not sure if there is as well. But frankly, for us, that was more ambiguity than we wanted or more blurring across the lines. And in the implementation that we've now built, date and time are distinct. And critically, a string is not a valid date or time; it is a string, that's another thing. And so there's a bunch of plumbing within the way you define the serializers. There are override methods so that you can locally within the serializer say, like, oh, we need to coerce from the shape of data into this other shape of data, even little like in-line proc, so we can do it quickly. But the idea is that the data, once it has been passed to the serializer, should be up the right shape. And so when we get to the type assertion part of the library, we expect that things are in the asserted type and will warn if not. We get surprisingly few warnings, which is interesting now. This whole process has made us pay a little more intention, and it's been less arduous simultaneously than I would have expected because like this is kind of a lot of work that I'm describing. And yet it ends up being very natural when you're the developer in context, like, oh, I've been reading these docs for days. I know the shape of this JSON that I'm working with inside and out, and now I'll just write it down in the serializer. It's very easy to do in that moment…

    Full show notes at the publisher

    358: Class Methods Oct 18, 2022
    Show notes

    Inspired by a Slack thread, Joël invites fellow thoughtbotter Aji Slater on the show to talk about when you should use class methods and when you should avoid them. Are there particular anti-patterns to look out for? How does this fit in with good object-oriented programming? What about Rails? What is an "alternate constructor"? What about service objects? So many questions, and friends: Aji and Joël deliver answers! Backbone.js collectionsQuery objectRails is a dialectMeditations on a Class MethodWhy Ruby Class Methods Resist Refactoring Transcript: JOËL: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Joël Quenneville. And today, I'm joined by fellow thoughtboter Aji Slater. AJI: Howdy. JOËL: And together, we're here to share a little bit of what we've learned along the way. So, Aji, what's new in your world? AJI: Yeah, well, I just joined a new project, so that's kind of the newest thing in my day-to-day work world. I say just joined, but I guess it was about a month ago now. I'm on the Liftoff team at thoughtbot, which is different than the team that you're on. We do more closer to greenfield ideas and things like that. So there's actually not much to speak about there in that project just yet. Rails new is still just over the horizon for us. So I've been putting a lot of unused brain cycles toward a side project that is sort of a personal knowledge base concept, and that's a whole thing that I could probably host an entire podcast about. So we don't have to go too deep into my theories about that. But suffice it to say I've talked to some other ADHDers like myself who find that that space is not really conducive to the way that we think and have to organize ourselves and our personal knowledge stores. So sort of writing an app that can lend itself to our fast brains a little bit better. JOËL: Nice. I just recently recorded an episode of this podcast talking a little bit about note-taking approaches and knowledge-base systems. So, yeah, it's a topic that's very much top of mind for me right now. AJI: Yeah, what else is going on in your world? JOËL: I'm based in New England in the U.S. East Coast, and it is fall here. I feel like it happened kind of all of a sudden. And the traditional fall thing to do here is to go to an orchard and pick apples. It's a fun activity to do, and so I'm in the middle of planning that. Yeah, it's fun to go out into nature, very artificial space. AJI: [laughs] JOËL: But it's a fun thing to do every fall. AJI: Yeah, we do that here too. There's an orchard up north of us where my wife and I live in Chicago that we try to visit. And Apple Fest in Lincoln Square is this weekend, and we've been really looking forward to that. Try another time at making homemade hard cider this season, I think, and see how that goes. JOËL: Fun. When you say another time, does that mean there was a previous unsuccessful attempt? AJI: Yes. Did the sort of naive approach to it, and there is apparently a lot more subtlety to cidermaking than there is home-brew beer. And we got some real strong funk in that cider that did not make it necessarily an enjoyable experience. Like, it worked but wasn't the tastiest. JOËL: So it got alcoholic. It was just terrible to drink. AJI: Yeah, I would back that up. JOËL: So recently, at thoughtbot, we had a conversation among different team members about the use of Ruby class methods, when they make sense, when they are to be avoided. What is their use case? And different people had different opinions. So I'm curious what your take on class methods are. When do you like to use them? AJI: Yeah, I remember those conversations coming up. I think I might have even started one of those threads because this is something that comes up to me a lot. I'm a long-time listener, first-time caller to The Bike Shed. [laughs] I can remember awaiting new episodes from Sage and Derek to listen to on my way to and from my first dev job. And at one point, Sage had said, "Never put your business logic in something that you can't call .new on." And being a young, impressionable developer at the time, I took that to heart, and that seems something that just has been baked in and stayed very truthful to me. And I think one of the times that I asked that and got some conversation started was I was trying to figure out why did I feel that, and like, why did they say that? And I think, yeah, I try to avoid them. I like making instances of things. What is your stance on the Class Method, capital C, capital M? JOËL: I also generally avoid them. I have sort of two main scenarios that I like to use class methods, first is as an alternate constructor. So new is effectively a class method that's built into Ruby's object model. But sometimes, you want variations on your constructor that maybe sets values by default or that construct things with some slightly different inputs, things like that. And so those almost always make sense as class methods. The other thing that I sometimes use a class method for is as an alias for newing up an instance and then immediately calling an instance method on it. So it's just a slightly shorthand way to call some code. AJI: That's usually been my first line defense of when there's someone who might feel more comfortable doing class methods that sees me making an instance and says, "Well, you don't need an instance, just make a class method here because it'll get too long if you have to .new and then dot this other thing." And so I'll throw in that magic little trick and be like, here you go. You can call it a class method, and you still get all the benefits of your instance. I love that one. JOËL: Do you feel like that maybe defeats the purpose? In terms of the interface that people are using, if you're calling it a class method, do you lose the benefits of trying to do things at the instance level instead? Or is it more in the implementation that the benefits are not at the caller level? AJI: I think that's more true that the benefits are at the instance level, and you're getting all of that that goes along with it. And you're not carrying along a lot of what I see as baggage of the class method version, but you're picking up a little bit of that syntactic sugar. And sometimes it's even easier just to conceptualize, especially in the Rails space because we have all of these different class methods like, you know, Find is one I'm sure that we use all the time to call it on a class, and we get back an instance. And so that feels very natural in the Rails world. JOËL: I think you could make an argument that that is a form of alternate constructor. It's a class method you call to get an instance back. AJI: Yeah, absolutely. JOËL: The fact that it makes a background request to the database is an implementation detail. AJI: For sure. I agree with that. I had a similar need in a recent project where the data was kept on a third-party API. So I treated it the same way as, instead of going out to the database like ActiveRecord does, made a class method that went off to the API and then came back and made the object that was the representation of that idea in our application. So, yeah, I wholeheartedly agree with that. JOËL: So in Rails, we have the scope keyword, which will run some query to get a collection of records. But another way that they're often implemented is as class methods, and they're more or less interchangeable. How do you feel about that kind of use of class methods on an ActiveRecord object? Does that violate some of the ideas that we've been talking about? Does it sort of fit in? AJI: I think when reaching for that sort of need, I sort of fall into the camp of making a class method rather than using a scope. It feels a little less like extending some basic Rails functionality or implying that it's part of the inherent framework and makes it a little more like behavior that's been added that's specific to this domain. And I think that distinction comes into my thinking there. I'm sure there are other reasons. What are your thoughts there? Maybe it'll spark an idea for me. JOËL: For me, I think I also generally prefer to write them as class methods rather than using the scope keyword, even though they're more or less the same thing. What is interesting is that, in a way, they kind of feel like alternate constructors in that they don't give you an instance; they give you back a collection of instances back. So if we bend the rules a little bit...these are not hard and fast rules but the guidelines. If we bend the guidelines a little bit, they kind of fit under the general categories for best uses of class method that we discussed earlier. AJI: Yeah, I can definitely see that. I tend to think, or at least I think when you had first brought up the term of alternate constructors, my first thought was of one instance; you ask for a thing, and it gives you this thing back. But it's the same sort of idea with that collection because you're not getting just one instance; you're getting many instances. But it's the same kind of idea. You've asked the larger concept of the thing, the class, to give you back individuals of that class. So that totally falls in line with how I think about acceptable uses of these class methods the way that we've been talking about them. JOËL: Rails is something really interesting where a lot of the logic that pertains to a single item will live at the instance level. And then logic that pertains to a group of items will live at the class level. So you almost have like two categories of operations that you can run that semantically live either at the class or the instance level. Have you ever noticed that separation before? AJI: I think that separation feels natural to me because I came into programming through Rails. And I might have been colored in my thinking about this by the framework. The way that I conceptualize what a class is being sort of this blueprint or platonic ideal of what an individual might be and sort of describing the potential behaviors of such an individual. Having that kind of larger concept be able to work across multiple instances feels, yeah, it feels sort of natural. Like, if you were to think about this idea of a chair, then if you went in and modified what a chair is to mean, then any chair that you asked for later on would kind of come with that behavior along with it. Or if you ask for several chairs, they would all sort of have that idea. JOËL: I think similar to you; I had that outlook on that's almost like a natural structuring of things. And then, years ago, I got into the hot, new JavaScript framework that was Backbone.js. And it actually separates...it has like a model for individual instances, and then a separate kind of model thing for collections. And that kind of blew my mind. But what was interesting, then, is that you effectively have instance methods that can deal with all things collection-related, any sort of filtering, any sort of transformations. All of those are done, which you have an instance of a collection, basically, that you act on. And I guess if we were trying to translate that into Rails, that's almost like the concept of a query object. AJI: Hmm, it's sort of an interesting way to think about that. And Backbone, I feel like I did a day of that in bootcamp. But it has been some time, so I'm not sure that I've worked with that pattern specifically. But it does sort of bring up the idea of how much do you want to be in one model class? And do you want it to contain both of these concepts? If you have a lot of complex logic that is going to be dealing with a collection, rather than putting that in your model, I think I would probably reach for something like a service object that is going to be specifically doing that and sort of more along that Backboney approach maybe like a query object or something like that. JOËL: Interesting. When you use the term service object, do you mean something that's not a Rails model, just in general? Or are you talking specifically about one of these objects that can respond to call and is... I've heard them sometimes called Command objects or method objects. AJI: Yeah, that's an overloaded term certainly in the real space, isn't it? Service object, and what does that mean? I think generally, when I say it, I'm meaning just a plain, old Ruby object like something that is doing its one thing. You're going to use it to do its implementation details. They're all kind of hidden behind in private methods and return you something useful that you can then plug into what you were doing or what you need going on in some other place in your app. So it, to me, doesn't imply any specific implementation of, like, do you have call? Do you use it this way? Do you use it that way? But it's something that's kind of outside of it is either a model, a view, a controller, and it encapsulates some kind of behavior. So whether that, like we're saying, is a filtering or, you know, it's going to wrap that up. JOËL: I see. So, for you, a query object would be a service object. AJI: Yeah, I think so. You know, maybe this is one of the reasons why I generally don't like the overuse of the term service object in our space. I don't know if that's a hot take, and I'm going to get emails for this. But -- JOËL: Everybody send your angry tweets @Aji. AJI: Yeah, do it to @Aji on Twitter because I've been trying to get that three-letter handle for years. No, but if you want to talk to me, I'm @DoodlingDev. But, yeah, certainly, it does feel sometimes like an overloaded term, and I just want to go back to talking about plain, old Ruby objects. JOËL: So, service object is definitely an overloaded term. It's used for a lot of things. One thing that I've often seen it referring to are objects that respond to call. And just to keep away the confusion, maybe let's call them Command objects for the purposes of this conversation. AJI: Sounds good. JOËL: I commonly see them done where the implementation is done with a class method named call. Sometimes it delegates to an instance that also has call. Sometimes it's all implemented as a class method. How do you feel about that pattern? AJI: I don't mind the idea of a thing that responds to call. It, in a way, sort of implies that the class is sort of named as an action, which I don't like. It has an er name, and that kind of has a class named as a pattern. And that always sort of bugs me a little bit. But what I hope for when I open up one of those sorts of classes or objects is that it's going to delegate to an instance because then you're, again, picking up all of those wonderful benefits of the instance-level programming. JOËL: You keep mentioning the wonderful benefits of instance-level programming. What are some of those benefits? AJI: One of the ones that sort of strikes me most visibly or kind of viscerally when I see it is that they're very easy to understand. You can extract methods pretty easily that don't turn into kind of clumsy code of a bunch of different class methods that all have four arguments passed in because they're all operating on the same context. And when you're all operating on the same context, you have really a shared state. And if you're just passing that shared state around, it just gets super confusing. And you get into the order of your arguments, making a big impact on how you are interacting with these different thing…

    Full show notes at the publisher

    357: Notetaking For Developers Oct 11, 2022
    Show notes

    Joël is joined by Amanda Beiner, a Senior Software Engineer at GitHub, who is known for her legendary well-organized notes. They talk about various types of notes: debugging, todos, mental stack, Zetelkasten/evergreen notes, notetaking apps and systems, and visual note-taking and diagramming too! @amandabeiner Mermaid.live Monodraw Zettlekasten Evergreen Notes Notion Obsidian Transcript: JOËL: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Joël Quenneville. And today, I'm joined by Amanda Beiner, a Senior Software Engineer at GitHub. AMANDA: Hey, Joël. Great to see you. JOËL: And together, we're here to share a little bit of what we've learned along the way. So, Amanda, what is new in your world? AMANDA: Well, one thing I'm really excited about is that my team at GitHub is experimenting with how we're going to incorporate learning and sharing what we've learned with each other in new ways, and I'm really excited to see where people take that. So, one of the things that we're thinking of is that we all get really busy, and we all have exciting projects that we're working on in the day-to-day, and sometimes it can be really hard to pull yourself away from them to do some learning that would be something that will probably help you in the long run. But every time we do do projects like that, people are really excited about it, and people like to collaborate. So we're just trying to figure out how we can make that a more regular thing because it's great for our whole team. JOËL: I love that. Do you have a project or something that you've been getting into recently to learn? AMANDA: Yeah. One of the things that I have been working on is that this is the first backend-focused role that I've had in my entire career. So I feel like I just kind of keep pulling back layers on how different forms of magic work. And I'm just trying to get closer to the metal of what is powering our databases. And that's something that I've been really excited to learn some more about. JOËL: So it's digging into a lot of, like, Postgres and just general database theory. AMANDA: Yeah. So for me, I've spent a lot of time at the Active Record layer as I have been settling into my role and figuring out what our domain models are that we care about. And I'm trying to get a little bit more into the questions of why did these tables end up looking the way that they do? Why are they normalized or denormalized where they are? And trying to get a better idea of the theory behind those decisions. JOËL: And this is a new team that you've joined. AMANDA: This is an existing team that I've joined a year ago now. JOËL: So it sounds like you're dealing with a somewhat unfamiliar codebase. You're looking at a bunch of existing models and database tables. That can be a lot to process and understand when you first join a team. Do you have an approach that you like to use when you're looking at unknown code for the first time? AMANDA: Yeah. I usually like to dive right in as much as I can, even if it's with a very small bug fix or something like that, something that allows me to just get my hands dirty from the beginning and poke around what models I'm dealing with, and maybe some of the adjacent ones that I don't need to know about now but might want to come back to later. JOËL: One thing that I find is really helpful for me are diagramming and note-taking. So if it's something like a database table or ActiveRecord models that I'm not familiar with, if it's more than maybe two or three, which is probably the most I can keep in my head, I have to start drawing some kind of like an entity-relationship diagram or maybe even just a bulleted list somewhere where it's like here are the things and how they connect to each other. Otherwise, I’m like, I don't know, I don't have enough RAM in my brain for that. AMANDA: That sounds like a really helpful approach. How do you approach creating these diagrams? JOËL: Occasionally, I will just draw it out by hand with pen and paper. But more recently, I've been using tools like Mermaid.js and specifically the website mermaid.live that allows you to just put in some names and arrows, and it will build out a diagram for you. And that's been really helpful to explore and understand what is going on with different entities that relate to each other. AMANDA: I've used Mermaid.js recently, and I really enjoyed it as well. I found that writing something that lets me write words or something somewhat like words and takes care of the drawing for me is probably best for everyone involved. JOËL: Yeah, that's a good point. It's kind of like Markdown, the ability to just write a little bit of text and move on and not worry about the size of boxes or the shape of the arrows or whatever. It helps you to really stay in that flow and keep moving. AMANDA: I definitely agree. I feel like I can't have been the only person that somehow ended up very deep into the Figma documentation because I didn't quite know how to do what I was supposed to do, and I forgot what I was trying to draw in the first place. JOËL: Right. It's really easy to put your designer hat on and want to make something like a beautiful diagram when this is really more of a capturing your state of mind. It's a rough note, not something you're necessarily going to publish. So, in addition to visuals, do you find yourself taking a lot of notes when you're exploring code or debugging code? AMANDA: Yeah. I feel like I tend to jot a lot of things down, maybe class names, maybe some links to PRs or issues, or anywhere that might have context about what I'm looking at and how it got in that way. At this point in the process, it feels my notes usually feel like a bit of a bullet point list that doesn't quite make sense to me yet but maybe will get some shaping later. JOËL: What kind of things do you tend to record in those notes? AMANDA: I think one of the things that I'm usually trying to get out of those notes is just a snapshot of what I'm trying to accomplish at the time that I'm creating them. What's the bug that I'm trying to solve, and how did I get into this rabbit hole? So that if it ends up being the wrong one, I can follow my breadcrumbs back out and start a different way. JOËL: Oh, that is really powerful. I love the imagery you used there of following breadcrumbs. And I feel like that's sometimes something I wish I had when I'm either exploring a particular code path or trying to find a bug. And at some point, I've gone a pretty long path, and I need to back up. And I don't remember exactly where I was or how I got to this point, especially if I've gone down a path, backtracked a little bit, gone down a different path, backtracked, gone further down a third path. And so having breadcrumbs, I think, is a really valuable thing that I wish I did more when I was debugging. AMANDA: Yeah. And one of the most helpful breadcrumbs that I found is just a list of questions. What was the question that I was trying to answer when I opened this file or looked at this method, and did it help me solve that question or answer that question? And if the answer is no, then I can refer back to what the question was and try to think about what else might help me solve that question. JOËL: I also love that. It's really easy to get sidetracked by other questions or other ideas when exploring or debugging. And sometimes I find that half hour later, I haven't answered the original question I came here to answer, and I kind of haven't even tried. And so, maybe writing down my questions before I go down a path would help me stay more focused during a debugging session rather than just trying to keep it all in my head. AMANDA: I very much relate to getting nerd sniped by something that looks interesting but ultimately doesn't solve the original problem that you were trying to. JOËL: This even happens to me when I'm pair programming. And so we'll say out loud the question we're trying to answer is this; let's open this file. And then you go into it, and you're like, oh, now that is an unusual line of code right there. AMANDA: [laughs] JOËL: I wonder why they're doing that. Let me check the git blame on this line. Oh, it's from 2015? AMANDA: [laughs] JOËL: I wonder what was happening there. Was that part of a Rails upgrade? And then, at some point, the other person has to interject and be like, "That's all fascinating, but I think the question we're actually trying to answer is..." and we get back on track. AMANDA: I feel like that's a really good opportunity, maybe for a different kind of note of just interesting curiosities in a given codebase. I find that one of the skills that I'm trying to get better at is, rather than building a repository of information or answers to questions, just building a mental map of where the information I'm trying to find lives so that when someone asks me a question or when I have to solve something I don't necessarily know the answer, but I just know the resource to find that will point me in the direction of that answer. And I feel like those kinds of explorations are really helpful for building out that mental model, even if it may be at the time seems like an unrelated rabbit hole. JOËL: So this kind of note is a bit more permanent than a bread crumb style note would be. AMANDA: Yeah, maybe. And I guess maybe it's less of a note, and it feels kind of like an index. JOËL: Hmmm. AMANDA: Like something that's connecting other pieces of information. JOËL: That's really interesting. It's got me thinking about the fact that note-taking can be very different in different situations and for different purposes. So we've talked a little bit about debugging. I think we've mixed debugging and exploration. Maybe those two are not the same, and you treat notes differently. Actually, do you treat those two as different, or do you have different approaches to note-taking when you're exploring a new codebase versus debugging a particular problem? AMANDA: I think that those kinds of notes could probably be a little bit different because I think when I'm onboarding onto a new codebase, I'm trying to cast a pretty wide net and give some overall information about what these things do that by the time I'm very deep in debugging, it might be information that I already know very well. So I feel like maybe debugging notes are a little bit more procedural. They are a little bit more I did X, and I did Y, and I did Z, and these were the questions. And the introductory notes to a new codebase might be more along the lines of this is what this model does, and stuff that will eventually become second nature and might be useful to pass off to someone else who's onboarding but which I might myself not refer back to after a certain amount of time. JOËL: I see. That's an interesting point because not only might the type of notes you take be different in different scenarios, but even their lifespan could be different. The value of a debugging note, that sort of breadcrumbs, might really only be that useful for a few hours or a couple of days. I can imagine notes you're taking while you're exploring a codebase those might be helpful for a much longer period and, as you said, maybe in passing them on to someone else when they're joining a team. AMANDA: So that makes me think of whether the debugging notes should be as short-lived as I'm making them sound because I feel like there are times where you know you've debugged something previously, but you didn't keep the notes. Maybe they were just on a scrap of paper, and now they're gone. And I feel like I'd like to do a better job of digesting those notes a little bit better and eventually turning them into something that can be a little bit longer-lived. JOËL: That's fair. I find that, especially for debugging, I like to capture a lot of what was in my notes in the eventual commit message for the fix. Of course, my random breadcrumbs probably don't make sense in the commit message, but a lot of what I have learned along the way often is helpful. AMANDA: That's a really good point. I hadn't thought of commit messages as notes, but you're right; they totally are. JOËL: One thing I've done is I've sort of taken this idea to the extreme. I was debugging some weird database table ActiveRecord model interactions, and the modeling was just a little bit unusual. There were multiple sources of truth in the relationships. And there were enough models that I struggled to really understand what was going on. And so I drew an entity-relationship diagram. And I felt that that was important to understand for people reviewing the code but also anybody looking back at the commit later on. So I used a tool called Monodraw, which allows you to draw simple diagrams as ASCII art. And so, I have a little ASCII art ERD in my commit message. AMANDA: That's incredible. I feel like if I were a developer git logging and I saw that commit message, I would be both thrilled and terrified of what exactly I was diving into in the git blame. [laughs] JOËL: Definitely both, definitely both. But I have referred back maybe a few months later. Like you said, I had to refer back to that commit because a similar bug had cropped up somewhere else. And I knew that that commit had information that I had gathered that would make the debugging experience easier. AMANDA: I guess the commit message is a really good example of having a note that's very closely tied to its context. Like, it's in the context of like a commit, which is a set of changes at a point in time, and it's really well situated in there. What do you think about the trade-offs of having that as part of a commit message versus something like some other sort of documentation where something like that could live? JOËL: I guess it depends on how you think you're going to use it in the future. Again, for debugging things, it feels like you don't often need to refer back to them, so I don't think you would want to just dump that on a wiki somewhere. It probably makes sense to have that either in just a collection of debugging notes that you have or that you could then dig into if you needed or in a commit message, something like that. But maybe some of the things that you learned along the way could be pulled out and turned into something that lives somewhere else that's maybe less of a note at that point and more of a publication. AMANDA: That sounds like a fine line between note and publication. JOËL: Perhaps it's an artificial line that I'm making. AMANDA: [laughs] JOËL: But yeah, I guess the idea is that sometimes I will look at my own debugging notes and try to turn them into something like either a wiki page for a particular codebase or potentially even a blog post on the thoughtbot blog, something that I've been able to synthesize out of the notes there. But now you've kind of gone a few steps beyond the underlying raw notes. AMANDA: I'm interested in your thoughts on that synthesis of notes into how does something go from a commit message into a blog? What does that process look like for you? JOËL: I have a personal note-taking system that's loosely inspired by a system called Zettelkasten and also another similar system called evergreen notes. The idea is that when you learn things, you capture small atomic notes, so they are an idea in your…

    Full show notes at the publisher

    356: The Value of Specialized Vocabulary Sep 27, 2022
    Show notes

    Guest and fellow thoughtbotter Stephanie Minn and Joël chat about how the idea of specialized vocabulary came up during a discussion of the Ruby Science book. We have all these names for code smells and refactors. Before knowing these names, we often have a vague sense of the ideas but having a name makes them more real. They also give us ways to talk precisely about what we mean. However, there is a downside since not everyone is familiar with the jargon. This episode is brought to you by Airbrake. Visit Frictionless error monitoring and performance insight for your app stack. Stephanie's previous talk Non Violent Communication RubyConfMini Ruby Science book Connascence as a vocabulary to discuss coupling Wired series "5 levels of teaching" Transcript: JOËL: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Joël Quenneville. And today, I'm joined with fellow thoughtboter Stephanie Minn. STEPHANIE: Hey, Joël. JOËL: And together, we're here to share a little bit of what we've learned along the way. Stephanie, what is new in your world? STEPHANIE: Thanks for asking. I am on a new project I just started a few weeks ago, and I'm feeling the new project vibes, I think, kind of scoping out what's going on with the client with the work that they're doing. Trying to make a good impression. I think lately I've been in that mode of where can I find some work to do even when I'm just getting on boarded and learning the domain, trying to make those README updates in the areas that are a bit outdated, and yeah, just kind of along for the ride. One thing that has been surprising already is that in my second week, the project pivoted into a different direction than what I was expecting. So that has been kind of exciting and also pretty interesting to see sometimes this stuff happens. I was brought on thinking that we were working on rebuilding the front end in React and TypeScript, pulling out pieces of their 15-year-old Rails monolith. So that was kind of one area that they decided to start with. But recently, they actually decided to pivot to just revamping the look of the existing pages in the Rails app using the same templates and forms. So it's kind of shifted from more greenfield-esque work to figuring out what the heck's going on in this legacy codebase and making it a little bit more modern-looking and cleaning out the cobwebs, I suppose as we find them. JOËL: As a consultant, how do you deal with that kind of dramatic shift in expectations? STEPHANIE: I think it's tough because I necessarily wasn't in those conversations, and so I have to come at it with the understanding that they have a deep knowledge of the business and things that are going on behind the scenes that I don't, and I am coming in kind of with a fresh set of eyes. And it definitely raises some questions for me, right? Like, why now? What were the trade-offs that were made in the decisions? And I hope that as a consultant, I can poke and prod a little bit to help them with the transition and also figuring out its impact on the rest of the team in a way maybe someone who is more familiar with the situation and more tied to the politics of the org might not have that perspective. JOËL: I have a lot of questions here. But actually, I'm thinking that onboarding as a topic would probably make a good standalone episode. So maybe we'll have to bring you back for a future episode to talk about how to onboard well and how to deal with surprises. STEPHANIE: Yeah, I think that's a great idea. What about you, Joël? What's going on in your world? JOËL: I'm doing an integration with a third-party gem, and I am really struggling. And I've gotten to the point where I'm reading through the source of the gem to try to figure out some weird errors, some things that come up that are not documented. I think that's a really valuable skill. Ideally, you're not having to bring it out too often, but when you do, being able to drop into the code can really help unblock you or at least make some amount of progress. STEPHANIE: Are you having to dig into the gem's code because you weren't able to find what you needed from the documentation? JOËL: That's correct. I'm getting some cryptic errors where the gem is crashing, and I'm finding some lines in my logs that point back to the gem. And now I'm trying to reconstruct what is happening. Why is it not behaving the way it should be based on the documentation that I read? STEPHANIE: Oh, that's tough. Getting into gem code is uncharted territory. JOËL: It's nice when you're working with an open-source gem because the source is there, and you can just follow the stack trace and go through the code. Sometimes it's long and tedious, but it generally gives you results. It definitely is intimidating. STEPHANIE: Yeah. When you're facing this kind of problem where you have no idea where the light at the end of the tunnel might be, how long do you spend with it? At what point do you take away with what you've learned and try to figure out a different approach? JOËL: That's a good observation because digging through the source of a gem can definitely be a time sink. I think how much time I want to budget depends on a variety of other factors. How big of a problem is this? If I can't figure it out through reading the source, do I have alternate approaches to debug the problem, such as asking for help, opening an issue, reaching out to somebody else who's used it, complaining about it on The Bike Shed and hoping someone responds with an answer? There are other options that I can do that might leave me blocked but maybe eventually give me results. The advantage with reading the source is that you're at least feeling like you're making progress. STEPHANIE: Nice. Well, I wish you luck on that journey. [laughs] It sounds pretty tough. I'm sure that you'll get to one of those solutions and figure out how to get unblocked. JOËL: I hope so. I'm pursuing a few strategies in tandem. So I've asked for help, but I'm also reading the source code. And between the two of those, I hope I'll get to a good solution. So, Stephanie, last time you were on the show, you talked about your experience creating talk proposals for RubyConf. Have you heard back from them since then? STEPHANIE: I have. I will be speaking at RubyConf Mini this year. And I'm really excited because this will be my first IRL conference talk. So last time, I recorded my talk for RubyConf, and this time I will be up on a stage in front of real people. JOËL: That's really exciting. Congratulations. STEPHANIE: Thanks. JOËL: What is the topic of your talk? STEPHANIE: I will be talking about pair programming and specifically pair programming through the lens of a framework called Nonviolent Communication, which is a framework I learned about through a friend who recommended the canonical book on it. And it's a self-help book, to be totally frank, but I found it so illuminating. It really changed how I communicated in my relationships in my personal life. And the more time I spent with it, the more I realized that it would be a great application in pair programming because it's so collaborative and intimate. I've experienced the highs and lows of pair programming. You can feel so good when you are super connected with your pair. You make a lot of progress. You meet whatever professional goals that you might be meeting, and you have someone along for the ride the whole time. It can be just so rewarding. But it can also be really challenging when you are having more of those interpersonal conflicts, and navigating that can be tough. And so I'm really excited to share this style of communication that might help others who want to take their pair programming to the next level and get the most out of that experience no matter who they're pairing with. JOËL: I'm excited to hear this talk because pair programming has always been an important part of what we do at thoughtbot. And I think now that we're remote, we do a lot of remote pair programming. And the interpersonal interactions are a little bit different there than when you're physically in a room with each other, or you have to maybe pay a little bit more attention to them. I'm really excited to hear that. I think that's going to be really useful, not just for me but for a lot of the audience who are there. STEPHANIE: Thanks. Joël, you have a talk accepted at RubyConf Mini too. JOËL: Yes, I also had a talk accepted titled Teaching Ruby to Count. And it's going to be all about series, enumerators, enumerables, and ranges in Ruby and the cool things that you can do with them. So I'm really excited to share about that. I've done some deep dives on these topics, and I'm excited to share that with the broader Ruby community. STEPHANIE: Nice. I'm really excited to hear more about it. JOËL: Did you submit more than one proposal this year? STEPHANIE: This year, I didn't. But I would love to get to a point where I have a lot of content on the backburner and can pull it out when CFP season rolls around to just have some more options. Yeah, I have all these ideas in my head. I think we talked about how we come up with content in our last episode. But yeah, having a content bank sounds really nice for the future, so maybe when that season rolls around, it is a lot easier to get the ball rolling on submitting. What about you? Did you submit more than one? JOËL: I submitted two, but this is the one I was most excited about. I think the other idea was maybe a little bit more polished, but this one was a newer one I came up with towards the end of the CFP period. And I was like, ooh, I'm excited about this. I've just done a deep dive on enumerators, and I think there are some cool things to share with the community. And so that's what I'm excited to share about, and maybe that came through the proposal because that is what the committee picked. So I'm super happy to be talking about that. STEPHANIE: Nice. Yeah, I was just thinking the same, that your excitement about it was probably palpable to the committee. JOËL: For any of our viewers who are interested in coming to watch the talks by Stephanie and myself and plenty of other gifted speakers, this will be at RubyConf Mini in Providence, Rhode Island, from November 15th to 17th. And if you can't make it in person, the videos will be published online early in 2023. And we'll definitely share the links to that when they come out. So as we mentioned in your last episode, thoughtbot has a book club where we've been discussing the book Ruby Science, which goes through a lot of code smells and talks about some various refactoring patterns that can be used to fix them. Most recently, we looked at a code smell that has a very evocative name; it's called shotgun surgery. STEPHANIE: Yeah, it's a very visceral name for sure. I think that is what prompted this next topic that we're about to discuss because someone in the book club, another thoughtboter, mentioned that they were learning this term for the first time. But it made a lot of sense to them because they had experienced shotgun surgery and didn't have the term for it previously. Joël, do you mind giving the listeners a recap of what shotgun surgery is? JOËL: So shotgun surgery is when in order to make a change to a codebase, you have to make a bunch of little changes in a lot of different files, a lot of different locations. And that means that all of these little pieces are weirdly coupled to each other in a way that to make one change, you have to make a bunch of little changes in a lot of places. And that results in a very high churn diff, and that's a common symptom of this problem. STEPHANIE: Nice. Thanks for explaining. MID-ROLL AD: Debugging errors can be a developer’s worst nightmare...but it doesn’t have to be. Airbrake is an award-winning error monitoring, performance, and deployment tracking tool created by developers for developers that can actually help cut your debugging time in half. So why do developers love Airbrake? It has all of the information that web developers need to monitor their application - including error management, performance insights, and deploy tracking! Airbrake’s debugging tool catches all of your project errors, intelligently groups them, and points you to the issue in the code so you can quickly fix the bug before customers are impacted. In addition to stellar error monitoring, Airbrake’s lightweight APM helps developers to track the performance and availability of their application through metrics like HTTP requests, response times, error occurrences, and user satisfaction. Finally, Airbrake Deploy Tracking helps developers track trends, fix bad deploys, and improve code quality. Since 2008, Airbrake has been a staple in the Ruby community and has grown to cover all major programming languages. Airbrake seamlessly integrates with your favorite apps to include modern features like single sign-on and SDK-based installation. From testing to production, Airbrake notifiers have your back. Your time is valuable, so why waste it combing through logs, waiting for user reports, or retrofitting other tools to monitor your application? You literally have nothing to lose. Head on over to airbrake.io/try/bikeshed to create your FREE developer account today! STEPHANIE: I think I came away from that conversation thinking about the idea of learning new terms, especially technical ones, and the power that learning those terms can give you as a developer, especially when you're communicating with other people on your team. JOËL: So you mentioned the value in communication there. Some terms have a very precise meaning, and so that allows you to communicate a very specific idea. How do you balance having some jargon and some terminology that allows you to speak very precisely versus having to learn all the terms? Because the more narrow the term is, the more terms you need to talk about all the different things. STEPHANIE: That's a great question. I don't know if I have a great answer because I think I'm still on my journey. I have always noticed when developers I work with have that really precise, articulate technical vocabulary, probably because I don't. I am constantly referring to functions or classes as things, like, that thingy over there talks to this thing over here, and then does something. [laughs] And I think it's because I maybe didn't always have that exposure to very precise technical vocabulary. And so I had an understanding of how things worked in my head, but I couldn't necessarily map that to words. And I'm also from California, so, I don't know, maybe some of that is showing through a little bit. [laughs] But I've been trying to incorporate more technical terms when I speak and also in written form, too, such as in code review, because I want to be able to communicate more clearly my intentions and leave less room for ambiguity. Sometimes I've noticed when you do speak more casually about code, turns out other people can interpret it in different ways. And if you are using, like you said, that narrower technical term for it, that leaves less room for misunderstanding. But in the same vein, I think a lot of people are like me, where they might not know the technical terms for things. And when you start using a lot of jargon like that, it can be a bit exclusive to folks earlier in their career, especially since software as an industry we have folks from all different back…

    Full show notes at the publisher

    355: Test Performance Sep 20, 2022
    Show notes

    Guest Geoff Harcourt, CTO of CommonLit, joins Joël to talk about a thing that comes up with a lot with clients: the performance of their test suite. It's often a concern because with test suites, until it becomes a problem, people tend to not treat it very well, and people ask for help on making their test suites faster. Geoff shares how he handles a scenario like this at CommonLit. This episode is brought to you by Airbrake. Visit Frictionless error monitoring and performance insight for your app stack. Geoff Harcourt Common Lit Cuprite driver Chrome DevTools Protocol (CDP) Factory Doctor Joël's RailsConf talk Formal Methods Rails multi-database support Knapsack pro Prior episode with Eebs Shopify article on skipping specs Transcript: JOËL: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Joël Quenneville. And today, I'm joined by Geoff Harcourt, who is the CTO of CommonLit. GEOFF: Hi, Joël. JOËL: And together, we're here to share a little bit of what we've learned along the way. Geoff, can you briefly tell us what is CommonLit? What do you do? GEOFF: CommonLit is a 501(c)(3) non-profit that delivers a literacy curriculum in English and Spanish to millions of students around the world. Most of our tools are free. So we take a lot of pride in delivering great tools to teachers and students who need them the most. JOËL: And what does your role as CTO look like there? GEOFF: So we have a small engineering team. There are nine of us, and we run a Rails monolith. I'd say a fair amount of the time; I'm hands down in the code. But I also do the things that an engineering head has to do, so working with vendors, and figuring out infrastructure, and hiring, and things like that. JOËL: So that's quite a variety of things that you have to do. What is new in your world? What's something that you've encountered recently that's been fun or interesting? GEOFF: It's the start of the school year in America, so traffic has gone from a very tiny amount over the summer to almost the highest load that we'll encounter all year. So we're at a new hosting provider this fall. So we're watching our infrastructure and keeping an eye on it. The analogy that we've been using to describe this is like when you set up a bunch of plumbing, it looks like it all works, but until you really pump water through it, you don't see if there are any leaks. So things are in good shape right now, but it's a very exciting time of year for us. JOËL: Have you ever done some actual plumbing yourself? GEOFF: I am very, very bad at home repair. But I have fixed a toilet or two. I've installed a water filter but nothing else. What about you? JOËL: I've done a little bit of it when I was younger with my dad. Like, I actually welded copper pipes and that kind of thing. GEOFF: Oh, that's amazing. That's cool. Nice. JOËL: So I've definitely felt that thing where you turn the water source back on, and it's like, huh, let's see, is this joint going to leak, or are we good? GEOFF: Yeah, they don't have CI for plumbing, right? JOËL: [laughs] You know, test it in production, right? GEOFF: Yeah. [laughs] So we're really watching right now traffic starting to rise as students and teachers are coming back. And we're also figuring out all kinds of things that we want to do to do better monitoring of our application, so some of this is watching metrics to see if things happen. But some of this is also doing some simulated user activity after we do deploys. So we're using some automated browsers with Cypress to log into our application and do some user flows, and then report back on the results. JOËL: So is this kind of like a feature test in CI, except that you're running it in production? GEOFF: Yeah. Smoke test is the word that we've settled on for it, but we run it against our production server every time we deploy. And it's a small suite. It's nowhere as big as our big Capybara suite that we run in CI, but we're trying to get feedback in less than six minutes. That's sort of the goal. In addition to running tests, we also take screenshots with a tool called Percy, and that's a visual regression testing tool. So we get to see the screenshots, and if they differ by more than one pixel, we get a ping that lets us know that maybe our CSS has moved around or something like that. JOËL: Has that caught some visual bugs for you? GEOFF: Definitely. The state of CSS at CommonLit was very messy when I arrived, and it's gotten better, but it still definitely needs some love. There are some false positives, but it's been really, really nice to be able to see visual changes on our production pages and then be able to approve them or know that there's something we have to go back and fix. JOËL: I'm curious, for this smoke test suite, how long does it take to run? GEOFF: We run it in parallel. It runs on Buildkite, which is the same tool that we use to orchestrate our CI, and the longest test takes about five minutes. It signs in as a teacher, creates an account. It creates a class; it invites the student to that class. It then logs out, logs in as that student creates the student account, signs in as the student, joins the class. It then assigns a lesson to the student then the student goes and takes the lesson. And then, when the student submits the lesson, then the test is over. And that confirms all of the most critical flows that we would want someone to drop what they were doing if it's broken, you know, account creation, class creation, lesson creation, and students taking a lesson. JOËL: So you're compressing the first few weeks of school into five minutes. GEOFF: Yes. And I pity the school that has thousands of fake teachers, all named Aaron McCarronson at the school. JOËL: [laughs] GEOFF: But we go through and delete that data every once in a while. But we have a marketer who just started at CommonLit maybe a few weeks ago, and she thought that someone was spamming our signup form because she said, "I see hundreds of teachers named Aaron McCarronson in our user list." JOËL: You had to admit that you were the spammer? GEOFF: Yes, I did. [laughs] We now have some controls to filter those people out of reports. But it's always funny when you look at the list, and you see all these fake people there. JOËL: Do you have any rate limiting on your site? GEOFF: Yeah, we do quite a bit of it, actually. Some of it we do through Cloudflare. We have tools that limit a certain flow, like people trying to credential stuffing our password, our user sign-in forms. But we also do some further stuff to prevent people from hitting key endpoints. We use Rack::Attack, which is a really nice framework. Have you had to do that in client work with clients setting that stuff up? JOËL: I've used Rack:Attack before. GEOFF: Yeah, it's got a reasonably nice interface that you can work with. And I always worry about accidentally setting those things up to be too sensitive, and then you get lots of stuff back. One issue that we sometimes find is that lots of kids at the same school are sharing an IP address. So that's not the thing that we want to use for rate limiting. We want to use some other criteria for rate limiting. JOËL: Right, right. Do you ever find that you rate limit your smoke tests? Or have you had to bypass the rate limiting in the smoke tests? GEOFF: Our smoke tests bypass our rate limiting and our bot detection. So they've got some fingerprints they use to bypass that. JOËL: That must have been an interesting day at the office. GEOFF: Yes. [laughter] With all of these things, I think it's a big challenge to figure out, and it's similar when you're making tests for development, how to make tests that are high signal. So if a test is failing really frequently, even if it's testing something that's worthwhile, if people start ignoring it, then it stops having value as a piece of signal. So we've invested a ton of time in making our test suite as reliable as possible, but you sometimes do have these things that just require a change. I've become a really big fan of...there's a Ruby driver for Capybara called Cuprite, and it doesn't control chrome with Chrome Driver or with Selenium. It controls it with the Chrome DevTools protocol, so it's like a direct connection into the browser. And we find that it's very, very fast and very, very reliable. So we saw that our Capybara specs got significantly more reliable when we started using this as our driver. JOËL: Is this because it's not actually moving the mouse around and clicking but instead issuing commands in the background? GEOFF: Yeah. My understanding of this is a little bit hazy. But I think that Selenium and ChromeDriver are communicating over a network pipe, and sometimes that network pipe is a little bit lossy. And so it results in asynchronous commands where maybe you don't get the feedback back after something happens. And CDP is what Chrome's team and I think what Puppeteer uses to control things directly. So it's great. And you can even do things with it. Like, you can simulate different time zone for a user almost natively. You can speed up or slow down the traveling of time and the direction of time in the browser and all kinds of things like that. You can flip it into mobile mode so that the device reports that it's a touch browser, even though it's not. We have a set of mobile specs where we flip it with CDP into mobile mode, and that's been really good too. Do you find when you're doing client work that you have a demand to build mobile-specific specs for system tests? JOËL: Generally not, no. GEOFF: You've managed to escape it. JOËL: For something that's specific to mobile, maybe one or two tests that have a weird interaction that we know is different on mobile. But in general, we're not doing the whole suite under mobile and the whole suite under desktop. GEOFF: When you hand off a project...it's been a while since you and I have worked together. JOËL: For those who don't know, Geoff used to be with us at thoughtbot. We were colleagues. GEOFF: Yeah, for a while. I remember my very first thoughtbot Summer Summit; you gave a really cool lightning talk about Eleanor of Aquitaine. JOËL: [laughs] GEOFF: That was great. So when you're handing a project off to a client after your ending, do you find that there's a transition period where you're educating them about the norms of the test suite before you leave it in their hands? JOËL: It depends a lot on the client. With many clients, we're working alongside an existing dev team. And so it's not so much one big handoff at the end as it is just building that in the day-to-day, making sure that we are integrating with the team from the outset of the engagement. So one thing that does come up a lot with clients is the performance of their test suite. That's often a concern because the test suite until it becomes a problem, people tend to not treat it very well. And by the time that you're bringing on an external consultant to help, generally, that's one of the areas of the code that's been a little bit neglected. And so people ask for help on making their test suite faster. Is that something that you've had to deal with at CommonLit as well? GEOFF: Yeah, that's a great question. We have struggled a lot with the speed that our test suite...the time it takes for our test suite to run. We've done a few things to improve it. The first is that we have quite a bit of caching that we do in our CI suite around dependencies. So gems get cached separately from NPM packages and browser assets. So all three of those things are independently cached. And then, we run our suites in parallel. Our Jest specs get split up into eight containers. Our Ruby non-system tests...I'd like to say unit tests, but we all know that some of those are actually integration tests. JOËL: [laughs] GEOFF: But those tests run in 15 containers, and they start the moment gems are built. So they don't wait for NPM packages. They don't wait for assets. They immediately start going. And then our system specs as soon as the assets are built kick off and start running. And we actually run that in 40 parallel containers so we can get everything finished. So our CI suite can finish...if there are no dependency bumps and no asset bumps, our specs suite you can finish in just under five minutes. But if you add up all of that time, cumulatively, it's something like 75 minutes is the total execution as it goes. Have you tried FactoryDoctor before for speeding up test suites? JOËL: This is the gem from Evil Martians? GEOFF: Yeah, it's part of TestProf, which is their really, really unbelievable toolkit for improving specs, and they have a whole bunch of things. But one of them will tell you how many invocations of FactoryBot factories each factory got. So you can see a user factory was fired 13,000 times in the test suite. It can even do some tagging where it can go in and add metadata to your specs to show which ones might be candidates for optimization. JOËL: I gave a talk at RailsConf this year titled Your Tests Are Making Too Many Database Calls. GEOFF: Nice. JOËL: And one of the things I talked about was creating a lot more data via factories than you think that you are. And I should give a shout-out to FactoryProf for finding those. GEOFF: Yeah, it's kind of a silent killer with the test suite, and you really don't think that you're doing a whole lot with it, and then you see how many associations. How do you fight that tension between creating enough data that things are realistic versus the streamlining of not creating extraneous things or having maybe mystery guests via associations and things like that? JOËL: I try to have my base factories be as minimal as possible. So if there's a line in there that I can remove, and the factory or the model still saves, then it should be removed. Some associations, you can't do that if there's a foreign key constraint, and so then I'll leave it in. But I am a very hardcore minimalist, at least with the base factory. GEOFF: I think that makes a lot of sense. We use foreign keys all over the place because we're always worried about somehow inserting student data that we can't recover with a bug. So we'd rather blow up than think we recorded it. And as a result, sometimes setting up specs for things like a student answering a multiple choice question on a quiz ends up being this sort of if you give a mouse a cookie thing where it's you need the answer options. You need the question. You need the quiz. You need the activity. You need the roster, the students to be in the roster. There has to be a teacher for the roster. It just balloons out because everything has a foreign key. JOËL: The database requires it, but the test doesn't really care. It's just like, give me a student and make it valid. GEOFF: Yes, yeah. And I find that that challenge is really hard. And sometimes, you don't see how hard it is to enforce things like database integrity until you have a lot of concurrency going on in your application. It was a very rude surprise to me to find out that browser requests if you have multiple servers going on might not necessarily be served in the order that they were made. JOËL: [laughs] So you're talking about a scenario where you're running multiple instances of your app. You make two requests from, say, two browser tabs, and somehow they get served from two d…

    Full show notes at the publisher

    354: The History of Computing Sep 13, 2022
    Show notes

    Why does the history of computing matter? Joël and Developer at thoughtbot Sara Jackson, ponder this and share some cool stories (and trivia!!) behind the tools we use in the industry. This episode is brought to you by Airbrake. Visit Frictionless error monitoring and performance insight for your app stack. Sara on Twitter UNIX philosophy Hillel Wayne on why we ask linked list questions History of Unix, Linux, and Open Source / Free Software Collected Histories of Unix Selected pages from the nine research editions of the UNIX® Programmer’s Manual illustrate the development of the system. Accompanying commentary recounts some of the needs, events, and individual contributions that shaped this evolution These are dates that every hacker knew were important at the time, or shortly afterwards. Unix at 50: How the OS that powered smartphones started from failure First hand account of history of Unix and Multics by Tom Van Vleck Transcript: JOËL: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Joël Quenneville. And today, I'm joined by fellow thoughtboter, Team Lead, and Developer Sara Jackson. SARA: Hello, happy to be here. JOËL: Together, we're here to share a little bit of what we've learned along the way. So, Sara, what's new in your world? SARA: Well, Joël, you might know that recently our team had a small get-together in Toronto. JOËL: And our team, for those who are not aware, is fully remote distributed across multiple countries. So this was a chance to get together in person. SARA: Yes, correct. This was a chance for those on the Boost team to get together and work together as if we had a physical office. JOËL: Was this your first time meeting some members of the team? SARA: It was my second, for the most part. So I joined thoughtbot, but after thoughtbot had already gotten remote. Fortunately, I was able to meet many other thoughtboters in May at our summit. JOËL: Had you worked at a remote company before coming to thoughtbot? SARA: Yes, I actually started working remotely in 2019, but even then, that wasn't my first time working remotely. I actually had a full year of internship in college that was remote. JOËL: So you were a pro at this long before the pandemic made us all try it out. SARA: I don't know about that, but I've certainly dealt with the idiosyncrasies that come with remote work for longer. JOËL: What do you think are some of the challenges of remote work as opposed to working in person in an office? SARA: I think definitely growing and maintaining a culture. When you're in an office, it's easy to create ad hoc conversations and have events that are small that build on the culture. But when you're remote, it has to be a lot more intentional. JOËL: That definitely rings true for me. One of the things that I really appreciated about in-person office culture was the serendipity that you have those sort of random meetings at the water cooler, those conversations, waiting for coffee with people who are not necessarily on the same team or the same project as you are. SARA: I also really miss being able to have lunch in person with folks where I can casually gripe about an issue I might be having, and almost certainly, someone would have the answer. Now, if I'm having an issue, I have to intentionally seek help. [chuckles] JOËL: One of the funny things that often happened, at least the office where I worked at, was that lunches would often devolve into taxonomy conversations. SARA: I wish I had been there for that. [laughter] JOËL: Well, we do have a taxonomy channel on Slack to somewhat continue that legacy. SARA: Do you have a favorite taxonomy lunch discussion that you recall? JOËL: I definitely got to the point where I hated the classifying a sandwich. That one has been way overdone. SARA: Absolutely. JOËL: There was an interesting one about motorcycles, and mopeds, and bicycles, and e-bikes, and trying to see how do you distinguish one from the other. Is it an electric motor? Is it the power of the engine that you have? Is it the size? SARA: My brain is already turning on those thoughts. I feel like I could get lost down that rabbit hole very easily. [laughter] JOËL: Maybe that should be like a special anniversary episode for The Bike Shed, just one long taxonomy ramble. SARA: Where we talk about bikes. JOËL: Ooh, that's so perfect. I love it. One thing that I really appreciated during our time in Toronto was that we actually got to have lunch in person again. SARA: Yeah, that was so wonderful. Having folks coming together that had maybe never worked together directly on clients just getting to sit down and talk about our day. JOËL: Yeah, and talk about maybe it's work-related, maybe it's not. There's a lot of power to having some amount of deeper interpersonal connection with your co-workers beyond just the we work on a project together. SARA: Yeah, it's like camaraderie beyond the shared mission of the company. It's the shared interpersonal mission, like you say. Did you have any in-person pairing sessions in Toronto? JOËL: I did. It was actually kind of serendipitous. Someone was stuck with a weird failing test because somehow the order factories were getting created in was not behaving in the expected way, and we herd on it, dug into it, found some weird thing with composite primary keys, and solved the issue. SARA: That's wonderful. I love that. I wonder if that interaction would have happened or gotten solved as quickly if we hadn't been in person. JOËL: I don't know about you, but I feel like I sometimes struggle to ask for help or ask for a pair more when I'm online. SARA: Yeah, I agree. It's easier to feel like you're not as big of an impediment when you're in person. You tap someone on the shoulder, "Hey, can you take a look at this?" JOËL: Especially when they're on the same team as you, they're sitting at the next desk over. I don't know; it just felt easier. Even though it's literally one button press to get Tuple to make a call, somehow, I feel like I'm interrupting more. SARA: To combat that, I've been trying to pair more frequently and consistently regardless of if I'm struggling with a problem. JOËL: Has that worked pretty well? SARA: It's been wonderful. The only downside has been pairing fatigue. JOËL: Pairing fatigue is real. SARA: But other than that, problems have gotten solved quickly. We've all learned something for those that I've paired with. It goes faster. JOËL: So it was really great that we had this experience of doing our daily work but co-located in person; we have these experiences of working together. What would you say has been one of the highlights for you of that time? SARA: 100% karaoke. JOËL: [laughs] SARA: Only two folks did not attend. Many of the folks that did attend told me they weren't going to sing, but they were just going to watch. By the end of the night, everyone had sung. We were there for nearly three and a half hours. [laughs] JOËL: It was a good time all around. SARA: I saw a different side to Chad. JOËL: [laughs] SARA: And everyone, honestly. Were there any musical choices that surprised you? JOËL: Not particularly. Karaoke is always fun when you have a group of people that you trust to be a little bit foolish in front of to put yourself out there. I really appreciated the style that we went for, where we have a private room for just the people who were there as opposed to a stage in a bar somewhere. I think that makes it a little bit more accessible to pick up the mic and try to sing a song. SARA: I agree. That style of karaoke is a lot more popular in Asia, having your private room. Sometimes you can find it in major cities. But I also prefer it for that reason. JOËL: One of my highlights of this trip was this very sort of serendipitous moment that happened. Someone was asking a question about the difference between a Mac and Linux operating systems. And then just an impromptu gathering happened. And you pulled up a chair, and you're like, gather around, everyone. In the beginning, there was Multics. It was amazing. SARA: I felt like some kind of historian or librarian coming out from the deep. Let me tell you about this random operating system knowledge that I have. [laughs] JOËL: The ancient lore. SARA: The ancient lore in the year 1969. JOËL: [laughs] And then yeah, we had a conversation walking the history of operating systems, and why we have macOS and Linux, and why they're different, and why Windows is a totally different kind of family there. SARA: Yeah, macOS and Linux are sort of like cousins coming from the same tree. JOËL: Is that because they're both related through Unix? SARA: Yes. Linux and macOS are both built based off of different versions of Unix. Over the years, there's almost like a family tree of these different Nix operating systems as they're called. JOËL: I've sometimes seen asterisk N-I-X. This is what you're referring to as Nix. SARA: Yes, where the asterisk is like the RegEx catch-all. JOËL: So this might be Unix. It might be Linux. It might be... SARA: Minix. JOËL: All of those. SARA: Do you know the origin of the name Unix? JOËL: I do not. SARA: It's kind of a fun trivia piece. So, in the beginning, there was Multics spelled M-U-L-T-I-C-S, standing for the Multiplexed Information and Computing Service. Dennis Ritchie and Ken Thompson of Bell Labs famous for the C programming language... JOËL: You may have heard of it. SARA: You may have heard of it maybe on a different podcast. They were employees at Bell Labs when Multics was being created. They felt that Multics was very bulky and heavy. It was trying to do too many things at once. It did have a few good concepts. So they developed their own smaller Unix originally, Unics, the Uniplexed Information and Computing Service, Uniplexed versus Multiplexed. We do one thing really well. JOËL: And that's the Unix philosophy. SARA: It absolutely is. The Unix philosophy developed out of the creation of Unix and C. Do you know the four main points? JOËL: No, is it small sharp tools? It's the main one I hear. SARA: Yes, that is the kind of quippy version that has come out for sure. JOËL: But there is a formal four-point manifesto. SARA: I believe it's evolved over the years. But it's interesting looking at the Unix philosophy and seeing how relevant it is today in web development. The four points being make each program do one thing well. To this end, don't add features; make a new program. I feel like we have this a lot in encapsulation. JOËL: Hmm, maybe even the open-closed principle. SARA: Absolutely. JOËL: Similar idea. SARA: Another part of the philosophy is expecting output of your program to become input of another program that is yet unknown. The key being don't clutter your output; don't have extraneous text. This feels very similar to how we develop APIs. JOËL: With a focus on composability. SARA: Absolutely. Being able to chain commands together like you see in Ruby all the time. JOËL: I love being able to do this, for example, the enumerable API in Ruby and just being able to chain all these methods together to just very nicely do some pretty big transformations on an array or some other data structure. SARA: 100% agree there. That ability almost certainly came out of following the tenets of this philosophy, maybe not knowingly so but maybe knowingly so. [chuckles] JOËL: So is that three or four? SARA: So that was two. The third being what we know as agile. JOËL: Really? SARA: Yeah, right? The '70s brought us agile. Design and build software to be tried early, and don't hesitate to throw away clumsy parts and rebuild. JOËL: Hmmm. SARA: Even in those days, despite waterfall style still coming on the horizon. It was known for those writing software that it was important to iterate quickly. JOËL: Wow, I would never have known. SARA: It's neat having this history available to us. It's sort of like a lens at where we came from. Another piece of this history that might seem like a more modern concept but was a very big part of the movement in the '70s and the '80s was using tools rather than unskilled help or trying to struggle through something yourself when you're lightening a programming task. We see this all the time at thoughtbot. Folks do this many times there is an issue on a client code. We are able to generalize the solution, extract into a tool that can then be reused. JOËL: So that's the same kind of genesis as a lot of thoughtbot's open-source gems, so I'm thinking of FactoryBot, Clearance, Paperclip, the old-timey file upload gem, Suspenders, the Rails app generator, and the list goes on. SARA: I love that in this last point of the Unix philosophy, they specifically call out that you should create a new tool, even if it means detouring, even if it means throwing the tools out later. JOËL: What impact do you think that has had on the way that tooling in the Unix, or maybe I should say *Nix, ecosystem has developed? SARA: It was a major aspect of the Nix environment community because Unix was available, not free, but very inexpensively to educational institutions. And because of how lightweight it was and its focus on single-use programs, programs that were designed to do one thing, and also the way the shell was allowing you to use commands directly and having it be the same language as the shell scripting language, users, students, amateurs, and I say that in a loving way, were able to create their own tools very quickly. It was almost like a renaissance of Homebrew. JOËL: Not Homebrew as in the macOS package manager. SARA: [laughs] And also not Homebrew as in the alcoholic beverage. JOËL: [laughs] So, this kind of history is fun trivia to know. Is it really something valuable for us as a jobbing developer in 2022? SARA: I would say it's a difficult question. If you are someone that doesn't dive into the why of something, especially when something goes wrong, maybe it wouldn't be important or useful. But what sparked the conversation in Toronto was trying to determine why we as thoughtbot tend to prefer using Macs to develop on versus Linux or Windows. There is a reason, and the reason is in the history. Knowing that can clarify decisions and can give meaning where it feels like an arbitrary decision. JOËL: Right. We're not just picking Macs because they're shiny. SARA: They are certainly shiny. And the first thing I did was to put a matte case on it. JOËL: [laughs] So no shiny in your office. SARA: If there were too many shiny things in my office, boy, I would never get work done. The cats would be all over me. MID-ROLL AD: Debugging errors can be a developer’s worst nightmare...but it doesn’t have to be. Airbrake is an award-winning error monitoring, performance, and deployment tracking tool created by developers for developers, that can actually help cut your debugging time in half. So why do developers love Airbrake? It has all of the information that web developers need to monitor their application - including error management, performance insights, and deploy tracking! Airbrake’s debugging tool catches all of your project errors, intelligently groups them, and points you to the issue in the code so you can quickly fix the bug before customers are impacted. In addition to stellar error monitoring, Airbrake’s lightweight APM helps developers to track the performance and availability of their application through metrics like HTTP requests, response times, error occurrences, and user satisfaction. Finally, Airbrake Deploy Tracking helps developers track trends, fix bad deploys, and improve code quality. Si…

    Full show notes at the publisher

    353: Mental Models Sep 06, 2022
    Show notes

    Mental models are metaphors that help us understand complex problems we work on. They can be a simplified roadmap over an infinite area of complexity. How does one come up with mental models? How are they useful? Are they primarily a solo thing, or can they be used to communicate with the team? What happens when your model is inaccurate? Today, Joël is joined by Eebs Kobeissi, a Developer and Dev Manager at You Need a Budget, to discuss. This episode is brought to you by Airbrake. Visit Frictionless error monitoring and performance insight for your app stack. Eebs on TwitterYou Need a BudgetSkill floors and skill ceilings Transcript: JOËL: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Joël Quenneville. And today, I'm joined by Eebs Kobeissi, a Developer and Dev Manager at You Need a Budget. EEBS: Hi, Joël. It's really good to be here. JOËL: And together, we're here to share a little bit about what we've learned along the way. So, Eebs, what's new in your world? EEBS: Oh, a whole lot. I'm a new dad, so I'm getting to experience all those things. But in the developer world, I've recently picked up programming on an ESP32, which controls LED lights. And so I'm having fun lighting up my office. JOËL: Is that like one of those little microboards, kind of like a Raspberry Pi? EEBS: Yeah, exactly. It's a little board that's compatible with the Arduino IDE. And I literally only played with it last weekend, so it's still very new to me. JOËL: Nice. Have you done any Arduino development or Raspberry Pi or anything like that before? EEBS: No, I have a Raspberry Pi that I run like a DNS server on, but I haven't done any actual programming. I did make an LED blink, which is pretty cool. JOËL: What kind of programming is required for a board like that? EEBS: From my understanding, it's either in Python or C. Those are, I think, the two languages that you can program on it. I definitely do not know C. And so I'm just going through a bunch of tutorials and reading some sample code. But I think if I ever end up trying to implement something more complex, I'll probably switch over to Python because that's a little more familiar. JOËL: So the coding feels fairly high level even though you're writing controller code for LEDs. EEBS: I hope so. I'd love to be able to take advantage of whatever abstractions I can. JOËL: Do you have any fun goals you're trying to do with this? Or is this just for the fun of trying a completely different environment than web development? EEBS: No, it's actually rooted in something visual. So I have these shelves behind me that are in my webcam when I'm in meetings or whatever. And so I want to be able to put a light strip across these shelves and have some sort of visual thing in the background. JOËL: Like LED mood ring? EEBS: Yeah, kind of. My eventual goal would be that as I'm talking, a little equalizer display pops up behind me. I thought that would be pretty neat. JOËL: That is amazing. That will give you all of the cred in the meetings. EEBS: Right? I thought that'd be pretty cool. What have you been thinking about recently, Joël? JOËL: I've been submitting to the RubyConf call for proposals which, as of the recording of this episode, has just closed this week. And like many people, I submitted on the last day. EEBS: [laughs] JOËL: And it was really fun trying to take some ideas that I'm excited about and then turn them into a proposal that is accessible to other people. EEBS: Nice. Do you want to share a little bit about what the talk is, or is it under wraps for now? JOËL: I don't know if anyone on the committee will listen to this before the review goes out. This might break the anonymity of the proposal. EEBS: Oh, right, right. JOËL: One thing I will share that's interesting is that there are topics that I'm excited about. It's like, oh, here are a bunch of cool things about something, some technical topic. But talks that are just ten cool things about X are not that great. And so I needed to find some sort of unifying idea that I could use to share that. And that generally is in the form of trying to find a story that I can tell. What unifies all of these things together? What tells a compelling story? Is there some metaphor I can lean into? EEBS: Nice. I think that's a really powerful way of communicating something deeper is through telling something that people can relate to. JOËL: One way that thinking about metaphors has been really impactful for me recently is the idea of mental models and how those can help us in development. I'm curious; we've thrown around the phrase a little bit you and I in past conversations; what does a mental model mean to you? EEBS: I tend to be a visual thinker. And from talking to others, I've heard similar statements. So for me, a mental model is how I think about a particular domain or how I think about code flow or structure. And for me, it's usually either as two-dimensional objects or occasionally three-dimensional objects that I have floating in my visual space. So, for example, if we had two classes that are collaborators in some way, I often think of them maybe as two rectangles that are side by side. And when they interact, there's some little amorphous blob from one of those rectangles that reaches out into the other one or passes a message from one to the other. And I sort of have this idea of how many connections are there between these two physical things. Or, if I'm thinking about code flow and the path of execution that code might take, sometimes I visualize it as maybe a tree or potentially loops if there are such cases. JOËL: So when you think of these concepts, just in general, you're seeing in your mind's eye squares and rectangles floating in the air. EEBS: Yeah, pretty often. Sometimes it takes those shapes, and as I build up a mental model of some code, I'm usually adding new shapes into that picture I have in my mind. I tend to view things sort of top-down. So like, the start of code or the start of execution is usually at the top or maybe the far left or far right. And as execution happens, I usually view that as moving in towards the middle and potentially going back out when a response is returned. If it's a web request, something like that, I view it as this sort of outside in. And there's a bunch of pieces in there that are all talking to each other. JOËL: That's really cool. So not only is there a geometric aspect to it, but there's a spatial aspect to it as well. EEBS: Yeah. And it's interesting, like, I haven't actually thought about it [laughs] in this level of detail before. But yeah, there certainly is a spatial aspect to it. And I have this idea in my mind of like things and domain objects kind of belong at the bottom, and they should have well-defined boundaries. But the pieces that are a little bit towards the outer edges may be a little more fuzzy and may have less definition around them. JOËL: That's really interesting because I also have this sort of in my mind's eye see these things when I'm thinking about concepts like that. But I've talked to other people, and some people don't even have much of a mind's eye at all. They don't tend to visualize things in their mind in that way. EEBS: Yeah, it's really interesting how different people approach this thinking about code. A lot of people write things down. And I write things down, too, and draw little arrows that don't really make any sense. But it helps me do something physically sometimes as well as just thinking about it. JOËL: Have you ever tried to convert these pictures you see in your mind and actually draw them on paper? EEBS: Occasionally. And for the most part, that usually takes the form of some kind of domain modeling, whether it's based on database tables or just domain objects. And sometimes I will try and draw them out and then specify the relationships between them like, oh, you know, this one model talks to this other model in this particular way. And I'll define a relationship between them, which helps me think about them and how they interact. JOËL: I've found that even though for some things I can see it very vividly in my mind's eye, I struggle to then concretely translate that onto paper or digital paper if you will. It's almost like trying to, say, translate an emotion into words and that even though I feel like I see a visual picture, I can't reproduce it by drawing necessarily. EEBS: It's interesting you brought up feeling because a lot of the times, I have this gut feeling about a mental model, like whether I think it is correct or not. And sometimes I have this uneasy feeling of, like, that doesn't feel right to me, but it's hard to articulate why. And I think sometimes that's when I have to pull out something physical, start making those relations, start connecting things. And that's when I might uncover, like, oh, this feels odd because I have a circle here or a cycle or something. Or I've sort of represented the truth of something in two different places. Do you have any techniques for getting it out of your head and into something physical that you could share with someone else, maybe it's text or a picture? JOËL: I think I do struggle with that conversion sometimes. Practice definitely helps. I think maybe there is a metaphor here between converting these, let's call them, pictures that I see in my mind's eye and then drawing diagrams with trying to take feelings and expressing them in words. In the same way that, maybe I might have some feelings, and then I want to journal how I feel, and I struggle to express that. But finding a way to express that gives me a certain amount of precision and a more concrete thing. In the same way, these things that flash in front of my mind's eye, if I can take the time to put them on paper, they're now more real. They're more concrete. I think you can probe the edges, the ways that it kind of falls apart more easily. EEBS: Yeah, that makes a lot of sense. There's a lot of value in writing that down and going through those details in a methodical way because oftentimes, you'll catch inconsistencies, or you'll find better ways to describe it. And being able to share your mental model with someone else is often...well, it can be really tricky. And I think that's why it's important to go through and maybe find a common medium that you can share because I can't see into your brain. You can't see into mine. But if we can share our mental models, then hopefully, we have a better chance of agreeing on the solution or finding inconsistencies. JOËL: Exactly. I think, in many ways, there are almost multiple layers of mental models and that you might have an abstraction or a metaphor for a concept that you're working with separate from the diagram. And then the diagram is yet another metaphor, but now we're going geometric to represent a broader idea. EEBS: Yeah. Are there any other ways that you take that picture from your mind's eye besides written documents or conversations? Do you use any diagramming tools that specifically help with that? Or is it just kind of free-form? JOËL: I do a mix. I am a big fan of draw.io, which allows you to just free-hand or pull shapes together, things like that. There are some more structured tools that I will use. I'll use Mermaid.js. EEBS: Yeah, I've been using that a lot too. JOËL: Yeah, that's great. I've been digging into more structured diagrams recently, particularly the idea of graphs, directed graphs. And those have interesting properties. EEBS: Can you share a little more detail about what you mean? JOËL: So a graph in the computer science sense is a bunch of nodes. They are typically represented as circles and then edges which are the connections between them. A directed graph is now there's an arrow pointing in a particular direction. A really interesting property that you can have with directed graphs is whether or not they include cycles. So can you only by following the arrows effectively create a loop? Or will the arrows always lead you to some kind of terminal node? EEBS: Gotcha. Is that a directed acyclic graph? JOËL: If there are no cycles, yes, it is a directed acyclic graph or DAG, as you'll often see it abbreviated. EEBS: [laughs] How do you relate that graph to code? And what benefits do you get from expressing it that way? JOËL: So this shows up in a lot of places. And I'd even say that thinking of certain aspects of my code as a graph and a potentially directed acyclic graph is itself a mental model or a metaphor that helps bring clarity to the way I think about things. So, for example, code, you know, you invoke some main function at some point to call the code, and then that's going to call out some other functions, which call out some other functions, and so on. You may have heard that referred to as a call graph. But that is a graph of calls. There might be cycles in there for co-recursive functions and things like that. But that is one way you can then sift through and analyze how control flow or how logic flows through your application is through a function graph. You mentioned earlier the idea of objects and how they're connected to each other. That's an object graph. EEBS: Right. Recently, I had to work through a state transition problem where a customer has some billing, and they can go through many different states, whether it's active, or canceled, or past due, those sorts of things. And so actually, I reached for Mermaid.js and built a graph of, okay, they start here in this empty state. And then they subscribe, which then they become active. They might cancel their subscription, which moves them to a different state. And by listing out all the states and the transitions between them, it helped me to understand what methods I might need to define on which objects in order to allow those transitions to happen and what checks I might need to make before allowing those transitions depending on the state of the system. JOËL: I'm hearing the keywords states and transitions. And that's making me think of finite-state machines. Are you drawing a finite-state machine graph or something a bit more free-handed? EEBS: It's a bit more of free-handed. I don't think I've actually drawn out a state machine since college but just representing the different states as different boxes and the transitions that are possible from those states. I mean, I guess that kind of is a state machine in some way. So graphs are great visual approaches. Are there any non-visual approaches that you take? JOËL: That's a great question because not all mental models have to be visual. I think the power of a mental model exists in a metaphor. And one that's kind of broad but that I've applied to a lot of different areas is the general idea of something being parallel or in series. I think I first came across this concept talking about electric circuits. And are we talking about two little light bulbs that are in parallel, and if the electricity to one is cut, the other one still lights up? Or are they chained together in series? EEBS: Yeah, like my LEDs. JOËL: Exactly, going back to Arduino, but it can also be applied to a bunch of other things. We can talk about code being in parallel or in series. We can talk about work being in parallel or in series. Interestingly, I took that mental model as a sort of quick shortcut when I was digging into some functional progra…

    Full show notes at the publisher

    352: Case Expressions Aug 30, 2022
    Show notes

    As developers, we care a lot about code quality. How do we know how good is good enough? When do we stop improving code? Alternatively, when working on code that's really bad, how much do you improve it before calling it a day? thoughtbot's Stephanie Minn joins Joël to chat about this and case expressions: We recently discussed these as part of thoughtbot's RubyScience reading group. Are case expressions bad? Are they equivalent to multi-way conditionals? When do you use polymorphism? This episode is brought to you by Airbrake. Visit Frictionless error monitoring and performance insight for your app stack. RubyConf 2022RubyConf MiniStephanie's talk at RubyConf 2021WNB.rbJoël's RailsConf 2022 talkRuby Scienceolder episode on wizardsTCR Transcript: JOËL: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Joël Quenneville. And we're here to share a little bit about what we've learned along the way. Today, I'm joined by a fellow thoughtboter, Stephanie Minn. STEPHANIE: Hi, Joël. JOËL: Welcome to the show. STEPHANIE: Thanks. Happy to be here. JOËL: Stephanie, what's new in your world? STEPHANIE: Thanks for asking. I've been working on writing a CFP for RubyConf, which you have been plugging internally at thoughtbot. I wasn't really sure if I wanted to do it, and then I found out about RubyConf Mini, which is happening as an alternative to the main conference in Houston. And that got me really excited to have some more options and just got me thinking about what I might have sitting on the back-burner that I might want to give a talk about. JOËL: That's really exciting. I'm curious, what is your process for coming up with an idea for a talk? STEPHANIE: I think they come in seasons, ideas, for me, so not even necessarily when it's conference time. But if something has been sticking in my brain for a really long time, especially as it relates to processes on teams that I'm on or my day-to-day workflow, and it's something that I keep coming back to and trying to figure out what it is about it that my brain wants to work through a process, that usually tips me off that this might be something that other people are thinking about or working through. In this case, I am planning to write a CFP about pair programming. And yeah, it's something that I've been thinking about doing for a while, and it seems kind of an evergreen topic. So I thought I would pull it out for this conference. And if it doesn't end up getting accepted, I can always resubmit again in the future. JOËL: I love that. So it sounds like you have a note or maybe an actual written notepad somewhere where you just, over the course of the year, build up ideas, and then you take a look at that when conference time comes around. STEPHANIE: Yeah, that's about it. I have just a very long-running note of half-formed thoughts. And then, when I give myself time to really reflect on how things have been going at work, I usually revisit it, and if any of them still resonate or stand out to me, I will go through and try to see if there's any content to come out of that. What about you? I know you are an extensive note-taker and ideas blogger. JOËL: I have to say I really like your approach of gathering ideas throughout the year. I've worked with many people who would love to give a talk at a conference as a professional goal but then get stuck in the I don't have any ideas. I don't know what I would talk about. And most people have a thing they could talk about. They just don't know it. And it sounds like you've done a really great job of gathering this info throughout the year so that when the time does come, you don't just freeze. You're like, no, here are the 10-20 things that I experienced or that I am an expert in or that I would love to share. And maybe there are two or three in there that would be very well-fitted for the conference you're looking at. So I love that idea. I have not done that myself personally, but maybe I should start doing that. STEPHANIE: What about you, Joël? What's up in your world? JOËL: So I've also been thinking a lot about RubyConf coming up, working on a few ideas for myself. And then, there are a few people that have reached out to me to help them craft ideas or get a little bit of feedback on their proposal. So I've been doing a lot of proposal reviews as well. STEPHANIE: What do you enjoy about reviewing other people's proposals? JOËL: I think for many people speaking at a conference is a really big, ambitious professional goal, and so helping people achieve that is really fulfilling for me. Some people might feel almost inadequate or unprepared. But because I know them, I know they've got good things to share. And so it's almost seeing the greatness in them that they don't quite see yet or that they don't feel confident about. And so being able to see that in their proposal and say, "Oh, there’s a core of a great idea right here, tweak it a little bit, and that'll give you a slightly better chance with the committee and help you towards that path of being on stage for the first time," is really exciting. STEPHANIE: I spoke at RubyConf last year, in 2021, virtually. And I remember that was my first time speaking at a conference. And I was worried that my talk was not super hardcore, technical enough. But my goal for my talk was to aim it towards other developers like me who are maybe mid-level and wanting to reach this whole audience of people who are attending these conferences to learn and to level up who aren't necessarily super senior experienced developers. And it was a really great experience. People seemed to really resonate with that. So I really encourage folks to speak about things that are resonating with them at whatever point in their careers because there are so many people out there who are probably in the same boat and want to hear what you have to say. JOËL: Absolutely. I'm curious, now that you have experienced the full cycle at least once, from ideas to crafting a submission, to getting accepted, preparing a talk, delivering the talk, and then recovering from that, what are maybe some lessons learned or some things you weren't expecting the first time you went into that that now you do know going into another cycle? STEPHANIE: Yeah, the power of community; I had a lot of support from WNB.rb, a woman and non-binary Ruby community. We crafted our CFPs together and then practiced our talks together and had a working group that met every couple of weeks to give feedback on our talks as we were working on them. And it was really awesome to have that accountability, to have that support, people to tell you that your talk is good and give you a thumbs-up. And I really want to continue investing in my community that way. And I really appreciate you asking this question because I guess I do have things I've learned and would want to share that with other people in my community, and yeah, just continue to encourage folks who may not have been traditionally encouraged to speak at conferences. JOËL: Community is so powerful. Even though I've spoken at multiple conferences, I still get nervous about my talks. I have a lot of self-doubt about whether my topic is good, whether I'm sharing it in a way that's going to be impactful. And I had a magical experience at RailsConf this year where a group of us were at a hotel lobby practicing our talks the night before. And I was just still so unsure about my talk. And the feedback that I got there gave me a huge boost of confidence that I was able to ride into the next day and give a talk that I think turned out rather well. But honestly, that was my favorite moment of the conference was 11:30 p.m., a group of people in the hotel lobby taking turns practicing their talks. STEPHANIE: Yeah, I love that. MID-ROLL AD: Debugging errors can be a developer’s worst nightmare...but it doesn’t have to be. Airbrake is an award-winning error monitoring, performance, and deployment tracking tool created by developers for developers that can actually help cut your debugging time in half. So why do developers love Airbrake? It has all of the information that web developers need to monitor their application - including error management, performance insights, and deploy tracking! Airbrake’s debugging tool catches all of your project errors, intelligently groups them, and points you to the issue in the code so you can quickly fix the bug before customers are impacted. In addition to stellar error monitoring, Airbrake’s lightweight APM helps developers to track the performance and availability of their application through metrics like HTTP requests, response times, error occurrences, and user satisfaction. Finally, Airbrake Deploy Tracking helps developers track trends, fix bad deploys, and improve code quality. Since 2008, Airbrake has been a staple in the Ruby community and has grown to cover all major programming languages. Airbrake seamlessly integrates with your favorite apps to include modern features like single sign-on and SDK-based installation. From testing to production, Airbrake notifiers have your back. Your time is valuable, so why waste it combing through logs, waiting for user reports, or retrofitting other tools to monitor your application? You literally have nothing to lose. Head on over to airbrake.io/try/bikeshed to create your FREE developer account today! JOËL: One thing we've been doing recently at thoughtbot is every other week book club discussion, and we've been looking through the book Ruby Science published by thoughtbot. Every week, we'll have someone who is a facilitator, who has done the reading and has prepared some questions for the group. And you recently facilitated a session on the topic of CASE expressions and why they might be a code smell. That sounds like a really controversial statement. How did you approach that topic? STEPHANIE: It's funny because I was looking at the upcoming chapters to pick a topic to facilitate for this book club, and CASE statements stood out to me because I was like, oh, I know what that is; that will be easy. [laughs] But it turned out to be a bit meatier than I thought it was going to be. I'd say that I didn't really consider them a code smell until I read the chapter of Ruby Science talking about them. So I was a bit surprised because they seem so common, which is probably also why I thought it would be an easy topic. JOËL: Would you say that reading the book or that particular chapter changed your mind? STEPHANIE: I think it did only because I hadn't necessarily given them a second thought or thought of them more deeply in that way. I think that, at least in my experience, you encounter CASE expressions pretty early in your career, and you think they're a cool tool for making your conditionals look a bit nicer. And it takes probably a bit more experience, a little bit more pain using them or trying to extend them that you start to have a bit of a more higher level awareness of what might be problematic about a CASE expression. But the book club that I facilitated, we had a really engaging discussion where most folks agreed that it was a code smell but also said that it depends. JOËL: Classic consultants. STEPHANIE: Truly. One thing that someone said that was a really nice takeaway for me was that CASE expressions get a bad rap in object-oriented languages because there are typically other tools or options you can reach for that might be preferred. And someone else said that it's probably a sign that you might be doing too much in the method. JOËL: Hmm. You mentioned that there are some tools and things that might be preferred over CASE expressions. What are the common alternatives that people say you should use instead of a CASE expression? STEPHANIE: I think one simple solution that we discussed in the book club for more straightforward cases would be a hash lookup to use instead of checking for equality via CASE statement. Another solution we talked about was polymorphism, which I think might refer back to the idea of having a bit of a higher level understanding of abstractions in the codebase and what things might look like in the future, especially when you might not have too many conditionals yet in your CASE expression. Another thing that really stuck out to me in our book club discussion was another thoughtboter mentioned Sandi Metz’s 99 Bottles of OOP. And in that initial solution, she presents a CASE statement as the perfectly fine solution for now. And I thought that was really interesting because, in some cases, that might be all we know about the problem, and that is perfectly fine. What do you think about that? JOËL: I love the idea of starting simple. Don't try to start with abstraction, especially if you're doing test-driven development. You have a test, make it go green, use the simplest thing, use duplication, use all the dirty tricks. And then from there, now that you know I have a test that was red and this code makes it go green, now the question isn't how do I solve the problem? It's how do I improve the solution? So we've kind of separated those two steps out, and I really like that. STEPHANIE: Yeah, I remember you mentioned that you had refactored something into using a CASE statement. And I'm curious if you want to share more about that. JOËL: Oh boy, this was a "fun" problem. Fun is in air quotes, by the way. It was a multi-step form, AKA a wizard in a Rails app, where every step submitted to the same controller, and the controller was a huge mess. It had to handle submissions from four or five different forms, some of which shared fields. And it was this huge, deeply nested conditional thing that checked if this field is present in params, that probably means we're on step three, except if this other field is also present, then it probably means we're on step four. But if this Boolean flag in the database is set to false, we might be on a variation of step three. And because there was branching, potentially, it was an absolute mess. By looking at the code, you could never know what step of the processing you were on. What I did is instead of all of these nested if else conditions, I wrote a flat CASE expression that just said, if step one, do step one logic or process step one form. If step two, process step two form and so on. So it was nice and flat. I was able to reuse some parts of the work across by making private methods or other objects, things like that. But you could easily tell in any part of the code what step you were processing. Which means if you get a new feature from the client that says, "Can you modify the behavior on step four?" Now you actually know where to go to. You go to this controller; you find the big CASE expression. You find the branch that says, "If step four," and then you drill down from there. STEPHANIE: So after refactoring that into a flat structure, did you find the code more readable? Did other folks on the project think so too? JOËL: Yes, it was unanimously loved because this is the part of the code that everybody feared to touch. It was the most awful, gnarliest code. And a few of us had touched it, and so if you did the git blame, our names would show up, which meant that anytime anybody got stuck in that code, they would reach out to us and say, "Hey, you're the last one who touched it. Can you fix this for me?" And it was a big game of not it. Cleaning it up made this code accessible to everybody on the team. STEPHANIE: And why do you think a CASE statement was the right solution in this particular c…

    Full show notes at the publisher

    351: Learning in Public Aug 23, 2022
    Show notes

    It's Joël's first episode as host of The Bike Shed! 👋 Joël has fellow thoughtbotter Steve Polito join him to talk about the benefits and drawbacks of "learning in public" and how there are many, many different ways to do it. This episode is brought to you by Airbrake. Visit Frictionless error monitoring and performance insight for your app stack. Transcript: JOËL: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot. I'm Joël Quenneville. And I'm joined today by fellow thoughtboter, Steve Polito. STEVE: Hey, Joël. Thanks for having me; excited to be here. And congrats again on the new hosting gig. JOËL: It's exciting to record with my first guest, and I'm excited that you get to be a part of this. And together, Steve and I are here to share a little bit of what we've learned along the way. So, Steve, what's new in your world? STEVE: Well, on the professional side of things, I've been working on a Rails backend application that connects to a React frontend. And specifically, it's in the healthcare space. My biggest, I guess, struggle but also [laughs] thing that I've learned the most from this project is working with an inconsistent API can be very challenging. And that's been the consistent theme with this project. But from that, I'm learning a lot. Because prior to this, I'd done a lot of work with just traditional CRUD apps where it's just all-encompassed in the Rails application. So you're kind of in control of everything. This is my first time where we're very much dependent on a third-party API. I'm learning a lot, but it can be challenging at times. But we've gotten in a space now where it's a lot more predictable, and therefore, working with it is easier. That's on the professional side of things. Personal side of things, I, for whatever reason, decided to run a marathon in September, which means all of the training has to happen in the heat of the summer. I live in New England, and it's been unbearably hot the past two or three weeks, which means training has been unbearable. [laughs] JOËL: Ouch. STEVE: Well, I mean, that's what I get for signing up for a marathon at the end of the summer. So I look forward to just working with the unreliable API versus [laughs] doing this right now. That's what's going on with me. What's going on in your world, Joël? JOËL: For long-time listeners of the podcast, they'll know that former host, Steph Viccari, has been working on a slow test suite. And part of that work has been converting some old Test::Unit tests over to RSpec. I've been working on the same project with her, and so the saga continues. One of the really frustrating aspects of this work has been the Test::Unit tests rely a lot on fixtures which are just full of mystery guests. The fixtures that are just loaded at the top of the file refer to a few thousand records in the database, most of which are not relevant to the test that I'm trying to convert over. The problem is that I don't know which ten records, you know, which two users out of the 100 defined in the fixture file are relevant. They're not referenced directly anywhere in the test. But if the RSpec conversion that I do fails, it will break because some user is not present in the database. And so I need to reverse engineer the code and figure out what is missing, which user record is just assumed to be in the database. STEVE: Yeah, that sounds frustrating. Honestly, until working at thoughtbot, I didn't quite understand the concept of mystery guest. Because when I learned Rails, I just did the Michael Hartl Rails Tutorial, which, in an effort to make it as easy as possible, he just kind of does vanilla Rails. So there's no Factory Bot or RSpec, for example, and it's all fixtures. And it works very well for teaching you how to build and test an application without getting bogged down with too many of the extra things that come along with that. So I always thought, okay, fixtures, cool, no big deal. Why does everyone always use Factory Bot?[laughs] Like, what problem is this solving? And I'm realizing now because I've run into this too, the issue that it’s solving is this mystery guest, so that's one of the issues that it's solving. And that's just one of those things that I didn't really appreciate until I would run up against it in a similar situation you're describing now where you're writing a test. It might even be a very simple test, right? Like five lines or something, and you're just expecting something trivial to happen. And it's failing, and it's failing for the wrong reason. The message is so cryptic. And you're just like, what is this thing talking about? It's like referencing something that has nothing to do with the test. And that pain right there is the pain of a mystery guest. I just didn't have a name for it until listening to these episodes. And now I can appreciate why you want to avoid that type of stuff and also why Factory Bot is helpful for that. JOËL: I think it's the kind of pain that tends to bite you more when you're modifying the tests later on than when you're writing them upfront. And since now, with the work that I'm currently doing, it's all modifying existing tests, I'm feeling this pain on a daily basis. Does that track with your experience as well? STEVE: Yeah, pretty much. And then what ends up happening is you're working on a feature, and the test fails for the wrong reason. And then you realize 30 other tests fail for the wrong reason. And then, before you know it, you've spent four hours going down a rabbit hole to clean up the fixtures, or the mystery guests, or the implied setup that might be shared across other tests. It's just such a momentum killer, first of all. You're in this headspace of like, okay, here's the feature I'm working on. Let's just bang this out real quick; no big deal. I want to go to lunch in a couple of minutes. [laughs] And then you're trying to fix this test because it's failing for the wrong reason. And then you keep pulling the string, and you're like, oh, okay, well, there must be a mystery guest or something, but that took like 20 minutes to figure out. And then you figure that part out but then maybe fixing that mystery guest involves either updating that particular fixture, which could then fan out and cause other tests to fail because it depended on that fixture to have certain properties. Or you have to create a new fixture. But if you create a new fixture, there's now an extra record in the database. And that could break other tests because they are maybe expecting there to be a certain set of users and other things. But that's just one of those things that early on, I would listen to episodes like this or hear about mystery guests, and I would be like, I just don't get what they're talking about. If you have a few fixtures, how is that so hard to keep straight in your head? And sure, at first, it's not a big deal if you have maybe two fixtures or something. But then it quickly just reaches an inflection point where either there's more than one person on your team, or you have to add more fixtures or whatever. And then it just reaches an inflection point where it's just not sustainable anymore. And that sounds like that's obviously the point at which this project is at, and that's where you're trying to rein it back in. JOËL: Yes. So it's definitely making the conversion from Test::Unit over to RSpec more difficult. I've been trying something a little bit clever to try to figure out what data is actually needed because that's my core problem. I have a Test::Unit test that doesn't define any initial setup data. It just assumes that data has been created by fixtures at some point. But there are thousands of records in the database. So which ones do I need to port over to this setup phase of my RSpec test? What I've been doing is hooking into Active Support notification and watching the records that get read from the database from the Test::Unit tests. And that can tell me, oh, it's these ten that this particular test is using. Those are the ones you're going to need to convert over to your setup block. STEVE: That's clever. I like that. So you were just looking at the logs essentially. Or did you have to do any puts statements or anything? Or was it just the default internal logging mechanism that Rails has under the hood? JOËL: The simple version of this would be to look at the logs, so tail the test log file. I'm trying to be a little bit fancier and hooking into Active Support notification, which is something built into Rails that allows you to just listen to certain events in the system and then do actions based off those events. So I can subscribe to any database read and then say call this block when a database read happens. And in that block, I can then update a stats object that, over the course of the test, will then tell me what objects have been read from the database. STEVE: Oh, okay. That's clever. I'm glad you shared that too. Based on this discussion of mystery guests, I feel like that's just a good use for that tool. I almost wonder if there's an opportunity not even to abstract that because that'd be too much work and overkill, but just, I don't know, make like a gist or something and just reference that for the future. Because I feel like this is the type of thing that other people are going to run up against...or maybe even a blog post or something because it's just like, if nothing else, it would be good for future Joël to be like, how did I do that again? Oh, yeah, here it is. Like, it's in this blog post I wrote six months ago. So I could just copy and paste the code snippet and call it a day. JOËL: It's funny you mention blog posts because we have a lot of these conversations internally at thoughtbot. And without fail, someone will eventually comment, "This is great content. You should turn it into a blog post," to the point where we now have an emoji reaction for you should make this into a blog post. STEVE: Right. That's what's really maybe special about the software industry is there's just a lot of knowledge share built into it just with open-source software, for example. I mean, that's already a form of knowledge share. It's not a blog post, but it's a form of knowledge share. And I just think getting into a habit of just sharing these little artifacts, big or small, whether it's a blog post or just a code snippet, is really helpful for a variety of reasons. But one, and in this case, to go back to the issue that you've been facing on the client work is you just explained...We talked about a lot of things; two of them were like, what's the mystery guest? That's helpful for some people to know because until very recently like I said, I didn't even really understand what the pains of mystery guests were. And then, we also talked about a potential solution to that. So a naive approach is tailing the logs, but then you took it a step further with that clever solution to use that notification object. And if we weren't recording this right now, that might be lost in the ether forever. Maybe the people you're working with on your team would know about it, but that would kind of be it. So I think there's an opportunity for you to maybe abstract that into like a code snippet or blog post or something and just store it away for later so that future Joël or another developer can learn from that. JOËL: That's a really good point, Steve. Creating public artifacts like that is a form of...I've heard it referred to as learning in public before. And that's actually a topic that I think you've really demonstrated mastery of. You are great at sharing the things you've learned or even the questions you have with your colleagues, and the team at thoughtbot, and the broader developer community. What was your journey into starting to share in public like this? Because I know it can be really intimidating, especially for someone who's early in their career. STEVE: Yeah, that's a good question. So a very brief background on my career history is I'm not classically trained, so to speak, and I'm doing air quotes for those listening. When I say, I'm not classically trained, what I mean is I went to school for graphic design. And there was some overlap with web design, obviously. But I ended my collegiate career really just knowing how to use Dreamweaver and knowing a little bit about HTML and CSS and barely anything about JavaScript, and I didn't know anything about server-side languages. That was my base. And I was fortunate enough to get a job at a small WordPress agency. I got really good at understanding WordPress and how to configure a website and then making it look like the Photoshop document. JOËL: There's a shocking amount of the web that runs on WordPress. STEVE: It's a huge amount. And what's nice is that it doesn't...as you just heard, I didn't have a lot of experience with making production websites. So WordPress made it easy enough for me to get my feet wet. But I would run into a lot of problems. And I was the only developer at this agency, so I couldn't turn to my co-worker and say, "Hey, can you take a look at this real quick?" It was just me and Stack Overflow. That was it. The reason I'm saying this is because Stack Overflow and being the only person at the agency forced me to learn in public but from a different mindset. I wasn't necessarily learning in public; I was desperately trying to solve a problem by the end of the day. And it just happened to be in public because I would have to either go on Google or Stack Overflow or forums to find the answer. JOËL: So were you asking questions on these sites then? Like, you were going into a chat room and asking questions or going to Stack Overflow and asking questions. STEVE: Yeah. If I couldn't find a solution quickly, I would just go on there and just shamelessly ask questions which they were, in some sense, naive questions. Looking back at them now, it clearly highlighted that I didn't understand the fundamentals, but that's okay because I know I didn't. [laughs] And I'm sharing that with everyone right now, so it's not like it's a secret. Because that was the only way I was going to figure it out, like I said. And I didn't have anyone at that agency to ask for help. So that got me into the mindset of just ask for help. But it also got me into a mindset of...one thing was, okay, I can't just paste the entire error message, like, the entire 3,000-line error message from the logs onto Stack Overflow. That's not going to help anybody. No one's going to answer that question. I needed to start to get good at distilling down the problem into its smallest part to then be able to share it, so I would at least incentivize someone to answer it versus pushing them away because who wants to read a non-formatted log file dump? JOËL: That is a skill in and of itself. STEVE: Yeah. I mean, it took time, don't get me wrong. And at first, I was posting those [laughs] giant log files. I would just say, "Hey, can you help me?" [laughs] And it's like, there's no context, and it's just 3,000 lines of gibberish. So obviously, I quickly learned, well, I got to make these bite-size. But then, from there, I slowly learned over time thanks t…

    Full show notes at the publisher

    350: 21 Bell Salute Aug 16, 2022
    Show notes

    It's Steph and Chris' last show. Steph found a game, and if you've been following the journey, all of the Test::Unit test files are now live in RSpec. JWTs really grind Chris' gears. They wrap up with things they've learned, takeaways they've had, and their proudest podcasting moments. They also thank all the folks who've helped make The Bike Shed happen. This episode is brought to you by Airbrake. Visit Frictionless error monitoring and performance insight for your app stack. Microservices Transcript: CHRIS: One more round of golden roads, our golden. So here we go. STEPH: Oh, one more round of golden roads. Okay, maybe that's going to get to me today. [laughs] CHRIS: [singing] Golden roads take me home to the place. STEPH: [singing] I belong. CHRIS: Yeah, there you go. Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Chris Toomey. STEPH: And I'm Steph Viccari. CHRIS: And together we're here to share a bit of what we've learned along the way, at least one more time. So with that [chuckles] as an intro, Steph, what would you say is new in your world? STEPH: Hey, Chris. Well, today is the big day. It is the day that you and I are recording our final Bike Shed episode, which we have all the feels about, and we will definitely dive into. But to ignore some of that for now, I have another small fun update I can provide about a new game that I found. So one of the things that's new in my world is I started playing a new board game with Tim; it's called Ticket to Ride. Have you heard of that? CHRIS: I have. I don't know if I've played it. I feel like it's a particularly popular one now. But I don't know if I've ever had the pleasure. STEPH: It's a very cute game, so we have the smaller version of it. For anyone that's not familiar, it's essentially a map. And then there's a bunch of spots where you can build trains and connect them, and then you get tickets. So your goal is that you're going to connect one location to another location. And then you get points and yada yada, but it's so much fun and especially the two-player version. It's like this perfect 20, maybe 30-minute game. I'll be honest; I'm not really a board game person. I always enjoy it. Once I get into it, then I'm like, this is great. I don't know why I was resistant to this. But every time someone's like, "Do you want to play a board game?" I'm like, "Not really." [laughs] I first have to get into it. But I have really enjoyed Ticket to Ride. That's been a really fun game to play. And it's been a nice way to, like, even during the day, we'll break for lunch and squeeze in a game. CHRIS: Well, I love good two-player games. They're hard to find. But when you find a good one, and it's got that easy pickup and play...I believe I'm going to now purchase this. And thank you for the tip. STEPH: Yeah, this is definitely one of those where it's easy to pick up, and then you can get the expanded board. So there's a two-player version, but then yeah, you can get one that's a map of the U.S. or a map of Europe. And I think it accommodates up to five players as the maximum, so not a huge group but definitely more than two. On a slightly more technical note, I have something that I'm very excited to share. It is a journey that you have been on with me, that everybody listening has been on this journey with me. And I'm very excited. I see you nodding your head, so I'm guessing that you're going to know where I'm headed with this. But I'm very excited to announce that all of the Test::Unit test files now live in RSpec. So that is a big win. I'm very, very excited for that to be a previous state of life and not an ongoing state of life. Because I have certainly developed too much niche knowledge around migrating these tests, and that became apparent to me when I was pairing with another developer that works with the client because they had offered...they had some time. They're like, "Hey, do you want help migrating a test file?" And I was like, "Sure." I was like, "But this is wonky enough, like, we should pair and work on this together because I just know some ins and outs. And I don't want you to have to learn a lot of the hard lessons that I've learned." And the test that we happened to pick up was very gnarly. It had a lot of mystery guests. And we spent, I think it was a good two hours. And we only migrated one of the tests, so not even a full file but one of the tests. And at the end of it, I was like, I know way too much about some of the oddities and quirkiness of this. And we got through it, but we decided that wasn't a good use of their time for them to go at this alone. So that's why I'm extra excited and relieved because I didn't want this task to carry on to someone else. So, hooray, we did it. CHRIS: Hooray. Just in time. You're Indiana Jones grabbing your hat right as you roll out and off to [laughs] be away from the project for a bit. So you stuck the landing. Well done, Steph. STEPH: Thank you. Thank you. So that's some great news. And then also, everything else in life is pretty much focused around getting ready for maternity leave. That's about to happen soon, and I am so ready. I have thoroughly enjoyed a lot of the things that I'm doing, [laughs] but goodness, being pregnant is hard. And I am very much ready for that leave. So also, a lot of the things that I'm doing right now are very focused on making sure everything's transitioned and communicated and that I just feel really good about that day of departure. That covers all the newness in my world other than the big thing that we're just not talking about yet. How about you? What's new in your world? CHRIS: Well, continuing to skirt the bigger topic that we will certainly get to in the episode, what is new in my world? I'm actually quite excited workwise right now. We have a much larger body of work that finally we got the clarity. All the pieces fell into place, and now we're sort of everybody rowing in the same direction. There's interesting, I think, really impactful code that we're writing for Sagewell right now. So that's really fantastic. We've got the whole team back together on the engineering side. And so we're, I think, in the strongest and most interesting point that I have experienced thus far. So that's all really fantastic. On a slight technical deep dive, you know what really grinds my gears? It's JWTs. JSON Web Tokens and I have never gotten along. It's never been a match made in heaven. And we have a webhook that comes from Plaid. Plaid is a vendor for connecting bank accounts and whatnot. And they have webhooks like many people do. So they can inform us when things change, lovely feature of how we build web apps these days. But often, there's a signature that says, "This is definitively from us, and you can trust us." And usually, it's some calculated signature, HMAC, or something like that. For some reason, Plaid's uses JWTs, and more than that, they use JWKs. So there's JWT which is the signature. That JWT itself is signed with a JWK. You have to fetch the JWK from their server based on the key ID in the header of the JWT. But how do you know if you can trust the JWT before you've gotten the JWK? All of this broke in a recent upgrade. We went from Heroku-20 to Heroku-22 to the new platform with Heroku, which bumped us to OpenSSL 3.0, and it turns out JWT doesn't work with it. And so that's sad. It's a no. It's going to be a no. It turns out the way that OpenSSL 3.0 works is incompatible with some of the code paths in JWT. And so I was like, wait, we just can't do this? And it's low-level cryptographic primitive stuff that I'm not comfortable messing around with. I'm not going to hop in there and roll up my sleeves. And even just getting to the point that I understood what was broken about this took like an hour and a half just to sort of like, wait, which is okay...so the JWT signs and encodes. And this will be a theme that we come back to later, but I think web development should be simpler. I think we should strive for simplicity. And this is a perfect example where I'm guessing Plaid uses JWTs and that approach to communicating security things often, but I've not seen it used much for signing webhooks. And, oof, it led to a complicated day. And it's unfixable now as far as I can tell. There is a commit on the JWT Ruby repo as of five days ago, but it doesn't build in our system. And it's not released. And it's just a mess. So yeah, engineering is complicated. I'm both wildly excited about what we're doing at Sagewell, and then today was this local minimum of like, oh, JWTs again. Again, we find ourselves battling. And you won today, but hopefully not for too long. STEPH: Oof, how did this manifest that you first noticed? So is it because a webhook suddenly stopped working, and that was like the error that rose up, and that's what helped you dive into it? CHRIS: Yeah, we have a little bit of code in the controller for where Plaid events come in. We calculate and verify the signature of the webhook to make sure that it's valid, and we reject it otherwise. And we alert ourselves via Sentry, and then we also have a Datadog scan that can show what's the status code of the response. Because these are incoming HTTP payloads or requests, and so we can see there were 200 up until this magical day when suddenly everything changed. And that was when we switched Heroku stacks. And then we can see it also in Sentry. So we're able to look at it, and we're like, why are none of the Plaid webhooks able to verify the signature anymore? That seems weird. And so then Datadog confirmed that it consistently was broken from this point in time. And then we were able to track that back. It was also pretty easy to guess because the error was "pkeys are immutable in OpenSSL 3.0," and that was the data. And I was like, oh, cool, that sounds fun. Let me go figure out what that means. STEPH: [laughs] Well, it's a nice use of Datadog. I remember in the past you were talking about adding it. And I was excited because I've never been at that point where a team has just introduced it; either a team doesn't have it, and they wish they had more insights, or they have it and don't use it. And nobody ever checks the board. So that's a nice anecdote for Datadog helping you out. Yeah, I'm not envious of your situation, friend. CHRIS: I do love the cup half full take [laughs] that you have on the overall situation, but that's nice how Datadog worked out for you. And you know what? It was. Thank you, Steph, for once again being that voice of positivity. STEPH: I appreciate that you enjoy it because there are times that when someone points it out to me that I do that, I have to be like, "I'm sorry, I'm not trying to be toxic positivity over here. [chuckles] That's just how my brain works." CHRIS: Oh, you are definitively not toxic positivity. That's a different thing. Because you ended with but also, I feel bad for you, and I'm glad that I'm not in your shoes. So you are the right level of positivity. I don't think I could have talked to you for three and a half years as co-host on a podcast if I didn't appreciate the level of positivity or the general approach that you bring to thinking about stuff. STEPH: Okay. Well, to borrow a phrase from Matt Sumner, who has been a guest on the show, cool, cool, cool, cool. I'm glad my positivity has been well calibrated. And I was about to say I'm interested to hear how this turns out for the team. [laughs] But we're in an awkward spot where I mean, you and I, we can still totally chat. But listeners won't get to hear the rest of that particular saga. I mean, you can share. I mean, you do you. I'm setting all sorts of boundaries for you right now. Okay. And now I'm just rambling, and I'm getting weird with it. Because the truth is that, you know, we won't be back. And this is our final episode together. So I think let's just go ahead and rip off the Band-Aid. Let's dive into it. Let's talk about it. Given that it's our last episode that we are recording, we thought of a couple of things that we'd like to talk about. You brought up a great idea that I'm excited to dive into. Do you want to lead us in? CHRIS: Sure. Well, if we go back all the way to Episode 172, that is the first episode that you came on as a guest. I actually continue to really love the title of that episode, which is What I Believe About Software. And it both captured that conversation really well, but also, more generally, it's actually become the tagline of the show when we do our little introduction. What do we believe about building great software? Et cetera. And I think that's been the throughline of the conversations that we've had is what remains true. What are the themes? Not necessarily the specific technologies, although we certainly talk about that. But what do we believe about building great software? And so today, I thought it would be fun for us to talk about what do we still believe about building great software? It's roughly three and a half years or so that we've been doing this. What's still true? STEPH: Oh, well, I have the first unequivocal one, the thing that I still believe about building great software, and that's you should hire thoughtbot. That's definitely the way to go. We'll help you get it done, not that I'm biased in any way. CHRIS: No. I'd say collectively between us; there's zero bias with regard to thoughtbot or any other web development shop out there. But thoughtbot is the best. STEPH: All right, perfect. So we've got the first one, the clutch one of hire thoughtbot. And then I also really like this topic. And I still think back to that first episode that I recorded with you and how much fun that was and how that really got me to start thinking about this. Because it was something that, at the time, I didn't really reflect on a lot in terms of what does it take to build great software? I was often just doing the day-to-day actions but then not really going high-level think about it. So I'm excited this is one of the topics that we're revisiting. So for the next one, this one is, I don't know, maybe it's a little cutesy, but I was trying to think of an alliteration that I enjoyed. And so this one is be an assumption assassin. So what assumptions are you making? And then how can you validate or disprove them? And that is something that I find myself doing constantly. And it always yields better work, better questions, better software, better code, better code reviews. And that's my first one is be an assumption assassin and identify what assumptions you have. And I had a really good example come up today while I was having a conversation with Joël about something that I was looking to merge. But I was a little hesitant about it because there are some oddities that I won't dig in too deeply. But essentially, there's a test that I migrated that highlights an existing concern in the code. And I was like, should I go ahead and merge this test that documents it, or should I wait to fix that concern and address it? And he brought up a good point. And he's l…

    Full show notes at the publisher

    Previous 1 14 15 16 17 18 51 Next

    Related Podcasts

    Know How… (Video)

    1

    Know How… (Video) Education
    JavaScript Jabber

    2

    JavaScript Jabber Education
    Programming Throwdown

    3

    Programming Throwdown Software How-To
    Software Engineering Radio – the podcast for professional software developers

    4

    Software Engineering Radio – the podcast for professional software developers Software How-To
    The Changelog: Software Development, Open Source

    5

    The Changelog: Software Development, Open Source How To
    Coding Blocks

    6

    Coding Blocks Software How-To
    footer-logo

    Contact Us

    Toll Free: 844-670-7747

    Links

    • Home
    • Top Charts
    • Networks
    • Apps
    • Independents Podcasts
    • Podcast Advertising
    • Podcast News
    • Contact Us
    • About Us
    • Analytics & Insights

    Stay Connected

      Privacy, Terms of Use & Our Code of Ethics Protecting Content Creators Copyrights