
Sign up to save your podcasts
Or


The panel explores the connection between programming and music. To begin, Mike shares how his passion for music influenced his career switch from molecular biology to software development, and each panelist reveals their musical experiences, ranging from choir participation and band membership to a keen interest in diverse music genres and car audio systems.
The discussion then delves into the similarities between music and software development, focusing on how both are forms of human-centric communication and creative expression. They discuss the importance of comprehensible coding for human understanding rather than for machine processing and draw parallels in communication styles and improvisational aspects of both fields.
The episode also features a live interactive segment on the integration of music and software, through the use of Sonic Pi. This tool demonstrates the practical blending of coding and music creation, exemplifying the tangible overlaps between these two creative domains.
Transcript;
MIKE: Hello, and welcome to another episode of the Acima Development podcast. A lot of times, we go with more technical topics, and it's still a technical topic today but taking a different approach than we often do. Today, we're going to talk about the overlap between programming and music. If you've been in software for very long, you've probably noticed there's an odd overlap there, where there are a lot of people [chuckles] in software who do music.
I am Mike. I'm hosting today. And we've got a panel with us today. We've got Justin, Eddy, Kyle, Dom, Ramses. I know I do music. In fact, little known fact, I'm actually the one who recorded the music that we play in the intro for the podcast [laughs]. I'm somebody who enjoys music, and I have enjoyed music for many years. Actually, it was music that got me into software in the first place. I was originally going to go into a career in biology, molecular biology, genetics, work on plant genetics, and do that with my life. I kind of made a change in direction [laughs] way back when.
And what kind of got me going in that direction was that I loved music. I thought about going in that direction. And I thought, you know what? If I go into software, maybe I can apply that to some of the music stuff. And I remembered, hey, wait, I really love this [laughs]. I had done software when I was younger, and I remembered how much I enjoyed it, and I stuck with it, and it became my career.
Music has taken more of the backburner [laughs] in the years since. But if not for music, I probably would not have gone into software in the first place. I very much have a story with music. So, I'm going to ask each of our panelists here, Justin, do you make music?
JUSTIN: [laughs] I've been in the music scene, but I am a singer. I'm actually a member of a choir, about 100 people. We go on tour. Like, last year, we went to Ireland and England, and we sang in London in the St. Paul Cathedral. It was a really cool experience. And I have a performance here in a couple of weeks for Christmas, so lots of stuff there. My wife...you may hear a piano playing in the background here in a little bit because my wife teaches piano. Basically, every afternoon, there's, like, piano students shuffling in and out.
MIKE: So, that answer was yes.
JUSTIN: Yes [laughter]. It's a long answer. Sorry.
MIKE: Very much yes. Eddy, tell us about you and music.
EDDY: So, I actually used to be in a band in high school. We formulated a group called [SP] Guitarchestra. And it basically is what it sounds like, right? Every member in that group played guitar. We played different sections. You know, we played backup, and some people would play melodies. Some people would play the chord progressions, et cetera.
And it was an interesting approach because initially, when you think of a band, you would always think of, like, piano, and trumpets, and drums. And, you know, it was an interesting take at the time. We're talking about, like, 10-plus years ago, probably a little over where it was still kind of fresh to say, "Yeah, the whole band is comprised of just guitar." We even took it a bit further, and we decided to do purely acoustic. We determined that acoustic had a more pleasant sound with what we were going for. So, not to go too deeply into it unless we want to, but yes, to a degree, I do have some background in music.
MIKE: Again, that's not just a little bit of a yes, right? But a big yes [laughs]. Dom, actually, I have no idea if you do music [laughs].
DOM: I'll be the first short, yes. I was never super musically inclined as a kid. I guess the recorder is about as far as I ever went in, like, fifth grade. I could play pretty mean Hot Cross Buns, so I'm going to keep it real.
MIKE: [laughs]
DOM: But I'm an avid enjoyer to listening. I listen to music all day, every day, pretty much whatever. People always ask me like, "What's your music taste?" And, you know, it's super basic to be like, "I listen to everything." But you should check out my playlist. It goes from, like, hardcore gangster rap over to some, like, classic rock, maybe some country in there, throw in some Bach. It's pretty wild. But yeah, it's definitely a big part of my life, even though I can't play anything. I wish I could.
EDDY: Dom, you should listen to Ramses' playlist, man. You'd have a blast.
DOM: I bet. I'm open to whatever.
MIKE: And this thinking here it's not universal, right? Not everybody who does software development does music, but there's a lot. Kyle, what about you?
KYLE: I'm going to have to mimic Dom quite a bit, basically everything he said, for the most part. Anything that I really focused on music-wise was in high school and a little bit of college. I did a little bit of DJing, and then I had a big interest in car audio for the longest time. I've kind of grown out of that a little bit, but stereo systems were my thing.
EDDY: What's car audio?
KYLE: [laughs]. Yeah, dude, I've done a few car audio systems for replacing and wiring of the speakers and the head unit, subs, capacitors, amplifiers, all that jazz. You get the little amp for your speakers up front and a big amp for the big boys in the back, a couple of twelves, a couple of tens.
MIKE: So, what about you, Ramses?
RAMSES: I have a bit of experience with music and making music for the, like, last ten years or something, but it's been less two or three years, you know, a larger emphasis on development currently.
MIKE: But you're a creator. Just thinking about the sample size, we've got one, two, three, four, five, six people here. And of those six, the majority, not, like, 1% or 25%, but we've got, what, 4 out of 6 people who have played publicly, right? [laughs] Who have done music in their adult lives. I haven't looked at the statistics, but that seems disproportionate. And it's been that way.
DOM: Does karaoke count?
MIKE: [laughs]
DOM: I rock some mean karaoke.
MIKE: Well, you know, why not? I actually have a lot of thoughts about music. I think it's really unfortunate, actually, the way that music is often taught, particularly, like, classical performance, because we teach people to perform somebody else's music. Can you imagine if we taught writing that way? Like, okay, we're going to teach you to be a writer. And what you're going to do is you're going to take this essay over here, and you're going to copy it over here. And make sure you copy it exactly. Don't make any spelling mistakes. Any spelling mistakes means you're not a very good writer because good writing means that you're copying very well with this other essay.
You take that to its conclusion, and it's ridiculous. But it's very much how music is often taught, you know, you learn to play with other people. It's kind of neither here nor there. But [laughs] I do think that those of us who are in music should work very hard to be more inclusive. And when music is taught, I think that it should be taught with performance and improvisation in mind as much. You know, it's kind of an equal peer to reading music and learning to perform music.
In fact, when I teach my kids, that's exactly what I do [chuckles]. We divide the time in half, literally in half. They set a timer, and they spend half their time improvising and the other half learning to play because there is some value in learning. If you want to be a writer, you better be a good reader [laughs], and I think the same thing applies to music.
EDDY: When you teach your kids, do you teach them how to read notes or how to read tabs or, like, a mix of both? Like, how do you approach?
MIKE: Yeah, great question. They haven't been that interested in guitar. They have been interested in piano. My daughter has a little bit of interest in violin, and for that, she's just kind of played by ear a little bit, definitely no note reading for that. For the piano, I have taught them to read sight music to learn to read music notes. You don't play tab on the piano. But I have no objection to tab.
To give another take here, I think that tablature sometimes gets a little bit of scorn. It's like, well if you want to be a true musician, you have to be able to read traditional European notation. Well, traditional European notation wasn't always traditional, and I think it was created in the Renaissance era. And people had to create it then, and they invented it as just a useful technique to communicate with each other. And tablature was invented in the same way. It's just a notation technique. I have no objection to that. I think that we should actually lean into communicating well and use the notation that works best for the instrument we're playing. Oh, there's my take on it. What was your thoughts on that?
EDDY: Well, I initially...when I first picked up guitar, I taught myself mostly just because I was interested in the art of playing with strings in general. And I always enjoyed the sound. I thought it was always soothing and such. And so, I thought...as a kid, it's kind of hard to teach yourself how to read music, especially since internet was dial-up at the time. So, it was extremely hard, you know. Also, we shared a landline for internet, too.
MIKE: [laughs]
EDDY: So, we had to split, like, home phone and internet. It was another time. Regardless, the easiest approach for me was to download tablature for guitar, and it just made more sense. It was less of a curve, like, a steep curve, to learn because each note correlates to a placement in the guitar versus the note itself. So, I'm quite fond of it. But I do understand, like, it doesn't teach you very much technique as far as, like, if there's a half note versus a whole note.
MIKE: Well, I think that's actually a good tie back into our topic because we're talking about software development. So far, we've pretty much talked exclusively about music. And I'm going to ask a question here: Who do we write code for?
RAMSES: Humans mostly.
JUSTIN: [laughs] In general?
MIKE: I [inaudible 09:42] for a reason. Go ahead, Justin.
JUSTIN: I mean, basically, companies employ coders to write solutions for their business problems. And, you know, that can take a variety of different languages and such. But I think, you know, when you talk about it that way, oftentimes, you're writing code in exchange for dollars and gainful employment. I have a feeling you're talking a little bit deeper.
MIKE: Well, let's start here. So, you said paid us to solve problems. I think a lot of times we think that we're writing code for the computers, right? We're telling the computers what to do, and so we write code. But computers don't speak code. Computer processors have a set of inputs that take, you know, electronic, you know, signals. It's on or off. And we often think about that as zeros and ones. And in the early days of computing, they used the zeros and ones, either with switches or the punch cards; you know, they talked like a computer. And we don't do that anymore.
I got this idea, I think, from Dave who sometimes has hosted here. He says that we don't write code for computers, and I think he's right. We use languages that are written for humans, and then we run it through a compiler or an interpreter in order to convert it over to something that a computer can understand. We don't use notation that would be the most useful for computers. We use notation that will be most effective for us to understand. That is an important realization [laughs] as a coder. It means that getting it to work isn't really your goal. Getting something comprehensible so future you [laughs] or your co-workers, whoever it is, can come back and understand it.
We write code so that humans can comprehend it, not so computers can comprehend it. And music notation [chuckles], likewise, you know, there's different styles of music notation. That's not written so that we can listen to music. It's written to communicate to humans so they can experience music together. Once again, there's kind of this convergence that there's goals, thinking about the goals of what we're doing.
We write music because we enjoy that human experience. We're notating it. We're not doing that because we want to prove our awesomeness. That's not why [laughs] we do so but because we want to share our experience with somebody. And we talk about tablature versus other forms of music notation. There's trade-offs, absolutely. They're both means of communication, so we can have that shared experience, much as computer code is.
DOM: I just want to mention something you said a little bit earlier. But you said we're talking about different styles of notation for music. I've heard it word for word from somebody telling me about different languages that you can use the right tool for the job. It's like, why would you go out and build a whole application in some certain language when X language does a better job at doing that thing? That's kind of resonated with me, for sure.
MIKE: Interesting. Because when we're writing code, we're writing it for people, but there's this deep, technical aspect to it. You're telling the machine what to do, and you have to create the structure accurately, or else your code is wrong. But the end audience isn't the computer. Versus when we notate music, we have to get it technically accurate. That paper, you know, that we're writing on is not the end audience. It's the humans who will then go and have that experience.
EDDY: Is the equivalent of writing a blog in programming similar to music by playing the wrong note?
MIKE: That's interesting, Eddy. Is it playing the wrong note? Is it notating the wrong note? It probably depends on the performance because a lot of music is never notated, right? A lot of live music it's ephemeral [laughs]. There is no persistent notation that captures it. There may be a recording. And, absolutely, there are wrong notes and some styles of music; maybe that so-called wrong note ends up becoming part of the music, right?
RAMSES: That's jazz for you.
MIKE: [laughs] Exactly. And very deliberately gets worked in the music, and it depends on how jarring it is, and sometimes people choose to embrace it. Much as in our code, sometimes a bug becomes a feature, a happy accident. This act of creating a representation of our thinking has this huge overlap between creating music and writing code. I would argue that maybe that is some of why there seems to be so much overlap between musicians and coders.
Why do you all think, just given the sample set? Like, I think it's pretty random sampling [laughs]. We have a lot of people who are avid musicians as well as coders, a majority. Why do you all think that there's overlap between people who code and people who write music or make music?
EDDY: Kind of funny how, on one field, copying and pasting isn't plagiarism but rather a common occurrence. And on the other side of the [inaudible 14:29], copying and pasting can get you in trouble. So, there is an interesting dichotomy.
MIKE: Well, that's interesting because it can get you in trouble if you wholesale lift it completely. When you copy somebody's style, you're totally fine, right? In fact, it's expected, and we've got genres that people seek out because they have a similar style. And there's a gray area as to how much of that borrowing is okay.
Bob Dylan wrote a number of years ago...I believe it's called Love and Theft. And in that, without telling anybody, he heavily borrowed his lyrics from, like, a 19th-century poet. And right in the title, he mentions theft and then didn't tell anybody. I remember it caused a bit of a stir when people noticed it.
I think people mostly got over it, and they realized that he's probably doing it on purpose, this big easter egg for people to go in there and find. He's kind of exploring the boundary, what counts as plagiarism because musicians borrow from each other all of the time. And particularly in the folk tradition, they quote pretty much verbatim from other singers. They maybe add their own tweaks to it. And that's how we got a lot of our musical heritage.
JUSTIN: All of the AI compositioning that is going on right now, you look at it, it's trained with existing corpus of music all across, you know, the world, you know. It can certainly use anything older than the copyright period, you know, as part of the training, and it can get a lot of the open-source stuff right now, and all that's completely legal. And so, you got to ask yourself, hey, is it real, or is it just what we do anyway?
EDDY: There have been, like, lawsuits, and court hearings about ownership of music and, like, the way music is written. And I think we've pretty much determined that, like, you cannot own notes [chuckles] and chords, right? Like, that's just not possible. But maybe the way the sequence of those notes, you know, can. And I think to some degree, development, you know, and coding is applicable. If you copy and paste something from Stack Overflow, that's okay, right? Because it's free. Everyone can get it; not a big deal. But if you get your hands on, like, the codebase, you know, of a company, then suddenly, that's plagiarism.
MIKE: And those boundaries aren't as rigid as we might hope, or maybe it's nice that they're not so rigid. We've got social convention that drives that. It's not inevitable that we have copyright law be what it is today [chuckles]. It's just simply not, either for software, for music.
And there's been a, you know, proprietary software was kind of king for a long time. And the open-source movement has changed that where a lot of our most fundamental tools like our operating systems, you know, Linux, which runs Android, which runs most of the servers out there [chuckles] is open source. But there's still a lot of proprietary software out there. They live side by side often and maybe, usually, side by side in the same companies, you know, kind of filling different roles.
And copyright law (I don't know for music.), you know, it's also gone through different directions. I don't want to get into a debate over copyright law [laughs], but it's a complicated area. And those social conventions can change over time. Have you all thought some about open-source music? I actually have thought a lot about this. But is this something that any of you have thought at length about?
JUSTIN: Yeah, what we're doing today, we're programming music. We can open source it, versus, you know, I think a lot of...there's a lot of copyright-free (I'm doing little air quotes.) copyright-free on YouTube and other platforms that you can use for whatever. And so, it's like, you know, is this code that we're going to go code, are we going to open source it, or are we going to just say it's ours? You know, it's all these things that we got to decide.
MIKE: To make those decisions [chuckles], you start getting into all this ethics. And sometimes you think, oh, I'm just [inaudible 18:32] coder. I don't want to think about that. Or I'm just a musician; I don't have to think about that. But it suffuses kind of everything we do. And it's inescapable that you have to make some of these decisions. And it's not necessarily very clear. And the people who say that they have all of the answers are probably leaving a lot out.
For example, we all love to get music and to listen to music, and we all kind of wish that it was all free. It seems really problematic to have a lot of our shared cultural heritage locked up and for the purpose of making some corporation money somewhere. I think that all kind of makes us a little queasy.
But on the flip side, how do the artists get paid if not by putting some restrictions on their work? So, that artificially limiting copying, which is essentially free nowadays, artificially limiting that and forcing people to pay for it. And I'm [inaudible 19:19] to have the answers. Much like the debate in the open-source community versus closed source, there are some questions that have a lively debate, and I think can and should continue to have a lively debate because there are multiple parties involved, and they have different needs. But we've talked a lot about some of the overlap. Anybody else have any other thoughts about why musicians and developers often overlap?
KYLE: One thing that I was thinking about as you guys were talking about, like, chords and written music, is it makes me wonder because, like I said, I've not really done a lot of music myself, but I've known people, dual majors in, like, Spanish and English lit or, you know, that know multiple languages. They tend to also like to know multiple programming languages. And how much is music, you know, is it just another language? Is it just something else to learn, some other way of communicating that people just tend to enjoy?
MIKE: The people love to communicate, and good communicators make good coders.
KYLE: Yeah, it's one of those that, you know, you're drawn to more of those universal languages, right? At least in my experience, you know, the more popular languages they are popular for a reason, you know, say what you will about, like, Java and stuff, but it's a popular language. I mean, that's cross-regional. And how often is music cross-regional? I mean, everybody can listen to music. You don't have to understand the language that it's sung in or, you know, I mean, even if it's vocal, I mean, you don't have to understand the language to enjoy it.
EDDY: And just like a software app, you don't necessarily need to understand the ins and outs of, like, how it's architected behind the scenes to enjoy the app, right? Much like merchant portal.
MIKE: We build software, yeah. And you don't see much of it behind the scenes, but you get to use it as a utility. I don't know if we always think about the utility of music. It has social utility. It brings us together as people. It lets us share emotions with each other. We find it useful, if only for our enjoyment.
Let's take this a little bit further. As Justin alluded to, there are tools out there that crosses boundary between software and music. I have a couple of tools that I had in mind, and we're going to try one out here in a minute. The first one that came to my mind was LilyPond. Has anybody else here used LilyPond before? Ooh, LilyPond is awesome [laughs].
It's an open-source tool, and it's written in Scheme, I believe, you know, a Lisp variant, which is very good for recursion and thinking about nested things, yeah, LilyPond. It's a fantastic tool for notating music. It does support tablature, by the way. So, if you want to notate music, I'd recommend to anybody LilyPond, particularly if you're a developer. I've shared it with some people who weren't developers, and they're like, "Huh, I don't know."
[laughter]
JUSTIN: We use MuseScore a lot. You are probably familiar with that already. It looks like it's very similar to LilyPond. But it's nice, and the fact that you can, I mean, it integrates well with a mini keyboard and things like that.
MIKE: The thing about LilyPond, like, the default mode is you write code. It has its own, you know, little domain-specific language where you write note names and durations. And you can nest them in staves, and, you know, it's built up around music notation. If you ever want to...I've used it quite a bit over the years, and I've really enjoyed it. So, there's one thing that I've used. But there are other ways of expressing music. What tools have you all used that cross the boundary between coding and music creation?
DOM: I mean, there's GarageBand. I don't know how much coding you can get into in GarageBand. I never dove into that aspect of it. It's always just been, like, different layers of recording and things.
EDDY: Has anyone heard of Guitar Hero?
RAMSES: Oh yeah.
EDDY: Okay. So, there's a huge community out there. It's still active today, right? Where we found out that we didn't want to be restricted to only the songs that they've licensed for the game, right? So, we, as a community, did an open-source project called Clone Hero. And essentially, you can modify the game and develop the charts yourself in order to compose the music to correlate with the sound, right?
And suddenly, it became huge, and everyone became invested into this open-source project that I think is amazing. So, that's the closest I've ever had as an overlap, I would say, where you see the passion of a project, right? And suddenly, you [inaudible 24:00] other tasks, like, be confined, you know, into some sort of project in order to do it. So...
MIKE: Well, that's totally legit [laughs]. That's absolutely the same kind of thing. What kind of notation is used for those charts?
EDDY: It's just circles, like, colored circles coming down on a highway chart where you have --
MIKE: Got it. [crosstalk 24:20] build those. How do you build those? Because I'm assuming you don't take a crayon and [laughs]...have you built any of these yourself?
EDDY: I have, yeah. I have actually posed a couple of those.
MIKE: What sort of format do you...again, because I'm assuming you're not using a crayon. What do you use to find what those circles are going to be?
EDDY: That's kind of interesting. They may have modified it since, right? But it's software that you have to download. You essentially choreograph the placement of the note manually, and you get a timeline, essentially, of the audio and you [inaudible 25:01] matching.
MIKE: Got it.
EDDY: Definitely no crayons.
MIKE: [laughs] No crayons. But at some point, it's a representation of time, right?
EDDY: Yes.
MIKE: Of time distribution and pitch over, you know, what frets [laughs] you're going to be playing on and duration, which is a kind of encoding, which is what we've been talking about all along.
So, there's this cool project; it's called Sonic Pi. It's been around for years. It's actually been, like, this labor of love for a long time. Boy, I probably first used this, I have to think about this, 7-10 years ago [laughs]. So, this has been a project that has been around for a long time. And it's free. You can download it. I think it's community-supported. You can probably donate money. Shout out here if, you know, maybe give some money to the developers in this project. And it's often used for education. And it's just a tool where you get to do live music creation.
My understanding is that there are DJs who use this for their shows, so it's not just an educational tool. It can actually be used for music generation in real-world settings. And the scripting language that you use inside of it is Ruby. We're mostly Rubyists here, certainly not exclusively, but there's a lot of Rubyists here. We will brush against Ruby now and again, at least [laughs], and Sonic Pi lets you do that.
One thing about a podcast is you can't show the visuals. As we're recording this, we're looking at each other's faces. But we just extract the audio stream and push that up. So, we can't really show you what we're doing. But there's...I'll give you an idea of what's going on. Sonic Pi is this tool that lets you just start writing [laughs], and it says, "There are no mistakes. There are only interesting accidents [laughs]." It's kind of what we said before. There's not exactly bugs. There's things that might not suit your inclination, so you change it.
I have a relatively new laptop. I didn't have a recent copy of Sonic Pi. I downloaded it, like, 10 minutes before we started our podcast recording. And I just went through the tutorial they've got and threw together some stuff, you know, in a few minutes and put in some loops. So, let me play what I did [chuckles]. There's no claim to greatness in music. But I just want you to see what kind of things you can do in 10 minutes in a tool like this.
[playing music]
So, I did a few things here. I just did a loop, and this is straight out of the demo. This is just the bass drum [chuckles]. Looped that eight times. Sixteen times, I do another loop where I play some other sounds, including the drum. And then I end with a kind of a trailing sound at the end.
What we should do is we should play around with this a little bit. And this is pretty much just from the tutorial. I changed a couple of different sample names, but this is out-of-the-box behavior [laughs]. No brilliance from Mike. And it sounds like music, just with that little bit of time. And I thought, you know, I haven't even tried this. I was going to see what happens if I threw an offset and bass drum in there with a slightly different rate. And I don't even know what's going to happen. Do we see?
[playing music]
There you go. It's different.
EDDY: Mike, I'm curious: can you use methods?
MIKE: Absolutely.
EDDY: Interesting.
MIKE: So, that is interesting. Should we write one?
EDDY: Yes, let's.
MIKE: Let's see what happens if we replace our bass drum here with a method.
[playing music]
There we go. Methods work great.
EDDY: Can we do loops?
MIKE: We can, and you may have noticed that it's already doing loops. And, additionally, and I may comment this out, it allows live loops. Let's try it. We press the run button. And we can stop it. Although with it still running, we should be able to change this.
RAMSES: Does the live loop just allow you to modify the code while it's running? Is that the idea?
MIKE: That's the idea. We're going to do our bass drum again. This is straight from the demo. [playing music]. So, what if we want to change the rate of our drum? So, let's see. [playing music] No change there. [playing music] There we go. I kept the duration of the sounds that's getting clipped. [playing music] Okay. What would you have me change? Do you want me to change the tempo?
DOM: I like the total tempo right now. I think adding some complementary snares will really help the composition of our piece.
MIKE: Let's do it. [playing music] So, I would say that that kind of overrode the bass drum a little bit. What if we change that a little bit? So, I'm going to add in a snare [playing music]. It works.
EDDY: Can we add a cymbal?
MIKE: Yeah, let's do it. Let's think about how we would do this. So, first thing, we've got our bass drum, right? It pauses an eighth note and then plays our snare. And then it's going to pause for a half note minus an eighth note. So, I think what we want to do here is...let's think about it. Do we want it exactly on the same positions as our bass drum? And then we sleep for an eighth note. We play our snare drum, right? And then, let's sleep for another eighth note. That will get us to our quarter, play our cymbal again. So, I don't think I've quite got this worked out to full quarter notes yet, but we've got a little bit. Let's what we've got. First take. [playing music] There we go.
EDDY: That's really cool.
MIKE: Yeah, and then we can start adding in more sounds, right? We can start adding in stuff right in the background. Let's add in ambient dark whoosh.
[playing music]
You get some rhythm in there.
[playing music]
Cool. And we wrote some code, and we made some music.
EDDY: I actually [inaudible 32:13] kind of interesting. I went ahead and shared external examples of people who have actively developed [inaudible 32:20] some code. I thought it would be interesting to kind of hear some examples of what you can accomplish with people who have taken presumably hours trying to get the right sequence.
MIKE: Okay, cool. So, we can try one of these examples. Let's give it a try, shall we? [playing music] Nice. Writing music using code. So, we've had some fun [laughs]. We started by talking about some of that overlap between the musicians and coders, some of our background [laughs], and then put it to work, you know, talking about some of these tools.
I'm going to go back to something I said a little bit before about creation. This is all fun. And [chuckles] you might think, oh, it's just fun. Well, I am not going to do that. Well, something that I found in software development, and this has come up before in our podcast, and it's going to come up over and over again, is that communication is vital for successful software development. It's come up in this session [chuckles]. Communication is so central to what we do. We're communicating with a computer, communicating with each other. Much of what we do is maybe...almost everything what we do involves communication.
Playing around with something like this might not seem very important, but developing shared communication together is one of the most important things that we can accomplish together as a team. You know [laughs], I'd invite anybody who listens to this to...it's maybe a little silly [chuckles] but, you know, to go spend a little time and play around with it but not alone. Here's my invitation, that you go and do it with somebody like we just did. The music that we've made together, I think, was a lot better than we would have gotten alone.
Any parting words that any of you would like to add before we end our session today?
DOM: Make sure to be on the lookout for the new Acima underground album featuring...
MIKE: [laughs]
DOM: Dirty Mike and the Boys. It's our new hit single. It's going to be awesome.
MIKE: [laughs] Thanks for the shout-out, Dom. Be on the listen for a future podcast session.
EDDY: [laughs]
MIKE: Great. Thanks again for listening to us on the Acima Development podcast. Until next time.
The panelists discuss work-life balance and avoiding burnout. Mike shares his personal experience of burnout from continuous long hours at startups and the positive impact of transitioning to a four-day workweek, which surprisingly increased productivity. The group identifies factors contributing to burnout, such as excessive workload, lack of autonomy, and value misalignment with the company. They explore symptoms of burnout, including diminished interest, difficulty focusing, and physical symptoms like headaches.
The conversation also touches on strategies for preventing burnout, emphasizing the importance of setting boundaries, disconnecting from work, and prioritizing tasks. They discuss how a supportive work environment, where employees have autonomy and their values align with the company's, can help mitigate burnout. The podcast acknowledges that sometimes, leaving an unhealthy work environment might be the best solution for avoiding burnout.
Transcript:
MIKE: Hello, and welcome to another episode of the Acima Development podcast. I'm Mike. I will be hosting again today.
Today, we have with us Eddy, Ramses, and Tad. You can probably tell, if you're listening to this, by the title that [chuckles] today we're going to be talking about work-life balance and avoiding burnout.
So, I'm going to start with a very personal story on this one. About, I don't know, ten years ago, I was at a startup, but not the first startup I've been at [laughs]. I had been at kind of a series of startups, where I had put in a lot of hours. And I realized that the work wasn't motivating me the way that it used to do. I felt, you know, the obligation to get the work done. But I just... it was harder and harder to focus. And I didn't enjoy it the way I once enjoyed it. I mean, coding is fun [laughs], and it just wasn't anymore.
I started thinking about career changes, thinking about...in my free time, I thought about a lot of things, and they weren't work [chuckles], and that said something. Some context: I had been working at a baseline of about 50 hours a week, and sometimes up to 70-80 hours a week, not usually, but, you know, I'd put in a lot of hours, probably averaged around 60, and I had done it for years.
I had worked at one place where I was the lead and sometimes the only engineer keeping things together. And this was in the days before DevOps, so [chuckles] not only did you do the engineering, you also kept the systems up. And, you know, there was, like, a data center you had to go to fix things [laughter] in case the servers went down.
TAD: Unlock the rack, pull up the little cards, the keyboard, and the monitor around it, put things in.
MIKE: Yeah, KVM keyboard. We did that [laughs]. I did that. [inaudible 01:50] I didn't have to go to the data center very often. But I did that, that, you know, kind of run the show thing for a lot of years. So, I went for multiple years where I didn't have any meaningful vacation. I took off one or two days here or there, and that was it. In fact, I took two days off once and I remember it feeling like the biggest vacation I'd had in, well, in years. I pulled it off. I did it. But there's a point when you start to question, even if it's not even conscious. My body was telling me maybe this isn't the right answer.
And I suggested...I'd been reading about the four-day workweeks that some companies were going to. And we had a team meeting, and the manager I had said, "You know, if there was anything you could have, you know, anything that you would change, what would it be?" And I said, "You know, what? Working less. What if we tried this four-day workweek thing?" And he said, "Okay."
And he went and got approval from the company, and, like, the next week, we did it. So, kudos to [SP] Mutch, by the way. If you ever happen to listen to this, thank you [laughs]. That was awesome. I'm still very grateful for having such an excellent, you know, partner in things. But we did that, and we did that for quite some time, actually. I did that for probably a couple of years there.
And here's the thing, this is the thing: we measured our output and story points. And you know what happened? It went up. It went up. It wasn't just me working four days a week. It was the entire team. We were a relatively small team. We had six or eight people, something like that. But our productivity went up. Our consistency went up, and we consistently delivered. And we were all happier.
So, I went from working 50 to 80 hours a week to working 32 to 40, and the productivity went up. It was a profound moment to see that sometimes, working harder does not make everything better or push the work forward. And killing yourself, you know, perhaps literally killing yourself with the stress and all that time and taking time away from things that are also important in life, was not particularly effective to getting more done.
Now, I don't want to be misconstrued as saying [chuckles] that over no timeframe that additional work can't be helpful. Everybody who's been to college has probably stayed up late studying, stayed up for a test the next day, or finishing a paper, or finishing a coding project if you're a coder, myself included [laughs], sometimes all night for a couple of nights. But that's over a very small, fixed time interval after which it ends. And over longer time horizons, that becomes less and less effective.
I've seen some research that was a big to-do...probably between 15 or 20 years ago, probably closer to 15, about somebody named...well, somebody whose pseudonym was EA_Spouse. You can look it up: EA_Spouse, EA underscore spouse. When there was a spouse of a developer at EA Games, who wrote an open letter about how their spouse was being mistreated and overworked. For some reason, it went viral, and a lot of people commented on it.
And one of the things that came out of that was there was some research done in physical world manufacturing, not in modern information industries but back when people were working more with their bodies. (So, you could arguably debate that it doesn't quite apply, but I suspect it does.) that they measured overtime. So, they had one group of people work 60 hours a week, and one group of people work 40 hours a week.
And they found that, initially, the people working extra hours had more productivity. But by about six weeks, the productivity was equal. So, after six weeks, the people who'd been working 60 hours a week for those six weeks had no more output, and their cumulative output was no greater. Their cumulative output was no greater than people who had worked 40 all that time. And [laughs], wow, right?
Imagine you're that poor group that worked 60 hours a week, only to realize you've accomplished nothing more than the people who just worked normal hours. That really resonated with me, and I've thought about it a lot in the years since. And I think about the four-day workweek. I worked the four-day workweek for several years. [inaudible 06:00] the Acima Development podcast, my first few years at Acima, I was a contractor, and I actually worked four-hour weeks, and eventually, I came on full time.
And in order to work well with the rest of the team, I've shifted away from four-day workweeks because my burnout had healed [laughs, and I was back and loving my job again. But I know that risk is there, you know, I know that I can destroy myself. So, I've made very conscious effort in the years since to be very careful about how I spend my time. When I'm done with work, I turn it off, and I do something else.
And I've learned that it has not affected my productivity. In fact [chuckles], if anything, I think I've done very well. I've done very well in the years since and have been able to be very successful. And part of that I ascribe, actually, to a willingness to maintain a boundary and say, "This is where work stops." I have an office. And when I'm done with my workday, I leave my office, and I go and I spend time with my family. But maybe I'll do other things sometimes, too. But, you know, I leave my office, and I go and do something else. And then, when the next day comes, I go into my office, and I work hard.
There are times when I do think it's appropriate to put in some extra time. There's times where there's an urgent project, and you put in that time to get that done. But if those are anything other than the exception, I think it not only is going to be the cause of a poor personal experience, but it won't actually help. When those long hours become the rule rather than the exception, they tend to actually be counterproductive.
And I'm speaking from anecdotal personal experience, though we did measure, you know, over a team. But there's also research backing that, that maintaining this balance and getting away from burnout is beneficial not only to individual health but to the company health, that we're able to contribute more because we're able to bring our whole selves in.
And it's interesting. I don't think we're necessarily personally aware that our productivity is going down when we're overworked. It's as much as a person who's intoxicated has a hard time being introspective and recognizing they're intoxicated, or a person who's been sleep deprived has a hard time recognizing. And they might know that they're sleepy, but it's hard to do cognitive introspection. You don't see that your productivity is going down. It [chuckles] inhibits your ability even to be self-aware. So, regardless of whether you think you're being less productive, if you're putting those kinds of hours, you probably are.
I think that there are probably some cheats, to some degree, to get you past some of those things. I know that there's some people in Silicon Valley who do, like, mindfulness meditation to find some break between things and then return to work. But there are human limits. At some point, you've got to take that break. And refusal to acknowledge those limits doesn't mean they're not there. As much as I can refuse to acknowledge that gravity affects me, but if I jump from a high place, my refusal to acknowledge its existence [laughs] is not going to make it go away.
I have kind of strong feelings about this one because I think it's important. I think that developers should be, and everybody should be treated with respect. And particularly knowing that overworking people doesn't get the job done better [chuckles] leads me to argue pretty passionately that we should be treating people well, not only for their own sake but for the health of the project and the company. We do better when we give people reasonable hours of work. What thoughts does this bring up in y'alls mind? What do you think?
TAD: A couple of questions that I'm curious about from you guys is, what does burnout look like? And are there other factors besides workload that contribute to burnout? Because workload is an obvious one, right? And that's what you're talking about, Mike. But I can think of other factors that would contribute to me feeling burned out, even if I'm working just a regular 40-hour week. So, those are a couple of questions for you guys. And I'm curious to see what you guys think.
EDDY: I feel like we need to find what the symptoms of burnout is first, right? Maybe fatigue, like, cognitive thought goes down, et cetera. Like, maybe we can engage the room and see, like, what other people's opinion is on the symptoms to burnout.
TAD: Like, just a lack of interest, right? You're like, I know I should care about what I'm doing right now, but I just can't bring myself to care enough. And I'm going to force myself and [SP] pinery, and I'll push through this. But, oh my gosh, this is a slog because I feel so indifferent right now to what I'm doing. That's something that I experience when I'm feeling burnt out.
MIKE: That's really well put. And related to that, focus becomes extremely difficult. Think about intrusive thoughts. Whenever you've had intrusive thoughts, something that you keep thinking about, well, that happens to you because instead of your mind staying on it, your mind wants to go somewhere else. You lose the ability to have the kind of focus you need.
And for software development, you need focus. It's important. It's a very focus-driven endeavor, and inability to keep your mind on it...you think, okay, I'll go for a walk, whatever it is that you do. You know, I'll go and read an article, whatever it is, you know, we all have our own things that you do to go and clear your head just because it's working.
EDDY: For me, it's headaches. If I'm staring at the screen for too long or whatever, my head starts hurting. It starts throbbing a bit, and I have to stand up, you know, walk away.
MIKE: It's interesting. You have to look for those things, that, you know, lost self-awareness. It's really hard to do a self-analysis. So, you have to kind of look for those things. Wait, why am I getting so many headaches?
TAD: I think it's potentially harder for us because we train ourselves to tune things out and to focus, right? That's part of the job. That's part of the skill set is: I need to be able to put the blinders on and set my mind to a task. And if I'm really into something, I'll forget. I'm like, oh shoot, I should have eaten lunch, like, an hour ago, right? Which is a sign that I was doing a good job of focusing but a terrible job of being self-aware of my body's promptings, right?
EDDY: So, what adds burnout? I think workload, like you said, Tad. I think that's where most of us go, right? Like, instinctively [laughs].
MIKE: It's not all of it, right?
EDDY: Yeah.
TAD: I know that if I have this possibility for something, but I haven't been given the ability or the power to accomplish it, then that puts me in this burnout spiral, right? Like, if they're like, "Oh, there's a very important deadline you have to meet this Friday. You have to get it done." And you're like, "But the API isn't even ready yet." I've just coded against vapor. And I don't have the power to change that, right? Like, the responsibility without the power to accomplish what you're responsible for that disconnect often just makes me stressed and burned out, right? There's, like, a control-responsibility balance that I need.
RAMSES: In hindsight, I don't know if that would be necessarily your responsibility. It's, like, the product manager's responsibility. You do what you can do, and, you know, if it's not delivered on time, that's their problem.
TAD: But I've been in a situation where I was working at a startup, and they say, "You got to take this data and build these graphs from this data." And I said, "That's impossible to do." Like, the data just it's not the sort of data that you can graph in that manner, right? And my manager said to me, "You're a smart guy. You'll figure it out. I need this done by Friday." And Friday came, and the data hadn't changed.
MIKE: [laughs]
TAD: The requirements hadn't changed. And I still I'm, like, you can try to match this data to this graph, but it's nonsense, right? It just isn't the right graph for the data. And that's just burnout, right? That's just stress. And --
EDDY: I feel like some of that responsibility does fall to the individual, too, right? I think we need to be able to be expressive when we feel that the deadline is unrealistic. So, like, part of that is imposed by management, like, product managers [inaudible 14:34] and such. But I think as a developer, you also need to be pretty conscious about that and be expressive if you feel it's unrealistic.
MIKE: Well –-
TAD: Yeah. And if they say, "You're a smart guy; you'll figure it out," then --
[laughter]
MIKE: So, that goes to your...you had mentioned...You didn't use this word, autonomy. I was going to say the same thing. You know, anytime that...and I've seen...I don't have it in front of me, though I've read about this in the past. That's the thing they mention first [chuckles]. It's often mentioned first is, when you don't have autonomy, when you have demands that you have no personal control over, autonomy or agency kind of related words, if that's taken away, it causes stress. And those are the kinds of things that lead most to burnout.
And it says something to management that [chuckles] it's their job to provide agency and autonomy to their employees. Give people the opportunity to do what they want to do, that is, to do their job, right [chuckles]? I don't mean the autonomy to decide to go on a three-year vacation but [chuckles]—maybe in some places—but the autonomy to choose how the work gets done. And that means listening.
When you say, "This is what I think the requirements are," and the developer says, "Well, what is the reason that you have those requirements?" And they say, "Well, I'm trying to solve this problem." And the developer says, "Well, I can think of this way to solve the problem. It doesn't quite meet those requirements, but it solves the problem." Now you've had a conversation. You've done what was really requested, was solving that problem rather than meeting a set of rigid requirements.
In the case you mentioned, Tad, "Here's this data. I need to visualize it." If it had been brought to you in a different way, saying, "I've got some data I need to visualize," that's a very different request because it steps back and has some humility, you know, some willingness to negotiate so that the problem gets solved. There's still a problem that needs to get solved. But solving the actual problem in healthy environments...I think we've spoken before about psychological safety. In healthy environments, interesting questions are celebrated and encouraged because they lead to better solutions. In unhealthy environments, there are demands made without any feedback.
And this is related to the idea of Agile software development, which is all around communication, recognizing it's really hard, actually, to communicate about requirements. And if you try to come up with a bunch of requirements upfront, you'll probably get them wrong. So, instead, focusing on an iterative process where there's communication at every step, you tend to get better software.
A prominent example is SpaceX. They're a physical world company that tries to run things like a software company, and they do this iterative development. And they've just dominated that industry recently because that process works. It works. The heavy communication, the tight feedback loops, where the communication is kind of the center of the cycle rather than documenting rigid requirements. Well, the same thing applies to your manager. You need to have that communication loop. And if management is not communicating, they say, "Here's our requirements. Get this done," then you end up with a project that runs over budget and over time, and nobody is happy.
EDDY: You know, we're talking about burnout. And both Mike and Tad have mentioned that earlier in their careers, they dealt with burnout. And I can finally relate to that, and I don't know if that's a good or bad thing [laughter]. To give some context, you know, our group was assigned to accomplish not an easy feat. You know, it was a feature that needed to be out within, like, a month deadline.
TAD: Yes.
EDDY: And some of us found ourselves, you know, working extra hours, working over the weekend, you know, to make sure that we were meeting deadlines. And I found quickly that I was, towards the tail end of us meeting that deadline, and I found that we were missing, me personally, I was missing really simple syntax, you know, that was being called out on my peer reviews, right?
They're just like, "Oh, Eddy, you forgot, you know, you misspelled this [inaudible 18:42]." Oh, man. I'm like, I would have caught that any other time, right? But, like, when you're crunching and, like, you're in a tunnel vision, you know, you start missing really easy mistakes, right? And that's when I realized, I'm like, okay, after this is out, after this is in production, and there's something tangible that's working, I'm going to take a couple of days, relax --
MIKE: As you should.
TAD: Yeah, I find my brain is...they usually talk about, like, exercising your mind, like, working your mind. And this reminds me of...one time I was working at a company, and several of us were, like, "Oh, Go sounds like a really interesting game. We should all teach ourselves how to play Go." And during our lunch hour, we would play Go against each other.
And it's a very simple game, but you have to think really, really hard about it, right? You have to be like, okay, if he goes here, and I go here, and [vocalization]. And you have to take really many, many steps ahead. So, we'd do that over our lunch break, and then we'd get back to work. And we'd just be like, "Ugh, I can't even, like, work. Like, I can't even focus on my code because this activity I did for an hour is exercising the same part of my brain as I was needing to write code. And I just can't bring my brain to do that still, right? Like, I need to find something different. I need to exercise a different part of my brain, right?" Like, if I'm doing --
EDDY: You need to stimulate your brain [inaudible 20:15]
TAD: Yeah. Just, like, I'm doing left-brain activities, like, very intense. And I think Mike has mentioned, you know, go and listen to some music or play the piano, or, you know, interact socially, or things like that. That's an activity that's very different. And it lets that part of your brain rest and lets some other part of your brain, you know, take over and do something for a while.
MIKE: My first manager in software grew roses. You got to have something different.
EDDY: I play fetch with my dog because I have a backyard, sometimes.
TAD: There you go.
EDDY: And with us kind of transitioning over to winter, there is very less time you can do that now.
MIKE: So, you need to find another outlet, you're saying?
EDDY: Probably. Yeah, that sounds about right.
MIKE: [laughs] So, we've talked a little bit about some of the things that lead to burnout, and we've mentioned the lost autonomy and then overwork. Anything else that any of you have experienced? You know, it doesn't even have to be necessarily work. You know, this can happen in school or other situations.
TAD: Actually, I was mentioning, like you, you know, go interact with your family, things like that. Something that leads to burnout for me is isolation, where I'm just by myself. And there's been times in my career where it's...I've worked remote; I'm by myself. And the project I was given is, like, a three-month project or something like that, right? Where there's no one else I can talk to about the project. They're all doing their other things. It's just me and the project that's going to take three months.
And it's hard for me to care as intensely on a three-month project by myself as if, you know, I'm pairing with somebody, or I get a break, or I get some kind of variety or something like that. So, it's...maybe I'm touching on some other things as well. But, for me, that isolation aspect, if it's just me by myself all day, every day for many months at a time, I start to feel it. And it's not a workload thing. It's just I miss the interaction with people. I miss being able to talk through some things.
EDDY: So, that's why you go into the office is to avoid burnout [laughs].
TAD: Yeah, like, I come into the office so I can talk anime with you. And you heal my burnout, Eddy.
EDDY: To the listeners out there, to avoid burnout for Tad, he likes to have conversations and go on tangents about anime [laughter].
TAD: Because I know you're a huge fan. But I am someone that probably needs to pair more than maybe other developers. I've got a buddy who works for Google who his ideal situation would be he's in the forest in a glass box so that, like, you know, he's somewhat protected from the elements, but he could still see nature. And he would be able to do that all day, every day, for the rest of his life.
He doesn't need to talk to anybody. He doesn't need to have anyone check in on him. He would just sit in nature by himself. And he's content, right? He's fulfilled with just that. But if your needs aren't getting met, is when you hit burnout. And, for me, I have a social need that I need to take care of periodically, or else I get that fatigue and that burnout.
EDDY: Change of scenery, Tad. I think that's awesome. It's a great idea. When you really mention it, anytime I do go physically in an office, since I do interact with more people to get that social stimulation in my brain, now that I'm thinking about it, it's very seldom that I do reach or hit burnout from the days when I do go to the office.
I can't do this anymore. I have a backyard patio, and I have a bunch of trees, and I have a garden couch. The couch is designed to be outside. And I would sit down, stretch my legs because it's a long couch, right? And I'd sit back and, you know, recline a little bit. And I'd find myself just hearing the birds. Suddenly, that's kind of soothing.
TAD: That's interesting because I have a spot on my balcony where I've set up a hummingbird feeder, and just going out on the balcony...every developer they get hung up on something and just kind of, like, stare off in the near distance and just kind of, like, ugh [laughs]. And just being able to watch the hummingbirds flit around while I do that has been beneficial for me.
EDDY: The power of nature.
MIKE: Are you familiar with the idea of forest bathing?
TAD: I am, yes.
MIKE: It is a Japanese idea. It's a practice of going to the forest, and it's not literal bathing of your body. It's kind of bathing of your mind. My understanding is it has been shown to be very therapeutic, nature, in particular, getting out of the office, outside into the woods and that glass box, wherever it is [laughs], someplace where you're exposed to somewhat unmodified [chuckles] universe around you. That could be the stars, right? Seeing non-human created environment changes you, and I don't have deep insight as to why that is, but I do have deep experience. That is very therapeutic for me. And I wonder if it's somewhat related to the socializing and that you're communing with the universe in some way.
EDDY: I haven't necessarily done forest bathing, unless you consider listening to a soundtrack of a forest. That's what I've done before trying to fall asleep, you know, and I take my mind elsewhere. I will say, like, "Hey, Alexa, play some sounds from the forest," you know, and just hearing birds chirping, and, like, the wind and trees being brushed and stuff like that, maybe it has a similar effect.
MIKE: Why wouldn't it, right? [laughs] Whether it's visual or audio, it's all a similar experience. I was thinking, as were talking about isolation, in prisons, they will put somebody in solitary confinement sometimes. Sometimes, that's treated as punishment. And whether or not it's treated as punishment or just keeping somebody safe, I read that it's associated with severe negative effects on mental health. It's, in general, not good for people to be alone, and, usually, it doesn't result in very good software either, oh, not as good; I'll say that. You know, software, in general, is done better in a social context like most things.
EDDY: You know, I'm pretty sure I've read something, like, a psychological somewhere a long time ago, where we've done studies that, actually, isolation is, actually, bad for individuals. And prolonged isolation does horrendous things to the body. I'm not saying that being a developer is coexisting with isolation [crosstalk 27:03].
TAD: It makes you [inaudible 27:04] crazy?
EDDY: [laughs] I'm not saying it makes you crazy, and it's relatable to prison. But --
MIKE: Right. They're different in degree, for sure. And I don't want to diminish the suffering of somebody who's in that degree of isolation; rather, to give an example of an extreme case and the deep trauma it perpetrates against your mind. And in a much lesser degree, like with my experience at work, you know, could lead to burnout.
EDDY: What are some of the actions or the things that you guys do while working to help productivity and also, in essence, avoiding burnout? I feel like some of us would say we listen to music. Anything else?
MIKE: I can't listen to music while working. I love music.
TAD: [laughs] --
MIKE: And that's why I can't listen to music while working because I can't do both [laughs]. I used to do it when I was younger. And if I need to have deep focus, I cannot also have something else that is taking my focus. You know, some people have ambient music that they can pay less attention to. To me, that's hard. I'm somebody who likes to think about the structure of the music.
Part of my experience of the music is maybe decomposing a little bit, thinking about the parts, thinking about the baseline, drums, you name it, or, you know, thinking about the harmonies or, like, oh, there's a key change, and kind of self-evaluating how it makes me feel. And with music I like, I'm going to go listen to it thinking about the lyrics, you know. I can't listen to music. It's stressful for me because it requires me to focus on two things at once.
TAD: Would something like the sound of rain or, you know, the ocean or something like that where it's maybe got some pattern, but it's not really musical and that structured...To be a developer, a lot of times you have to have a very analytical mind. And I'm guessing that deconstructing music is kind of the same muscle as breaking down code and analyzing code. So, that's going to be competing in your mind, right?
MIKE: You got a point. I bet I could listen to rain, and it would probably be fine and help push the other things away because it's close to white noise. It has a beautiful structure but one that's largely chaotic; you know, there's not a pattern that can distract. It's a good thought. Maybe I should give it a try.
TAD: I've kind of been thinking about different things. Maybe there's a lot of things that cause burnout for me. But I was thinking about a startup I worked at, and their value proposition was all the other people in this industry take your data, analyze your data, sell your data, invade your privacy, you know, all these things, and we don't, right? And that was their sales pitch. And that was their special niche that they're like, we only sell your data if you want us to, you know, we could partner up. We'll sell it. We'll give you a little bit of a kickback. But by and large, we store it, encrypt it, and it's private, and all these things.
And that was something that I really kind of believed in. And I'm like, yeah, like, people's privacy, and we don't sell their data. And I'm kind of proud that we're the only people in this particular segment of the industry that are doing that. Then, the company got sold to a much bigger company. And one of the first things they did is like, oh, yeah, we're going to make a ton of money by selling off analytics of everybody's data.
And when those values shifted, so they didn't align with my values anymore, suddenly, my enthusiasm for my job just went way down. I'm like, oh, okay [laughs], we're doing the same things that everyone else is doing. And we're not cool and awesome and an ally for people. We're just exploiting people [laughs] like everybody else. And that probably caused some burnout for me, just because I didn't care. This isn't cool. This is just a job that I'm slogging through now. And it's kind of something I'm doing. And I don't necessarily love myself when I do this. It's causing friction against my personal values.
SPEAKER: And I think that it happens with every change in management, when there's a big change in management and the philosophy changes. That's what happens because you are used to have the same vision. And it happened to me. I was working at a startup. And we were, like, disrupting the proptech ecosystem in Mexico. And there was a CEO, did something wrong, and they needed to replace him.
And this guy was, like, a big person in the ecosystem. But it was an old guy, like, really married to how things were done 50 years ago, and he wanted to take the company back to that. And I was very happy on how we were disrupting. And when this person came, it's like, the whole happiness of me working there it was off.
TAD: Would you say that caused burnout for you?
SPEAKER: Yeah, it was like, oh, no more happiness when you wake up. And, you know, you don't feel like going to work. And it's like, oh, this guy is going to ask...what [inaudible 32:27] project is he going to ask now? [laughs]
MIKE: Similar experience I had working for a company that got bought out. The company that bought us out started doing some things I found really shady. [laughs] And it bothered me more and more till one day I left [laughs]. At first, you know, things were fine. But as things got shadier, I got more and more uncomfortable; not just me, but the entire development team actually walked out. Not a good thing for your company, by the way, when your entire development team walks out [laughs]. Try to avoid doing shady stuff.
TAD: [laughs] It sounds like values and culture are big factors, yeah. I'm actually able to handle a higher workload if I enjoy the people I'm working with and I believe in what I'm doing.
EDDY: I hope I attribute to that.
TAD: [laughs] Of course.
EDDY: [laughs]
MIKE: We've identified several things that cause burnout. And if these are the factors that cause burnout, what's the opposite of that? Because I think we can take practical steps to avoid each of those things. And I think that'd be a great way to round out our time here. And the first one we all jumped to was overwork. So, what did we do?
RAMSES: I think you mentioned this earlier, Mike, but one of the main things, at least, I try to do, with my own work is set boundaries. I try not to work too much. I personally try to get up from my desk at least every hour. It's a little bit harder because my chair is so comfortable [laughter], so I can sit there all day. And then outside of work, I just try not to think about work too much; you know, I might be working on a problem in my head, but you just have to put it away until the next day.
MIKE: You know, and our listeners don't know, but Ramses is a machine. He gets a ton of code written. Realize that when he's saying he takes breaks, that means he's exceptionally effective with the time he has.
TAD: It feels like the Pomodoro thing sweeps through the software development community periodically, where you work for maybe 25 minutes, and then you take 5 minutes of break. And then you work for 25 minutes, and you take, like, 5 minutes of break. And in those 25 minutes, if something comes up, like, oh, that's a distracting thought, you could write it in a notebook, knowing you'll give yourself 5 minutes to address it later on. And you could free your brain from worrying about it, right? And I don't do that well, but there have been times where, you know, doing that kind of timeboxing has been effective for me.
EDDY: Disconnecting from work, I think, is crucial to avoiding burnout. In certain occasions, I've wanted to uninstall Slack on my phone, on the weekends. It's one of those things where I instinctively check to make sure nothing's on fire. But you can't really disconnect from work if you always have that connection wherever you go. I actually hid the icon...
MIKE: [laughs]
EDDY: Somewhere else where I'm not used to looking for it as a way for me to...if I [inaudible 35:31] try to go for it, I have to go out of my way to find it. And then I catch myself, and I'm like, oh, okay, no, I shouldn't be checking it. So, I think disconnection from work I think it's important. And also, try to avoid thinking about stuff over the weekend.
MIKE: And it's hard if you're on-call. You know, if you're responsible for a project, you have that obligation, but you can still timebox it. You can say, "Well, you know, I need to check on this. So, I'm going to check it at..." and you pick your time and then set it aside, unless there is an active push notification, you know, something that's pulling you in. And you can set up your notification preferences appropriately; you don't go back. There's more of that boundary setting.
I get off work. I do have Slack on, you know, if somebody needs to get a hold of me or they text me. I put my phone in my pocket, and I walk away. Yeah, maybe I'll use my phone to read something, but I will walk away from my desk. And that willingness to walk away has made such a difference. I used to really struggle with that, having that boundary, having an edge. But I've learned that, you know, I need to if I want to be effective at either side of that [inaudible 36:35].
EDDY: Early on, my wife would catch me on there, right? And she would be like, "What are you doing?" "Oh, I'm just answering the message in Slack on my phone."
TAD: [laughs]
EDDY: And she's just like, "Why? Aren't you off work?" I'm like, "Yeah, but I can provide input. Like, let me go ahead and do this." Eventually, like, she's like, "Babe, like, you're off work. Distance yourself [inaudible 36:54]. They'll live without you until tomorrow." Imagine I wasn't on-call.
MIKE: Well, and I schedule some time. I know that people might have some needs. So, I generally try to take 15 minutes to check Slack in the morning and in the evening, so I'm keeping, you know, a regular cadence. So, if people are stuck, I can do that.
Sometimes, in my current role [laughs], I have a lot of requests. I'm looking at 65 right now, and I recognize that it's not even possible for me to get to all of them. And you have to make a choice that you're going to be okay with that, that you can't get it all done. So, you have to prioritize and do what's most important, and then walk away. And that's really uncomfortable because I think we all want to do everything. And that recognition that we can't is hard but necessary.
TAD: The hard thing is that answering people's questions, helping things out, I mean, that's part of your job, and that's part of the reward of doing your job. If you didn't enjoy that stuff, then you would have a different job. So, it's hard, but it's something that you enjoy where you get positive feedback from it. Like, if Eddy is on, you know, helping me out with something, I'll be like, "Hey, Eddy. Thanks," you know, thumbs up, high-fives, and stuff like that. And it's hard to put that away sometimes.
MIKE: And we have to remember that we're not an unlimited well. You can drain it dry. That water table has to be replenished. And if you're not in a healthy spot, it's hard to help anybody else out. There are finite boundaries. We absolutely should celebrate, I think, that willingness to help and also recognize that, you know, if you destroy that ability to help, you're not helping anybody, and those boundaries make a difference.
Living without boundaries will only destroy yourself, and that's a difficult thing to realize. The answer is no [laughs]. You can't do it all, so you have to choose, but vital. And the same thing applies in lots of different contexts. If your business can't do everything you'd like to do, you got to choose. And in our personal lives, we have to choose. You have to choose to do the things you can do within your allotted time and then be done.
So, there's a lot to be said for choosing wisely, spending your day saying, "Well, these are the things I need to get done today. I'm going to work on the most important things first," or else you get to get the end of the day, and you're going to have that lost autonomy because you haven't done the most important things, and you're stressed out because they're not done. And you feel like they were taken away from you. But a lot of times, we do have some agency there. We can choose what we do first, and that, I think, goes a long way.
EDDY: You mentioned something that kind of harmonized with me where you said, you have to be comfortable being uncomfortable with doing so, right? Well, I'm paraphrasing, and you said [inaudible 39:35]
MIKE: I think you said it better than I did [laughs].
EDDY: The thing is, at least for me, it was a lot harder to do that early on in my transition to a developer. When I first started, and I'm going on five months now, it was really hard to disconnect because I really wanted to hit the ground running. I was pushing 200 miles per hour, trying to make sure that, like, no one made mistakes, and I'm providing the value that I said I would, so I'm not trying to make a liar out of anyone.
But the longer you go, you know, the more experience you get; I think it becomes easier to disconnect and be putting yourself in those uncomfortable situations. So, for anyone listening who's starting to transition or starting to get their foot in the door, just know that it gets easier the more experienced and more wise you grow.
MIKE: It stays uncomfortable [laughs]; I can say that. But like you say, you become more mature at it and okay with it. You've made a conscious choice to embrace imperfection. A lot more gets done when it doesn't have to be perfect. So, we've talked about priorities and how vital it is to set priorities. That also helps some with autonomy. It helps with your time because it allows you to set those boundaries and give yourself some time.
So, boundary setting, prioritizing, and I don't know if there's much else to be said about the autonomy aspect because priorities has a lot to do with that. It was also mentioned that willingness to communicate is important, that when you see something you don't like, you say something.
TAD: It's nice if you're safe saying something.
MIKE: Yes. And that kind of yields the final point. If you're at a place where you don't have autonomy, when unethical things are happening around you or things that don't coincide with your values, and where you're being overworked, the answer is you probably need to leave. And, again, sometimes you just need to make that choice. Look around yourself and say, "Well, this is not the right environment for me." And that's an okay decision. You'll live through it [laughs].
And maybe that's a good place to end today. We've talked about the problems. We've talked about the solutions. Thank you to everybody who's participated today. I think we had a great discussion. For our listeners, thank you for joining us again on the Acima Development podcast. You'll hear us next time.
The panelists discuss Ruby, a primary programming language at Acima, notable for its popularity in startups and major companies like Shopify and GitHub. They attribute its success to the Ruby on Rails framework and the language's community support. Mike shares a personal story to parallel the complexity of understanding Ruby, linking it to its creator, Yukihiro Matsumoto (Matz), who views Ruby as a language of love, embodying a philosophy of developer happiness and care.
Additionally, the group explores Ruby's technical aspects, focusing on its object-oriented and functional programming features and syntax that mirrors spoken language, simplifying programming. They discuss Ruby's history, its influences from languages like Perl, Smalltalk, and Lisp, and its evolution with Ruby on Rails. Additionally, they touch upon Ruby's versatility beyond web development, its role in shell scripting, and considerations regarding its scalability. They end with an endorsement of Ruby for its user-friendly approach to programming, prioritizing problem-solving and user experience!
Transcript:
MIKE: Hello, and welcome to another episode of the Acima Development podcast. I'm Mike. I'll be hosting again today. We've got a group of us here with me. But yeah, kind of starting, we've got Sergio, Eddy, Dom, and Jonathan.
Today is a topic that I have been interested in for almost decades now, which is the Ruby programming language. At Acima, we do a lot with Ruby, and it's been our primary language. It is not the only one we do, but we've done a lot of Ruby for a long time. And I've done Ruby for a long time. A lot of us here have done Ruby for a long time.
And certainly, there's reasons to do Ruby, you know, it's got a community. Ruby on Rails framework has been popular for a while. It was particularly influential, like, I don't know, 15 to 18 years ago [laughs] and has continued to be used a lot by startups in particular. And there are some, you know, major companies using it, such as Shopify or GitHub. There's a community out there of Ruby users. And there's reasons just for that.
But today, we're going to talk about the language itself and what it is. So, if you're interested in a quick whirlwind tour of Ruby, that's what we're doing today. And I'd like to start with a story. I think a story is a great way to begin a podcast. When I was in ninth grade, I remember an essay assignment I was given. And I remember because I had no idea what to say. [laughs] And I think we were studying Romeo and Juliet, and we were supposed to write some essay about love. And I don't even remember what exactly about love we were supposed to say, but we were supposed to write something about love.
And I remember that I thought about it, and I didn't know what to do. So, I wrote some sort of silliness about how love is poorly defined and lots of people see it differently. And I spent all of my time talking about the question rather than actually answering it. It was probably a pretty lousy essay [laughs]. I probably wouldn't even remember it. I think I stumbled upon it some years later, and I read through that [laughs].
But, you know, I had this question. At that age, I really wasn't sure. I didn't know how to define love very well. And there are a lot of different answers to that in the world. Well, there's one very interesting answer to that question. The Ruby programming language was created by a guy named...I'll try to pronounce his name right. It's Yukihiro Matsumoto, and he's lovingly referred to by the community as just Matz. They shortened his name to just Matz. And he's very much beloved by the community.
He has said on more than one occasion that the Ruby language is love, and that says a lot about what the Ruby language is. And I'm going to talk a little bit more about the history [laughs]. But the Ruby language was created to be an embodiment of that idea of, you know, I care about you. I want to make your life better.
The Ruby language is built on ethos. And, in fact, there's a saying within the community, "Matz is nice, and so we are nice," MINASWAN [laughs]. The creator is nice. He wants to be nice to us. He tries to be nice to us. He reaches out with his language and also just his demeanor. If you've ever seen him speak, he's just a soft-spoken, super nice guy. And the language reflects that aspect of Matz, the creator.
If there's kind of one thing you leave with about what Ruby is, it is this language that's supposed to make you feel good [laughs] and then lift you up as a person. And, hey, well, a programming language does that? Well, it's kind of its goal. Different programming languages have different goals. Some languages have been intended to be very high-performing. They're really good at running fast, and that's a great goal, right? We should have some languages to do that.
Other languages take a particular idea, like being functional, and take it to its extreme. What would happen if we made a purely functional language? And I'm thinking about Haskell here. But there's some other languages that go that direction. Other languages focus maybe on type safety or on whatever particular problem they have at the time.
Well, Ruby focuses on developer happiness. It's a language that was designed from the beginning to try to make developers happy so that if you're a software engineer and you use this language, it makes your day a little better. And that's what Ruby is about, as opposed to other languages. It doesn't mean the other languages are bad. In fact, Ruby is not written in Ruby; most implementations of it are not anyway [laughs]. Ruby is written primarily in C, which is one of those high-performing languages. So, every language has its purpose. But Ruby is intended to make your life happier as a developer. Did Matz succeed? [laughs] Do you feel loved?
EDDY: I'm curious about the time why the name Ruby was given. Was it just because it signified or represented love at the time, or is there some sort of correlation with the name and happiness?
MIKE: That's a good question. The one thing that I have heard about Ruby is Matz was inspired by Perl, which is another precious stone [chuckles]. And he came up with Ruby to kind of mimic that idea and [inaudible 05:08] Ruby is following kind of a similar niche, where it's an effective scripting language, easy to use. And it may be that Ruby references some of that a lot, you know, it's this red stone. And it's kind of heart-shaped frequently in its cut.
So, I can't speak to that for sure. I don't know the answer. You'd have to ask Matz. I have not heard about that. If anybody knows, you know, please speak up. But I was having the same thoughts as I was talking about it. Well, he says Ruby, the language, is love. That stone could represent love. And so, it [laughs] might actually be a symbol that's suggesting that gift he's trying to give back with. Have you felt the love when using Ruby?
EDDY: It's easy to pick up, I will say that. You take the layer of complexity of syntax out of the equation, and suddenly, you're one step closer to thinking as a programmer.
MIKE: Ruby is a language that's designed to read a lot like spoken language. That definitely changes the way you think [laughs]. Instead of trying to think like a machine, you think more like a person. Certainly, you do have to think somewhat like a machine for developers [laughs]. But the syntax fits a little more naturally to the way that humans speak.
Let's talk about that. Let's talk a little about the history and why that might be. So, Ruby, the first release—and I've looked this up—the first version of the Ruby programming language was released on the 21st of December 1995, so we're going on 30 years. It's been around for a long time. And Ruby was and certainly inspired by other programming languages. I'm going to try to quote Matz a bit [chuckles] in several ways.
But he said that he was inspired by several other languages. I'm going to point out three of them: Perl, Smalltalk, and Lisp. Perl is this kind of utility knife of a language. You use it for scripting. A lot of early websites...Perl isn't used as much for this anymore. But a lot of the early web applications were built in Perl because it's this really useful text processing language that was originally kind of used more for shell scripts but, well, for other text scripting scenarios like you have with a web app. So, Perl was a big inspiration for Ruby.
And Smalltalk–and I'm going to talk about that next; Smalltalk is a pure object-oriented language. It's not just a language. It's like an environment. You get, like, this Smalltalk environment you interact with, which was actually influential in a lot of other languages. Object-oriented coding has really taken off in the years since, but it was really experimental and new when Smalltalk came out.
And the thinking that everything could be an object was kind of a radical departure from some of the ways other languages think about things, and Ruby embraces that. In Ruby, everything is an object, and when I say everything, I mean everything. An integer is an object. You can call functions on an integer. A string is an object. You can call functions on a string. There are no true primitives in the way that a lot of other languages have. Well, here's the, like, when you think about Java, you have primitives that you don't call things on. They're a different thing from everything else. In Ruby, that's not the case. Everything is an object, kind of taking that Smalltalk inspiration.
And the other language that I'm going to call out is that Lisp, which is a very functional language, kind of the archetypical functional language that other functional languages have drawn from. In functional languages, you think about everything as a function, you know, the unit in functional languages is the function. In object-oriented languages, you think about...you structure your modules with objects, right? And your object is your unit. You have classes, and you build objects from those. Well, functional programming thinks about things a little differently. It groups things in functions, [inaudible 08:47] that objects don't have functions. But when you're thinking about kind of the primary organizational idea in functional languages is functions, and Ruby embraced that from Lisp.
In Ruby, every expression has a return value, which means that you can write anything that could reasonably evaluate as an expression in Ruby, and it has a meaningful return value. If you write the number one, you can run a Ruby program with just the number one in it, and that is a valid Ruby program. In some other languages, that wouldn't make any sense, but in Ruby, that makes sense. It's an expression. It's the number one. It has a return value of one. [inaudible 09:23] doing something, right? It's expressing this number, and it even has a return value.
And that changes the way you think about things, this idea that comes from functional programming where everything is an expression. Everything has an implicit return value because that expression evaluates to some value. And that idea is deeply embedded in Ruby as well. Not only is it object-oriented, where everything is an object, everything is also an expression, which implicitly has a return value, which means you could think about every expression as somewhat implicitly being a function as well. It also leans heavily into the idea of anonymous functions, but I'm going to hold off on that for a little bit and go back to this idea of its creation.
So, I want to give you a little history of Ruby. Ruby is this language that takes these big ideas of functional programming and object-oriented programming and smashes them together into a scripting language. And it gives you Ruby to try to make this tool that makes developers happy. Ruby was created in Japan. Matz is Japanese. He lives in Japan. I believe he still lives there [laughs]. And has developed there for a long time.
Because Ruby was originally in Japan and had documentation in Japanese, it became fairly popular in Japan. It became a popular programming language there because you could get documentation in Japanese. All of us like to be able to read things in our native tongue, so [laughs] it makes a lot of sense. So, it became kind of this niche language that was popular in Japan. Eventually, it started reaching out of Japan as other people discovered it. In particular, in the mid-2000s, there was a development team that decided that they would use Ruby to build a new web framework called Ruby on Rails.
And I believe that Ruby on Rails was—I'd have to go look this up—was released around 2005. It made a big splash in the web application community/web development community by its usage of convention over configuration [laughs]. At the time, most web development involved setting up lots of configuration files for everything. Anybody who did Java development back in the day, you know what I'm talking about [laughs], so many XML files.
The Ruby on Rails, this framework, cut through a lot of that and said, oh yeah, let's just do the obvious thing by default. You don't even have to configure it. And the object-relational mapper it had called Active Record, as a result, was really easy to use in a way a lot of other systems weren't. Now, other frameworks have borrowed a lot of those ideas. So, Ruby on Rails really isn't this path setter anymore. It's not in the vanguard because other frameworks have taken the same ideas, which is fantastic. Web development is better as a result.
But it meant that Ruby made a big splash and was heavily used by startups in the United States. You know, it had left Japan, still there in Japan, but it became heavily used throughout the world by largely web developers because of the Ruby on Rails framework. It's been somewhat in decline in recent years. Some other languages have become more prominent, but it's still got a thriving community behind it.
EDDY: Who did the transcribing for when it left Japan, do you know? Like, who did all the documentation translations and --?
MIKE: That's a great question. I don't personally know the answer to that. I know that Matz himself is, you know, bilingual. He speaks English [laughs]. Japanese is his primary language, but he knows English. He has spent some time in the United States, which I think has helped a lot [laughs], helped him to document things in more languages than one.
Let's talk a little bit more about the language then. We've talked a little bit about how Ruby is object-oriented all the way down. And it's also functional, deeply functional all the way down. So, I gave an example of how you can just write any expression. You could write a string or an integer. That's a valid Ruby program. Just put a string into a file; that is valid Ruby. It's not very useful [laughs], mind you. But you could run that as a Ruby file and give it a Ruby extension. You don't even need a Ruby extension. Call the Ruby interpreter, and it will be interpreted successfully and will run because every expression is valid Ruby that can be written in Ruby.
That has some side effects in that if you have a function written in Ruby, you rarely need explicit return values, and, in fact, most Rubyists don't use them. And this is common among functional languages, that the value of the final expression in the function is implicitly...because everything has a value, right? Every expression evaluates to a value. That is the return value of the function. So, to return something in Ruby, you just simply write the expression you want to be returned as the final line in your function.
And for those who've been using more procedural languages, that is weird. But I'm not going to tell it to return things [laughs]. But, in Ruby, it's not that way. Instead, you think about, well, what does this mean? Well, it's saying something. Well, that's what it's returning, the thing it said. You don't have to say, "Hey, this is the thing I want to say." It's already implied because I've already said it. And that idea, going back to this idea of convention over configuration, kind of goes all the way down. Everything is an expression.
I'll take that a little bit further. Ruby does not require parentheses in function calls. So, you can call functions without using parentheses; just put some spaces in there. [inaudible 14:30] put commas between your parameters. That means in cases where you have a function that doesn't take any parameters, it's indistinguishable. If you don't put parentheses, it's indistinguishable from another expression. And that can feel kind of weird if you want to be able to tell the difference. Ruby actually kind of leans into that; some Ruby actually kind of leans into that.
So, when you're reading the code, you don't have to know if a given line is an expression or a function because it's kind of both. And it allows you to build out domain-specific languages; that is, you can write out code that looks more like configuration than it does, like, a traditional programming language. And you can write out little sub-languages within Ruby that look very much like their own language where some of these things that look like keywords are really just function calls. But they appear to be a keyword because you don't need the parentheses. It makes for some very legible tools; tools such as RSpec, a popular testing framework in Ruby are built in that way.
One other thing about Ruby is that there is...I want to be careful how I say this. It is implicitly typed. We do not use explicit typing in Ruby. So, if I set a variable equal to an integer, I never had to declare that that variable was an integer. However, I can't then go and add that integer to a string. That doesn't make sense. So, it is strong typed in that there's not implicit casting; rather, everything is typed. It's just implicitly typed.
That also allows you to do some really cool stuff. Unlike in other languages where you might need to write five different copies of a function to take five different types of incoming parameters, you can just write a single method signature that can take the incoming parameter and expect the incoming parameter to be an object. In fact, that's how Ruby expects things to work.
Since everything is an object, you can pass an object into anything, and they handle the type later. It allows for really clean calling syntax. If for some reason I did want to add a string to an integer, I could write code to do that and make it very transparent. I could make it very transparent so that other people didn't have to know about it. It would just work within my program. I'm not saying that's a good idea, mind you [laughs]. But if you had some need where you needed to add two of your own kinds of objects that were neither integers nor strings, you use a plus sign. It's easy to just define that method to do so and put them together.
I can take this a little bit further. And this is both a strength and a weakness. Ruby leans into what we call duck typing. That is, if it walks like a duck, talks like a duck, quacks like a duck, it must be a duck [laughs]. And so, what you see commonly in Ruby code is that you don't have a lot of validation on parameters that get passed into functions. You kind of expect the callers to do the right thing.
So, if something meets the requirements of what your function needs, you're not going to ask about its type and, instead, you're just going to assume that they gave you what you needed. In other languages, you might use some templating features built into the language. Ruby, you don't need to do that. It's kind of implicitly a template. We're just going to assume that you're going to do the right thing.
And, of course, if you want to do validation, you're more than welcome to do so, but you need to be explicit about it, and it's not going to be built into the language. Again, this is a strength and a weakness. It means that you can have very easy refactoring of your code where you can pass in a different kind of object to a function, and it'll still work.
On the flip side, you don't get some of the type safety guarantees that you get in strongly typed languages that put a lot of validation on type. And it means you get different kinds of bugs. It means your code tends to be a lot shorter…a lot easier to reason about in Ruby. However, you can get some type safety bugs that you would not get in other languages because I think it's a big thing to notice.
This wading into, hey, you know, everything's an object; you can pass anything anywhere; it allows you to write code that's just amazing, legible, and terse, and easy to refactor. It also means that you can end up with subtle bugs sometimes because type safety bugs are hard to face. I'm not saying that it's a showstopper. But depending on your domain, you know, some people would argue that's a serious problem.
And there actually are several different tools within the Ruby community for dealing with this, for adding type, some that add type within the language, and some that add it by adding an additional file. It's kind of experimental, but you can add a type file adjacent, you know, kind of next to your Ruby file to add typing to it. So, you can get some of that type safety you get from other languages.
RAMSES: Yeah. There's tools like Sorbet that provides the type checking, which is very interesting.
MIKE: And for large companies, like, Sorbet came...did that come out of Shopify? I'm trying to remember --
RAMSES: Yeah, yeah, I believe so.
MIKE: I believe so, too. They built this tool because they wanted to have the best of both worlds. They wanted the expressiveness and ease of use of Ruby but still have the type safety. So, they've built some tooling to provide that. So, there's tools available to give you the type safety that you'd like to have in Ruby, if that's something that's important to your use case. And I think that it's important to a lot of use cases, something that I actually encourage leaning into in a new Ruby project. It avoids certain kinds of bugs and allows you to be explicit about what you intended to happen.
The next thing I'd like to talk about that Ruby does...we talked about everything is an object. We talked [laughs] about some of the things it does, getting those advantages of being truly purely object-oriented where everything is an object. Actually, I'm going to talk a little bit more about that. [inaudible 20:06] everything is an object. It also has some sort of class, you know, that prototype that you use to define it. And you do not have to completely define that class before your code runs. It can be written at runtime. It also means that you can reopen classes and start adding functions to them or even change their behavior at runtime.
Coming back to this Lisp idea [chuckles], I mentioned Lisp before as one of the inspirations for Ruby. In Lisp, you can rewrite the program. The program can write itself as it runs. And that's a really weird idea when you first hear about it. We actually do it all the time in Ruby. We have code that writes code.
I mentioned the Object Relational Mapper in Ruby on Rails, ActiveRecord. It accomplishes a lot of what it does by what people call magic, but not exactly magic. It just uses Ruby's features to go in and look at your database, check out the table name, and figure out where the columns are, and let's go ahead and write some functions. Go ahead and write some functions at runtime into your class to be accessors to those column names within a record.
And so, rather than having to explicitly define something that's already there, it can just look it up and generate it on the fly. You're not usually going to do that in your code, but for a framework, that's amazing. It means that a lot of the configuration...if something is discoverable in the world, the code can write itself. It can go out and write methods at runtime that didn't have to be conceived of [laughs] by the people who wrote the framework. They just had to write code that's able to do that perception of the outside world and deal with it accordingly.
It's amazingly powerful. And it's one of the strongest aspects of the Ruby on Rails framework because it allows it to be very terse and very easy to understand. So, it's a practical use, right? Why would a code want to write code? Well, it's because you don't necessarily know, when you're writing a framework, what code you're going to be working with. And you don't want to have to explicitly say all those things because it's discoverable. So, code that can discover some things about the world around itself and write new code within itself to deal with those things is actually incredibly useful.
Listeners can probably think, oh yeah, well, what's some things I could discover? Well, maybe you're working with some web service that tells you about the weather. Well, you could have code that goes and pulls that and figures out what fields are available and then creates functions to tell you. And then, again, while running live, it could do some self-analysis, some reflection on itself to determine what things are available, to determine what could be printed out to a screen.
It's a different way of thinking about things than thinking about things as just text processing. It leans into this idea of, well, this is an object, and I can learn some things about this object and use that for display. And this is just an idea popped up with-it might not even be a good one—off the top of my head. But it allows you to think about the world differently, think about the ability to create objects that represent the world on the fly that you didn't know about when your program launched. That's a level of usability that is really great [laughs]. And it may feel weird when you first hear about it, but it ends up being exceptionally useful.
The next feature I'd like to mention about Ruby that I think is maybe the most idiomatic of all of the Ruby features, and I've mentioned some things that are very Ruby-ish, but there's one that's the most Ruby-ish of all Ruby things, which is that Matz built-in language support with special syntax for anonymous functions. And that is fundamental to your development as a Rubyist.
We've talked a lot about the object-oriented features. Now, we're going to talk about some of the functional features. Again, Ruby has a built-in syntax with special scoping rules for anonymous functions. They call those anonymous functions blocks. And people who've started using Ruby might not even think about it that way. Like, a block is a function? Well, yeah, it's a function [laughs]. It's a section of code that takes parameters and can execute those parameters. Yeah, that's a function. And that's how Matz talks about them. He designed blocks to be anonymous functions in the Ruby language.
But, again, they have special scoping rules. These anonymous functions have special scoping rules such that their return semantics will return from the surrounding explicit function. So, if you have a function with this anonymous function inside, the anonymous function will return from the wrapping function rather than from itself if you have an explicit return statement. That allows you to not have to worry about defining it as a..., and this is a fundamental difference between Ruby blocks and anonymous functions in other languages.
You can return from a Ruby block and return from the enclosing function rather than just returning from itself and then having to figure out what to do. It allows you to build lots of these little lightweight functions throughout your code and not have to worry about handling the return values and then passing them up and then handling a return value and passing them up. Because they'll do just kind of what you expect. Again, Ruby is about trying to make things friendly. It pretty much does what you expect.
It also means that these anonymous functions are used ubiquitously within Ruby to the point that Ruby almost never uses looping constructs. I say almost never, occasionally, you'll see a loop. Maybe you'll see a while loop that runs forever in some sort of, like, web service listener where something really should run forever. So, infinite loops are actually more common in Ruby than non-infinite loops if it's done explicitly. Because, in most cases, when you have something that can be enumerated over, that is you can step through a thing, you'll just pass an anonymous function to it. You'll pass one of these Ruby blocks. Give a block to it.
And instead of having all of the bug-prone, hard-to-understand syntax issues that you get around for loops, or while loops, and maintaining a loop counter, all that just goes away because Ruby is built in containers like arrays, and what's called a lot of different things in a lot of different languages: an associative array, or a dictionary, or a map. Ruby calls it hash. Those are all the same thing. Ruby just happens to call them hashes. I'm talking about kind of the implementation behind it. So, an array, a hash, or a dictionary, whatever you want to call it, and those are, of course, the primary ones.
But there's some other subtypes of those like sets. You can enumerate over those by just passing an anonymous function to it. There is an array in each method. And there is an integer or a times method. You can do three dot times, pass it a block, and it'll run that block three times. It's a revelation for those of you who [inaudible 26:24] in other languages before you came to Ruby [laughs]. It's like, what? I can do that? [laughs] Yes, you can. Yes, you can.
Like I said, this is the most Ruby-ish thing that you can do in Ruby is you pass these anonymous functions to anything. And because of the nice scoping rules and these are a function, you can do some really nice setup and tear down. So, if, for example, you wanted to set up a connection to some remote service, do something, and then tear down that connection, well, that's great because you can have that in the function, right? You can build that into a function that will do all the setup and tear down and then just run the function that they passed in, in between.
It allows you to really wrap any piece of code in some setup and tear down and execute that code inside of it. Of course, you can do that in different contexts as well, but being able to pass the function in is just really convenient. In other languages, you do it all the time. If you look at JavaScript, it uses functions, anonymous functions everywhere. But it doesn't have the advantage of the friendly return context that Ruby has where you have to do lots of kind of weird binding sometimes in JavaScript to get the right returning values and get it to return the right thing [laughs] from the right place, where Ruby just kind of does what you'd expect, which is really convenient.
Anybody who's listening to this and you're not looking at the code, you're like, "Huh, well, what do I make of this?" Well, go look at some Ruby code [laughs]. And those of you who've been Rubyists for a little while, this may be the most; for me, it was really illuminating. Well, people are telling me about these blocks. This is weird syntax. What is this? Well, it's just an anonymous function. It's an anonymous function with special return semantics. And that allows you to just call this section of code, hand off this section of code to another section of code.
And it's really, really useful to be able to hand a section code to another section of code. That idea comes from other languages. Of course, it's not unique to Ruby. These are inspired some, again, by Lisp and macros and by...anonymous function [inaudible 28:19] other languages, but Ruby really leans into it. It means a for loop will almost never be found. I can't remember the last time I saw a for loop in Ruby. They just don't use them because you don't need them.
In fact, I can't really think of the last time I saw much of an explicit looping structure at all because you think about it functionally. You call map. You call reduce. When you think about your code, it's a series of change and transformations, much as the functional language people do. And I think it's a very effective and less error-prone way to write code.
DOM: You're talking about, like, enumerables and being able to iterate through things. And I actually remember, Mike, it was when you first interviewed me, like, two summers ago. You blew my mind. You were like, "You will never ever see a for loop in any of our codebase, like, at all whatsoever." And I was like, that's not physically possible. Everything I've ever done in my entire –-
MIKE: [laughs]
DOM: Software engineering career has included a for loop. It was awesome to see that you can use these block statements, and they're just so powerful. There's so much you can do to just information while you're running with them. And coming from a language like Java, it was a happy surprise. I was super stoked that I could do dot each and dot map and not have to worry about writing for int i, i is less than counter, i plus plus, you know, all that stuff.
MIKE: And was I right? Have you encountered any for loops in our code?
DOM: No, no. I have not.
MIKE: [laughs]
DOM: And I have adapted the map mentality, never using each ever again.
MIKE: Yeah. --
EDDY: That is an interesting observation. I've never actually noticed that we didn't use [inaudible 29:56] [laughs] in our codebase. I actually wanted to fact-check that really quick. And I went through my IDE, and I wanted to make sure I did global search before. Well, it did pull up some results, but it was just comments [laughter]. Nothing explicitly calling, like, for action on something, which is a really interesting observation I haven't noticed.
MIKE: It makes a big deal into the way you write your code. One thing that has happened in the evolution of programming languages for years is that we try to hand more and more off to the language instead of doing something yourself. We [inaudible 30:31] compilers to figure out the machine language so that we don't have to write the zeros and ones [chuckles] because we want to think about it at a higher level. And we don't use assembly language much anymore in most contexts unless you're maybe writing some sort of embedded software, writing device drivers, or something.
You write code that thinks at a higher level and then compiles down to that assembly language. Because, honestly, a compiler does a better job of thinking about problems than you do. Because there's been generations of smart people who've been improving those compilers to think about how to solve problems. And in almost all cases, they're going to solve the problem better than you can. And, likewise, now we've got interpreted languages. And there's a range of popular interpreted languages today: Python, JavaScript, Ruby, for example.
And if you let the language do the work, you're going to have fewer bugs, and your code is probably going to perform better. If you're writing the loop yourself, you might do it wrong. If you let the language do it, the language is going to get it right. Let the language do it. If there's one thing you take away from this, let the language do the work. If you're doing it yourself, you're doing it the wrong way. The people who designed the tool...if you think you can do it better, you're probably not right.
There's a lot of people who've been thinking about how to solve this problem within the language you're using, whatever that language is, and the language will probably do it better than you can because it's been designed to. It's been designed to. We shouldn't do the looping. We should let the language do the looping. This is a very functional way to think about things [chuckles]. Functional languages very much lean into this. You shouldn't be doing the looping yourself; let the language do it. Because it lets you think about what the problem is, rather than how you're going to solve the problem.
Well, here's the problem; I want to go through each of these things. Well, let the language go through each of the things. Don't do it yourself. As Dom was saying, use map [laughs], you know, tell the language to return a value from each one of these things that you can enumerate over. Don't do each where you're going to explicitly go through and figure what we're doing for each one. Usually, what you want is to transform a set of things into another set of things. And thinking about the code in terms of that transformation is transformational in the way you think about the problem.
EDDY: I do want to add more to sort of, like, the scope of what Ruby can be used for. When I first started, I initially thought, oh yeah, Ruby, you can do it for web development. And that's what is its intention, and that's what its functionality is for. We did a Skill Clinic project a few months back, going a little bit over a year, where we wrote a service purely on Ruby, right? To go ahead and do some of our assignments, you know, for pull requests.
And that really kind of dawned on me, right? Like, Ruby is a lot more dynamic than just web development, right? I mean, granted, you can do web development, like, but it can do, like, web servers, like, data processing, scraping, et cetera. So, it's [chuckles] much more broad than just web development. And I think that's something, for me anyways, that was a little bit of an epiphany when I realized just how dynamic it can be.
MIKE: Yeah, and it's used a lot as a shell scripting language like Perl. We've been talking a lot about web development because, again, that Rails framework. But there's a lot of shell scripting that goes on in Ruby as well. And some popular DevOps frameworks are written in Ruby; kind of think of it as the new Perl [chuckles]. Perl is still around, by the way. And it's an interesting language, if anybody's curious; not as popular as it once was, but still an interesting language. So, we've done kind of a whirlwind tour here.
SERGIO: Yeah, I just wondering why Ruby the popularity has been declining by the years, for example, in comparison with Python [laughs]. I don't know why. Because all the people say that it's because of its slowness, but no, I don't think so. Because many of the company has been using Ruby for a long time. So yeah, I don't know why.
MIKE: Yeah. No, honestly, I think Ruby sometimes outperforms Python, but they are kind of sibling languages. They're languages that fill a very similar role. Python happened to catch on within the machine learning community, which is, like, rocket fuel in the last few years [laughs]. And, really, I think that's it. Python happened to catch on really well within the machine-learning community, which has caused it to explode in popularity. And JavaScript is another interpreted language that's simpler than either Ruby or Python, and yeah, that's got pros and cons, right? [chuckles]
SERGIO: [inaudible 34:50]
MIKE: Simple is good in some ways and not as capable in other ways. But, JavaScript, you have to learn to do web development. So, everybody who has written any front-end code has to learn JavaScript.
So, when JavaScript became available on the server side, a lot of people said, "Well, why should I learn more than one language? I'll just go with one language." So, JavaScript, in some ways, has become...has filled a lot of a similar role as well. So, I don't know that it's so much that Ruby has failed anyway. It continues to be a popular language. But there are other languages that fill in the same niche, you know, they kind of do the same thing that are popular for other reasons. And that's great. Again, I'm not criticizing JavaScript or Python. I think that they're both very useful within their areas as well.
EDDY: I feel like there is a bit of a stigma behind scalability with Ruby, probably with Ruby on Rails as a whole. But I think the reason to why a lot of us get the impression, well, I'm speaking for myself, is that a huge factor to that was when Twitter decided, hey, it is not scalable. Let's switch away from Ruby on Rails and use a different framework, right? So, for me, that sort of just keeps ringing, right? I'm like, huh, yeah, no, maybe it's good for a quick startup, you know, but not necessarily scalable. And I've realized that that's not true [laughs].
MIKE: Well, I've read about this, I read a really interesting article about this many years ago, so I couldn't tell you where it is, about Twitter specifically. Twitter was originally using MySQL or MySQL, or whatever you want to call it, the database as a router for messages. And that didn't scale. And that's not speaking anything wrong about the database or about the engineers who built the application. It was a good way to do things initially, but that didn't scale as they grew because it wasn't the purpose of the database. The database is not intended to be like a telephony switch. It's not a telecommunications tool. And at scale, because that's not what it's designed for, the intense levels of reads and writes just didn't work.
And so, they decided to build their own layer to handle [inaudible 36:48] messaging and all the kinds of caching that go on top of it. And to do that, they did want to have something that was high-performing. And it made sense not to write that in Ruby, right? To use that using a very high-performing language. I believe they did it in Scala, didn't they? Scala, Scala, however, you pronounce it. And which was a kind of a preferred tool of the developer who did it.
And I don't object to any of those decisions. But none of that has anything to do with the scalability of Ruby at all, right? Ruby worked great for handling the web front end. But I wouldn't want to use Ruby to do something, you know, some high-performance computing. I'm not going to use Ruby to program a supercomputer because that's not what it's designed for.
You probably do want once you reach the kind of scale that formerly Twitter, now X, was [inaudible 37:33]. You're going to have to optimize certain parts of your stack. That is advisable regardless of the language that you're using. So, I think we had a lot of those claims. There was kind of some talk around that at the time that Twitter [inaudible 37:48] that I think was just really misleading.
And [laughs] if it didn't work, then why are big companies like Shopify and GitHub still using Ruby? Obviously, it works for large companies. That's not really where the concern was, but rather, they just had specific business needs. And really, yeah, they shouldn't be using Ruby for what those specific business needs were or really any language x, right? [laughs] Use the right tool for the job. Whether that'd have been Java, or JavaScript, or Python, anybody who reached that scale would probably have changed languages for that portion of their code, and rightly so.
In fact, the machine learning aspects, like the deep, nitty-gritty stuff that goes on in Python, isn't written in Python either. It's written in some variant of C, C++. The lower-level tools are not written in Python. But just like in Ruby, you can have extensions in other languages. Python does the same thing.
If I can go back to where I was at, we've been through this whirlwind tour [laughs] of talking about this language. And, of course, this is a podcast. You're listening to it. You can't see the code. I hope that if you haven't done Ruby, it's given you a taste of what Ruby does and what it's about, and, hopefully, some of why it might be really friendly to developers, why your developer happiness might be increased using that language.
You can think about things functionally. You don't have to do a lot of things that you would do in other languages, like working around the limitations of integers, of primitives, or having to do all the looping yourself. You can really think about problems in a way that maps well to natural language because it's designed to think more like humans do.
I love Ruby. I have done Ruby now for a long time, close to 20 years. And I've loved it. Again, there's no perfect tool. But I have been very grateful. Matz, if you ever happen to listen to this podcast, thank you. Thank you for your active love toward us in the development community.
EDDY: You know, I actually wanted to retort a bit earlier in the podcast and say, oh, yeah, it's developer happiness, and that's true. Until you have a nasty bug that you can't find for the whole day [laughter].
SERGIO: But you can find the same issue in whatever language, you know. So, it's in the language the issue.
MIKE: Yeah. And there are people who've complained about Ruby because it makes some things too easy, some of that magic [laughs].
SERGIO: Yeah, yeah, I heard that before.
MIKE: That you can't find anywhere [laughs]. It's really hard to find because it doesn't exist. So, there are some things that are absolutely harder to find because of that, and we've got to deal with that. So, there's a mindset issue here [chuckles] that you need to learn to think about problems in a different way, and that requires a different set of tools. It's a good call out. Thank you.
I hope that if you're curious, you do go give Ruby a chance. It's a great language. And if not, if Ruby isn't your language, that you've learned some things, to think about problems a little bit differently, and you can use some of the strengths of Ruby in whatever language you are writing. With that, until next time on the Acima Development podcast.
The panelists discuss the nature of debugging in software development. What even is a bug? Various perspectives are shared, highlighting that bugs often result from unexpected behavior in software despite the software doing exactly what it was programmed to do. Sometimes bugs, sometimes seen as errors, can become features or lead to new insights.
The discussion shifts to more philosophical and methodological aspects of debugging. It's pointed out that encountering bugs in software implies a need for more understanding of the program or the problem it solves. This realization opens avenues for deeper exploration and learning rather than fixing a fault. The role of testing in avoiding bugs is emphasized, particularly the importance of understanding and aligning with user expectations. The group also touches on the evolution of debugging techniques over time, moving from simple console printouts to more sophisticated methods but still acknowledging the effectiveness of basic approaches in specific scenarios.
Additionally, they talk about the complexities of debugging in a modern, service-based architecture, where bugs might involve multiple services and systems. Strategies like dividing the problem space, creating narratives or models to understand the issue, and ensuring environmental consistency are discussed, and the conversation ends with a focus on the human aspect of debugging, including the necessity of taking breaks, the value of teamwork and peer review, and recognizing one's own cognitive limitations during the debugging process.
Transcript:
DAVID: Hello, and welcome to the Acima developer podcast. I'm David Brady, and we are going to talk about debugging today. And we put out the call that we're going to talk about debugging, and we got quite a quorum. So, it's exciting. We've got just a whole pile of people on. When you jump in the call, just tell us who you are, and we'll just go from there. Debugging, why?
TAD: Well, should we even get more simple than that?
DAVID: Sure.
TAD: What exactly is a bug? What would you call --
DAVID: Okay, yeah.
TAD: Is it bad values? Is it bad process? Is it bad behavior? Like --
EDDY: I would like to premise that bugs, historically, have led to some really good features.
DAVID: Minor trivia bit: the very first bug was an actual bug. Google that if you want. Grace Hopper fished an actual moth out of one of the relays, one of the very first computers. And there's a picture of it online. She taped it in her journal and saved it for posterity.
MIKE: Well, that says something about what a bug is, though. She went and pulled that out of the relay because there was unexpected behavior.
DAVID: Yes.
MIKE: [laughs] And the software does exactly what we tell it to do. The problem is sometimes that doesn't match our expectations. And that can be a minor inconvenience, or a neutral, even a positive thing, or it can be catastrophic [laughs]. I worked at a plant nursery many years ago. And my boss asked me, "What's a weed?" And I tried to give some explanation. And he says, "A weed is any plant that's growing where you don't want it." Bugs is kind of the same thing. I think it's unexpected behavior.
DAVID: One of the best things that somebody told me really early on in my career is kind of an intellectual ego check. He said, "Whenever you have a defect in your software or a bug in your software, it means you don't understand your program." And I'm like, "But yes, I do," oh, no, I don't. Provably, I do not because I think it will do this, and the computer is doing something else.
And that kind of opens you up to the wonder and puts you in a positive frame of mind of like, well, I need to figure out why this is doing this, rather than, like, I'm dumb, or the computer is dumb. Just like, okay, I wanted this, but I got that. Let's figure out why.
MATT: And that could also mean that you don't understand the problem that you're trying to solve.
DAVID: Or the solution, right? You don't understand the solution you're trying to do.
TAD: I thought it was really interesting...last week, David and I wrote some code together, and we put it in production. And they had us pull it back out. And some of the people in management are like, "Well, you should have tested it better." And the thing is, we had written a bunch of tests for it, and the behavior was exactly what we thought the behavior should be.
But when we put that in production, the people who were using it were like, "Wait, this isn't what I wanted. This wasn't what I expected." This wasn't [laughs]...like, the tests proved that the behavior was exactly what we thought it should be. But it was unintended, unexpected behavior by the end user. And so, technically, is that a bug? I guess if it's unintended behavior, and it's from somebody's perspective that's using it.
MATT: And maybe we can talk about how do we prevent these bugs, right? I think it starts with a clear understanding of requirements, a clear definition of requirements, and testing, too, those requirements. Because a lot of times in software, the business side will have a lot different expectation than we do on the engineering side of what should happen, right? And I think if you can clearly define those things, then we run into fewer, what we call, bugs.
DAVID: That's an interesting definition. One of the early things that we talked about when unit testing was getting popular in the early days of XP, so, like, we're talking, like, Y2K, like, 20 years ago, they mentioned that one of the great things about a unit test is that it restates the problem or, you know, it kind of describes the behavior at a higher level.
And it gives you this ability to go to, like, the end user and say, "Is this not what you wanted it to do? Because if this is what you wanted it to do, I've got green dots. I can prove that it does this. But this is that, right?" It's like, "No, that's not what I wanted it to do. I wanted this other thing."
MATT: Yeah. You know, many, many, many moons ago, before all of these testing frameworks existed, we were writing code based on our expectations, right? The early days, old PHP days, Perl days, those are the languages I was in primarily, you know, 20-plus years ago. We were creating our expected behavior, and it was really hard to meet the needs of the requester because there was no clear test case to prove that you're meeting those needs. So, you run into a lot of unintended consequences and a lot of downstream problems.
JUSTIN: One of the things I've seen as well in my career was, initially, I was programming to meet the requirements. And then, I was programming to meet the requirements, assuming that the customer is an idiot. And now I'm programming to assume that the customer is malevolent. So, it goes along to, you know, really define what your requirements are and what your limits are.
DAVID: You've moved from programming Murphy's computer to programming Satan's computer, right?
JUSTIN: [laughs]
DAVID: The actual quote from a security talk I went to a while ago which is that Murphy's computer, anything that can go wrong, will go wrong. Satan's computer, everything that can go wrong will go wrong, at the same time, at the worst possible moment because that's what an attacker will engineer, right?
MATT: That being said, what happens when we introduce a bug? How do we track them down? What tools are we using to find them? And what is everyone doing? Because I imagine everyone in this room and on this call uses some different techniques.
MIKE: Can I say something here on this one? In some groups, I'm an outlier; in some groups, I'm not. Early in my software development career, I learned to be kind of shy of debuggers because they sometimes got in my way [laughs]. You know, they're great when they work, and other times, they're slow, and they break. And then, you could spend a lot of time wrestling with the tool rather than solving the problem.
So, almost all of my career, I may print out a line to the console debugger more than anything else. I'll go in my code, have it print something out. It works in every language. You can have a consistent process that you just know what to expect. You can get good at it. You can get it to print something out. You run the code. You exercise it. You know that you're exercising that code because you get something printed out. You get good at filtering through logs. It's a really straightforward process that anybody can do.
I don't want to say that debuggers can't be useful, and sometimes they can be really useful. I might have used, like, a C debugger to debug Ruby to try to get down to some really gnarly stuff before, but I do that very, very rarely. And I find that just printing out stuff to the console is extremely effective. Because, for me, the most important thing I'm wanting to do when I'm debugging is figure out what's going on somewhere. If the bug is something that's unexpected, then there's something in there that I don't understand.
And so, I want to document, you know, to have some documentation thrown out from the code saying, "This is what's going on here," so I can figure out where my expectations are not being met. And I think that we'll probably talk about more sophisticated tools than that. But I think that kind of helps set the stage for further conversation is that what we're really trying to do is figure out what's going on. And simple tools, honestly, I've been doing this for a long time, and they've served me very well.
MATT: Seeing your output, right? Because, generally, that's the bug is you're getting output that is unexpected. And just seeing the output as you step through your methods or your classes it's powerful. And that's generally how I track them down as well.
TAD: Some of the hardest bugs I've ever had have been bugs with, like, timing issues, where the IO of a put statement or a print statement throws off the timing. And so, putting print statements in fixes the problem, and taking the print statements out reintroduces the problem.
MATT: Nice.
DAVID: Nice, a wicked Heisenberg.
EDDY: What's a Heisenberg?
DAVID: Oh, sorry --
MIKE: Ooh, you're learning a beautiful, new word [laughs].
DAVID: Yes. So, it's a corruption of the Heisenberg Principle, which is that at the quantum level, you cannot observe a thing without changing it because the act of bouncing a photon off of an electron moves the electron, right? You can't observe something, so... And so, yeah, Heisenberg is a bug that when you look at it, it changes, or it goes away.
My favorite demonstration of this is some code, and you're teaching somebody to step through it in the debugger. So, you write a loop. It's like ten times do, and then you seed the random number generator with time dot now. And then you say, print, you know, puts, you know, rand, and it puts rand 10, right? And so, you run it, and you step through it in the debugger, step, step, step, three, step, step, step, five, step, step, step nine, right?
And then you take out the debugger, and you run it, and you get 7777777. It's all sevens. And you're like, what? Time dot now returns time down to the second. If your entire program runs inside one second, you're seeding the random number [inaudible 09:24]. But if you're standing there going, 'next instruction' in the debugger, you're burning down the clock. And that changes the state of the time input.
EDDY: So, it's actually really interesting. Mike, you mentioned...you said that you, early in your career, you printed stuff out, right? Do you actively use that as part of your go-to resource in order to debug something, or has that –-
MIKE: It's almost my exclusive resource still, after decades. [crosstalk 09:50]
JUSTIN: So, when you print stuff out, at what logging level are you printing it out?
MIKE: Oh, good question. So, guys, nothing against using log levels, right? Using a logger saying...my default, it depends [laughs]. It depends. If I'm in a local environment, I'll probably use debug. That way, it's harmless if it actually went into production [laughs] because production doesn't have debug turned on. It's a nice little safety thing.
JUSTIN: I'd like to push back on that just a little bit because I have seen releases to production with the debug turned on because it didn't understand which environment it was in. And that resulted in passwords being [laughs] put out in the logs.
MIKE: Oooh.
DAVID: Oooh.
JUSTIN: So, that was a fun time. But I think that even if you are debugging or you're doing a debug log level, you shouldn't ever debug with PII data. And so, either mask that or log something else that will help you debug. That's my only advice there, so...
MATT: And for context, to our listeners who are not going to visually see this, that was Justin who was just speaking. And he is on the Acima security team. [laughter]
JUSTIN: Yes.
DAVID: You guys are actually implicitly talking about something that I think is really, really interesting. I will debug with puts statement. I won't even use logger.debug. I'll use puts.
MIKE: I do, too.
DAVID: It's sloppy. It works great from localhost. And we have a code quality checker that will say, "Don't use puts; use logger." I'm like, no. What I want is to delete this, right?
MIKE: Exactly.
DAVID: But I don't --
MIKE: That's actually what I usually do as well, too [laughs].
MATT: I do the same. I use Awesome Print because it formats for me and makes things look a little nicer.
DAVID: Oooh. Awesome Print is a tool I haven't looked at. That, I'll have to check that one out.
EDDY: Can you explain what Awesome Print is? When you're done, Dave.
DAVID: Yes. I was just going to say the converse is that if I'm running something on preflight, I don't have access to the IO console, or if I'm...well, in production. This week, I got access to preflight, so I can see things that go to the console there. But, like, in production, I don't have that. So, going to a logger is really good.
But you know what also falls down in production? Is running the debugger because I can't stop the server, you know, remotely. I mean, I can. Right now, I can. Justin would stop me if I did, at least in production. But, like, that's a bad idea, right? Bringing down the entire website just so you can debug something in one thread, probably a bad idea. So, there's trade-offs here. It's fantastic. Eddy, you were asking about Awesome Print. Matt, tell us about Awesome Print.
MATT: It's a Ruby thing. It's a gem. It will just output to your console, but it formats for you. It'll color-code hashes, you know, just make things really readable and legible. I use it every single day, and that's my go-to usually. Second would probably be Pry. But I also still do some really old-school techniques, and that is just tail dash f my development log, and that way, I can see live output.
DAVID: There's a lovely thing...we got to see if we can track down Charity Majors see if she would come on. She loves talking on and on and on about observability. And she works at a company that does logging and metrics, and so she's all about that. But when you talk to somebody about this, you start realizing that's all debugging really is, right? Is we've got all these questions, like, what's going on, and how can I look into this? Where can I get some observability into my data, or pretty-printing, console debugging, and logging, right?
I will say, as a person who came from, like, the C world and debugging, I spent a ton of time down in, like, Ruby debug land. I love using, like, Byebug because I can watch a variable. I can do a thing where it's like, I don't know who's changing this, but I can stop the program when they do. And I can, you know, put a breakpoint on this. And then I can walk away and go do another thing. And then boom, it hits. It triggers. That's a little harder to deal with.
But, I guess, with the puts, you could go in and say, you know, "Print when this happens." But if it's like a variable, like a change on a variable, you can track that. And that's very, very exciting to watch something, you know, live, but have the thing actually fire a trigger and say, "No, no, no, no, hang on. We want to talk about this." And that's, like, a great observability tool.
MATT: Yeah, and for things like Ruby, you can step through with debuggers, and a lot of the IDEs just provide them. And that's nice. I rarely use them because, generally, the things that I am looking for I know where to look. But that's really powerful if things are happening deeper in your stack, and you don't know what you're looking for.
DAVID: Yeah. The downside compared to Pry of, like, Byebug or Ruby debug is that your REPL, your little read-eval-print loop thing, is just kind of, like, a one-line thing. You can evaluate a statement in Byebug, and it will return you the value, but, like, modifying code on the fly is a little bit trickier.
I know that the folks that use Pry love this because it basically gives you an IRB prompt. You can rewrite a function and then rerun it. I am not super fluent in that. Is somebody here...does anybody on the call like to do it that way? If not, we can tell people to go Google it. But does anybody here debug that way, that's good at that way, that can talk to that?
MATT: I've done it a little bit. If I have an idea of a change, if I'm in the right console, occasionally, I'll make that change, and then see if the output is what I expect, and then go make the change in the code. I wouldn't say I do it often, but I certainly have done it.
EDDY: I think I use it religiously, honestly.
DAVID: You do?
EDDY: Yeah. Like, I'll inspect something, and I'm like, cool, is this outputting whatever I expect it to output? Or, you know, if I have a check in place, you know, like, if current user dot permission granted, or whatever, and like, I'm trying to make sure that it does have the right rules or whatever. Or if I'm checking for a bool output, I want to make sure that that [inaudible 15:43] class is doing what I expect it to do. It could be a typo, you know; it could be checking something that I wasn't expecting. So, being able to manipulate the data inside that session is pretty nice.
DAVID: Fantastic. Does anybody here use, like, the code rewriting ability by Pry? Because that gives an IRB prompt. You can literally just, like, open a class and jam in a method. There's a related technique that I also don't do, which is writing code at an IRB prompt or at a Rails console. Does anybody use that technique?
MATT: That's what I was referring to. Like, if I have a class method that is doing something unexpected and I have an idea for a change, I'll just put the entire method in and rewrite it inside of the console.
DAVID: Okay, yeah.
MIKE: I do a REPL all the time, you know, that's why I use simple, you know, print statement out to the, you know, standard out. And then when I want to test something, I'll pull up, you know, the interactive console and play with it. Software isn't quite tangible. That's about as close as you get to tangible [laughs].
DAVID: Oh yeah. It's [crosstalk 16:42]. Yeah, you can actually manipulate it.
MIKE: I'll often write methods where I put...and you almost never use semicolons in Ruby. You're like, you can't use semicolons in Ruby? Well, you can, but nobody does. But when I'm doing interactive coding with a console, I do that all the time. I'll have my method written with semicolons between it, so I just tap my up arrow, go back and modify it, run it, tap my up arrow, go back and modify it. It's just really easy.
MATT: We use the semicolons a lot in the production environment. So, we don't get output when we're loading models.
DAVID: Oh yeah. It's like load user semicolon nil.
MATT: Yep. And I'm finding a little bit of a pattern here. I'm noticing that those of us who have, and, you know, I don't want to state age, but those of us who are a little bit older and been around for a long time use a lot of very similar tactics. And we have what one may refer to as old-school methods.
DAVID: Yeah. I'm actually coming from a different side of the old school, right? Where for me, I almost never code at the console or an IRB. For me, it's the code, compile, test mentality. So, like, if I want to play with something, I'll open it in the editor. I'll tweak it, and then I'll rerun it, and then, you know, tweak it and rerun it. And then I'll, like, edit the test and then rerun the spec. And that's an instinct to me.
Modifying something in IRB is great. Like, if I'm trying to explore, like, I don't know how this thing works, I love going into IRB and doing this. But, like, if I'm actually trying to write the function, I want to be in my editor so that when it does work, I'm done, rather than having to pull it out and drop the code into an editor. Like, I want to be done. I don't want to have an extra step.
MIKE: For me, I care about how long is it? If it fits in one line, I'll do it in IRB.
DAVID: In IRB, sure.
MIKE: I'll do it in IRB. If it doesn't comfortably fit there, then I will pull up a file and do it that way because I don't want to have to restructure everything and fight with that. So, for me, it largely [chuckles] comes down to just I want to do less typing, you know, lazy developer.
TAD: So, Dave, is that debugging? Or is that just writing code, or is that both?
DAVID: For me, both. With debugging, it will be a lot...I guess what I'd say is if debugging, I probably won't edit code. It's, like, I don't program at an IRB kind of thing. But I'll crack up an IRB to explore or a Rails console to explore and find out, like, where is this coming from? And who is doing this to me? That sort of thing.
It's very, very rare that I will grab object dot method, colon, method name dot source location. I'll do that at a console all day long. It's like, you know what? Ask Ruby to tell me where this source code is so that I can track it down. I think I've done that once or twice from inside code, but very, very rare.
JUSTIN: One question I have for the group is, like, what is your strategy if you get handed a bug from production?
MATT: That was a little bit of where I was about to go.
JUSTIN: Oh, perfect.
MATT: What I was going to say is we've talked a lot about a bug inside of our codebase. However, we operate in a large ecosystem of services. What happens when you get a report of a bug from your production environment that is hitting five or six different services? And then, how do we debug that, and what kind of things can we do and put in place to make that easier on us?
DAVID: I have a first technique that I will go to, which is Newton's approximation, which is to split a thing in half and then subdivide it. And, man, I learned this soldering radios back in high school working, like, ham radio stuff. If you get a circuit, a long-convoluted circuit, and it doesn't work, and there's 1,000 components on it, you pick a point roughly in the middle, and you inspect. Like, you get in, and you basically say, "The data at this point, is it messed up already, or is it still good?" If it's still good, the 500 things upstream are probably okay. The bug is probably downstream at that point. I've just eliminated 500 candidates from the list.
And if it's bad already, then I know it's upstream, right? Then you split again 250. You split again 125. You keep splitting, splitting. And if you've got 1,000 components in 10 splits, you can come down to the line of code or to the specific component that is causing that thing. And I learned that with a soldering iron, you know, trying to isolate, you know, is this is a bad capacitor or a bad transistor? And it translated so easily onto, like, systems programming. And I was like, well, yeah, it makes sense.
JUSTIN: Did you understand the entire thing? Because sometimes, with a big, complicated system, it's hard to understand, like, all the parts to it, right?
DAVID: Mm-hmm. Mm-hmm.
MIKE: For me, I think a lot of the place I start is...and I don't know if I took this quite explicitly. I'm thinking about the conversation I [inaudible 21:18] earlier. What's the story here? You're probably not going to do very well; just kind of random cherry-picking. Well, might it be over here? Might it be over here? Instead, you say, "Well, what was the process that led to this? Who was the user that caused this? What steps did they go through to get it?" You know, and part of why steps to replicate are so critical to being able to diagnose problems. How did they replicate it, and what was the exact outcome?
And you can start thinking through what's possible and filtering down with that story. Narrative structures really work well with our brains, I think. And having that structure gives you a place to start. So, if you don't have the story, you've got almost nothing, you know, you've got a whole bunch of letters and numbers, and that doesn't do you very much. But if you have a story, well, I can do something with that.
DAVID: If you don't have a story, your brain has a working memory of about seven items. So, you know, a system with seven components, you can debug. You need a story if you want to go bigger than that.
EDDY: I think the most challenging part [crosstalk 22:15] of debugging stuff is when you can't replicate stuff in lower environments, and you're just playing with, like, I'll just shoot up in the air, and hopefully this fixes it, right? Like, how do you go about debugging something like that that isn't reproducible in a controlled environment?
TAD: Can you debug something that you can't reproduce, that you can't tell the story about?
MIKE: Those are the hardest ones [laughs]. But I think the answer is still the same. It's about becoming a really good storyteller [chuckles], honestly. You think, well, I don't know what's going on here, and I can't reproduce it somewhere else. But I can think about what's going on in this environment. And then you start asking questions, well, how does that environment differ from my local environment?
MATT: Yeah, there's a Latin term called ceteris paribus used all the time in economic principles, and what that means is all things being equal. So, one of the first things—and we have learned our lesson a few times with this—is we need to check our environments. Are they equal? Are they set up the same? Do we have the proper feature flags in place in one versus another environment? You know, we've been caught a few times with that. That's a really important thing to take into consideration.
And a lot of times, we overthink a problem when we're trying to solve it instead of thinking in the simplest terms. And if you can think of the simplest things first, a high percentage of the time, that's the cause.
TAD: Is this just science where I observe, I form a theory, I test my theory, I observe, I form a theory, I test my theory?
DAVID: Yeah, the method of hypothesis makes sense.
MIKE: I think it is. I was going to say something slightly different that there's been a number of times and probably a lot of times when I've had a bug that I couldn't understand, and I said, "Well, this is impossible." And I think every time I've ever thought that I was right [chuckles]. Going back to what Matt said, I was absolutely right because my mental model of the situation had a critical flaw [chuckles]. And if it had happened the way I was thinking it was happening, it wasn't possible.
So, going to what Matt was saying [chuckles], stepping back to think, well, all this is equal; apparently, something is wrong. Something is different here that I am not thinking about. And I have to think about, well, if this is impossible, that means I'm the one who's wrong. I'm thinking about this problem wrong. And I have to start exploring options as to what might be possible, which means that my focus is too narrow. And it's usually kind of a meta thing. Like, maybe the environment is different [chuckles]. Well, what is different about my environment?
TAD: I actually had a manager, and he'd say something like, "Well, did you drop the apple?" right? But that meant, did you test the gravity is working right now? Something that you assume is always true. Like, I'm going to drop this apple. It's always going to fall. Gravity is always working. And it's always attractive, da, da, da, right? Like, a fundamental assumption that I totally believe.
And it's like, okay, I've established that assumption. Okay, maybe I need to back up and drop some apples and test all these assumptions that I'm making and see, oh, this assumption that I believed was always correct is 90% correct, right? Or there is something that I assumed to be absolutely the thing isn't actually the thing.
DAVID: There's a thing that I'll do in RSpec called writing a cockroach test, and it's the opposite of a canary in the coal mine. A canary is any little breeze kills your spec, right? It's literally a flaky spec. A cockroach spec is if you've ever worked on any of the projects I've worked on, you will find me doing expect 42 to equal 42. I have seen that test fail, and when that test fails, it means gravity isn't working.
Okay, to be fair, it wasn't that 42 wasn't equal to 42. It was that RSpec was broken. And we all thought it was working the way we thought it was, and it wasn't all. Like, the whole framework was broken. So yeah, dropping the apple, I'm going to steal that. I like that.
MATT: There are also some things we can do to make our lives easier, especially in service-based architecture. One of the things we do here at Acima is we create a request ID for any request that gets passed along to all of our services. So, if we go look in our logs, we can search by that request ID and track it through each of our systems, you know. And I think being proactive is also something that we need to be really conscious of as well.
JUSTIN: I like how you said proactive, and I'm a big believer in logging and logging all the paths you're on, and especially logging that enables monitoring. So, logging enables monitoring so you know when things go wrong. And, you know, logging your request IDs is good, but also, looking at the path that the user went through at each level is really helpful for understanding the history of that user or that request and seeing if it took the anticipated path. Of course, any errors are really useful with that as well. So, I think the request ID is attached to that error case, isn't it? When an error gets logged.
MATT: It depends on where we're logging and what we're looking at. For instance, in, like, our Grafana logs, that request ID is attached to everything.
JUSTIN: Perfect.
MATT: Rollbar may or may not be. It depends on how the engineer logged it when they were catching errors.
MIKE: And Rollbar catches exceptions [chuckles], so things that are unexpected. You may not have access to everything you wish you had.
DAVID: Matt, when you say proactive, what do you mean?
MATT: Exactly what it sounds like. Put things in place so if you do run into bugs, it makes them easier to track down.
DAVID: Okay, okay.
JUSTIN: Catching and logging those exceptions.
MATT: Yeah, but --
DAVID: Knowing we're definitely going to need this. Let's go ahead and do it now.
MATT: Right. Right. The more preventative you can be, the fewer bugs you're going to run into. And let's be real with each other; bugs are inevitable at some point. I have never seen a piece of software that is bug-free, again, because we are humans, and we build software. But the easier we can make those bugs to crack down, the easier it is to fix and the fewer we're going to have.
DAVID: There's an interesting epiphany you guys have given me as we talk through this, which is a thing that I got told years and years ago is that debugging doesn't stop when you run out of answers. Debugging stops when you run out of questions. And the epiphany that I'm getting from talking here in the call is that the best debugging skills is knowing which questions are going to eliminate the most false candidates from a thing. And I'm liking this.
Yeah, it's like, if I need to trace this down and I don't have the request ID, and if I have to go at every step and go, okay, when you pass this to this system, you got back that ID, okay, now we have to switch to that ID to trace through. Make it easier to track down the data you need. That totally makes sense.
MATT: And a lot of it just comes with experience, you know, it's trial and error. You find what works for you. Everybody's workflow is going to be a little bit different. And we find what works for us, and then we just go with it. And we improve on it. And listen to your peers; other engineers are an amazing resource for this stuff.
EDDY: I was actually going to say that one of my tools that's always my go-to is seeking help with people who are more experienced than me because they have a leg up. They've been through that before, you know, and they've had that ingrained in their head on, like, what their go-to is to debug something. So, not only is rubber debugging, for me, supercritical for debugging something, but, like, interacting with someone else in my team who is also involved and can help me get unstuck.
MATT: And then after that, you're more experienced, right?
MIKE: Experience helps. I liked the framing that Tad gave. It's just a science [laughs]. It is. In modern science, they don't use the word...they do talk about theories and that that is real, but a lot of times, they talk more about modeling. What we're doing is modeling the problem. You observe. You try to create a model that describes the behavior, and then you start testing your model. Does it actually work? I'm not saying that theory isn't a thing, but model is kind of a broader idea. It captures not just your idea of what's going on or your hypothesis, but it's provable. It's something that is...not provable but disprovable [laughs]. Disprovability is the key aspect.
Does this work in this scenario? Does this work in this scenario? And you start looking for holes in your model, right? And, hopefully, you find some because that means that there's new things to learn. And, likewise, when you've got a bug [laughs], you're like, well, what's the problem here? And then you already have some mental model, right? But maybe it is weak. And so, you try to come up with a better model, and then you test that model. Does this actually explain the behavior? And you try to disprove it, right? [laughs] And if you can't disprove it, then it's pretty reliably going to be your answer.
And thinking about that methodically, in that way, about problem-solving, I think, is extremely valuable, and it can be a shortcut. Because otherwise, again, you just got a sea of text and a problem, and there's no relationship between the two. And modeling is that process of giving it structure in your mind and maybe even having something written down. You know, what's the structure here? So that you can understand it and start trying to test your model for reproducibility.
EDDY: And staying calm.
MIKE: The hardest problem I ever had to debug was working with a library that...it was a messaging library that was intended to run in a kind of a sidecar thread. So, you had your request come through, and it would fire off a new thread as soon as the request came through. And it actually tried to be persistent. It lived permanently between requests. So, this thread lived in the background, and it would spawn multiple other threads. So, it had multiple threads running concurrently to do messaging. And so, it ran in the background. And the publishing was asynchronous...it was concurrent like that.
And it was also grabbing messages by pulling from the remote server with this concurrent set of threads. But it was also distributed because you're communicating between your system and another system. So, you had multiple systems, you know, there were multiple separate systems, generally, two, which is nice. It didn't have, like, eight, but you had two separate. So, you had a distributed system that was also concurrent at both ends.
And I was asked to fix a problem with the messaging. There was something that wasn't working: figure out what's going on. And it turns out that the library I was using had multiple critical bugs in it. And the messaging was unreliable. We were dealing with messaging that was a little bit flaky. So, the messaging was unreliable. I had to deal with concurrency, something distributed.
And [laughs] the code that I was expected to depend on that was supposed to be doing the work didn't always work. And I did get through it. But it took me about a month to do something that I thought would take me a day or two. And every day, I was just so defeated [laughs]. Like, at first, I'd, like, you know, after a couple of days, I saw, like, okay, this is a hard problem, but I can get through this.
But to your point, Eddy, about staying calm, I've believed this for a long time: that software development is about frustration management as much as anything else [laughs]. Just keeping on looking for flaws in my modeling of this problem. Just saying, you know what? I'm just going to keep on working on it and not get broken by it. It eventually got through, you know, that was a trial. You know, that's kind of an extreme example. It will probably lead to other discussions, too, where people say, "Oh, this is the other one I fixed." But it illustrates some of those things.
Sometimes, you're working with some hard things that don't line up, so your log messages could come in random order. You can't trust the code that you're calling. You have to jump from system to system. The transfer layer is unreliable. And there are so many things that can go wrong, and that that randomness in the system is one of the hardest things. Anything that has randomness in it is really hard to debug, but continuing to just work at it and not give up [laughs].
And you think, well, I wouldn't actually give up. My job is to keep working on it. But it is; it's easy to, at least some part of you, to just kind of tune out. You're like, well, there's nothing I can do. And just taking a moment to calm down [laughs], take a step back, maybe go for a walk, and think, well, how do I tackle this problem next? Matters a huge deal.
JUSTIN: So, I'm curious, Mike. What was your solution there? Is this something that you could summarize very quickly?
MIKE: Yeah. So, that's a great question. So, what I ended up doing was focusing on smaller parts of the problem. I knew that there were problems in messaging between two systems. And that's just so ambiguous, you know, sometimes the messages weren't getting through. And the systems were running slowly, too. And the unit tests I was using weren't really unit tests. They were all integration tests, too. They were actually calling the live message [inaudible 34:50] [laughs]. So, I was handed that kind of testing.
So, there's a couple of things I did that were really critical. One of the things I did was essentially throw out the unit tests that I had been trying to get working because integration tests run incredibly slowly, and that was costing me a ton of time and not giving me what I wanted. I needed to get information and instead, they weren't really giving information.
So, I started with a smaller...I mocked out the actual messaging so I could focus on just what I was looking at. And by mocking that out, I restricted the scope of the problem I was looking at. That helped a lot. And then, I could look at just one particular request. What's going wrong with this particular request? And then look even smaller, like, well, sometimes this works, sometimes it doesn't. Why would that be? Which eventually led me to look into the library and think, well, again, this is impossible if the library is working.
So [laughs], I go into the library and put in some logging there and find the line like, oh, wait, this is spawning up a new thread. I don't remember the exact details of it. But, I found the problem in the library was using an array rather than a set. So, things weren't actually unique when we thought they were, something like that. And I find the library, and that freed me up a little bit, right? [laughs] And then I looked for...well, is it working now? No, it's not. There are still some other aspects of the problem.
So, then I focus down on the smallest component I possibly can. The bigger the problem you're trying to solve, the bigger the scope, the more you have to deal with. And getting out as much stuff as you possibly can so you can narrow down a tiny, little slice of the problem helps a great deal. And then find something wrong in the app in the way it's calling the library. I remember fixing some of that.
It actually ended up firing off more than one thread when it should only have been firing off one. Fixing that solved a problem because then things started running faster because you only had one thread running multiple. And it still wasn't working, again, just working on piece by piece. Focusing down on the smallest possible piece you can work on was incredibly helpful.
DAVID: You said focusing down, and you mentioned at the start that you had, like, a many to many, like, many distributed in, many distributing out on it. And coming from the debugger side where I want to jump onto a console and I want to interrupt the code flow, you can't do that if there's 20 nodes. And you don't know which node is going to... logging would be a good solution, right? We just put logging on all of the nodes. Is that --
MIKE: It is. Logging actually works.
DAVID: Yes.
MIKE: So, this is something a debugger doesn't [laughs], and logging does.
DAVID: Yes.
MIKE: And you think, well, I need a more sophisticated tool, and the answer is no. The last thing you need is a more sophisticated tool. You need the simplest tool possible. It was really counterintuitive. You think, for a tricky problem, you need a more sophisticated tool. And, no, for this problem, I needed the most basic kind of tool possible because it would work [chuckles] in this kind of environment. That's a really good observation.
JUSTIN: And the log entry would contain all the information you need, like the thread ID.
MIKE: Right.
JUSTIN: The time entry and things like that.
MIKE: Yeah. And knowing which thread it is in matters a great deal, right? [laughs] And being able to say that and then logging the threads, like, ooh, I see. This actually happened in this thread. I thought it was going to happen in this one, or these are out of order. That means that some of my locking and the semaphore stuff was going wrong. And bringing those kinds of things out, yeah, is a huge deal.
EDDY: You know, I kind of want to propose a scenario if we're okay. Let's suppose that you do merge something in production, and it's a bug that wasn't caught. Our natural instinct would be, oh, shoot, roll back [laughs]. Let's roll back. Let's go. Let's get rid of the bug. Let's make sure that we step back and, you know, we can work on this.
But what if it's already further along? You know, you've gone a couple of weeks, and it wasn't caught. And suddenly, rolling back after it's been so long, you know, just isn't really feasible, right? But suddenly, this bug has turned into something huge. Let's say, for example, you're, like, leaking PII or something. And you're like, shoot, I need to get this out quick, right? In that sense, are we okay with bypassing unit testing and throwing out a potential fix to fix it? Is that good practice? Or should we still be concerned about writing passing specs?
RAMSES: How would you know it's working if you don't have tests?
MATT: I would say without your tests, you open up a really big door to introduce more bugs and different bugs.
MIKE: There's a phrase that people use, and it's derogatory, cowboy coding, to try to describe that kind of thing. Oh, I'm just going to throw something out there and see what happens. It's a figure of speech, and there's a metaphor there. I don't know if this idea of the cowboy in the way that it's described ever truly existed in history [laughs]. But it's this image from movies about somebody who does things their own way. They don't really care about the consequences. They shoot with their guns, and they don't really care what happens.
Well, if they're going out and shooting with their guns, some people are going to get killed [laughs]. There's a lot of chaos and sometimes tragedy that happens for others and for your environment. And the best usage of that phrase it speaks against that kind of action, that if you have this lone [inaudible 39:56] that thinks they can control everything, that they can get away with anything.
And maybe in some scenarios, you're just building out something that doesn't have any real-world consequences. You haven't deployed yet. Then, that kind of development might be okay. But when there's consequences, people are going to get hurt. In your scenario, it's already been out for two weeks. Waiting an extra 30 minutes, waiting an extra hour to verify your solution, you know, you think about the cost-benefit analysis, it's probably going to save you some in the long run.
DAVID: If you're hemorrhaging money and the [inaudible 40:26] actively damage by leaving the server, you know, running in that mode, another good option is to take the server down, right? You're just, like, stop production. We're going to stop the company from making money, but that's okay because we're also stopping the company from hemorrhaging money, you know, that kind of thing.
I think pushing an emergency hotfix into production without a second pair of eyes on it I think that's a very, very bad option. I can imagine a world in which, at one shining, dark moment in time, that was your best option. Sometimes, you know, the, like, cowboy coders that mentality, of, you know, running around firing your guns everywhere, it's like, sometimes, the environments need clearing out. But that's you're in a bad situation, to begin with, when that's your best option.
But to answer the question behind your question, possibly, Eddy, like, what do we do in this situation? I would not sit down and spend 10 hours writing a test suite to verify all the new edge cases that we think, you know, it's like, oh, you know what? This is a problem. This needs to go out. We're not hemorrhaging money, but we're not making money. We're losing, you know, conversion. We're losing sales. Let's get this turned out.
And there are things that you can do very quickly and low cost that give you a huge mitigation on the pushing a new bug, like, grabbing a co-worker and saying, "Look at this," right? Like, a unit testing is just automating pair review; that's all it is. So, having another human, especially, like, a senior developer who has a very complex mental model of how the system works. You say, "Does this make sense?" And they'll take one look at it and go, "Oh no, don't do that," right?
MIKE: [laughs]
DAVID: You say, "Okay, good. I'm glad I didn't push this fix," right? Now, we're solving your solution down the road. Or they look at it and go, "Yeah," right? And the next thing you can do to mitigate this risk is, after you push it out, stick around and watch the server, right? Try it out, you know, confirm. Eventually, like, by this time next Thursday, there should be tests for exactly the problem that you have found and that prove that we have solved it, and whether or not we need to get, you know, cash flow protected in the moment. That's a valid question. But it's definitely a different operating mode than a stable, steady, patient maximum risk mitigation development.
This has been a fantastic call. I could go for another hour. This was awesome. Any other thoughts on debugging and, like, how and why? Just don't write bugs?
TAD: I thought Mike said something interesting about go for a walk. It's an interesting debugging aspect.
DAVID: Reset the scope in your brain.
MATT: Yeah, get away from your tunnel vision because --
EDDY: Getting a good night's sleep [laughs] [crosstalk 42:53]
MIKE: That's so true.
DAVID: There's a paper trail in an email somewhere that I sent years...I don't have it anymore. But literally, I have written the sentence, "The most effective thing I can do to solve this problem is to unplug and get my head down for six hours." And that's what I did. And I got up in the morning, and I had the solution and was able to get it, but I never would have come up with it.
Specifically, going for a walk, Brain Rules by John Medina is a fantastic book. And he talks about if you get your quads moving, the biggest muscle in the body gets oxygen moving; this gives, like, a 30% boost to the Broca's area of the brain, the part where you executive function, which is your ability to reason through difficult problems and make decisions. So, going for a walk actually makes you smarter. So, if you need to be smarter for a problem, there's the door.
MATT: Yeah, many of you have probably heard me say, "I have not gotten much sleep. I am not going to try and solve this right now," because that's how mistakes are made, and we introduce more problems. So, it really is; rest is important.
DAVID: We could do a whole separate show about recognizing the mental unit tests that we run on ourselves, right? Because a microscope can't look at itself. And the first judgment that gets impaired when your judgment gets impaired is your ability to determine if your judgment is impaired. So, finding those things like knowing I'm running on no sleep. I made this call last night, and I knew, and now I have to recognize that I feel fine. I feel tired, but I feel like I'm here. But you know from experience if I keep typing, pain and suffering will come of this. That's a really dark place to end. Somebody say something brighter.
MIKE: I can go darker if you want.
DAVID: Okay, fine. That works. As long as I'm not the one ending us on a dark call, somebody else could do it.
MATT: Light outs for a nap.
DAVID: That's right.
MIKE: My father-in-law had diabetes. And he was in a serious accident because he was not thinking clearly, and they sent him home from work. And so, he rode home on his motorcycle. Our ability to understand the consequences of our choices is impaired when we're impaired in some way when our thinking is impaired. And having some sort of checklist almost to say, well, should I be doing this that is external to yourself, I think, is really valuable.
DAVID: That is fantastic. We get into a go mindset, right? We gotta go, gotta go, gotta go. We stop checking to see, wait, is it safe? Is the smartest thing to stop? The best way to go might be to stop.
MATT: Avoiding burnout is important and possibly a topic for another Acima podcast.
DAVID: That is a fantastic idea, yes.
MIKE: It's a fantastic idea.
DAVID: 100%. All righty, folks, this has been a fun, fun chat. Thank you all for coming. And thanks for the contributions. I really appreciate it.
This week, the panelists discuss the best Integrated Development Environment (IDE) for beginners. Eddy emphasized the importance of an IDE being ready to use post-installation, reducing the need for additional configurations or extensions. Steve advocated for a minimalist UI to help beginners, suggesting simpler interfaces are more approachable. The conversation covers various IDEs, with Visual Studio Code holding a significant market share. Notepad++ was humorously mentioned as a practical option for beginners. They also touch on the suitability of IDEs for different types of development, such as mobile or game development, highlighting the specialized needs like managing assets in game development.
They also delve into the trends in technology adoption, using TypeScript as an example. Tad mentioned the typical hype cycle where new technologies are quickly adopted and gradually lose appeal. This leads to a broader discussion about the evolution of programming languages and frameworks, like Ruby, influenced by user preferences and industry trends. They also discuss the importance of features like Live Share in Visual Studio Code, especially for collaborative programming and mentoring newer developers.
Towards the end, the conversation shifts to personal experiences with different editors. Panelists share their first and second editors, reflecting on their transitions and experiences. This part of the discussion underscores the diversity of preferences in development tools shaped by individual comfort, project nature, and programming language. They conclude with a light-hearted debate on the merits and challenges of using various editors, encapsulating developers' varied perspectives and experiences in choosing their ideal programming tools.
Transcript:
TAD: Hello. Welcome to the Acima Dev podcast. I'm your host today, Tad. Joining me is Eddy. Will you introduce yourself?
EDDY: Hi, guys. Been in here a couple of times. I'm a developer for Acima.
TAD: And Ramses.
RAMSES: Hi, everyone.
TAD: And Steve.
STEVE: Yeah, I'm a developer here at Acima. Steve.
TAD: And Kyle.
KYLE: Yeah, DevOps engineer here at Acima.
TAD: I like that we get a little bit of a mix because sometimes DevOps is a little bit different than regular development. So, they sometimes get some different tools that work well for them. Welcome, everybody.
Today, the question is, which IDE is best for someone starting out with development? Maybe to start off with, let's establish some criteria. What do you think you would be looking for in an IDE or just, like, a code editor if you're starting out? What do you think are some good features?
EDDY: I want to just premise by saying I think the closest the IDE can be ready to go by just natively being installed in your computer, the better. Because, like, you necessarily don't know what extensions or stuff you're going to need in order to progress and, you know, make your productivity better. So, like, the closest out-of-the-box configurations that you can get, you know, when you're installing, I think, is a huge win.
TAD: Okay, so Notepad?
EDDY: Yeah, definitely. I think Notepad's the best one. It's always installed.
TAD: Yeah, I think that's a good point, though. If you don't have to go through a lot of setup and configuration, that definitely gives you a head start, right?
STEVE: For somebody who's brand new, a minimalist UI kind of helps with the learning curve. When you have something that's very feature-rich, and you're just dipping your toes in the water, sometimes something simpler is more approachable. So, I guess it depends on where they're at. Like, are we talking about somebody who's never seen code before, and this is the first thing they're doing? Or is it somebody who's dabbled but they're not a professional, they want to land a programming job, and they're just kind of doing their thing on their own? I just think it depends on where you're at.
TAD: What if we assume that it's someone pretty new to programming overall?
STEVE: Yeah, in that situation, I would lean towards something like Sublime. I haven't used Notepad, so I don't know what that's like. But something really minimal but still feature-rich. That's my --
EDDY: You know, we joke around about Notepad. And I actually used Note++ as my primary IDE for a while.
TAD: Right. You know, I'm joking, too. But the first web page, like, HTML file I ever wrote, I think it was in Notepad. I mean, like, putting an HTML tag at the beginning, an HTML tag at the end, head tag, head tag, body tag, body tag. I think I wrote that in Notepad.
STEVE: I didn't even realize you guys were joking because Notepad++ is, like--
EDDY: [laughs]
STEVE: It's not like TextEdit. Like, if you had said TextEdit, then I'd have been like, yeah, obviously a joke. But Notepad actually has formatting, or at least Notepad ++.
EDDY: Well, I used --
RAMSES: [inaudible 03:14] have syntax highlighting too?
EDDY: It does. Yeah.
RAMSES: Yeah, that's [inaudible 03:19]
STEVE: I think it's actually usable on, like, something like text editor.
EDDY: Again, like, a few days ago, I was curious sort of because I knew this topic was coming, and I just looked worldwide top IDEs. And I don't think it's surprising to anyone when I say that 27%, almost 28% of the market share for IDEs is taken out by Visual Studio Code.
STEVE: What are the other market shares, and where are you getting that number?
EDDY: So, this number is coming from Github.io.
STEVE: Microsoft.
EDDY: Yeah. [laughs] Github.io, yeah, so it's Microsoft. So, there is some sort of bias there, right? But 27%, assuming that that's correct, is one-fourth of the market share, which is tremendous, right? To give you other context, right? Others coming close at 11% is Eclipse, and PyCharm, Android Studio, IntelliJ, NetBeans, Xcode, and Sublime, and Atom. So, those are the top 10.
RAMSES: Atom is still in the top 10?
EDDY: I was surprised.
TAD: That's surprising to me, yeah.
RAMSES: Yeah, that's interesting --
TAD: And that GitHub kind of discontinued it and said, "Feel free to continue to use it. But we're not going to be adding new features or fixing things."
EDDY: I would advocate for Visual Studio Code in the sense that, like, I use it on a day-to-day basis, and I know my way around it pretty well. I know which extensions I like to use, cater it to my productivity, et cetera.
TAD: You've had some experience now, right? And you didn't start with VS Code as your first editor, I imagine. So --
EDDY: No. I used Notepad for a bit and then transitioned to Atom because it was, like, the hot thing. And then Visual Studio kind of just came in guns blazing [laughs].
TAD: Yeah. I think it's kind of funny that we keep mentioning Notepad because, really, you've said minimalist UI. It's certainly got that. We talked about easy-to-use, easy-to-understand, something that comes native with your laptop. I might throw out there you don't have to learn magic key chords or special modes or anything. It's just, you know, CTRL + X CTRL + V to cut and paste.
Do you think it's valuable if you have something that feels kind of like, I mean, Word or one of these other, like, document editors? Because you might have some of those keyboard shortcuts memorized, and you might have some familiarity with something like that. And if those transfer over to your first IDE, that might be useful.
STEVE: Yeah, I think it definitely makes a difference. One point I was going to bring up about Sublime, which is the one that I've used for most of my development career, which isn't terribly long, but I've used that and VS Code. And the thing that I loved about Sublime was the file explorer looks just like the native one on Mac, or it feels similar to it. And it's very easy to use.
Whereas VS Code, it's really not usable, practically. I mean, you can't really see the indentations, and they throw these gigantic icons in front of all of the files as if they're catering to, like, a toddler. Like, this is a Ruby file, or this is a file or a directory. Here's a huge folder icon, you know.
So, I think stuff that looks like your native system, stuff that you're familiar with, just means less learning, which means that you can focus your attention on things that are kind of new concepts that are more important to you in the beginning. So, minimalism and familiarity are things that I would look for, you know, if learning something, but that's my [crosstalk 06:59]
EDDY: So, let me ask you this: so, is Sublime scalable in a sense where, like, you can continue to use it as your knowledge increases and your tech stack goes up?
STEVE: Yeah, definitely you can. The thing is, you have to add extensions, of course, just like you do with any editor. And I'm not really sure why I switched. I didn't have any problem with Sublime. There was nothing that was really slowing me down. I think it was just, out of curiosity, I wanted to try something else. And then once you make the switch, then you're kind of like, all right, I'll just stay here.
EDDY: [laughs]
STEVE: Like, it's not bad, you know. And in the case of VS Code, VS Code isn't bad. Actually, it's very good. I would rate them probably the same. But since I've switched to VS Code, I just stick with it for now.
TAD: So, Eddy, are you suggesting that another criteria would be something that you can start with but also continue with, right?
EDDY: Yeah, well, like --
TAD: You know, integrating it with GitHub.
EDDY: Yes.
TAD: Or adding themes and extensions and things like that, that you want something that you can start with, but you can also continue to use even as you gain more advanced skills and get more experience.
EDDY: Yeah, exactly. Well, I don't want to go on record to, like, sound like, I'm bashing Sublime in any way. I did try it for a few days. My biggest problem I had with it installing packages or extensions were a lot more difficult than they had to be. And, like, VS Code just gave you [laughs], like, a really nice intuitive UI that you can search and install, right? Like, that, for me, was a game changer.
STEVE: Yeah, I agree. I think that's a strong point for VS Code.
TAD: Discoverability might be an important characteristic, right? Because Sublime code was great. I used it for probably a couple of years. But yeah, it's, like, installing things is just, do you know the right key combination to bring up the magic menu that lets you install something, right?
KYLE: So, as you guys have been conversing about this, I was thinking about the question and how broad it is. And I'm having an issue kind of answering it myself just because there's a lot of unknowns in it, right? Like, okay, where do you start? Are you starting alone? Are you starting with a team? Because if you're starting with a team, they're going to have recommendations, and that's going to affect it. What kind of development are you doing? You know, what language? Where are you starting?
And then, like, are you starting in development, or are you starting in systems? Like, where are you starting? Because that can change whether or not you're going to be using Sublime, Visual Studio, PyCharm, even Vim, or Emacs, you know. Like, maybe somebody's really familiar with the terminal, and it's just a lot easier for them to use Vim.
TAD: Yeah, I mean, absolutely. Like, if you're doing Swift, you probably want to be using Xcode, right? I mean, certain languages have very opinionated tooling, I think. I think that's a great point, Kyle.
KYLE: I mean, the other one is, are you on Windows, or are you on Mac? Because that's going to sway you one way or the other as well.
EDDY: Are you actively...in DevOps, are you guys coding?
KYLE: So, we have scripting languages that we utilize. So, that's going to be HCL for, like, Terraform and Bash, and we do Python, or we do Ruby. So, for us, in this question for us, we need more of a generalized IDE, something more like Sublime, Visual Studio, right? Something that's not specialized.
TAD: Do you guys have some Go code? I think I saw some Go the other day.
KYLE: Yeah, we do Go, too. Yep.
TAD: Yeah. So --
EDDY: And so, why do you guys use them, if you use any?
KYLE: So, we have a couple of members on the team that really prefer to use Vim, and then the rest of us will use Visual Studio Code.
TAD: This question is actually timely for me. There's another developer that invited me to volunteer with a local group called Tech-Moms. And they're women who are learning to code for the first time. They're just starting out, and, you know, they're moms. I don't know that's a requirement or anything, but they're pretty new to it.
And I volunteered for a couple of hours this last Saturday. And most of my time was spent trying to get them to understand how to clone their GitHub stuff, how to find that cloned repo with Visual Studio Code, and then make the changes, and then push those changes up. And I was talking with some of the people afterwards, and one of the things they really struggled with is it's bring your own machine, right? So, some people bring a Chromebook; some people bring Windows, some people bring Macs.
And I was actually wondering, since VS Code is basically built in a browser with all the Electron stuff, you can actually go to vscode.dev and run it in a webpage. And I was looking at that this past weekend. And I think that might be what I recommend to people right now because you don't need to find it on your machine. You know, something like that works even on a Chromebook, something like that.
And you can get that developer experience just by going to a web page, which is pretty easy to do for most people. Most people know how to type in a URL and go to a page, and then hooking it up with a GitHub repo is also pretty easy. And you can just edit your code from there and just push it from that page. And you don't have to find anything. You don't have to install anything. You just go to a page and install maybe a theme or some extensions, and you're good to go. And I thought that was pretty compelling.
KYLE: I'd second that. Just because about a year and a half ago now, I was actually helping somebody, you know, because I should be paying attention at church. But I was helping somebody with their code on their phone at church using the online Visual Studio editor. It makes it really easy.
EDDY: Doesn't github.dev technically use Visual Studio on the surface?
KYLE: Yeah, it does now, I think.
EDDY: So, that's just another prime example of, like, the market share for Visual Studio [laughs].
STEVE: Yeah, I mean, honestly, Eddy, I don't doubt that it's 27%. That wouldn't surprise me at all. I mean, you just look around; everybody's using it at the office. Again, it depends on the language and what you're doing. But I wouldn't question that statistic. Sounds like all of us on this call, except Ramses, is currently using it, so...But being mostly Ruby developers, Ramses, you use RubyMine, right?
RAMSES: Yeah, currently. I've used VS Code for a while. Most of my time I've spent using Vim, and I still use Vim. But I think it's the best tool for Ruby on Rails development. Also, it's just great. It's made for the language. I don't know, like, [crosstalk 14:03]
TAD: Well, it's a true IDE. Like, it's a true integrated development environment, right? Whereas if I'm doing Ruby development, I might have to open the terminal, and that's kind of part of it, and drop in some terminal tools to, like, investigate some stuff. But I have to install a bunch of extensions, maybe have some command line tools and things like that before I get to the same level that RubyMine gives you out of the box.
EDDY: You know, I'm trying to recall, way back when I did pairing sessions with my older brother, he had me use NetBeans for a bit. And that was super intuitive and really friendly with JavaScript at the time. I don't know if it's still the case, but I almost never hear anyone talking about NetBeans. And from what I recall, it was just a great experience.
TAD: I think people still use NetBeans.
STEVE: I've never heard of that. Okay.
KYLE: I haven't used that in a long time.
EDDY: Yeah, it was great. Especially, like, I want to preface by saying, like, being a web developer, especially with Ruby, you're going to be writing a bunch of templating stuff, so, like, some sort of HTML template, you know, in Ruby, in even JavaScript. And I feel like of all the other IDEs that I've used; JavaScript just works really nicely with VS Code. Am I wrong in that statement? Like, do you guys disagree?
TAD: I'd have to look at the stats. But I've done a few of these, like, JavaScript state of the language surveys and things like that. And I want to say it's maybe... I hope I'm not exaggerating, but I think it's, like, 90% of JavaScript developers use VS Code. And when I say JavaScript, I'm also going to lump TypeScript in with that, just because they've really done a great job of tooling it for JavaScript and TypeScript.
KYLE: The only thing that I've even used that compares is WebStorm.
TAD: Wow, I haven't used WebStorm in a while.
EDDY: You know, and this is kind of a side topic, but you mentioned TypeScript, and you lumped it in. But all I'm hearing now is, like, big projects are ditching TypeScript, right? [laughs] There was, like, a big boom and suddenly...
TAD: I think there's a hype cycle, right? Where it's the cool thing, it's the new thing, and a lot of people adopt it. And then some people realize, oh, I didn't really adopt it for the right reasons, or this promised me things, but in my particular case, the promises are unmet, right? Like, it's like, you're going to write better code and safer code, and it's going to be so much better. But sometimes people don't see that, right?
And so, a lot of times with these technologies, I think you'll see a big early adopter rush. It cycles through the hype cycle, and then it kind of loses its shine. And so, people are, like, eh, I don't...whatever, and they kind of go find the next big thing. But still, a lot of people who are just happy with it and want to continue using it they're probably not going to write a blog post that says, "Yeah, I'm still happy with this technology [laughs]. And I'm going to use it again tomorrow."
I've seen a lot of that in the Rails community when the hype was really high, and now it's just a well-known framework. And it's not going to get your picture on the front cover of any magazines or anything. I think DHH was featured on a bunch back in the day, right? But people still use it. And it's just kind of typical boring technology now. And I'm not going to write a blog post that, yeah, I still like Ruby, right? It's usually the things that, like, we tried TypeScript, and we didn't like it after all, and we're switching. That's a more interesting blog post.
EDDY: So, I have a genuine question, and I haven't actually looked much into it. But I feel like if you're going to be a web developer, the default is always Visual Studio Code. But what happens if you want to be a mobile developer or, like, some sort of scripting language? Is that still, like, work neatly with VS Code? Or does that sort of mentality shift a little bit depending on, like, the stack? Or even, like, [crosstalk 18:13] game development, right? So, like, Triple-A games that are being developed actively, like what IDEs do they use? Like, is it still VS Code, or is that just a given with web development?
SERGIO: I just developed two video games in the past; one was released in Steam. And I used to work with C++ and also with C# on game development stuff. But when working on Unity, Unity has their own IDE, which is cool. It's good enough. But also, I've been working lastly with Visual Code. I think Visual Code is still missing some stuff like all IDEs has.
But lastly, I've been testing compiler with Visual Code, and it looks really nice. It's very useful when I work in unit tests in many stuff with JavaScript, with HTML, with Ruby, and even, I guess, with C#. So, I can say that's my answer. It's kind of it's really cool right now. But other IDEs like Unity built-in IDE is nice enough as well.
EDDY: I didn't know Unity had its own built-in UI or, like, IDE. That's [laughs] really cool.
TAD: I mean, I think it depends on the game framework because you might have something that helps you...and I haven't done a lot of game development myself, but from what I've seen, you have to manage a lot of assets and things like that. And if you've got Visual Studio, then you're just kind of left to whatever tools you want to, like, manage your assets, or edit your sprites, or do those sorts of things. But there are integrated development environments for game development that have all the tools that you need to build the game in one place. And you don't have to add additional outside tools to get that same experience.
SERGIO: Yeah, yeah, that's the way it works right now. So, it's kind of integrated all the things you need. And essentially, when you're working with 3D and 2D assets, it's really complex. You know, you have a scenario where you have to import assets and also, you have to modify code at the same time, so you need something really custom. So, it's cool.
I'm working a lot of time with C#, and I'm working with Visual Studio. At this point in time, I do prefer Visual Studio Code instead of Visual Studio. It's lightweight. And also, you can extend, you know, many things. Like I mentioned before, [inaudible 20:59]. I have plenty couple of things that worth testing. And also, one extension that I like so much is when we do pair programming. Do you remember that one, Eddy? I just learn many things from many people from --
EDDY: Live Share.
SERGIO: Yeah, Live Share. Yeah, that one. Awesome. Yeah, you can do that with...I guess Visual Studio doesn't have that functionality, but instead, Visual Studio Code it does. I am not sure about this, but I'm almost sure that you have to pay the MSDS subscription. So, you have built-in functionalities that the normal Visual Studio doesn't have on this. You pay for it. So, that's cool.
TAD: Yeah, I think, for me, Live Share is a killer feature, especially for pairing and especially when I'm pairing with somebody who's new to coding, where I can get them to send me their session string, and I can join their session. And I can explain to them what I'm doing as I'm doing it, as it appears on their screen. I can kind of stub out or kind of trace out some things and then have them fill it in.
Like, yesterday, Damon and I were pairing, and we couldn't get the Live Share working. But something that I desperately wanted to do was I had kind of outlined all our tests, right? Like, the context, and the blocks, and things like that. And then to be able to hand it over to him and say, "Okay, I've outlined this; now fill it in for me," I find that really compelling, especially the fact that it has built-in chat. I don't know that we use that much. We chat through other things.
But it tells you who's editing which file, and you can either follow them and see what they're doing, or you can go off and do your own thing. I mean, those kinds of features I often call it multiplayer programming. I think that's probably one of my favorite features of VS Code, especially when it comes to helping newer developers.
EDDY: Yeah, that's awesome. That's super cool to know that you, like, outlined it for them in the live session [laughs]. That's so cool. It's also cool...when was it? Like, Sergio, myself, and Jonathan would pair in a ticket, and, like, one of us would, like, be writing the specs at the same time the other person's writing the code. It's also another way to be super productive because you get things done much quicker, which is another compelling thing with it.
TAD: Yeah, I don't know if you guys were familiar with the old XP things. But there used to be, like, these hardware setups where you'd have, like, two separate keyboards that both fed into the same thing. And you could type, and you could do these things. And Live Share is basically living the dream where I don't have to hand off my laptop to someone else.
I don't have to have some crazy setup where we have two keyboards plugged into the same computer that we're looking at. I mean, basically, when I do it, the thing I'm looking at is what they're looking at, and what I'm talking about is what they're looking at. And that's, like, the dream of the guys that really kind of pioneered the XP movement back in the, gosh, '90s.
SERGIO: Hey, Tad, you did XP before. It's kind of the old-school way. Yeah --
TAD: Yeah, kind of. To be honest, we did it in college. And I don't remember what distinguishes XP from some of the other things. But we did have times where it was basically two people sit down at the same computer and team up and pair and work on stuff.
SERGIO: Yeah, I tried that in the university when we have this project. And we have a big monitor and everything else. People working is kind of [inaudible 25:04], I guess, and only one main programmer. It's kind of the other people is only seeing you. But that's weird, you know, it's kind of odd.
I like to do stuff. So, this extension, Live Share, is kind of cool because everyone can write code at the same time. It's kind of you are not alone just seeing the code. You can interact directly with the code and write your own things. So yeah, many times, we broke things because watch people is doing one thing, and the other is trying other stuff [laughs]. But it's part of the coolness, you know [laughs].
TAD: Right. Are there any other needs that maybe a newer developer would need that we haven't talked about yet?
EDDY: I guess also, like, what operating system? Should they use Mac, Windows, or [laughs] Linux distro?
TAD: Linux? Well, that's why I'm thinking about pushing the browser because then it doesn't matter. You know, start out with the editor in the browser and learn how you like things, and then graduate to something else.
EDDY: Yeah. But will the browser sort of compile the code for you if you needed to?
TAD: I don't think so. But I don't work with a lot of compiled languages nowadays, so I don't know. I tried going to vscode.dev, and I noticed that some of the extensions I like don't work in the browser, which makes sense, you know, so that's the thing. Like, it's probably a good place to start. But, ultimately, most people shouldn't stay there. So, for my own maybe curiosity, but of the people here in this call, what was the first editor that you used? And what was the second editor that you used for actual developing and writing code?
STEVE: My first one was Sublime, and I stuck with it for a long time, I think four years. And then VS Code. I think I've tried something else along the way. I don't remember what it was, but I wasn't impressed, obviously, if I don't even remember which one it was.
KYLE: I started out with Visual Studio as my first one, and my second was actually Vi.
EDDY: What's Vi?
KYLE: Precursor to Vim.
TAD: [inaudible 27:21] Vim.
RAMSES: Just the original.
EDDY: Okay [laughs]. I know now. I use it from time to time when I shell into an environment.
TAD: Was Vi just because that's easier to use remotely on, like, servers and stuff?
KYLE: Yeah, it was part of a networking class. And we had to do all of our development on a remote server in the professor's office, basically.
EDDY: It's actually really funny how Sergio joined halfway through the call, and he mentioned Notepad, even though we were kidding initially. It just goes to show, you know, like, how embedded Notepad really is.
TAD: Well, there's Notepad, and then there's, like, Notepad++, which is different, but it's still a very simple but very intuitive editor.
STEVE: I didn't even know you guys were joking [laughs]. I was under the impression Notepad++ was just, like, a normal editor.
TAD: It is. Eddy, what did you start off with, and what did you...
EDDY: I started off with [laughs] Notepad and then...but it wasn't Notepad++. It was the Microsoft Notepad, you know, all the do-do that is given to you pre-installed to write notes. Like, that's how I initially started writing, like, HTML. And then, like, I opened the file in my browser, you know, and the file--
TAD: [inaudible 28:45]
EDDY: Yeah, it was great. It was super cool.
And then the next one, I believe, if I'm not mistaken, was Atom. Because, like, I joined forum groups and Reddit threads and, like, people talking about this whole new thing called Atom. So, I installed it, and it was, like, a full 180 for me because it was like, oh crap, going from black and white to, like, suddenly, like, my code is linted [laughs], you know. And so --
TAD: Syntax highlighting: so good.
EDDY: Yeah [laughs]. You're like, oh, your brackets know, like, if you have, like, nested statements, or whatever, you know, like, suddenly, your open and close brackets are aligned by color and stuff like that, which made it much easier and more intuitive. And using Atom for me has a warm place in my heart.
TAD: Ramses, what did you start with, and what did you pick after that? Or did you start with Vim and stayed forever with Vim?
RAMSES: No, I started with Atom and then went to VS Code, actually, for a little while. All of my professional development experience has been in Vim until now, that I'm in RubyMine. Outside of that, yeah, Vim all the way.
EDDY: Dude, you started out using Atom? That's awesome.
RAMSES: Yeah, that was probably, like, three years ago when I started using it. It worked out pretty nicely. I actually don't know why I stopped using it, just did. I've always been curious about different editors, so I've tried a whole handful.
TAD: Sergio, what did you start with, and what was your second editor?
SERGIO: Notepad ++ recently. Probably Notepad, the normal one, like Eddy. I used to learn in Notepad ++. Later, I tried many, I guess, most of the [laughs] IDEs out there. But I used to work with Java, and Java has their own IDEs like Eclipse and NetBeans. And also, that one included in Android, which is JetBrains with supercharged Java stuff built-in, I don't know, some mixing of things.
And lastly, I ended up with Visual Studio Code. It's kind of my favorite out there because lightweight. And I used to remember when I tried to open Eclipse on my computer, it was kind of, oh my God, it's draining all the resources in my [laughs] machine. So, oh gosh, that time was hard. And right now, I have a computer that is, yeah, better, and it's not draining all the resources. And that's cool. So, the only one that is draining resources is Unity because the nature of being greedy 2D and whatever else is kind of resource demanding. But everything else works fine in almost any computer out of there. But Eclipse is a nightmare [laughs] [inaudible 31:45].
TAD: Yeah, with great power comes great resource usage, great hardware abuse [laughs]. Yeah, it's funny that for some people, VS Code feels light. For other people, VS Code feels very heavy because it's basically a mini browser just to edit text, right? And so, if you're probably somewhere at the Emacs or Vim end of the spectrum, VS Code feels like a ton of resources and very heavy. But if you've worked with some of these bigger IDEs, VS Code is probably refreshing.
SERGIO: Yeah, yeah, I agree. I do have a question, maybe. Why I will use Vim? It is kind of new for me. I never worked in that before. It's kind of complex because you have to learn about when you have to use SS, or you have to edit, or something like that. I didn't know why I will use Vim. Can you answer that? Can you tell me someone that is actually using Vim why I will use this? Well, I understand it if you work on serverless stuff, you have to use it, and that's fine. But someone who is not using that for serverless, why I will use Vim?
KYLE: Their approach to modal editing is just fantastic. I find myself to be a lot more productive. Once you learn the Vim motions of editing text, it just becomes much more fluid. But the problem with it is it requires a steep learning curve, so, you know, not great. But once you get a hang of it, you just want Vim everywhere.
TAD: Yeah, I don't use Vim, but I know people who do and, basically, once they get really good, you're editing code at the speed of thought a lot of times, where your fingers are just moving automatically, and you're moving lines around. You're editing things across multiple lines. And, you know, the joke is you never have to pick your fingers up from the keyboard. You never have to touch that mouse.
But yeah, like, I tried Vim for about a month because I figured that I needed to give it at least that long. And I just don't think in that way. So, it didn't work for me, but people who think in a very Vim way they can be really productive, and it feels really elegant to them.
STEVE: I think you also mentioned one of the key things with Vim. And I'm not speaking from experience, but people that I've spoke to about it tend to not like using a mouse, so there's that. I think Vim is kind of is the go-to if that's you.
SERGIO: Cool. Okay.
EDDY: Yeah, some people are religious to not using a mouse, and I'm not calling anyone out, but I am looking at that person. Some people just refuse to use a mouse. And they really do try their best to never lift their hands off of the keyboard if they don't have to. And Vim does facilitate that [crosstalk 34:45].
TAD: Well, it's unnecessary motion, right? If you can keep your hands practically on the home row and move everything around, suddenly, excess motion feels inelegant, right? It feels like unnecessary wasted behavior.
EDDY: I feel like we can't end this topic without mentioning Emacs because Emacs is also a really strong competitor against Vim. And it's really solid out the gate.
TAD: Yeah, it's interesting because we all have mentioned that we develop Ruby, and Ruby was actually shaped by Emacs, meaning Matz, who's the original creator of the Ruby programming language, uses Emacs in his day-to-day editing of everything. And the elegance of Lisp, and how Lisp kind of did things, and the interpretation of it, and things like that, really influenced what he wanted in the language and really added to Ruby's development.
So, one maybe final question for you guys: is there an editor that you've tried that you absolutely hated? Like, you're just like, "Oh my gosh." You know, you tried it for, like, 10 minutes or something, and you just realized this absolutely is not the editor for me. And if you've had that experience, I'm curious: what was it about that particular editor that really you found so off-putting?
STEVE: Vi [laughs]. Because why would I use that? There's no reason for it. But every time I'm stuck having to use it just by chance, like, I don't enjoy it at all.
TAD: Is it the modal nature of it? Is it the fact that there's nothing discoverable about it? Like, what's the --
STEVE: Well, it's just I don't know how to use it, so I have to look it up every single time. Depending on how my environment is set up, I might find myself in a Vi session and, I don't know, maybe during a rebase or something if I haven't set my editor yet. And that always annoys me [laughs].
EDDY: I think there's benefit learning Vi, especially where we work, right? Because, you know, you shell into a certain cluster and then, suddenly, like, you need to modify some code. But you're like, ah, I don't want to, like, wait for my build to be ready again in order for me to make sure that this would have worked. And so, using Vi to go in there in your session and being able to change that on-demand is super cool.
KYLE: I think I run into the same things as Steve, just with Nano.
SERGIO: I have to say Eclipse a long time ago. But something I tried recently is Vim, and I didn't like it at all. But maybe I need to give it another chance to try to really understand why it was built that way, so maybe.
TAD: Yeah. The angriest I think I've ever gotten is using VS Code. This is way back in the day. And I was taking a class on UI development, and the first half was Java. We created, like, these Java apps with Swing. And the second half was with Microsoft, and we had to use these things called Microsoft Foundation Classes. And they were so complicated that the editor tried to fix things for you behind the scenes.
But sometimes you really wanted to have a certain thing in a certain place. And I would say, I need to make this button blue, right? So, I'd go into the code, and I'd change the attribute to make my button blue. And Visual Studio didn't think that was the right place. And it would take it out and try to do other things for me behind the scenes. I would stare at things, and I'm like, oh my gosh, I don't know why this isn't working. I don't know what's going on.
And it turned out that the editor was actually moving my code around without me knowing it. And I spent, like, hours sometimes trying to figure out what the heck was going on. If VS Code was a person, I'd punch it in the face [laughs], oh my God. It made me so angry to have an editor changing my code on me behind the scenes without my knowledge or permission.
Well, it looks like [laughs], I guess, maybe we're ending on that note. Anything else we should mention before we wrap this up?
RAMSES: What I gathered from it was that we should all use Vim.
TAD: [laughs] That's an excellent takeaway.
STEVE: Yeah, that's it.
TAD: If you have someone that comes to you and says, "I want to get into programming. Where do I start?" You point them at Vim [laughter] or --
EDDY: And if they still stick around, they definitely want to be a developer, is what you're saying.
TAD: Yeah. Or maybe you just point them at Notepad or vscode.dev or something like that and then see what they lean to. And then find a better tool for them later when they settle into something.
STEVE: Just ask them the question, "Are you a masochist or not?"
TAD: [laughs]
STEVE: And then adjust accordingly.
TAD: How's your self-esteem? Do you like yourself? [laughter] Cool, awesome. Well, thank you, everybody.
The panelists explore the value of learning new programming languages. The conversation begins with personal stories about their first programming experiences, discussing languages like Logo and BASIC and, later, more complex ones such as Java, Pascal, C, C++, Perl, PHP, Haskell, and Python. They emphasize how each language forces a developer to think differently about problems, highlighting the significant role of learning various languages in a developer's growth. They also touch on the practicalities and peculiarities of different languages, like the ease of PHP compared to C for web development and the sophistication of memory management in languages like Java and Rust.
The discussion then pivots to the core question of the podcast: the value of methodically learning new programming languages. Mike shares his perspective, noting that while he hasn't learned a new language every year, the variety he has learned has been crucial for his career development. Tad recounts an insightful conversation with Matz, the creator of Ruby, about the joy and utility of learning diverse languages, even those with limited professional application. This leads to a broader discussion about how each language, with its unique approach to solving problems, can add valuable tools to a developer's toolbox.
In the final part of their conversation, they delve into the future of programming languages and discuss the potential of domain-specific languages tailored to particular industries or needs and the role of emerging technologies in shaping how we interact with technology. Mike speculates about conversational interfaces and their implications for future software development, emphasizing the importance of adapting to new ways of thinking and interacting with machines. They end with an affirmation of the continuous need for learning in the ever-evolving field of software development, underscoring that learning new languages enhances problem-solving skills and prepares developers for future technological advances.
Transcript:
MIKE: Hello, and welcome to another episode of the Acima Development Podcast. I'm Mike. I'm going to be hosting today. And together with me, we have Ramses and Tad. Today, we're going to be talking about learning new programming languages, specifically what value you get from learning them. And beyond that [chuckles], not just learning them because you're forced to, but deliberately going out and learning languages regularly, you know, once a year or some cadence like that. And why would you do that sort of thing? That's the premise we're going to start with.
And before we really dive into the conversation, Tad, before we jumped into the recording, said, you know, a good place to start here is talking about the first language you learned. Like, yeah, you know, actually, that's a great idea. And thinking back to childhood, the first programming language I learned was Logo. They called it the turtle, but I think it's really just a triangle. And you [chuckles] make it go around the screen, and it leaves a trail behind it. And you could use it to draw pictures.
I didn't have a computer at home at the time, and I'd used it at school. And I thought it was just the coolest thing ever. I believe that it usually ran in a real-time mode, where it was interpreting what you put in. It was actually pretty sophisticated for back in that time. The read–eval–print loop is, you know, very common now in interpreted languages, but back then, that was pretty sophisticated.
My understanding is that Logo is a variant of Lisp. I didn't know I was learning Lisp. I was just learning how to move the turtle around. I thought it was the coolest. And I do remember that I could go back into a screen where you could actually write some code, rather than running in that real-time evaluation loop, and then have it draw cool patterns on the screen, and I thought that was just the best [laughs].
I remember thinking it was so cool, but then you had to have shared computer time with everybody else in the grade. It might have even been shared with everybody else in the school. So [chuckles], I didn't get a whole lot of time on the computer. And I didn't really pursue programming that much other than thinking that it was cool. Sometime after that, I couldn't say exactly when, but I think I had friends that introduced me to the BASIC programming language.
BASIC has a very different take on things. The lines are numbered. You always had to put numbers, and you developed a habit of incrementing by at least 10. You'd do line 10, line 20, and line 30. So, in case you ever needed to insert anything in between, you didn't have to renumber every line. I've had to do that [laughs] in BASIC, to go back and renumber everything. When my family first got a computer, it came with a BASIC interpreter. And we had a book, and I went through, and I did a lot of BASIC programming. And I did. I'd fill up all my spaces; then I'd have to go renumber everything.
The thing, though, about switching out of the languages, I learned about BASIC-supported subroutines, they called them. They had GOTO, so you just bounced around just at random [laughs]. If you wanted to be able to have any ordered thing at all, you would develop...it wasn't a function like you'd think about in more modern programming languages but the same idea what they called a subroutine where you could go to this region of code that would execute independently.
TAD: GOSUB [crosstalk 03:09] GOTO.
MIKE: Exactly. GOSUB [laughs]. I think you could even treat them as function calls and pass variables to them. Do you remember Tad?
TAD: You couldn't with the BASIC I learned. There might have been BASIC variants that could do that.
MIKE: Yeah. It seemed like they could maybe have return values. There was something that distinguished them from a GOTO. And then I did a lot of that when I was in my early teens. And the next programming language I learned was probably Pascal in school, and asked to learn Java, and C, and C++. And professionally, your first job, you usually end up picking up a language because you end up having to do stuff you haven't done before. I learned Perl and then did a lot of Java, PHP, web languages back in the day. But I ended up touching a lot of things. There was ColdFusion [laughs].
TAD: Oh gosh.
MIKE: Yeah. And then later, as I moved along in my career, there were actually some languages I learned just to learn, and I think I'm going to come back to that. But Haskell, specifically, is one that I deliberately chose to learn, and I'm glad that I did. I've learned Python somewhat in recent years, which has been a useful tool.
The interesting thing about this, I'd mentioned the subroutines [laughs], is that every one of these languages forced me to think about problems differently because these languages represent a way of thinking. They approach a problem in a slightly different way. There's a lot of overlap between them. Once you've learned one, it's a lot easier to pick up another. But making that switch between languages really forces you to recognize that maybe there's more than one way to think about a problem. And then you're forced to evaluate, well, which way do I want to think about the problem? And that switch between frames of thinking, I think, has been very useful.
I would strongly recommend that people take the time to learn other languages, especially languages that are very different than what you're used to. I think it's useful to learn Assembly language, for example, maybe not in-depth, but at least to understand how it works so you can think about how a processor works. I recommend learning a functional language. I've mentioned Haskell. It's a pure functional language that really forces you to think in a certain, very mathematical way, and it helps you approach certain problems differently.
And you should probably learn an interpreted language if you've been a compiled language person all the time and so on, approaching problems differently. So, there's my limited introduction. I'm saying this history of languages I've learned has helped me a lot, and I'd recommend others to do the same. Now, Tad, you've been talking a little bit. What's been your history with programming languages?
TAD: My first programming language was BASIC, which is probably really common for anybody who grew up in the '80s like I did. My parents bought the family an old computer. Texas Instruments used to have a computer that they sold that you could plug into your TV. It was called the TI-99. And if you put a cartridge in, then you could play that cartridge. But when it booted up, there was always a menu.
Number one was it dropped you into a BASIC shell thing, or number two was play the game. And so, after you've been using this computer for a while, you're like, huh, I wonder what that, like, number one option is, right? And it just basically just dropped you into BASIC. And, like you were saying, it came with a manual that gave you the basics of BASIC. It was, like, line numbers, and you'd always do 10. You're like, ten prints, you're awesome, 20 GOTO 10. And you're like, ah, like, you show your sister like, "Oh, look, our computer thinks I'm awesome," or whatever.
But yeah, like, that was just being able to have something to show up on the screen. It gave you BASIC syntax, you know, control structures like ifs and thens and all that stuff. If this, go to there; if else, go to this, that kind of thing. That was what I thought programming was all about was just big, long, BASIC programs.
And I remember later in the '80s, Macintosh Classics became pretty ubiquitous at, like, high schools or just different schools and stuff. They all came with HyperCard, which had a programming language behind it called HyperTalk. And I remember trying to look through the mail trying to figure it out because I looked at the examples, and they didn't have any line numbers. And I couldn't conceive of programming without line numbers. I was like, how do you go to something if you don't go to a line number? Like, how do you use your GOTOs if you don't have line numbers, right? And so, that was kind of an eye-opening idea that, wait a second, I don't need GOTOs at all? How does that even work, right?
MIKE: [laughs]
TAD: And HyperTalk was really interesting because it was very English-like. And the idea was you basically have a stack of cards. Each of those cards, you could put different buttons and different like UI elements on that card. And then, you could have those UI elements; each of them have some code behind them. And then you could swap between the cards and things like that.
And so, the very first thing that you could do was make a stack of cards and do a different picture on each card, and then your program would just be, show all cards. And that would just flip through all the cards and create a little animation for you, right? And just the fact that it was English and you could say, "Show all cards," and that was just intuitive, right? And was just kind of mind-blowing. You could set the speed that it shows all the cards. And so, something like that where it was very English-like, very intuitive.
But it was also evented. So, you could write little handlers. Like, you could say, "On mouse up," and then you would write the body of the things you want to do when the mouse is clicked, or whatever, or on button clicks and things like that. And so, it kind of put me into a mode of looking at things from, like, a UI perspective and event perspective, you know, messaging back and forth between the different elements and stuff. And so, that was a huge departure for me from BASIC.
And then probably the third language I learned was C, which, again, is very different because it's the first time I ever had a compiled language. It's the first time I really thought hard about functional programming, probably the first time I ever encountered libraries and shared libraries. Because I'd have to yell pound, include standard io at the beginning, right? You don't just get that for free. You have to, like, ask for io stuff. You have to set up a main function. You have to do those sorts of things. So yeah, that was also a very different language from the first two I learned as well. So, anyway, yeah, like, it's all very interesting to learn.
MIKE: You talked about HyperTalk changing your perspective because you thought, oh, things don't have to be this procedure where you control the flow yourself. The language can do some of that for you.
TAD: Right. Yeah.
MIKE: And teaching you about libraries. I mean, those are major concepts, right?
TAD: Yeah. I mean, my simple BASIC interpreter didn't have libraries. HyperCard just had everything built in. You didn't, like, grab things from external sources. I think you could, but I had no idea of what that was or what it meant.
MIKE: So, you know, there was that step, the step between this in a progression. Sounds somewhat similar to the things I did, I have learned over time. So, Ramses, I'll ask you, I don't know how many languages that you have worked with.
RAMSES: Certainly not as many as you or Tad, I'm sure [laughs]. Probably started with Lua, I want to say. Like –-
TAD: Oh, nice, yeah.
MIKE: Embedded development.
RAMSES: Yeah, it was great.
TAD: A lot of kids are, like, Roblox and stuff when they start learning Lua.
RAMSES: Yeah, it's a pretty good platform for that. It teaches a lot of the basics and gets you familiar with a lot of the core concepts of programming and, you know, communicating between client and server and back. And my primary, of course, is Ruby, mainly Ruby on Rails. I do have experience with JavaScript. I'm currently learning Java, and I have tinkered a little bit with Elixir, not enough to be proficient.
MIKE: Well, let me ask you a follow-up question. Maybe I should ask about Elixir because it stands out among those as being distinctly different. But there's, I mean, there are differences between those languages. What's something that surprised you or helped you progress from one of these languages, Ramses?
RAMSES: Mostly curiosity, I would say. That's the biggest driver for why even try to approach something different.
MIKE: Absolutely. Curiosity kind of drives the learning. What is something you've discovered in a language that made you think, oh, well, that's different?
RAMSES: Well, I don't know if this is the biggest one, but I thought the pipeline operator in Elixir was very interesting.
MIKE: I was talking with some people about that this morning [laughs], just this morning, comparing that with an attempt to do that in a language that didn't support it. That didn't work out so well. That pipeline idea of having a series of steps that you can break out on it's a great idea, right?
RAMSES: Yeah.
MIKE: Once you see it, you know, like, you can't unsee it [chuckles]. Like, wow, that's a good way to approach a problem. And, Tad, you've mentioned a couple of things that were enlightening to you [laughs], the epiphany. Are there any others that have really stood out to you?
TAD: I did a bit of Closure for a while. Ruby is Lispy, but it's not Lisp, right? Ruby has certainly stolen a ton of Lisp ideas, but it's not, like, that pure. I see a bunch of parenths on my screen. Everything is nested parenths Lisp. And they also have, like, a kind of a threading operator—I think that's what they call it—that kind of pipes things through. And I mean, with C, you get pretty functional. But Lisp is probably the grandpa. I'd say it's probably the purest, most influential functional language there is.
So, once you get into that mindset of, oh, everything is data, everything is streaming data and transforming data, it's interesting how you start to see every problem of, oh, how could I just make this as a series of pieces in my pipeline and my data is just going to flow through them all, right? And you realize, oh, this is very predictable. This is very easy to test. And it's really interesting to get put into that kind of functional programming mindset.
MIKE: I can say you're noticing a similar idea of these pipelines.
TAD: Yeah.
MIKE: There was a moment for me...I could talk about a different language, but, actually, it was, I think, a comment I read in a book I was reading that said, "Well, if you think about SQL and how it does things, that's basically the way that functional languages do things." Like, wait, what? I've thought deeply about that since. SQL or SQL, some people call it, sometimes it stands for some things, sometimes it doesn't [chuckles]. The language used for creating databases.
It's this widely used language that is completely declarative. There are, like, variants on it that allow you to do some procedural stuff where you can have loops and so on. But out of the box, you can declare the kind of transformations you can run on the data you start with to get a set of data out. And you might think, well, what good is that? What good does that do? All you can do is transform data. I mean, does it do things? And yet, it manages to be kind of the foundation of a lot of what the web is built on, right?
We have databases. We have data storage. And somehow, you need to present that to your users, and in between, you need to transform it. And I don't know if I want to say we overthink our value, but I don't think that's quite true. I think I would rephrase it differently that sometimes we don't recognize how valuable it is to be able to take some source data, run some transformations on it, and display it to somebody.
You think of even a social network, pick your social network. Somebody who's listening to this 20 years from now they'll go, "Huh, they were using those?" [laughs] But what's the biggest one today? It's probably Facebook. You know, they collect vast amounts of data on people, maybe scary amounts of data [chuckles] on people. And then, they compile that together and present it to you. And it's really data transformation. And they start with some source data, they mix it with some rules, and they show it to you. And they've managed to build this massive company. It's one of the top five most valuable companies on Earth. It's what they do.
Or you look at, say, Google, that has powered the, you know, web for four decades now. They store a bunch of information about their web crawls, and they show you that data [chuckles] after they've, you know, stored it and indexed it. The ability to efficiently store information and efficiently take that information and somehow transform it into a useful format to read because, you know, the whole web out there is not very useful to me because it's too much. I can't find anything in it.
But if you can save that in a way that's well indexed and can be returned to me in a sorted form with the most relevant things up front, well, that's exceptionally valuable to me, you know. It has made them vast sums of money because it was incredibly valuable. Advertisers have spent a huge amount of money on these platforms because people use it because it improves our lives.
So, this transformation of data, this idea that you start with some data, you run some transformations on it, and you get data out on the other side that's in a more useful form, I think is fundamental to most of what we do in software development. And once you think about that that way...and both Ramses and Tad talked about this kind of pipeline idea, that you start and you go through these series of transformations, and you get something out the other side. It's been transformative to me.
I think I mentioned I studied Haskell a few years ago, a functional language. Everything's built around that idea. And internalizing that idea, of course, not just from Haskell but from other resources, I think has been very influential on me as a developer, and some of the best code I write is rooted in those ideas.
TAD: What's a language that's on your radar right now?
RAMSES: I know Python is kind of the new hot [inaudible 17:49]. It's been the hottest for a while.
MIKE: Yeah, the old hotness [laughs].
RAMSES: The old stuff. I mean, there's --
TAD: Since the '90s.
RAMSES: Yeah, it's kind of a big one currently; probably would like to learn it more at some point. But, my current focus is Java.
MIKE: If you know Ruby, switching over to Python is almost trivial, not completely. They're slightly different, but they have very similar paradigms. My language, I would say, Julia.
TAD: Oooh. For data stuff, huh?
MIKE: Yeah, I've been interested in data for quite a while. And I am really interested in machine learning. And a lot of machine learning world is using Python. That's mostly what I've done with Python. But Python is not known for being efficient [laughs]. There's people working on that. There's people working on that, I'll say. I'll give them credit for that.
But there are, you know, lots of different tactics people have taken to try to deal with them; one of those is to create a new language, and Julia is one of those. And that's one that I've been interested in trying out. You know, I don't know that I'd use it on a day-to-day basis, but I'd like to see that approach to the world. What about you, Tad?
TAD: I remember when Swift came out, they gave you a free book like, Apple says, "Here's a book on Swift," when it first came out. And I've always thought that Swift looks really interesting. It's obviously a language that has drawn on a bunch of other languages and looked pretty clean.
And some of the interesting things that I liked about it that I'd like to see in other languages are optional typing because I don't love forced typing. But I think typing can be useful sometimes, right? And so, I'd like to steal the idea of optional typing from a language like Swift and then give it to maybe a language like Ruby, right? Because Ruby is all dynamically typed. But I'm like, uh, sometimes I'd like to have types.
I've had some Elixir books for a while. They do some really interesting things, especially with their matching, where it's basically make this side match that side. The destructuring that you see kind of popping up in other languages has largely been inspired by Elixir and its ability to just really nicely destructure things, right?
MIKE: Yep. That pattern matching has been a thing in functional languages for a while, and it's cool.
TAD: Yeah. I think Elixir really took it to the next level. I don't know of other languages that did it. Well, I'm sure Erlang does just because what's under the hood of Elixir [inaudible 20:27]. Elixir put a nice, approachable veneer over that whole beam, the whole ecosystem there.
What other languages are interesting? I like Lua. I learned a little bit of Lua with my kids. I think it's like a better JavaScript. I wish that they would have discovered Lua, and we would have had that instead. Rust has been on my radar for a while, but I just don't have any use for it in anything I do day to day.
You know, just speaking about how languages change your thinking, I did a ton of C in college. And then, when I got to some of the upper-level classes, we started doing Java and stuff like that. And I was like, oh wait, what? You don't have to do memory management? There's a garbage collector? Wait, what's going on? Like, the fact that I could basically run my Java programs cross-platform-ish, you know, on the JVM for whatever operating system I was on.
And Java, you can kind of fake it where you could put pointers to different references...I forgot. I haven't done Java in a while. But you could mix and match an array, and you could stick different objects in an array if you just made your array object references. I was like, wait, I'm getting tricky, right? But yeah, the fact that Java had different memory handling was really interesting to me. And Rust, I think even more so, the fact that you can get the performance of, like, a compiled language with memory safety, and you don't have to hand that off to a garbage collector, is really interesting, I think.
I've seen the argument or the joke: you're just moving all that stuff from the compiler into your head, where you just have to think real hard to do your memory management instead of letting your compiler or your language do it. But yeah, so there are still languages coming out that have interesting ideas that I'd like to explore.
MIKE: I think that provides a good pivot to what kind of our central theme was that we wanted to talk about in this podcast. We've talked about some value we've gotten from languages. What's the value in methodically going out and learning them? Is this something people should do, and if so, how often and why? And maybe a split question: what happens if you don't? [laughs]
I will say I have not specifically made a point of learning a new language every year. But if you add up all of the languages that I've learned, I'm probably not too far away from it because there are a lot of languages out there, especially if you count non-procedural languages, you'll get HTML, CSS, SQL, even, like, Regular Expressions. There's a lot of languages that we learn as developers, and if you start adding all the languages up, it can add up to quite a few. And I think I'm not too far from one a year.
I would say that if I hadn't done that, I would not be in a good spot. If I'd stuck with Perl, I'd be an aging guy still doing Perl [laughs]. And Perl's not a bad language, don't get me wrong. But professional opportunities are rather limited nowadays in that language [laughs]. And it has a lot of interesting ideas. Perl is actually a fascinating language where they've experimented with some things, kind of tried to push the boundaries. It's Larry Wall, right?
TAD: Yeah.
MIKE: That built the language. He studies languages professionally. He really thinks about interesting things you can do with language. So, great language. I'm not saying something bad about Perl. But if I was just doing Perl, or if I was just doing Logo that I learned in elementary school, again, it's a Lisp variant. Lisp is great. We've talked about that already and how it helps us think, but there are some constraints there.
If I had not moved into modern variants of Lisp, if I had just stuck with what I had, then it would have constrained the boundaries of my world. And I'd rather break down some of those walls and go explore places that I hadn't been, and maybe find places that I'd rather be. What do you all think?
TAD: It's interesting because I actually was at lunch one time during a conference, and, Matz, the creator of the Ruby language, was at lunch with us. And we were talking with him, and he learns all sorts of languages all the time. I guess that makes sense. If you're the creator and a maintainer of a programming language, you want to scan what's out there and see if anything's interesting to incorporate into your language.
But for him, he learned languages that he wouldn't even consider including in Ruby, right? Like, he told us, "I love every language. I just love learning languages. And I love every single programming language." And we kind of poked him on that a little bit. We're like, "Well, do you love PHP?" And he's like, "Yeah, I love PHP," or like, uhhh, or a groan, or whatever. And we threw a bunch of languages at him, and he's like, "Yeah, like, I just love to see what language designers are trying to do. I love to see what languages are about." And his take was every programming language offers something interesting for him. And so, that was a really interesting conversation.
I don't love every language. But he's probably right. If you stop and think, what does the designer try to do? What is a problem set that this language is trying to accomplish, right? Then maybe that gives you another tool for your toolbox. I don't know Fortran, but I imagine if you're a scientist, Fortran is, like, an amazing language, right? You're like, oh man, this maps really well to my whole world, you know, like everything I need to do. I think I probably should be learning more languages because there's still a lot of new ideas coming out, right? And every language that you've learned shapes your thinking a little bit.
You look at Ruby, and then you can see, like, oh, Matz uses Emacs. So, he did a bunch of Elisp, and Ruby is heavily influenced by Lisp. And he did Perl programming, so Ruby is influenced by Perl. He loves object-oriented stuff, so Ruby is very Smalltalk-influenced and stuff like that. And you can see how, for him, he wanted something that made him happy. And he's like, these are some parts of other languages that make me happy. I'm going to instill them all into a single language, and that will be my ideal language.
But other people have other ideal languages. I think every language designer the language that they design is probably their preferred or, I mean, Rich Hickey loves Closure, right? Like, he thinks it's the ultimate best language. He is just sitting in his hammock thinking about Closure [laughs]. Like, he has a lot of stories of him just working out new ideas about his language, just sitting in the backyard.
MIKE: You brought up a couple of interesting things. You said Matz loves PHP. The first time I used PHP, I loved it. Now, let me put some qualifications on this. I have actively avoided doing PHP professionally for a long time. But when I first used it, the very first time I used it, it fulfilled the need I had at that moment.
It provided me a template with some simple access to code so that I could put some control structures into the template; you know, I could loop a section, for example. And if you think about what it was good at and its purpose, you know, the reason it came into being, for people who are met with that need, that's an extremely useful language and has been widely used, you know, around the world for a long time.
TAD: Did you ever generate HTML pages with C?
MIKE: Oh.
TAD: Or did you do any of the cgi-bin kind of stuff?
MIKE: I have done it a little bit with C, and, boy, that's --
TAD: Yeah, I did it, and it was absolutely awful [laughs]. It was the worst. And PHP was a breath of fresh air.
MIKE: Exactly.
TAD: Like, it was, you know, ten times faster to make a webpage with PHP than with C.
MIKE: Absolutely. At least ten times, right?
TAD: Oh, absolutely, yeah.
MIKE: Maybe 100 or [laughs] more, depending on the specification of your page.
TAD: You're like, oh, the string manipulation, ugh [laughs].
MIKE: Yeah, and PHP maybe has a bad, you know, I said I've avoided it. Maybe it has a bad reputation for some of the security issues that it's had in the past. But, you know, I think they've mostly gotten around those. And they've got good modern frameworks, and you can get good work done in PHP. And understanding where it came from, you know, it's served that purpose well. And to your idea about building your own, a year or two ago, we built, as a group, during our Skills Clinic time when we were building our skills, we built some programming languages. And that was fun.
TAD: Yeah, one of the crazy things is we decided...one of our languages we created was basically a text adventure as a language [laughs]. And it's not super useful, right? But it's, like, can I build a language around the idea of text adventures? And the answer is yes.
MIKE: Yes, you can.
TAD: It's weird. It's probably not the most efficient way to code something, you know, grabbing equipment and putting it in your backpack and moving things around into different rooms. And [laughs] I forgot Dave and I had a bunch of plans for it. But it's that kind of thing. There's still novelty out there. There's still new ideas that you can incorporate.
MIKE: And we laugh about that language. You know, in early computing, you spoke computer language. You spoke, you know, machine language. You used to punch a card, and here's the zeros and ones. You know, you'd look things up in the processor and map. And you'd call those instructions directly, you know, you kind of mapped your mental model to those series of instructions. And that only scaled so far.
It wasn't very long before they came up with tools they wrote using machine language to be able to interpret something at a higher level, to take characters that looked more like English and map those to machine instructions. And they built Assembly language [laughs]. And in that many years writing in a language like that, they think, well, what if we could take that to its next level? What if we could take higher-level ideas and map them down to machine instructions? And so, you started getting compiled languages.
And in the last, you know, really for a long time, it didn't take very long to get from compiled languages to interpreted languages. We've talked a lot about Lisp. And there's a lot of interpreted languages, like, we talked about JavaScript, and PHP, and Ruby, and Python that power a lot of the modern world. And it's a higher level of abstraction. But if you think about what happens next, what if you have tools like the large language models that are coming out? ChatGPT being a prominent example.
What if we get to a situation where we're interacting with our computers in a little different way? And you can generate effectively, generate compiled, or interpreted programming languages. Well, what does the interface look like then? It's a lot different, right?
TAD: Yeah. Is it a conversation interface? [laughs]
MIKE: Exactly. But it's still an interface. And the ability to think methodically is going to be a valuable skill that I don't see going away, ever [chuckles], because being able to clearly communicate what you want to happen is valuable, whether you're using your punch cards or whether you're speaking to a conversational interface to build software that layers and layers and layers down. Those layers are just going to keep happening. Those layers are going to keep growing. And being able to think at a higher level, well, maybe I want to think in terms of [laughs] exploration of a text game. That might be really useful.
I remember interacting with those [chuckles] years ago and wishing that their interface was a little more useful. Having a more useful interface that made a lot of sense could be a lot of fun. And maybe it could be a great thing, even embedded in another game. And I think we should be thinking about those and shouldn't be too surprised when we have conversational languages that come up in the near future.
TAD: Well, another thing is, a lot of these languages answer, like, what-if questions, right? You're saying, what if my programming was backed by a large language model? But most of these languages are like, Lua is like, well, what if everything was tables [laughs], right? And Forth is like, what if everything was stacks? Or you got, like, you know, and Haskell is like, what if everything were functional? I'm curious: what are the what-ifs that you think are going to be questions for programming languages in the future?
MIKE: You're thinking about the large language models. There's a grounding problem that's long existed in machine learning, which is you can train something in a simulation, but your simulation doesn't really match reality. And it's really hard to take software that you've trained in a very sterile, controlled environment and make it work properly in the real world, which is messy. I think that a really interesting question is, what if the real world existed? How do you deal with that? And how can we build interfaces that interact with the real world in effective ways without destroying our hardware?
You know, you got a robot or robot defined broadly, you know, I've got a self-driving car, for example. And the self-driving cars today they are these bespoke software. Some of the most effective companies...well, I think all of the companies effectively doing self-driving cars software, there's certainly machine learning that goes in there because they learn to see and interpret their environment. But there's also a lot of heuristics that they have to use [laughs]. You know, where are you on the map? And so, you end up with this really kind of messy model.
And I don't know exactly what this programming language would look like. But thinking about the kinds of problems that we're getting to with some of these large language models, with a higher level interface, we might start thinking about and, you know, other things that have happened in computing that allow us to understand the world in better ways. I think that we're going to maybe think at a higher level of abstraction to say, well, I want to build web pages. What if I could tell a computer to do anything? What would I tell it to do? And what kind of constraints would I run into?
So, you're thinking about stacks. Well, you know, with some of the advances in computing, I might be able to say, "Hey, build me an app that will do such and such," and it can give it to you quickly. So, you have to think at a higher level, well, what kinds of apps do I want to build, right? [laughs] You get into that higher level of thinking, well, what is a business need that I need to solve?
Or, if you think about robotics, what is a real-world situation that I might need to deal with? You know, do I need to deal with a hazardous environment so I can do clean up? Or do I need to deal with sweeping minefields and removing mines after a war? You know, what are some of those constraints? And then we start thinking about, well, what are the real-world problems that I'd run into?
I'm kind of jumping out ahead. But thinking about this idea of having an interface that's more conversational, I think you start thinking about your problem domain more. You know, what if the world is made out of programs that are written for you? I think that you still have problem domains you have to deal with. That was my take.
TAD: One thing that I am curious about is we see so many languages out there with so many different attributes. I wonder if you could create domain-specific languages. You can just say like, "Okay, here is my industry; here's my domain; here's my needs. Generate a language with all the features that would work well in this domain." I mean, I alluded to it a little bit. Like, Fortran is, obviously, very specific to, like, you know, science and mathematics. And COBOL was specific to, like, business needs and things like that.
What if the language itself became a little more abstract? Where you're just saying, like, you generate a language. You give me a language that would be ideal for driving a car, right? And then, give me a standard library for that language for driving a car. And then, I will use that standard library as I develop the software. I mean --
MIKE: That's a fascinating idea.
TAD: Is there a reason why we couldn't get there soon? I don't know if that would be beneficial, but...
MIKE: Well, why not? Every profession has its lingo, right?
TAD: Oh yeah.
MIKE: It's things that they do. You know, why not? If we already have systems that can build software, and a programming language is just a kind of software, I mean, that's something that could be perfected, maybe not perfected, but, you know, but greatly improved. Build me a language that has these attributes for this business domain or even outside of business for this fun domain, right? [chuckles]
TAD: Yeah.
MIKE: I can describe the instructions, you know, build a language that will let my kids interact with their game of choice and do cool things in it. That sounds like a really valuable idea.
TAD: Yeah, I've got several Amazon Echos in my house, right? My daughter is like, "Hey, read me a book. And hey, do these things for me already." I don't even think to do this, but for her, it's part of her world. When she wakes up in the morning, she says, "What time is it? What's the weather today?" Like, those are the first two things she asks, my little eight-year-old kid. She's like, "Oh, cool." And then she picks her clothes based on what the weather is going to be like and whatever.
But what if it was like, hey, help me build controls for the TV or something like that? And give me a language that an eight-year-old could understand that could control some of the appliances in my house. And then, it would just say, like, "Okay, here. [laughs] Here you go." I don't know; that seems possible in the near future.
MIKE: Yeah. Ramses, where do you think the programming languages are going following our thoughts? Do you have anything you'd like to add to that?
RAMSES: Yeah, I think it is interesting, and it seems like there certainly is a kind of a culture shift with how we interface with just technology in general. I'm really interested to see how that sort of [inaudible 38:31] in the next few years
MIKE: Well, and to kind of tie this all together, it will be fascinating to see how it shakes out. But in all of this, we're going to have to interact still, right? We're going to have to interact with these machines if we want to use them. And to do that, you have to learn how to talk to them [chuckles]. It's a learned skill. Regardless of all of the layers that are underneath, there's still a learned skill in getting better at communicating with the machines, which means you have to keep learning. You have to actively seek out and be learning new ways of thinking about the problem and learning those languages.
In my mind, it is pretty definitive. It was maybe going into the conversation, but it's only reinforced my belief that learning languages improves your ability to think about the world and improves your ability to get things done, and that's not going to change. Even as we develop more powerful interfaces, that's still not going to change.
RAMSES: One thing I'm curious about is the cadence in which we might learn a new language. You know, you'd probably learn it just maybe once a year or once every couple of years, depending on how maybe complex a language is or your rate of absorption in the language. But sometimes, it seems like it might be out of necessity. You might work at a place that adopts a new tool, so you have to learn it if you don't already know it.
MIKE: It's interesting because early in my career, career and studies, there was probably a five-year period where I learned between 10 and 20 languages, to some degree, not perfectly all of them. But I remember doing an accounting, and I think it was somewhere between 10 and 20 over five years, which is generously more than one language a year. And I think it was closer to the 20 category. Again, not every language learned well because there was a lot of stuff being thrown at me at the time. I was working on a lot of different things, so I had to learn a lot of different languages. And I think that was really useful. It helped me see a lot of things in a different way.
But then I became more of a specialist, and I think that's a natural progression in a career is you specialize. Even in medicine, for example, you know, there's a lot of generalist learning you do. And then, in the end, you specialize and focus on a particular area. And I think that's a natural progression in software is that you kind of need to specialize if you want to get good at one thing. Because if you're a generalist in everything, you're not going to be as good in all of them.
So, learning a lot when you're starting and then focusing, I think, makes a lot of sense. But then, the cadence afterward, I would still argue that you should probably be...I'm thinking at a cadence of maybe once every few years, you know, between one and five, you should be learning something new because, eventually, that specialization might peter out. There's value in having a specialization, but some of those specializations lose their utility over time.
TAD: I've learned a ton of languages, but I don't know that all of them were useful.
MIKE: Would you say at this stage of your career...you've been doing this for decades.
TAD: Wow. I've probably been a developer for 20 years or so.
MIKE: Yeah. What cadence do you think makes sense for you to be learning now? I mean, would you just learn a new language if you had to switch jobs? Would you argue for continually learning new languages so that you're ready for the next thing?
TAD: Yeah, I think there's probably two different arguments there. Because you probably want to learn things that are relevant for the job market, right? Like, you don't want to be the guy that's still coding COBOL, or maybe you do. I mean, there's still a ton of old systems that still need COBOL programmers and stuff like that. So, there's, like, the financial, like, job thing.
But then there's just, like, the personal betterment, like, personal enrichment aspect to it, and, for me, it's a matter of time and a matter of novelty. Like, if I have the time and if I encounter a language that's different than anything I've seen before, I'd look into it. I'd probably learn it. But I see some new languages, but it pretty much covers all the same things I've seen in languages that I already know. I'm just kind of like, eh.
That's probably the biggest reason why I haven't learned Python is because Ruby kind of scratches that itch for me or fills that niche. It's an object-oriented, interpreted language that's multi-paradigm and has some cool features, right? And so, I'm like, uh, maybe I'd learn Python if I needed to do some data stuff or if I had some need. But I probably won't learn Python just because I wouldn't learn anything radically new from it.
MIKE: Sounds like a good checklist [laughs]. Does it help me learn something new? Does it provide utility?
TAD: Yeah. And so, that's why you probably learn a lot more when you're new and younger than when you're old like us when you're like, I got, like, 20 languages under my belt. 21? Eh, right? Maybe you're a little more discerning.
MIKE: Like we've been talking about, there may be some new things coming in computing that would mean that number 21 is going to be really valuable [laughs]. Well, I'm looking forward to seeing what that language 21 is. I'd like to see a language called 21 [laughs] that meets those needs. There's probably one out there [laughs] I haven't found.
But, you know, this has been a great discussion. I really like some of the thought-provoking questions that we haven't had answers to, recognizing there's a lot out there yet to learn, and that will still be happening in computing. I'm excited. With that, we'll catch you next time on the Acima Development Podcast.
The panel dissects the world of machine learning and artificial intelligence. They unravel how machine learning algorithms function, using the game of Pac-Man to break down complex topics like reinforcement learning and reward-based systems. Mike dives deeper into reinforcement learning, explaining how it operates on reward signals that assess the value of a series of actions over time. Dave chimes in with his insights on AI's ethical considerations, arguing that lacking a moral framework could lead to unintended and potentially harmful outcomes.
They navigate the expansive "state space" concept in machine learning, using chess as an illustrative example, and explore how understanding all possible board states and moves can help develop an unbeatable chess AI agent. This sets the stage for a pivot to natural language processing, where Taylor provides a thorough explanation of transformer architectures, including sequence-to-sequence problems and attention mechanisms.
Dave returns to his earlier point about ethical considerations, spotlighting the importance of the paper "Attention Is All You Need," which has been instrumental in developing transformer models. He then shifts to the challenge of making AI systems more explainable. While Taylor and Mike acknowledge that the complexity of neural networks makes them difficult to interpret, Dave insists that striving for explainability is crucial to making AI more accountable and transparent.
Transcript:
MIKE: Hello, and welcome to another episode of the Acima Development podcast. I'm Mike. I'm going to be hosting today. And we have a panel with us here today of Dave, and Taylor, and Francisco. Welcome, everybody. Interesting topic we're going through today. And we're going to approach it a little bit differently than we've sometimes done in the past. We're going to be talking about the fundamentals of machine learning.
Taylor is with us from data science. So, he does this for a living day in and day out.
TAYLOR: Yep.
MIKE: And has the smarts here to talk about it. I am very interested in this topic. I have been for a long time [laughs], honestly, since I probably heard about it as a kid [laughs]. So, this has been a long-standing interest of mine. And I've played around with this. I follow the topic closely, but I am not a professional practitioner. So, hopefully, that'll qualify me to at least give you an overview. And we're going to lean on Taylor [laughs] to be the expert.
Usually, we have a heavy panel discussion. We do have a panel here today to have a discussion. They will maybe be doing more question-answering and filling in the blanks. The goal here...I was talking about this in our pre-call discussion that I'd like somebody who listens today to walk away and say, "You know, I have a basic idea of how this works. I might not be able to implement it, but it's not magic, you know, it's not this dark magic. It's just somehow these machines can think." But you have an idea of how this might work.
I wanted to start by telling a story. Grounding things in real-world stories is usually very helpful to help us conceive of how things work. The story is about a hike I took a number of years ago. And I couldn't tell you what year it was. It was a long time ago. A friend of mine and I decided to go hiking up in the mountains, and we hiked several miles up a trail. And I really wanted to try something different. My buddy had not done a lot of hiking. So, my ambition was probably bigger than it should have been. Chris, if you ever listen to this, I'm sorry.
And we decided to go on this hike. And I wanted to try a new route that I'd never been on before because I knew that there were trails and two parallel canyons. And we were going on a canyon that was not that deep up high up on the ridge line. And there was a canyon parallel to the one we were in that was much lower, hundreds of feet down, hundreds of meters for anyone not in the United States, at least 100 meters, right? It was a long way down into this parallel Canyon. And I wanted to see if we could find a route between these two canyons in an area that was trailless.
It was late spring. I thought, oh, this would be great. The weather's nice. So, we went up. We hiked up the one canyon, got up to the high spot, saw what was an easy place to drop over into the next canyon. And we went over the edge. And it turns out that there was still late spring snow, like, all the way down that canyon wall down through the woods that were there [laughs], and decided to do it anyway.
But it was smooshy snow. It was, like, up past our knees. So, we were just postholing, you know, stepping into it. You jump down in up above your knees with every step going down this hill. And it was hard work. We were just absolutely exhausted. We did, however, eventually find the trail that we were looking for. And the way we got there was really very simple. I knew that it was down, and I went that way. We had to walk down through the woods, you know, I didn't have a compass. I didn't really have a map of the area. This was kind of pre-smartphone era. This was a long time ago.
But I did know how to make my way down. And I knew the trail was at the bottom of this canyon. So, what I did was I just walked down. Now, there were certainly obstacles along the way. Again, it was forested. There was a lot of trees to weave our way through. But for the most part, that was obscured by the snow; we just had to, at every point, say, well, which way is down? And take a step in that direction.
And when we finally got down to the bottom, there was the trail. And [laughs] we were finally free of the snow. It was wonderful. We got out of the snow, and not much further was the trail. And then things were much better, and we walked down and made our way back, you know, to the car, which was a bit of a walk because we had to go between canyons. Again, Chris, I'm sorry. But we did find out that there was a way.
Why am I telling this story? It's because you might think that machine learning is based on something really sophisticated and complex, but it's actually a lot simpler than you might think. And the basic math that it uses is something that you probably learned in either junior high or high school. So, think back about your math. And if you're not a math person, think about this mountain I'm talking about, or think about a road that you have to drive that's got a hill.
And there's really only a couple of things that define that hill. First of all, how steep is it? [laughs] Like, it matters how steep it is, and that's kind of a direction. And where's your starting point? Like, if you're starting most of the way up the hill, then you don't have very far to go, right? If you're starting at the bottom of the hill, there's a long way up. So, there's kind of two parameters that define that hill, which is how steep it is and your starting point. Now, I'm simplifying some here.
But in the math that you may have learned way back when and try to remember, you may have learned something like y equals mx plus b, which sounds really mathy, but that's really trying to tell you something simple. It's telling you that you have some input, and you're going to multiply by that and then add a number. Well, and that's still not very practical.
The second example I'd like to give is one I usually think about, and there's a few that we could think about. But the one I usually think about is, and that I've seen a lot online, is, let's say, that you want to predict how much a house is going to cost. You want to predict how much a house is going to cost. And you only have one piece of information to predict that, and it's the size of the property it's on. And there's probably a pattern there, right?
I would imagine that if you're on a tiny city lot, the value is probably going to be lower than on a large city lot. If you've got a house on a large city lot, that's probably a pretty valuable house because city lots are expensive. And there's going to be a lot of noise in that data, though, because that tiny city lot is probably worth a lot more than a tiny country lot. And, you know, maybe it's in a neighborhood where not many people want to live. How close is it to public transportation? I'm going to get back to that minute.
There's all of these other things that you could measure. But we're just going to think about one thing, the size in... we'll say in square meters or square feet. I'm in the United States; I'll say square feet. I know that [inaudible 06:07] allows a unit. Meters are better [laughs]. But it's what is commonly used in the United States. So, you know the square footage of your lot. And you want it to have that one number and predict what the price of a house will be.
Now, let's say you're doing it within the city. Well, there's some simple math you could do there. Here's what I'm going to propose you do: you take the size of that lot in square feet, and you have a number, we'll say 1,000. That's a very small size, but I'm going to use a small number. You can say that 1,000, and you will multiply it by a number, by some weight we'll call it. And you'll get another number that you say that's the price of the house. But you're going to add one other thing, and that is, where does it start? Because there may be a floor to how low the prices will go.
It may be even if you have a square-foot lot, it's worth something. It's still worth something more than zero. So, you've got a starting point that's higher than zero. Or maybe you're in, like, Detroit after they went bankrupt, and some property values are worth less than zero, right? [laughs] The city will pay you to take them [laughs]. Either way, there's a starting point that may be above zero. It might even be below zero that the zero, you know, the property with no size would still be worth. And then you go up from there.
And I'm going to call that value...I didn't give it a name. They call it in the machine learning world the bias. They call it the bias. That's the starting point. And the other one, that multiplier you use, is usually called the weight. There's another name you can call it, though, on a line you often heard in math: slope. It's the slope. If you want to get fancy and you think about the steepness of the road that I mentioned before, they call that the grade.
And in math, if you're thinking about a complex grade where it's in multiple dimensions, they call that the gradient. They call that the gradient. But it's really just a fancy name for the slope, you know, how steep is it? And so I got two numbers: the weight, which is the steepness, and the bias. Where's your starting point? So, I'm going to look at Taylor here. So, you with me, Taylor? What gaps do you think I have left so far?
TAYLOR: No, I think you're doing pretty well. I mean, that's why we call the y equals mx plus B slope form. It's describing lines and their slope and how they traverse through [inaudible 08:21] space. When you were talking about traversing from different trails––last time, obviously, you're talking about gradient descent here.
MIKE: And I'm going to get there in a minute [laughs].
TAYLOR: Yeah. And one of our co-workers had a sticker that he gave when he left, and it was a ski resort called Gradient Descent or, like, Gradient Slopes or something like that.
MIKE: [laughs].
TAYLOR: I thought that was a really cool sticker. It's a fun play on words. But no, I think you're doing a great job of explaining these concepts so far. I could interject with a lot of, like, data science terms for these. But I think for explaining to a junior high student, then we're spot on.
MIKE: Well, excellent. And you're like, what does this have to do with machine learning? You're talking about the stuff I learned back in junior high.
TAYLOR: [laughs]
MIKE: Well, and here's where the next step is that we really get to magic. I'm going to go back to this idea of houses; then, I'm going to use this to tie things together. If you have ten houses that you want to do this with, and you say, well, here's the property values, and here's the houses, you could draw a picture, right?
You could say, well, this house has a property size of 30,000 square feet, and this one has a property size of 50,000 square feet. And then, you draw a picture, you know, mapping your...on one axis...so, you just draw a line, and then, as you go higher along, you're going to put the size of the property. The higher the property size, it goes higher on the line. And then, along the other axis, you're going to put the price of the house.
And if you kind of map those, you're going to see them following a pattern where it goes up into the right, assuming that the higher values go to the right. And you could draw a line through that and probably eyeball it and get a pretty good number to say, hey, here's the line that I'm going to use to fit to that data, you know, that you got that line of best fit. There's a fancy, mathy word for a line, for things referring to lines. They say linear because it has the word line in it with an E-R at the end, a linear, or an A-R at the end. You know, it's liner. A line you can use to map the data.
And it's probably not a perfect fit, right? But lines are pretty simple to use. And one thing about line is they've only got really two characteristics that you care about, which is how steep is it? And what's the starting point? There's starting to be a pattern here. How steep is it, and what's the starting point? Which you can use with that y equals mx plus b. You can use those two numbers. All that is...I can go back. Well, the two numbers that you care about is how steep it is, which is the same thing, as we said before, as that weight. The number that you're going to multiply by the size of your property and that bias sort of, you know, where does your line start?
But what if you have a million? What if you have a million houses? Well, you're probably not going to do that by hand. It's going to take you a long time. Even with the size of a million modern computers, you could probably figure out an exact line of best fit. But as you get to increasingly large datasets, it becomes less and less tractable.
Here's what gets even worse. What if those other data points that I mentioned are also into play? What if you also want to involve the proximity to public transportation? What about the neighborhood that it's in, and you want to treat that as a data point? What about how urban or rural or, you know, which urban area that it's in? You know, what about the age of the home? What about the company who built the home? There's all kinds of things that you can measure.
We're often used to thinking about things we can measure as being in our world around us and tend to mention Cartesian coordinates. We often think about, well, how far is it in front of me? How far is it to either side of me? How far is it up and down? So, we've got these three things we can measure: in front of me, to the side, and up, and we call those dimensions. But that word dimension just means things I can measure. So, I could also measure the distance from public transportation. I could measure the distance from the city center. I can measure in kind of a categorical sense categories of, you know, what these neighborhoods are. There's many things that I can measure.
And dimension is just something I can measure. Well, I could probably measure hundreds of things. And that's really hard to picture drawing [chuckles] when I've got hundreds of things. And for all of those hundreds of things, I want to find a best fit that kind of maps all of them in some complex multi-dimensional space. Well, that sounds really awful.
But the concept is very simple. I just want to have a weight for every one of them and a bias for every one of them. And then, I multiply those all together and, add it together, and get a number out of the other end. Well, that sounds like something I could do, although I don't know how to do it on paper. And if I've got a huge number of things coming in, I might not even be able to do it easily on a computer. But there is something I can do.
Here's where the learning part comes in: the moment of magic. What if I do my math...and I'm going to go back to the example of just one, and I'm just going to draw a line completely random, no thought going into it whatsoever. None at all. I'm going to draw a random line. And then, I'm going to take my first house, and I'm going to figure out, like, some exact numbers. Like, what do I have to multiply the property size by to get to the size of that house? And that will give me a number for my weight that's different from the one I have because the one I have is totally random. I mean, the chance those are exactly the same is basically zero. They're different.
And I'm going to take my number that I guessed at random, and I'm going to move it a little bit, not much, just a little bit toward the value I got for the house. Remember, these weights can also be called the slope or, in a fancy word, the gradient. So, I'm going to move my gradient a little bit more toward the one that that house would suggest it ought to be. And then, I'm going to do it again with the next house on my list. And then again, and then again, a million times, or a billion times.
And if you think about what's going to happen to that gradient, sometimes it's going to go the wrong way because we have some rundown mansion that's actually not worth very much [laughs] and some little place that's actually really fancy. It skews it the other way. But if I keep on doing that a million times, just moving a little bit each time, there's going to be a little bit of bounce around, thinking about following that gradient, following that slope towards the right one. Over time, I'm going to follow that difference, right? The difference between the slope values until I get something really close.
Think about me walking down that hill on that mountain. I didn't always go exactly towards the trail, I guarantee that. Sometimes, I was going around trees. Sometimes, I probably went uphill to dodge an obstacle, but as long as I was going in the direction of the trail, changing my position a little bit each time going in the right direction. And if I'm not being very watchful, maybe I'm going to pass it [chuckles] and then have to come back to that direction. But then I'm going to come back downhill the other way because I go back up the canyon on the other side and wave until I get down to that trail, which happens to be right at the bottom. And there's a fancy name for that: gradient descent.
But all that that really is...and you think that, oh no, it's got to be more complicated than that. Well, actually, no, it's not. Because simple things are how you solve really ugly problems a lot of times, that is really what machine learning practitioners have been doing for a long time is: they thought, well, okay, well, let's take a simple approach to this problem. Let's take my input data and, multiply it by some weights, add some biases.
And I'm just going to start with some random weights and biases. And now I'm going to adjust them a little bit with a batch of data, and then a little bit more and a little bit more and a little bit more. And I'm just going to do this a whole bunch of times. And if I do that enough times with enough data—and it helps to have a lot of data—I'm eventually going to get some pretty good weights and biases, right? It's actually going to be pretty good. And this is not a new idea. There is something called the perceptron, which followed this pattern, and it was invented in 1943.
TAYLOR: Wow.
MIKE: That does just this. Back then, computers were feeble enough compared with today's. They actually originally designed it in software, but they built hardware for it. They built hardware that would do this, and they thought this will change the world. This learning will change the world. Well, they didn't have very much data. And they didn't have, you know, a very big machine. So, it didn't really change the world that much. But it was able to learn from a set of data. Remember, this is 1943.
TAYLOR: That's amazing.
MIKE: And these ideas have been bouncing around since then, and people probably thought of that. This idea of linear approximation or linear regression, which is trying to find that line of best fit, has been around for a long time. Well, in the 1990s, some mathematicians started working more on this. One guy, particularly named Yann LeCun, and the team...he is a professor...a team of his started working on that. And they explored some of these ideas. Another important person here is named Geoffrey Hinton.
They kept thinking that this idea of using these weights and biases to solve the problem and making a whole network of them was going to be really useful. And at the time, you know, back in the '90s, there were actually a lot of people who thought it wouldn't work. Because they thought, well, that's too simple, you know, our brain really has these concepts of things. And we need to come up with relationships with things and make large databases of things. And that's how we'll really solve the problem.
The problem with that is you have a lot of different things. You've got a lot of different relationships [inaudible 17:04] them. It's just too hard to map out. The work involved in that is mind-boggling. And how do you do kind of fuzzy relationships between things? The whole thing just falls apart. It's just impossible to build that database, practically.
But there were a couple of really important things that happened between the '90s and the year...and I'm going to say, specifically, the year 2012. And here's the couple of things that happened. First, well, the internet. People started posting things online, which meant we ended up with vast amounts of data, huge amounts of data points that we could start doing stuff with. And the other thing that happened is maybe a little bit unexpected, which is the rise of computer gaming. And computer gamers really, really love to have good graphics. They want to have beautiful graphics that are very immersive.
And so, like, what does all this data and these graphics cards have to do with things? Well, first of all, it's really hard to learn something if you don't have very many examples to learn from. And in the older era, the only way you could get a bunch of examples of things is kind of find them for yourself and write them down, and that's just impractical to do as a single team. But by the early 2000s, there were teams that started scraping the internet, and you could get a million images.
Well, now you got a whole bunch of data. What can we do with this data to learn about it? And second thing with the gaming is that gamers, in order to have these good graphics, they use graphics cards, which is a specific, like, little computer in your computer. So, it's a dedicated processor that's really, really good at doing linear algebra. It's really good at doing this line math that we've been talking about. Well, they do that so they can navigate the way that light passes through space. But that also happens to just match really well anytime you want to find a line of best fit for things.
TAYLOR: Light moves in straight lines. That's why that matches.
MIKE: So, some researchers started to use those graphics cards to start crunching a whole bunch of this linear algebra to say, what if I take a whole bunch of data, start running through these graphics cards using these old techniques that have been around since the 1940s? And really, they go back farther than that, and these predate computers for the linear regression. But, the idea of using gradient descent with a computer to do it has been around since the 1940s. What if we start applying these ideas we already knew to some of the input data?
And they start with a lot of input data because an image, you think it has a lot of pixels in there. But really, those are all just a whole bunch of data points. We talked about a lot of dimensions. Well, each of those pixels just has a brightness, right? And some position, you know, it's like an X and a Y position. It's got a position on the screen, and it's got some brightness. Well, those are just data points. Those are just dimensions.
Now, if we throw all of those many, many dimensions into some of these little classifiers I told about where we just add a whole bunch of weights and biases that we picked at random, and then we adjust it and say, "This image you throw all of these numbers, and then that is a cat," this other big set of numbers and say, "That's not a cat; it's a dog." Well, you know, that's something that's just almost impossible to think about doing as a person. But the graphics card it does that all day, every day. And the combination of the two was amazingly effective.
And I've mentioned 2012 because, in 2012, the team of Geoffrey Hinton built an image recognition network, as they called it, that followed this process. And there's a couple of little tweaks that I haven't mentioned, which is that they did something a little tricky. Rather than predicting immediately with just one set of weights and biases, Elvis is a cat; they dumped the output of those weights and biases, so those numbers that come out of there into another set of weights and biases. Like, wait, what? What does that even mean?
So, you put another set of weights and biases in between and then another set, several layers of these linear approximaters, and then they get now put out of it. Well, that's kind of weird, right? I mean, why would you put layers? Because what does that even mean on the in-between?
It turns out that that allows something magical to happen [laughs]. I'm going to keep using this word magic because it feels like it when it finally works. Is that these in-between layers start not predicting directly the price of the house; they start predicting something maybe more sophisticated. Like, based on this input data, I'd maybe have some prediction about the value of the roof. Even if you didn't have that directly, they start learning that concept because you can see, like, how new it is, maybe something...the color of the roof. They start to learn these concepts. Go ahead, Dave.
DAVE: Right. Is this, like, literally, like, you're like, okay, this is a point six hectare, you know, acre lot. It's going to be a $180,000 house, and you're going to need to take the lead out of the paint because...right?
MIKE: So, that lead may never be explicitly specified. But some of these intermediate layers because they don't have to directly predict the price of the house; they can predict something in between. And remember, they're just starting with random initialization. So, maybe one of them actually started out pretty good at predicting the lead just by random chance. And by keeping with that and getting even closer to this lead idea, somewhere in between these layers, it was able to improve the predictions of the network as a whole. And so, it sticks with it.
And with images, you can actually look at what comes out of these intermediate layers when they do this. And you see things like some of them recognize lines, some of them recognize circles. You know, they start recognizing interesting characteristics of the image that are not cat, but they might be important for cat, something like eyes, for example. Or circles lead to eyes [chuckles], which lead to face, which leads to, oh, cat. And just by throwing numbers at it and adjusting your gradients each time.
Now, there's a problem here. It's hard to directly adjust your gradient when you have multiple layers. And here's where I'm going to get a little bit more math-y. And this was some of the trick that some of the researchers figured out. I think it was particularly in the '90s but then in the 2000s. And this trick is...it comes from calculus. And this is where I'm going to get math-y for a second.
If you've ever done calculus, there's something called the chain rule, which is that if you want to find the derivative, which is another fancy word because mathematicians have, like, ten fancy words for the same idea of this slope. And it's a little more sophisticated because they can find it, you know, it's more than a line. But the idea is another idea of this slope.
And if you want to find the slope of some complex curve that has a bunch of things happening to it, there's a rule you can actually use to work back from the final one to the first one. Well, if each of these layers in the network is just applying some lines, some weight, and a bias, well, we know how to find slope from that. And so we can work backwards through the layers using that calculus chain rule. If you know calculus, if you're interested in that, they call that backpropagation. And that was the trick they learned for training this thing when it got more and more layers. And adding those layers really ended up allowing this magic to happen.
So, in 2012, they made a network called AlexNet that absolutely clobbered a competition for image detection. And people are like, "Oh wow, I wasn't expecting that [chuckles]. We're onto something." And it's approximately decades since things have gone on. So, Taylor.
TAYLOR: Yeah, I was just going to mention that there are standard datasets used to analyze these models. So, if you ever have a great idea on how to like, detect images, and classify images, you can test them on these standard sets of images and produce research using those. And I'm sure they're different today, but I'm sure you can still find the dataset that that was trained on and see how newer models perform on it.
MIKE: It is. It's called ImageNet, and they still use it a lot in training. And ImageNet happened because some professors...I think it was Fei-Fei Li. Is that her name? I think she's at Stanford. And her team got together a whole bunch of images off the internet and came up with a classification competition. And then the graphics cards gave us the power to do a whole bunch of line math of linear algebra, put them together, and out of it comes something that we never had before: the ability for machines to very effectively recognize images. And that really has kind of sparked the progress toward modern artificial intelligence and machine learning.
And after that, you know, things started happening like Siri and Alexa, you know, name your smart assistant that can understand language. Well, underneath, they were using these same kinds of linear classifiers built into a network called a deep because there's more than one layer, a deep neural network. And it works. There's a couple of other things that I wanted to throw out there to kind of complete the story. But I'm going to pause here for a minute.
But I think we should have a little bit of discussion because we've covered the most important parts, which is you start with just trying to find some multiplier for your input, for your input dimension, your input value that will give you the output value you wanted. And you adjust it a little bit each time with your incoming data, and then you just pump a whole bunch of data at it. And that idea is the idea, and it's not a new idea.
But if you have the computers that can handle it and you have the data, you can throw at it with a whole bunch of values, right? A million images is a whole lot more than five. And today's datasets are absolutely enormous. With some of the text datasets, you have, like, a trillion data points that you...a trillion...I say data points, a trillion examples maybe you'll throw.
So, there's just huge amounts of data that they can throw at really big networks that are big enough to learn a lot of these little nuances, and that's it. But the math behind it is actually not that scary in the small scale. It really is just finding that line. Now I'm going to be quiet for a bit because I've talked a lot. Like I said, this one's going to be a little bit different because I wanted to lay out these ideas.
Dave said he was going to approach this more as the, hey, tell me more, and Taylor is more of the field expert. Well, there's a couple of things that I want to visit. For example, I have not talked about gradient-boosted trees, which applies the same idea to decision trees. There's other ways they apply this gradient idea to something that's also pretty simple but is a little bit different.
And I haven't yet talked about transformers and about what might go in between these layers where you do something to get something that's a little bit more than a line. But those are all just tweaks to this core idea. So, Dave, I'm going to look at you first. What are your thoughts?
DAVE: I am just falling all over myself to preemptively yield the floor to Taylor.
MIKE: [laughs]
DAVE: Because I have lots of ideas and lots of questions, but the actual implementation details of machine learning is something so far outside my ken that this is just fantastic. I'm really, really, really digging this.
TAYLOR: Yeah, I honestly deal a lot more with, I guess, the implementation details of machine learning, like in the day-to-day here at Acima. Oftentimes, that is far more important than the training of a model. Handling data in production and, assembling that data, and making successful predictions is very difficult, and doing it correctly at scale is even more difficult. But, Mike, I really liked how you're describing neural networks. They are inspired by the human brain, and that's where the neural part comes from.
So, it's a really interesting abstraction of how humans learn. And that when we're born, we're sort of initialized with a really basic [chuckles] neural architecture that the weights really aren't well defined, like, outside of our instincts. And as we grow, we really start to develop more neural pathways, and we strengthen those neural pathways. We correct those neural pathways. And over time, we optimize them so we can be, I guess, contributing members of society and successful humans.
But, like, when I'm learning, I conceptualize it in that way as well. Like, you have to take an integrative approach. If you do things more than once, it's going to take a while to get those weights to where you want them to be and to get them optimized, so, yeah, we take the same approach with machine learning.
But really contextualizing the problem is a lot more difficult when it comes to machine learning. It's really had to define all your input variables, and you have to structure everything very well, very consistently. You have to be very organized. I think, as humans, we kind of take that for granted. It kind of happens just almost subliminally. Like, we don't have to worry about categorizing data and storing it [inaudible 29:12]
MIKE: Because we've been building our model since we were born [laughs]. It feels like common sense because we have been practicing it.
TAYLOR: Yeah. So, when we're training these machine learning models, we have to be, like, very diligent and very specific. And if you're not careful, you're going to teach the model something that you didn't intend to because you didn't contextualize the problem correctly. And in machine learning, we say that the model is not going to generalize if the data you gave it isn't like the data it's going to see. So, that's yeah; it's just a fundamental part to training machine learning is getting that dataset correct such that it mimics the real world, it mimics what the model is actually going to be predicting on.
And we spend a ton of time here at Acima making sure that's the case. Because if you train a model and you think it's doing well, and your accuracy metrics are where you want them to be, but when you deploy, it performs totally different, like, that model is not successful at all. It might have done well in training, but it doesn't do anything for us if it doesn't do that same thing in production. And stuff like that's happened before, and that's when you have to debug and figure out where that dataset was corrupted or queried the wrong way.
MIKE: What you're saying there, it's hard to emphasize this point enough. I'm going to go back to the thought that this perceptron was named in 1943. But we didn't have this big AI explosion until after 2012. And remember, there are two halves to that: first one was getting the computers that could handle it, and the other one was getting the data and [laughs] everything Taylor is talking about here. That work of getting a good dataset was what it took 70 years to get together.
TAYLOR: Yes, it truly is the culmination of several different domains, like, really just getting to the point where they can mesh and do things really well. I think a lot of what we consider machine learning is just classical statistics, and it's been in use for decades at this point. We joke about the term AI in our department, and we think it's kind of funny because it's kind of just a buzzword. And artificial intelligence often isn't that intelligent. Like you said, they're fairly basic concepts that are playing out.
These newer forms of large language models are closer to what I would consider AI and more of the Sci-Fi stuff. We're still not there yet. But yeah, classical machine learning has been around for quite a while. We've had actuaries for a long time, and statistical methods have been used to underwrite risk for decades.
MIKE: I remember as a kid, a good friend of mine, his dad was a statistician, and I thought, wow, that sounds so boring. And I wanted to go into other areas of science. It turns out now, like, I work with that kind of thing for a living, and it's so cool [laughs]. And he went into other areas of science. We kind of swapped roles. But it's been around for a long time. We've just gotten better tools for applying it.
And I want to say kind of repeatedly that the basic ideas here...if you've been scared, like, I want to learn this, but, man, that sounds too complicated, but they use a lot of fancy symbols and stuff in the papers and sometimes, you know, it takes a while to wrap your head around. But the ideas here, at their fundamental, like the basics of what's going on in machine learning, are not that complex. It's mostly these weights and biases.
TAYLOR: Yeah. To add to your point earlier on, like, actually implementing these, the great thing about all these machine learning algorithms is that they're packaged really well, especially in Python. You'll see almost zero math notation when you're training a machine learning model, other than how you choose to define your variables and methods. But it's incredibly easy to sit down and get started with machine learning. There's tons of datasets online that you can play around with. And there's standards that people have come to, prediction standards on those datasets. So, you can get an idea of if you're doing something completely wrong or you're hitting the nail on the head.
But yeah, they're fairly easy to implement. We actually use a hosted solution to train and deploy all of our machine-learning models; it's DataRobot if you guys are familiar. And there's dozens of machine learning algorithms packaged up in there. It handles all your training data and iterates through different training methods, and we do some work to select the best models in there and deploy them there.
But tools like that are great, and, like, now is the best time to get into machine learning and artificial intelligence because there truly is just so much material out there to learn, just countless hours of Khan Academy or YouTube videos. Yeah, if you're looking to get into machine learning, you shouldn't be too scared.
I'm trained as a computer scientist. So, I don't have, like, a specific data science degree or even a math degree like some of the co-workers here at Acima. But, I was able to make the transition into data science because it really is just computer science mixed with statistics and mathematics, and I've really enjoyed it. And it's one of my favorite domains of computer science if not my favorite.
MIKE: You know, unless you are inventing some addition to kind of the toolset used in these models, you probably are not going to be doing a lot of math because you're not going to be inventing your own architecture of layers and such because people have already built that. And you can get it pre-packaged. You just should have some understanding of what's going on under the hood.
TAYLOR: Yeah, you can get yourself into trouble if you don't understand the underlying fundamentals. Machine learning models are very finicky. And, like I said earlier, if you feed them wrong data, they're going to learn the wrong thing, and they're not going to perform well.
MIKE: I think I said that I'd come back. There's a couple of things that I want to mention I haven't mentioned before that you're probably going to run into pretty quickly if you start studying this stuff. First of all, we've been talking about neural networks. But, there are a few other approaches that people use to do machine learning. Generally, they also use this gradient descent idea [chuckles] to learn over time. But, they may approach the problem a little bit differently than having layers of weights and biases.
There's support vector machines, which have kind of fallen out of favor, but there's one that's actually very effective. And if you look at competitions for machine learning where you have tables of data, something that looks like it came from a spreadsheet, they actually don't usually use neural networks because they don't work as well for that kind of category tabular data. You can fit something better with what's called a gradient-boosted tree.
And it follows that gradient approach, but they don't apply that to lines exactly. They apply it to decisions that are made to divide the data into sections. You take your data, and you come up with a lot of really simple classifiers that just say, well, taking the input data, I'm going to divide some of the data over onto this side and some of the data on the other side. And then, I'm going to subdivide it again and then subdivide it again until I get all my answers. They call that a decision tree.
And if you have a lot of simple decision trees, like, a whole bunch of them, and then you use your gradient descent together with your input data to emphasize, to increase the ranking of some trees versus another, you actually get a very effective model that tends to be better for tabular data. And it's a gradient-boosted tree. So, most of what you see, like ChatGPT, doesn't use gradient-boosted trees. But a lot of the machine learning that you actually use in the real world that you might not even think about is probably coming from those gradient-boosted trees because they're very effective for a lot of the less flashy but also important kinds of things that happen in business.
The other couple of things I wanted to mention is that if you have a whole bunch of lines, the best prediction you actually can get is just lines. It doesn't map to curve things very well, things that just really don't follow a line. But there's a little bit of magic you can do, which is you take your weights and biases, and you run them through another thing that isn't a straight line.
And the thing that they usually run it through, and this is going to sound ridiculous because it's so simple, is that if you get any value that's below zero, just cut it off and say it's zero. It's called a rectified linear unit, which is really a fancy way of just saying if it's less than zero, just call it zero. They call them ReLUs in the literature.
If you put that on your predictions between your layers, it makes your layers not be able to predict a line because, you know, a line that comes down and then stops at zero is not a line anymore. It's got this point in it that's not linear, and that discontinuous spot there actually–– throws everything off. And it allows these models to learn something that's not aligned that actually might have sophisticated curves in it. Because now it's got something that throws the lines off and can be bendy, and they call that the [crosstalk 37:21]
TAYLOR: Because, yeah, a lot of times in data science, we're talking about error and our loss function. And let's say that the true line of those house prices looks like this. But your prediction might...if it's really bad, it looks like this, and you're off in every direction. And your error is really high because the point over here is really far from the true point, and your point down here is also really far. And our loss function helps determine on each iteration of training how far off we are from that true line. And there's countless different loss functions and accuracy metrics that we use.
And, oftentimes, you have to train a lot and test a lot to figure out what the right loss function is or what the right...oftentimes, we're developing [inaudible 37:59]. Like, it's not as simple as just there being a home price. We have to do some work to develop sort of what we want to predict, like, is it home price? Or is it average home price over, like, the last six months? Because home prices change, and some of that's variance and random noise.
But backing it up to some of the different domains in machine learning, broadly, there's three categories: we call them supervised, unsupervised, and reinforcement learning. Here at Acima, we use supervised learning, so all of our records have outcomes associated with them. We've labeled them. We've supervised the data. We've given it a supervision on what to consider good and what to consider bad. And that's what the gradient-boosted tree classifiers would fall under. Unsupervised would be more of that neural network where it doesn't have labels on how it should consider the data necessarily, but it can learn relationships in that data in an unsupervised fashion.
MIKE: Well, let's talk a little about that because people have actually seen this, and ChatGPT, which has been so famous, is actually a good example of unsupervised learning. They didn't go out and say, "I want you to predict English, and this is what English is. Match that." Did not happen. Because nobody can define English, it's too big. Nobody even knows all of it. Instead, what they did, and this might seem crazy, but they just gave it a bunch of text and said, "Predict the next word," and that's it. They do that billions and billions and billions of times. And you do that enough times; it gets pretty good at figuring out what the next word is going to be.
And, in fact, it has to learn concepts about the real world that are embedded in our language, understands hot and cold, and all these other things. It understands these ideas because it had to to be able to figure out what the next word is. But there was no supervision to say, "Hey, this is what English is. And if you get good grammar, you're right." No, all they did was just say, "I got some data here. Pick the next word."
Also, if you've seen a lot of the amazing image generation that's out there, they did the same thing where they take an image and they'd make it blurry. And then they'd say, "Predict what the real image is." And they got that with blurrier and blurrier images until they just gave it pure noise and say, "Ah, predict a horse." And it manages to predict a horse out of pure noise because it's learned the idea of what a horse looks like.
Where unsupervised learning is like, what are you talking about? We're just talking about trying to make sense of the world around you without having, like, a standard. You're just trying to predict based on some data that you've got that isn't classified other than to say, well, maybe this is a category.
TAYLOR: And I guess the past few years, it has become less so. But, traditionally, those unsupervised techniques require a huge, enormous amount of data because to figure out the actual underlying meaning in that data requires a whole bunch of data because there are so many examples of, like, what does a horse look like? What does the light look like? Where is it? Like, what color is the horse? So, to be able to extract that information from data,––it requires a whole lot of data––some sophisticated machine-learning techniques.
But over time, these models have become very good at extracting, like, the underlying relationships between pixels and the full image or words and meaningful texts. And that's really been, I think, the groundbreaking revelation in the past ten years. It's just how much meaning can we extract from this data?
MIKE: And I interrupted a little bit to go into a little more detail about unsupervised learning. You're going to talk about reinforcement learning, something I love as well. Do you want to talk about reinforcement learning?
TAYLOR: Yeah, my first introduction to reinforcement learning was the game of Pac-Man. Our job was to basically build the Pac-Man game such that the ghosts try to eat Pac-Man. and Pac-Man tries to avoid the ghosts and eat the food.
MIKE: [laughs]
TAYLOR: And to do so, you have to go through thousands if not millions of iterations of the game of Pac-Man, developing rules to make Pac-Man eat as many food pellets as you can and not die as often as possible. And on every single one of these iterations, you're learning something, and you're reinforcing the behaviors in the model. Maybe the tweaks that you made didn't perform well, so you have to roll back those changes. Or maybe they perform really well, and you want to see how far you can push those changes. So, that's sort of the idea behind reinforcement learning.
And ChatGPT actually has a layer of reinforcement learning on top of it. And this is what you'll see sort of when it says it's just a large language model, and it can't do certain things. This stems from the actual humans' sort of, like, reinforcement learning the underlying transformer model to produce things that, I guess, the humans would prefer not to say. Maybe you guys have seen ChatGPT be hacked before, hacked in a way, or break out of its bounds [crosstalk 42:33] of that. So, you can kind of get, like, the raw output of the transformer model.
Yeah, the reinforcement learning on top of ChatGPT is really interesting. In many ways, I think it makes me productive. Like, it keeps students from cheating on their homework, or it stops people from making weapons of mass destruction. But that layer on top is reinforcement learning. And it did require a huge amount of human capital to label output from ChatGPT and kind of weight it in a way where ChatGPT was more user-friendly.
MIKE: Right. And you use reinforcement learning when you have a reward signal like winning the game [chuckles] or getting away from the ghost, or, you know, not saying racist things that you can use to give this number, like, that was good, or that was bad, a reward signal for an output that involves a series of actions over time. Generally, you know, you've got a sequence. And you need to be able to have this incoming state. Well, this is what happens already, and I want you to make a prediction of the value of a certain action going next.
TAYLOR: Yeah, like, in reinforcement learning, we'll oftentimes talk about the idea of, like, the state space. It's really easy to think about, like, in terms of the game of chess. The state space is the chess pieces on the board and the board itself. And depending on how those chess pieces are arranged on the board, you have a different state space. And there's certain optimal moves and the outcomes from that state space.
Like, obviously, the state space of all the possible moves and board conditions in chess is astronomical. But if you were able to calculate that entire state space and the optimal move from every state space, then you have, like, basically a perfect chess agent. And that's kind of where we're at [chuckles] with chess agents. Like, I think it was back in the '90s with Deep Blue. The artificial intelligent chess agents were able to beat...is it Kasparov or? I forget...the Russian grandmaster.
MIKE: Garry Kasparov.
TAYLOR: Yeah, Kasparov. I think there's a phenomenal documentary about that on Netflix or somewhere. But yeah, they developed an algorithm that was able to traverse the chess state space and determine optimal moves. And I believe that was an example of reinforcement learning. I forget what the specific algorithm they used was [inaudible 44:46] model.
MIKE: I think that Deep Blue actually didn't use...I think Deep Blue didn't use reinforcement learning. But --
TAYLOR: Yeah. They might have brute-forced it, right?
MIKE: Yeah, I think they did. It's just that if you look at enough games from enough grandmasters, you can avoid making some of the same mistakes that they did [laughs] --
DAVE: I heard an interview from Kasparov where they told him, "We just kept adding more and more memory to Deep Blue until it could beat you." And he was kind of disgusted to find out that, oh, you did brute force me. And they're like, "Well, we were going to brute force you from the beginning. That was the whole point."
TAYLOR: [laughs].
MIKE: But some of the newer models that have come out of Google's research teams, the Alpha class, AlphaGo, and AlphaZero, that are able to use reinforcement learning to do self-play, play against each other, and learn over time have gotten much better, much better than any previous modeling has.
TAYLOR: Yeah. And, obviously, with the game of go, you weren't able to brute force it because the state space was, I think, it was orders of magnitude higher than chess.
MIKE: Yeah, I think so.
TAYLOR: So, they had to develop these other techniques to extract optimal outcomes from, I guess, more abstract spaces, not specific state spaces.
MIKE: Fascinating stuff. And we're giving you a taste. So, our listeners, we're giving you a taste here of [chuckles] what's going on here. There's one other thing I said that I was going to cover, and so I want to make sure I don't neglect it, which is transformers. There was the wonderfully named paper that came out a few years ago. Taylor, do you remember what year? "Attention Is All You Need." It came out in --
TAYLOR: 2017.
MIKE: 2017. That has really allowed some of these models to get a lot better. And I mentioned that simple ReLU layer—they cut things off—that puts things in between the linear layers. Well, they came up with a more sophisticated one. It still isn't that sophisticated. They use some Gaussian curves, you know, like, the bell curves you're used to seeing, to try to predict where are the hotspots in the incoming data here. What data is important? And to emphasize that and use that, you know, to be able to kind of focus, again, the attention on some data versus others.
So, if you look at a lot of text, not all of it is going to be important for what your output is going to be. And being able to predict what is important this works better with these transformer models, as they call them, that pay attention. And those have been developed and have allowed kind of the next stage, the next level of skill in these models. And some of the amazing things like ChatGPT and some of the image generation use some of these transformer layers inside.
TAYLOR: Yeah. If you ever want to learn more about transformers, Spencer Reschke is actually the guy to go to from Acima. He's a mathematician by training. His degree should have also been, like, a computer science degree. He's got a phenomenal understanding of self-attention mechanism. He actually showed me that paper. He's tried to implement a transformer here at Acima.
Transformers are really good at tackling sequence-to-sequence problems. So, in the case of ChatGPT, sequence to sequence is just token to token or word to word or letter to letter. But in the case of Acima, we might use a sequence to sequence to predict how a lease traverses through; I guess, like, the rental period. So, given that the lease is this size and it's the first day, what is the probability, or what's the most probabilistic outcome on the second day? And, like, are they going to be delinquent, or are they going to make their payment?
So, we'd like to use a sequence-to-sequence model to predict eventual yields on our portfolio. So, these transformers and sequence-to-sequence models can actually generalize to a whole bunch of other problems as long as you can format them in that sequence-to-sequence format.
MIKE: You know, there were other kinds of models used for sequence to sequence prior to that, and they still use some, and hence the name of the paper "Attention Is All You Need" said, well, you could use those other techniques. And, originally, some of this transformer used...self-attention was used in tandem with those other techniques. Eventually, they realized––actually, just drop the other techniques entirely. The self-attention is everything you need. And that's been transformative with these transformers. I'm going to look at you, Dave. You've said a little bit, but not a lot. It's mostly the Taylor and Mike show [laughs].
DAVE: It's been fantastic. I've just been eating this up.
MIKE: Do you have any final questions or, you know, clarification you'd like to put in here?
DAVE: I think this is either going to have a quick answer, or much more likely, it's going to be like the beginning of another episode. But I worked with a PhD gentleman. I guess we call them doctors. I worked with a guy who had a Ph.D. in data science from Stanford. And he said that through the '90s and early noughties, the AI stuff was producing stuff that was really spooky. And it was like, you know, how is this? Why, you know, da da da. And there was a shift in the late noughties, early teens into explainability, where you could literally get your doctorate in explaining why the AI arrived at this. Is that still going on? Is that still a dominant feature of the industry?
MIKE: [laughs] It's still hard --
DAVE: What's going on with explainability? It's still hard?
MIKE: It's still hard [laughs]. I'll say that. It's still hard. Again, these things are bigger than we can fit in our head. So, somehow, you have to come up with a signal that we can comprehend [chuckles] in something that's far vaster than you can fit in your head. Explainability is still an active area of research. Go ahead, Taylor.
TAYLOR: And I think that's especially true in the areas of, like, transformers and neural networks and these larger models with many layers and tons of neurons. But in terms of some of the more basic machine learning approaches, those are fairly easy to explain or are responsible for explaining some of our decisions using these models here at Acima. And in the case of decision trees, we'll basically say you are on the wrong side of, like, these splits in the tree. Like, your credit score was too high or too low, or your income was too high or too low.
And in the context of, like, a trees classifier, you can explain those splits a lot easier than, I guess, the inner layers of a neural network and what those individual neurons meant and why they fired one way for you and worse for another person. So, I do think that is worth spending some time on explainability. Because if you don't understand why your model is producing some outputs, then it lacks in utility in that respect, especially in the area of finance that we're in.
So, we've never deployed a neural network or something like that. We tend to stick to models that have what's called SHAP predictions or SHAP-supported values. And that's basically a methodology we use to explain prediction output and which features or independent variables lead to the output.
DAVE: Awesome. Does explainability get into the positive side as well of, like, you get back a prediction, and it's like, oh, this lease is going to become delinquent in two weeks? And you're like, wait, what? Because they made a payment at 3:00 p.m. on a Tuesday, that's why. And you're like, okay, that's dumb. Stop...and then two weeks later, the lease goes delinquent, and they all do. It's like the data is there, and it's predicting. Does explainability get into that kind of spooky [inaudible 51:44] Ouija board stuff?
TAYLOR: I mean, sometimes there'll be odd predictions from a model that turn out to be accurate, but in retrospect, I think they would make sense. But for the most part, I think most of the decisions are intuitive. And there is some, like, some understanding you can gain just from looking at the decision. We make predictions a little differently from what you described. Like, we're not predicting delinquency. We're basically predicting if the account is good for the company or bad for the company.
And there are certain attributes that make the accounts good, certain attributes that make the accounts bad. It's pretty rare that there'll be an attribute that makes the account good for some strange reason or vice versa. And part of our job is to make sure that doesn't happen. Because that might suggest that the training data was malformed for some reason or it's representing a relationship that's not going to hold true in production, so we'll test to make sure that's not the case. And when we deploy new models, it's definitely something we're looking out for is: why was our input data suddenly not looking like the data we trained on? Like, we've got to do something that will stop this model.
DAVE: That's awesome. I have follow-up questions, but I'll save them for the next time we talk about this.
MIKE: Taylor, do you have any final things you'd like to say?
TAYLOR: I don't think so. I think we've covered a lot. And we can definitely spend another call just covering machine learning and, especially as it pertains to Acima. I would like to extend an invitation to anyone from Acima who wants to learn more or has questions for us; even if it's just a personal project, we're always willing to help and extend an olive branch.
MIKE: Awesome. Well, thank you. Thank you to our listeners for listening to another episode of the Acima Development podcast, and until next time.
In this episode, the panel dives into the nuances of learning and developing as a coder. They discuss various approaches to learning, such as "committing" code every day, even if it's just a tiny chunk, to build fluency and comfort with programming. Mark mentions the trend of long online tutorials aimed to take someone from "zero to master" and the varied success of these methods. However, they stress the importance of building foundational skills first and note the ever-increasing capabilities of technology, stating that if you can imagine it, you can code it.
As the conversation progresses, they focus on managing one's learning through their work environment. There's a discussion on the benefits of aligning one's professional tasks with personal learning goals by steering management toward mutually beneficial projects. They also discuss various approaches to learning from online video tutorials, with some arguing that replicating a project step-by-step doesn't provide real value. In contrast, others see merit in iterative learning, especially when the tutorials are feature-focused. The panel then discusses the importance of balancing this with hands-on coding, experimenting on personal projects, and checking out the latest documentation to stay updated.
They conclude with an emphasis on adequately utilizing video tutorials and online resources for optimized learning. While video tutorials are helpful, they aren't the end-all solution; referring back to community insights and updated documentation is crucial for growth. They also appreciate the duality in learning methods, acknowledging that there's a time for guided learning through tutorials and a time for experimental, hands-on coding. Overall, the episode serves as a comprehensive guide for developers at all levels, highlighting that the journey of learning and growing in coding is ongoing and multifaceted.
Transcript:
DAVID: Hello and welcome to the Acima Developer podcast. I'm your host today, David Brady. We have a small panel with us today. We've got Eddy Lopez, Kyle Archer. We've got Mark Hymowitz. It's going to be a fun, tight little show. Today, we want to talk about picking projects to learn from. Or how do we pick personal projects? Where do we get the ideas for that? I will just open it to you guys right off the bat. How do you guys pick personal projects? Or what problems do you have?
EDDY: When I first started working with the idea, well, actually, before I even got into the tech industry, right? Here at Acima, I started to discipline myself and be like, hey, I want to learn programming. How can I better rearrange my habits so I can learn and hit the ground running when I do get hired on, et cetera? When I get good enough to convince someone to hire me [laughs].
And my origins when I started learning, I was like, cool, yeah, let me pick up random projects, you know, let me watch a tutorial on YouTube, you know, about someone who is walking me through on how to implement an app on a certain framework, et cetera. So, that was my origins. And I was extremely motivated to do that.
Now, when I was finally able to progress to the point to where I was able to convince someone, "Hey, yeah, bring me on the team," you know, and they accepted, the majority of the bulk of the learning that I have had up to this point has just been business needs, right? Like, "Hey, Eddy, I need you to implement this. Hey, we need this to work this way. Can you make the changes?" Under pressure [laughs], I worked pretty well, right? But suddenly, as far as having personal projects to work on, et cetera, has kind of dwindled to better cater to specific business asks. So, the bulk of my learning has been on the job versus personal projects, if that makes sense.
MARK: For me, the first part of personal project was just creating something that didn't exist. Like, my first personal project wasn't some elaborate code or anything complex. It was, hey, I wanted to make an EPUB file of an online book because you can read the book online, but there's no offline version of it. And they didn't sell a paperback or digital copies. My first project was to, hey, how do I create an EPUB file? How --
DAVID: Nice. EPUB, that's like send it to your Kindle, right?
MARK: Yeah, it's a book format just like PDFs and other file formats that you can import into Kindles, iBooks. It's a very generic book file that you could just import and just start reading from. So, my first project was like, hey, I wanted to create an EPUB file for this book. But I didn't want to make it for everything. I wanted to make sure I properly broke it down into multiple EPUB files for each volume of the book. And from there, I started going, hey, I want to automate this. I got into Python and just learning web scraping and trying to automate my process of getting the book from the website and turning it into an EPUB file so I can just read it offline.
And that's been my kind of goal since, like, personal projects: build something that doesn't exist. My current personal project is I have so much media now. I can't keep track of where it all is. So, I'm trying to create a web app that can organize it and then be able to use that web app both on my phone and my laptop while having a universal experience.
DAVID: Back in my day, back when the dinosaurs roamed the earth, there was a thing that we kept in our kitchens called a recipe box. And it was just a thing the size of, like, a stack of three-by-five index cards. And when the first PCs were coming out in the '80s when I was a kid, the first program we all went off and wrote...well, the first program was always "Hello, World."
But, like, the first, like, real big program we always wrote was, hey, let's put recipes on computers. And we were able to, like, transcribe all these recipes into computer format and put them on a floppy diskette and then lose them because floppies were wildly unreliable. But, you know, that was educational as well.
Mark, you said something that caught my attention. You came up with a problem. Like, you had the idea after you had a problem. And one of the things that you will hear in the open-source community over and over and over is scratch your own itch. And I think you've nailed that right on the head, right? Find a problem, find something that bugs you, and then figure out how to solve it.
MARK: Exactly. Like, no matter how much I search online, I can find, A, there's a web app for just tracking one thing, or, hey, this is the greatest news app for learning all the new media you want. I just want one app that I can just index to all these things and say, hey, I'm tracking all these things. Where do I go to find it? I have five apps on my phone. I have 13 bookmarks in my browser. I have Amazon and Apple. Where am I keeping all this stuff?
Because I want to make sure I don't fall behind or forget about it because there are so many things I enjoy, and then I just lose track of them and forget about them. And then I come back, like, months to a year later and be like, oh, I remember that. I liked it a lot. But I'm, like, so far behind now I don't want to...I'm a little scared to actually jump back into it again. Hence, my current project: something that indexes my life so I can actually remember where everything is.
DAVID: I can confirm to you that that is a common itch. And, actually, what I'm going to say I'm going to say this very carefully. I have scratched that itch many times and have never been completely satisfied with my own scratching of that itch. I'm not going to tell you that, "Oh, good luck with that. You'll never solve it, da da da." No, no, no, you're going to learn a ton coming up with partially great solutions to that problem. Pick an itch that's just chronic, right? And just find a way to scratch it, find a way to scratch it, find a way to scratch it.
I gave a talk at a conference years ago about building a planner page. Like, I used to work for Covey Leadership Center years and years and years ago. And so, I designed my own day planner system off the back of that, and I would print them out. And every week, I would print out a single eight-and-a-half by 11 sheet that had the week's plan on it, and then I would fold it up and, you know, stick it in my pocket, and down the road I go.
And I ended up writing a thing that would open up a Visio document. This was, like, a Windows automation script that would open up a Visio document, fill in all the dates and stuff like that, and then send it to the printer. And it would run every Monday morning, and I would have a day planner for the week. And then, a few years later—I got into Perl at the time—I automated the Visio scripting thing with a Perl script. A couple of years later, I got into Python, and I just ported it straight over from Perl to Python. And then, when I got into Ruby, I ported it from Python to Ruby.
And the interesting thing was is I had written the original version in Perl. And I had not used any object orientation. I had not used any object messaging. It was all just start at line 1 and just go for 1,200 lines of manipulation code. At some point, I stopped printing a Visio document, and I switched to drawing a PDF document myself by hand because [chuckles] Visio quit making Visio. It kind of sucked. But that's the problem with having a project that lives for 20 years, right? It outlives the architecture it's built on.
So, I got to a point where I was writing this thing in Ruby. And I was literally trying to port it to Smalltalk, which is a very object-oriented language. It's very hard to write imperative scripts in Smalltalk. And I couldn't do it. And it's because I had written this thing in an imperative style so many times that I did not know how to do it in object-oriented. And so, this was, like, a super great learning curve for me or a way to approach a learning curve. And this is a really subtle thing of, like, how do you pick a project to learn? The question is, what do you want to learn, right?
When I ported this from Python to Ruby, I had two goals in mind: one is, I wanted my stupid planner sheet to work again. I just needed to solve that itch. But the other thing was I wanted to know how to automate this from Ruby, the same kind of automation that I was doing from Python. And I did not want to know how to solve the problem of drawing a planner sheet. That was solved. That itch was well scratched.
But now I wanted to learn this new language, and I wanted to learn this automation system. And I wanted to have the planner sheets working again. Those were the itches that I wanted scratched. So, it's a really important thing to think about what exactly is the itch that you want. And sometimes, finishing the project isn't the itch. Does that make sense?
MARK: I know exactly what you mean. Besides, like, my current project, I've had several other projects over the year where the itch was just thinking of the project or just starting out some of it and then just getting a bare-bones thing working. Like, there's many different phases to the itch.
DAVID: So, okay, I have a trick question. And that kind of sets up everyone to understand that this is a trick question. But I'm going to ask it with a straight face, and then we can decide...we can get into answering it, like, straight. And then, we can get into, like, why it's a trick question and what is the trick here. Big project or little project? Should you tackle, like, oh, hey, I'm going to go learn this web framework, and I'm going to do full-stack JavaScript to database and back again, or should you take a little, tiny thing like, oh, hey, I want to boldface the titles in all of the EPUBS in this directory?
MARK: I'd say little projects are better. You have incentives of thinking, hey, this isn't a lot of work. You can get this done over a period of time. But you should try and have an idea that have these little projects stacked on top of each other or expand on each other so that, eventually, it becomes a fairly big project. But you never thought of it as a big project. You always thought of it as many small projects.
DAVID: Nice. I like that answer. You've got half of the trick figured out. When would you want to tackle a big project?
MARK: I guess that depends on, like, what the problem is I'm trying to solve.
DAVID: The trick to it is that it's the exact same answer, just in the other direction, right? You can take on a big project. How do you take on a big project? Well, you start breaking it down into smaller and smaller things, right? On one end, you can start small and stack your way up. On the other end, you can start big and crack your way down.
I tackled learning Ruby and Ruby on Rails in, like, 2005 because it looked like a really interesting language. And I was making a good living as a PHP programmer, but I hated PHP. And I thought Ruby looks like a really interesting language. I want to get paid doing this. So, I jumped straight into; I'm going to learn this whole darn framework from tip to tail and just grind my way all the way down through it and see how far I can get. So, the itch there was I wanted a job. Does that make sense? I wasn't trying to learn how to stack up bits and bytes. I was trying to learn how to get paid.
MARK: I understand that feeling. But my experience is, like, with a school, like, I had a teacher who gave us one large project, but instead of having us build the whole project at once, she would make us build each portion of the project over the quarter. If you fail to make even one portion of the project, you were going to fail that class.
DAVID: Wow.
MARK: Because you just couldn't build on what you had achieved.
DAVID: Yeah, that's a great way to teach someone how dangerous the waterfall process is [laughter]. You tripped in week one. Congratulations, you're going to flunk the entire year. That seems a little excessive. Although I guess that would be an important lesson, wouldn't it?
MARK: Yeah. Anyway, how do you guys think of project ideas?
KYLE: Well, as far as coming up with, like, project ideas, for me, I look at kind of just issues that I run into in my daily life, maybe not just issues but just, like, things that I think could be more convenient or make my life easier for me. Like, you know, my dream project...I worked in restaurants for a really long time. You know, I've used ten different POS systems, you know, point of sale systems for selling different stuff. You know, there's a nickname for POS, but we won't go into it.
But, you know, dream project: I've always wanted to make my own POS just because, you know, I think I have valuable insight just working in the industry. So, I think there's at least some part of me that might be able to do some things better than, you know, the big competitors: Square, Toast, whatever. Obviously, that's a long shot to dream.
But more, like, reasonable more, like, viable things, I suppose, is I'm really into chess. So, I really always wanted to create some kind of application where it's like, oh, I can record all my chess games and figure out a way to, I don't know, make some algorithm or study some books into my site that's able to, like, tell me where my weaknesses are or, you know, things like that. So [inaudible 12:31] will improve my game. I guess, really, it's just personal things that I think I can improve. That's usually inspiration for projects.
DAVID: Absolutely. That is awesome. One of the best examples of scratching your own itch...I had a friend. He and I had worked in the gaming industry together, the video game industry. And we went our separate ways after leaving that company. And he decided to go back to school. He had been making six figures as a developer, and he went back...because he was going back to school, he had to work part-time, and part-time pays entry-level. So, he was making, like, seven bucks an hour doing data entry.
And his job was to key in all of these checks, like, literally paper checks that people were writing with dollar and cent amounts. And he had to balance up the till at the end of the day with, you know, like, typing these 150 check amounts. And he would be off by a penny, or he would be off by 11 cents somewhere. And he'd have to go back through all these things. And he was on, like, a Windows, you know, like, Windows 95 or Windows 2000, just a desktop and with, you know, no tools, no dev environment, nothing. But he's like, this seems like a problem that a computer would be really good at solving.
And so, he went home. He wrote a little application in Visual Basic that let him key in all of the checks to copy and paste them because he could copy them out of the system that he was entering them into. So, he would key in all the checks into the system. And he would be off by 22 cents somewhere. And he would select the whole thing–paste it into his app.
And all his app would do is it would just go through every single item and add one and subtract one from every item. It would swap every pair of digits. And after each change, it would add up everything and check to see, you know, do I have the same wrong answer that you do? And if I do, I'm going to show you what mistake I made so that you can go look for it and see if that's the mistake that you made.
And he went from spending, like, 30 to 90 minutes a day tracking down, you know, transposition errors in his ten-keying to just copying and pasting and getting these answers out. And the hilarious bit is, because programmers are terrible at optimizing their time, he probably spent 15 hours writing the application to solve that kind of problem. And so, it was probably a wash by the end of, like, the semester. He probably had gotten those 15 hours back, probably. And if he worked another semester, he probably would have been time ahead.
But I think it was really, really neat for him to spend 15 hours doing something he loved to solve a problem that really pissed him off. And, in a way, it's an immediate victory because he's spending time doing what he loves in order to not have to spend any time doing something he hates.
So, it's not really, like, a 15-hour, you know, loss against a half an hour gain. He's, like, the very first time I pasted this in, and it found my error right off the bat; I sat back and pumped both fists in the air and just went, "Yes!" And everybody was looking at me like, "What? What's going on?" He's, "Oh, never mind, I just found what check I messed up. I'm off by 22 cents. And I had keyed in a minus 11 instead of a plus 11, and that's why I'm off by 22." That kind of thing.
I think it's a lot of fun to, like, scratch your own itch. Find out what bugs you because when you're done with it, instead of going, "Oh, I can't believe I spent all this time working on this stupid thing, and now I'm just happy that it's over," you're like, "Ah, I got to spend all this time learning this really cool thing. And now I have this cool tool." So, it's like you're doubly ahead instead of, like, just trying to struggle to break even.
MARK: What's also nice is having that tool to look back on and whenever you're, like, working in the same language again, and going like, how did I do that again? Oh, right, I built that within my app. Let me see if I can find the code.
I once interned at a place where they had me write the same program twice, once in Python, once in...I'm forgetting the other language. And I still had a copy of both programs in my GitHub repo. So, I was referring back to the Python version, going like, I definitely did this before, and the documentation hasn't changed. But, like, how did I do it in Python? That helped me understand the API a lot quicker than trying to relearn the entire documentation again.
DAVID: You've fallen neatly into the trap that I have set for you. You have stepped perfectly into a segue to something that I wrote down before coming on the show today, which is that I love really small tactical learning. Like, I love to just sit down and go, you know, I don't have a built-in sort of method. How am I going to do this? Or how do I do this thing in Python? That kind of thing. I know how to do it in Ruby. How do I do it in Python?
So, there's two repos that I keep on GitHub; one is just called bin. And bin is always in my path. And anytime I need to do anything from the command line––if it's more than 20 characters long or it's hard to remember, I will write a script and put it in there. And my scripts do two things: one is they do the thing I need to do, and the other one is they print the thing on the screen the way it needs to be done.
So, I see the correct command fully typed out. That way, if I ever don't have my script folder with me, I'm like, oh, yeah, yeah, I remember. It's dash dash force, or whatever, right? Whatever the options are to that particular script. And so, that's like, super, super useful.
And so, bin is this place with tiny, tiny solutions, right? I literally wrote a thing to remember when I create a pull request on GitHub. I wrote a thing called git set PR. So, I can go in, and I can say, okay, this branch is PR 10902. Then I wrote two more scripts; one called git get PR, which then just says, oh, you're in this folder, and you're on that branch. Yeah, you made a pull request for this, and you told me it was 10902. Go nuts.
And then the other one I wrote was because I don't want to have to open a browser and type in github.com, slash the name of the company slash name of the project. The computer knows all that. So, I wrote a thing called git open PR that opens up the git config, finds the fetch URL, where is it on GitHub, what's the repo name. And then just puts in the slash pull and then the PR number, which was recorded earlier. And then it tells the computer, "Open this in a web browser, please." So, I type git open PR, and I'm in a webpage with the PR, super handy.
And that's just something that's, like, bothered me off and on. And I got that working, like, yesterday at work. Like, we were in the middle of, like, deploying three PRs, and I was switching back and forth between them. And I'm like, this is annoying me. It's making me crazy. I'm just going to switch back and forth between these. And so, [inaudible 18:56].
So, bin is where I keep tiny, tiny, little solutions. But, Mark, you nailed the other side of this. I keep another repo called scrap bin. And scrap bin is where I store fragments or scraps. So, scrap bin is where I'm going to have a thing that says, how do I get the current date stamp in Python? Like, in Ruby, I just know it's time dot now dot star f time. How do I do that in Python? Oh, it's import date time, date time, dot date time, dot...and down the road, you go. But you have to know what module it's in.
And if you forget the module, if you're coming from Python to Ruby, you might want to make a little scrap that says, hey, here's how you get the date stamp, and you open...oh yeah, it's time dot now. Okay, cool. That's what I keep in scrap bin is, like, oh, how do I loop over this thing? Or how do I...it's like Python doesn't have a detect method. I might be a liar about that. It might not be detect. Like the ability to loop over a collection and find the first thing that matches some criteria.
And I want to say I'm going to get flamed in the comments. You know what? I need to learn, so teach me a lesson, people, if you're listening to this. I think in Python, you have to give it either like a lambda, or you just have to write a loop and loop over the collection, and if you find it, then bounce out. And that's how I ended up solving it, as I recall. This was a couple of weeks ago on the Python team.
And I love that Ruby just lets you say collection dot detect or collection dot find, and you give it a block that matches a condition. And that's great. I love it. It's super easy. But I couldn't remember how to do it in Python. So, I ended up writing these four lines of code loop every time I needed the stupid thing. And once I've found a good way to do it, oh, I take it back. I did find a way to do it. You build an enum, and then you call next on it. That's right.
My point is that's in my scrap bin. I don't have my scrap bin open, or I would have known this off the top of my head, which, by the way, is the value of the scrap bin is: you don't make yourself look dumb on a podcast. But yeah, anyway [chuckles], the point is, I have two repos: one for solutions and one for fragments of solutions, itches that I have scratched in the past. It helps you build the next back scratcher.
MARK: You're reminding me of my...Slack gives you your own channel of just you talk to yourself. And I've been using that as my scrap bin where I'll post any useful commands or pieces of information that I need to remember. Now that we're switching teams, I need to export that entire scrap [laughs] bin into, like --
DAVID: Nice.
MARK: A git repo. You just reminded me of another scratch that I itched recently. It was a...I had a pull request that was, I don't know, 50-60 commits long. And every time I rebased it, I was so concerned about things getting overwritten because of all the merge conflicts that kept popping up every time. I ended up writing an alias to squash the entire branch into one commit, destroying the history, but it put all my changes into a single commit.
So, every time I get a commit list that's too long, I will squash the branch. That way, it's just all right in that nice, one commit. So, even though it gets rid of the history, it gets rid of, like, all the conflicts or at least most of the conflicts that you have when doing your rebase. And the other concern, I added conditions to it to say, hey, if on master, if on develop, if on main, abort because I don't want to be the guy responsible for erasing our entire [laughs] Git history.
DAVID: Yeah, I've got a thing in my bash prompt that will check to see what is the current branch that we're on. And yeah, in my bin folder, I have a script called git current branch, you know, git space current dash branch, and it tells you what the name of the current branch is. And there's a peer script in my bin folder called git main that gets the main because five years ago, the master branch was just master.
And that's become problematic in some cultures here in the West, especially because it's problematic language. So, there are people that are switching to a main branch called main or a branch called develop. Well, now you have this problem that, like, what do we call the master branch, right? If we can't call it that anymore because, problematic.
So, I wrote a thing called git main that figures out what is the name of your main branch. And when I put the git branch in my bash prompt, if it's the main branch, it will bold white text on a red background, like just a warning label in your bash prompt letting you know, hey, you are on the main branch, right? Have a care. Go cautiously. But if you're on a story branch, it turns green. And I find this, like, super, super helpful, as, like, just a little warning flag that says, hey, maybe don't squash the entire branch history right now.
MARK: [laughs] Yeah.
DAVID: There's two fragments that I ended up writing. One is called git is clean, that checks to see if you've got any files just hanging out modified and not committed. And a lot of my git tinkering operations, the first thing they'll do is check to see, do you have modified changes that are staged or that are modified and not staged? Maybe you don't want to remaster this branch right now. Maybe you don't want to pull in everything and rebase the main branch back into this. You're going to clobber something important. So, I will use that git is clean all the time.
And yeah, and then the other one is, are you on the main branch? If you are, maybe don't do the thing you're doing, or if you do, you need to rerun this script again but run it with dash dash force or dash dash––I know what I'm doing. Let me shoot myself in the foot.
MARK: [laughs]
DAVID: Force is a lot simpler to type. By the way, for the people that have gone to their keyboards to yell at me, it's a list comprehension in Python that then returns something that's enumerable. And if you call next...you build a list of all the things that match the criteria, and then you call next on it, which gets the first item from the list. And I believe that's lazily evaluated. So, it's not actually, like, doing dot map dot first.
It does actually lazily evaluate through the generator, through the list comprehension to find the thing that you want. So yeah, you say item for item in collection if, and then you give it the matching criteria. And then, you wrap that whole thing in a call to next, which returns the first one. And I got that by looking it up in my scrap bin just now. So, there you go.
MARK: It feels like we're going off-topic because, like, our --
DAVID: Oh, yeah, yeah.
MARK: [laughs].
DAVID: The whole point of, like, learning projects is to get off into the weeds, which I think is great. But you're right.
MARK: [laughs]
DAVID: Let me hang a lampshade on this exact problem. Sometimes, the thing that you want to learn is a meta thing, right? So, you want to take a project you already know and use it to do a thing. So, like, if you want to learn how to do TDD, or if you want to learn how to...I did a thing a few years back where I wanted to get in the habit of committing code every single day. Because I was in the habit...at that point in my career, I was in the habit of authoring 1,000-line commits, which meant that I would go for 2,3,4 or 5 days without committing anything to the source code repo.
Now that we're on git and everybody's got kind of a tiny process, and we're like, you know, we're deploying things that are, like, five-line code changes and that sort of thing...but 10-15 years ago, the tools that we had were much more unwieldy, and it made a lot more sense. It was a lot more efficient to just drag a lot more work in one go. And so, I had to train myself to make tiny commits. I had to literally break the habit because if you're going to do something big, you can keep pushing off some important part of your commit. You can keep pushing it off to the end.
And by saying I have to commit every single day...and I'll tell you what, I spent better than half of the days in that experiment timeframe frantically writing code at 11:45 p.m. because I had spent all day pushing something important down the line, right? Sorry, I'm off in the weeds again. But this is kind of the point is that I was trying to learn a technique for how to commit. And so, I just picked a project that I was very comfortable with. Largely, it was my bin folder and my scrap bin folder.
I would go learn a thing, figure out how to do the thing, and then write a five-line thing and, push it up and commit it. And that was my commit for the day, and I was done. And now it's very, very easy for me to write stuff and commit. And it's weird in my development process if I'm not writing commits at least every half hour to an hour, which is fantastic. When I'm on a roll and really cranking code, the commits come every five minutes. Honestly, it's insane. So, the point of that is you can take learning projects in a direction where it's not the project itself that you want to learn.
MARK: Learning can happen in weird and strange ways. One of the most interesting things that I've been seeing now is that there's a lot of online videos saying, "Hey, take you zero to master in X language," right? [laughs] And it's, like, a 12-hour long video. I tried going to a CSS one, and I only got about six hours through before I kind of gave up on it. But you learn so much just getting the basics, learning the cool features they have. And it just causes so many new ideas to spring up in your head.
Even though I'm a developer, I kind of wish I took more user design courses now before I graduated from college. Because I'm now just thinking, like, if I can draw down what I want properly, then there's no way in hell I can't code this. We're, like, at that stage with technology where if you can imagine it, you can definitely code it. Like, there are websites that if you scroll downward, it looks like you're moving in 3D space, seeing stars move around you, and just have amazing animations.
DAVID: When CSS 3 and the 3D transformations came out, there were two things that people wrote and put in the browser that were just amazing. One was an asteroids game where they gave you just a little ship from asteroids, and you could turn and flow and fly it around. But you were shooting the document model. Like, you literally could shoot the title off of the webpage. And then you could shoot the pictures embedded. And the page would, like, collapse. They'd literally shoot words out of the [inaudible 28:44]. It was just weird. Like, why would you want that? Well, because it's cool.
MARK: You're reminding me of, like, all the cool Google searches. Like, if you just search—I think it was monkey bear on Google or gravity in Google—amazing things would just happen to the web page. Like, all the text would fall down spaghetti-wise. -
DAVID: Nice.
MARK: Or it would drift around in space.
DAVID: Nice.
MARK: There's probably [crosstalk 29:06]
DAVID: I like “askew.” If you Google the word askew, A-S-K-E-W, that's a fun one. I had to show this to somebody a couple of weeks ago, and it works on a phone. So, if you're just hanging out around, open up Google and type A-S-K-E-W and hit Enter and just, you know, see what happens.
MARK: Oh my God [laughs].
DAVID: I think Mark just did it. Fantastic.
MARK: [laughs]
DAVID: Circling back around, Eddy, you said something at the top of the call. You mentioned you tend to learn things when your boss hands it down to you. This is something that I was kind of in the same way, well, a little bit in the same way. I've always had just, like, this unnatural fascination with learning things. But this taught me how to kind of manage my manager.
And I'm curious if you've given any thought, like, if you walk into work and you know that you learn things when work gives them to you, have you ever considered steering your boss into saying, "Hey, I want you to give me an assignment that lets me do a thing that we can both agree on that I would like to learn, and you would like to have done"? Have you ever tried playing that game?
EDDY: I have not. But I know that's an option that is given to employees, right? Just recently, we talked about, hey, if you're wanting to work on a codebase from a different team, you're more than welcome to do that, right? And we're open to the idea. As far as me flirting with the idea of doing that practically, I have not, but it would be something to consider, for sure.
DAVID: Absolutely. I learned this from a boss, ironically. I was really passionate about learning stuff, like, on my lunch break. And I was learning crazy stuff that had nothing to do with what work wanted me to do. So, all right, that's fine. I'm just kind of off in the weeds, learning my own thing. And my boss came in and sat down. And she's like, "Okay, so, I've got this really crazy hail Mary just bat poo crazy idea. And I think you're the guy for the job." And I'm like, "Oh, do tell."
And she said, "We've never been able to script our application from an outside language." This was back in 2002. And so, she was like, "I've heard good things about this language called Python. I want you to go learn enough of that language to see if we can embed it and script our application from Python." And so, it became my job to learn Python and to figure out how to hack into it and to, like, compile it into our application so that you could write Python scripts to control the code.
So, I was basically writing, you know, like the Lua console that when you play video games, that you open up the console and type in cheat codes. It was literally that but for a Planetarian controller, which was crazy awesome. And it had never occurred to me to collaborate with my boss on coming up with weird things until she literally walked in and said, "We were in a team meeting today. And they said, 'Well, we got this crazy idea, but we have no idea if it'll work.'" And she said, "Oh, I've got a guy who loves crazy ideas."
EDDY: I have a question. So, a lot of us, when we take inspiration on building an app, do you tend to lean towards something that's more stabilized and uniform in a sense that, like, you'll follow a project where it will walk you step by step to implement something that you're wanting to implement, you know, and then you learn that way? Or do you just start from scratch and you just build it from the ground up, and that's your best method of learning?
KYLE: For me personally, I'd say it's probably, like, a combination of both. I don't see any benefit of just, like, pulling up a YouTube video and copying down a project word for word, bar for bar, because, you know, anybody can do that. You just install something and then just copy exactly what they're writing. But I think having a video like that is helpful because you're able to, like, get a basis on, like, what kind of goal you might be trying to achieve, what kind of project you're trying to make.
And then, given that foundation, I think it's important for you to, you know, experiment. And that's where I think, like, reading articles online and checking out what other people have to say is helpful because you can start with this foundation of a project and kind of customize it and explore, create as many new features as you can. And I just think that's the best way to get exposed to new technologies.
EDDY: Let me ask you this: do you think it hurts you in the long run to watch a video tutorial on how to build something?
KYLE: I think if you watch the video and then just copy everything down exactly, absolutely. Like, you know, I could go, you know, watch a three-hour video on how to make a glorious full-stack application, and then I'll do that six times and then put them all on my resume and be like, hey, look at what I did. Like, these are my skills. And then I actually get to the position, or I get to the interview, and I have zero idea what I'm talking about. It's definitely a negative.
MARK: I'm going to have to push back a little. I've done some of those online projects. And it's like, I agree, doing one large video project is bad. But if you're following, like, say, a learn the language guide where they take one project, iterate through it, or make several copies of the same project and then tweak each one separately so you learn the language, I find those helpful. I've done one of those to learn how the Vue framework works, as well as I did the same thing with the CSS.
So, again, one large project is not helpful, but finding a video that says, "Hey, you're going to make several, maybe a dozen projects throughout this video. All of them are going to be very bare bones, but they're each going to go over highlighting a different piece of code or how something works within this language," I find those useful because then you can actually see, hey, here's a prime example of what this code does, and a bare-bones method of how it's implemented.
KYLE: Yeah, I mean, I think that's fair. I think for learning purposes, it's definitely, like, just going through a video and kind of mocking out the steps going through how, you know, how to actually start doing something; I think that is definitely beneficial. But I wouldn't really consider those to be, like, projects per se.
You know, my definition of projects are more something that you come up with that, like, has some kind of application that is useful to you or other people that you don't just copy online because, you know, there's a million copies of every single one of these videos. You know, there's a million different people who all made the exact same project. So, it's like, it doesn't add any additional usefulness to do the exact same thing. So yeah, for learning purposes, that definitely is true. Following a video would help. But, like, that's just...in my definition of what a project would be, it doesn't quite fit the criteria, if that makes sense.
DAVID: That's actually really well put. My initial answer to Eddy's question was: it depends. And you guys just beautifully represented both sides of the it depends. There's a time when you want to just, you know what? I don't need to scratch an itch. I'm in a completely foreign land. Please show me how to build back scratchers. And that's nice to have. Well, we start here, and we build all the way to here. And it's undirected. I'm not trying to finish anything.
And then, there's other times where it's like, no, just tell me how to get this out of the database and transform it. I don't even need to know how to build a clock. I just need to know what time it is. And those are both, like, really, really useful.
EDDY: I think I've found when working on personal projects myself, I've got this thing where I'm always wanting to use the latest and greatest. So, videos are great for a start, I feel like, but by the time a video is out, it's old information. Some of it will be applicable. But I feel like I have to go to the documentation to figure out, what have they changed? Why is this function not working? Something like that to where may be a good starting spot, but I always refer back to the documentation in the community to be able to move forward.
DAVID: That's well put as well. There was a set of videos called RailsCasts back in the late noughties that were really, really good. Ryan Bates, I think if I'm recalling correctly, Ryan would put together these videos, and he would explain, here's how you do this in Rails. But he would then peel the top off and say, "And here's what you're doing."
And so, he's got...I don't know if it's still up there, but, like, the video that he made that made the biggest impression on me was called “How to roll your own authentication or authorization.” And it was literally how to deal with, like, what Devise or Warden or CanCan what all those things do. And it was super useful because then when we stepped into using Devise or some kind of authentication product, I knew what it was doing under the hood.
And 15 years down the line, there's a different way to do this every single time. But every time I open up those tools, I find myself, you know, saying to myself, ah, this is solving that same problem. The same three problems that we had in 2008 we still have today. We just have a different DSL for dealing with them, and that's, like, super, super useful.
What's less useful is finding a video from three years after that shows you how to solve that problem in a different language that's now too old to be useful and doesn't show you what the underlying problem is. It's like, oh yeah, that's a coat of paint on a different house. And it tells me nothing about architecture, and it doesn't fit the house that I have now. You run into those, too.
That is actually pushing us close to time. We had a late straggler join. Ramses, welcome. We're talking about how to pick a project to learn from. You've got 30 seconds to give us our closing thought. Go for it.
RAMSES: Pick something that you're passionate about or not passionate about, something that you hate, or something that's really monotonous and brings you pain, and try to solve that.
DAVID: We've been talking about scratching your own itch, but picking something you are passionate about and then saying that you hate it, beautifully put. There you go. Pick something you love or something you hate. That's a fantastic way to sum it up. Thank you, guys, for coming. This was a lot of fun today. I had a great time talking with you guys. We will see you in a couple of weeks.
The panelists discuss the role of a team lead in a software development context. Mike shares a personal story about a family hike and draws parallels between being a team lead and guiding a group of hikers. The discussion revolves around the challenges and benefits of being a team lead, considering factors such as size, experience levels, and the balance between technical contributions and leadership responsibilities.
Afton, Matt, and Eddy share their perspectives on the role of a team lead, emphasizing that it can vary greatly depending on the team's dynamics and the individual's career goals. They discuss how being a team lead can provide opportunities for mentorship, architecture design, and a broader understanding of project management.
Overall, the conversation highlights the importance of considering one's career goals and the specific circumstances of the team when deciding whether to take on a team lead role and how it can enhance one's skill set and career trajectory.
Transcript:
MIKE: Hello, and welcome to another episode of the Acima Development Podcast. Today, we are going to be talking about being a team lead, specifically being a team lead. Why or why not? There's often a choice that you have in your career, and team lead starts you down a path sometimes toward being more involved in leadership. There's trade-offs involved there.
You know, to have a good conversation, we have several current or former team leads. We have Afton with us, who has been a team lead. We have Jared, who is currently a team lead over at QA team. And we have Matt, who is currently a team lead over an engineering team. Justin, have you been a team lead before?
JUSTIN: Yeah.
MIKE: I figured. And we also have Eddy with us, who has not yet been a team lead. I would like to, as usual, start our discussion with a story to kind of guide the discussion a little bit. And I've been thinking about this and how we might lead out. I decided I'm going to start by talking about a family vacation I took last year to Colorado. On the way out, we weren't quite where we were going yet. We ended up going to the Great Sand Dunes National Park. I think it's one of the less visited ones, and it's really beautiful.
We stopped in the Denver area. I don't remember exactly where it was, so I can't tell you [laughs] precisely. But we wanted to get some fresh air. And we went for a hike. One thing I learned from my dad, which is a really good idea, is that when you're going for a walk or hike together as a family, it is a great idea to have the youngest or the slowest person on the group that you're with take the lead, be the person in front. The strongest walker or hiker you put in the back, and there are really compelling reasons to do that.
If you put the fastest person in front, then they will have to look behind them regularly to stay together with everybody else. And pretty soon, they'll be way out ahead, and the group is all separated, which is a bad situation if you ever want to coordinate. That was particularly important back in the days before cell phones. But it works out great. I do the same thing with my family. I generally have the youngest person in front, and then we follow their pace. It works out pretty well.
MATT: That's how wolf packs operate.
MIKE: Is it? That's good to know. It's just a really effective way to get everybody going at the same pace. We went on this hike. Like I said, it was beautiful. And we got up to a good stopping point where there was a loop that went around a small peak that [inaudible 02:27]. And my oldest son was looking at that peak up ahead, and he thought, I'd really like to do that. And he still had the energy, right? He really wanted to go ahead and do that loop. Or he actually just wanted to go straight up the mountain. [laughs]
I said, "You can go around the loop. There's probably a trail on the backside." And everybody else was kind of tired out and wanted to go down. In the end, we kind of compromised. I went with my oldest son. And we quickly went and did the loop around the top. He went up over to the very top, and I went around the side. And we met, and then we came down, and we met the rest of my family. My wife went with my younger kids; them go out in front. We thought we'd catch up to them before we got to the bottom, but they actually beat us by a little bit.
I'm telling this story for a reason. My wife was an excellent team lead because she stayed with the people who needed guidance through the entire hike. My oldest son was the strongest hiker, but he did not stay with the team. He was just really hungry to go get to the top. And there was nothing wrong with that, right? It was great. You know, he's peak age physically. [laughs] So, you know, it's great that he wants to do that. But it meant that he wasn't really a good candidate to lead the rest of the group.
Contrasting the differences between what my wife did in staying with the younger kids the entire time, making sure she never left them behind, and my oldest son, who's just really eager to go and get to the top, I think, provides some perspective as to points that all of us may find ourselves in at different points of our career. Being in either position isn't necessarily bad, but they are different. And you kind of need to commit yourself to a role if you're going to be in one or the other.
But, sometimes, you're going to be an individual contributor, and you just want to get to the top. There's some value there in contributing a lot of code to the team. And sometimes, you can provide more value in helping others along and making sure they get to where they're needing to go. I thought that was, in my mind at least, a good way to kind of frame this conversation.
I'd also like to add that joining us a little bit late is Ben, who's also a team lead and has been a team lead multiple times in the past. So, I think I'm just going to open the question. And what are your thoughts, particularly towards the team leads or former team leads? What are your thoughts about the contrast between being a team lead and not a team lead, and why you would or not take that position?
AFTON: I had some thoughts while you were telling your story because I was a team lead over, at first, 8 to 10 engineers. That dwindled down a few for the longer term. But a few months back, I moved to a new team, back to being an individual contributor. And the dynamics of my new team were so different than I had experienced because the team was much smaller. The average engineer had a lot more experience than on my prior team.
So, as you were telling your story, I was thinking the leader of the hike would have a vastly different experience and vastly different demands upon them, depending on who they're hiking with. You know, you may have really young, inexperienced, or out-of-shape hikers [laughs] and also very skilled hikers. And keeping them together it takes more work or more coordination, more communication, more group understanding of people's levels and capabilities, and how you can bring those together to meet in the middle.
Versus if your whole group is very skilled, it's going to take a lot less overhead to keep that group in sync with each other and moving along together. Whether that group is all skilled or all inexperienced, it's largely the same. The overhead of managing that group will be, I think, much simpler. [laughs]
The broader the levels of experience of those team members, the more work it is for the leader to keep everyone together. And the skills required of the leader can be different, so high communication and collaboration and making sure everyone understands each other, so people skills and team building. And you need to know who you're going to be leading, what the dynamics are of that group, the skill levels of that group, in order to ever even start to think, is that the challenge I want to take right now? Is that going to get me where I want to go in the future?
MIKE: That's a fascinating insight. You're saying that being a team lead is not one thing necessarily. It's going to depend a lot on the team that you're working with.
AFTON: Yes, absolutely. The team that I was leading was, I would say, majority junior developers with a sprinkling of very skilled developers, and even developers from different parts of the world. So, I had a few team members in India. So, also cultures of the different team members can come into play as well.
And when I moved to my new team that I'm on currently as an individual contributor, most of the team members are very skilled have a lot more experience generally. And also, everyone is local. [laughs] We can all get together and sit by each other, which makes it easier to understand one another, work together, build some sense of teammanship, easier to manage overall.
So, yes, the dynamics of the team, I think, will change what's required of the team lead, the skills that they're going to need to help their team be successful, and change the experience of what the team lead can then gain from the experience of leaving the team.
MATT: I strongly agree with that statement. You know, as Afton was just saying, I believe, currently, my team is represented in six different countries. And that adds a little bit of complexity because of scheduling, some language barriers occasionally, and just getting the right people on the right project so the communication can be there.
One thing I think a lot of people worry about is if they become a lead, that they aren't going to be able to contribute. Well, sometimes that's true. And you may not be writing a lot of code like you are as an individual contributor. Your contribution aspect is still there. It's just in different areas.
Here at Acima, our leads do a lot of architecture, and lead the design flow, and help with requirements, and a lot of the higher-level stuff that, as a contributor, you don't get as much experience doing. So, it really depends on where you want to go in your career. But I would highly recommend, if given the opportunity, everyone take the opportunity to lead a team at least once and get that experience.
MIKE: So, Matt, you say that it's worth doing at least once. It's a valuable experience, even if you don't stick with it.
MATT: Absolutely. I've done this a number of times. I enjoy the role personally because I love helping lead the architecture and helping make some of these business decisions, where you might not have the opportunity as an individual contributor because you aren't in the right groups, you know, for instance, in meetings, things like that. I know everyone says they hate meetings, but they're a necessity. And if you want to build good software, it's vital to have that understanding.
MIKE: You mentioned the meetings; that will probably be a recurring theme. If you're going to be doing some leadership, you're probably going to have to meet with some people, which means that you're going to have a higher meeting load than you would otherwise. It's just intrinsic to the nature of the role.
EDDY: Can I add I feel like there's a stigma with being a team lead. There's an association with being bombarded with meetings. So, as someone who enjoys thoroughly coding on a daily basis and constantly contributing to a codebase, would that individual be a prime candidate to the same [inaudible 10:22] position?
MIKE: I might refer some to what Afton said [laughs] that --
MATT: I'd agree.
MIKE: It's going to depend a lot on what team you're working with. If you're going to work with a large, diverse team, probably going to be a lot of demands placed on you, and you're probably not going to have much time to also be an individual contributor. It really does depend a lot. I've had times when I was leading a team, but I'd still spend most of my time coding. And, generally, that was with a fairly small team. And I still had lots of time to code. And I've had times when I had almost no time to code. It really depended on the constraints that were on me.
MATT: Because our listeners may or may not know much about Acima and our structure, I came from a smaller team initially. And, on that team, at the time, we were extremely small. In fact, our team name was Nano. Our lead was able to write a lot of code most of the time because we were a very senior team. And we just kind of divided up projects and went at them. So, there wasn't a whole lot of guidance that he had to provide to us.
Whereas, as Afton stated, the Atlas team is larger and has a lot more junior representation. So, it's a different role as a lead, a lot more mentorship, a lot more guidance, different tool set to lead that team as it is a small, more senior type team.
AFTON: I've been thinking a little bit about this. Eddy's question seemed to be kind of saying, when would this be a good time? [laughs] Like, I've done the team lead for, you know, a year, year and a half, and still love to sit and just write code. Going back to individual contributor, I was in heaven [laughs], spending a whole day writing code again.
MIKE: [laughs]
AFTON: Super fun. But that doesn't mean I didn't love the new skills I was developing and the new challenges I faced as a team lead. My situation was that I had been professionally developing for about three and a half years, is all before I started acting as team lead. And, at the time, I had been around the longest. I had a lot of business knowledge and a good foundation of technical skills. So, I felt like I could be a good mentor. Even if I was lacking in some technical skills, we did have some more experienced developers very available to me and on my team who I could rely on to help with technical leadership.
I do think it's an amazing experience that everyone could benefit from. You know, if you're given an opportunity, think about, well, first of all, the team dynamics of who you're being asked to lead, what it might require of you to lead, and how much time that might leave you to continue developing your technical skills. And if there's potential that you won't have much time, then to realize that you might start to feel like you're falling behind in your technical development, your own technical development, if it requires so much of the other skills to lead a team. But if you are being asked to lead a more experienced team, then you may have more time to continue working on your own development.
I think it's really important to look ahead in the future. Think, a year from now, if I take this role and this is what I see it looking like, a year from now, is that going to move me ahead in my career and where I want to go? Or could this potentially be sidetracking me to somewhere where it might actually hinder my ultimate goal?
So, think ahead of the future: a year from now, am I going to be glad that I did this? Is it going to put me in a better place? Or could this somehow put me in a worse place [laughs] hold me back from my ultimate goal? So, considering your goals is very important. Think about that and take the time to know where you want to be and to say, a year from now, where do I want to be? Two years from now, where? Five years from now, where? And now, does this fit within a path to get me there?
MIKE: Well said, Afton. You said --
MATT: The way I look at it is, let's use an example. Say I am going to work on my car. I have a toolbox. All I have in this toolbox is a screwdriver and a hammer. I can't get really far with that screwdriver and hammer only. And I see taking on new challenges, for instance, being a team lead, and there are other roles absolutely that help you fill this toolbox. It's just adding more tools to that toolbox.
When we're individual contributors, sometimes we also get stuck in the weeds, right? We don't see the broader scale of things because we're picking up a story. We're trying to meet the requirements of that story. And we don't have a lot of input on overall architecture or how it's going to work with, say, other services.
And I think when you take on that team role, you start to build those skills as well, more so than you might as a contributor, because you're seeing the bigger picture. You get to help guide how all the things are going to work together, defining contracts. And what does the structure of this look like? Is it a new service that we get to roll out?
And you get to help design all these things almost like an architecture role, right? I think it would be a great segue into an architecture role if that's where someone would like to go with their career. And on the other side, if you want to go into people management, also get experience there. It's just I see it as another way to add tools to that toolbox.
MIKE: Kind of combining what you're saying there, Matt, with what Afton had to say, you may be at a point in your career where you look, and you just see that hammer and a screwdriver, and what you need is maybe some wrenches, [laughs] and some basic tools. You don't need a very special tool. You don't need, like, a transit for doing surveying. You just need some wrenches or a saw.
Depending on where you're at in your career, looking at the team lead role, some of the tools that you may be putting into your box are not the ones you need right now. And maybe what you need is more language skills, you know, some of the basics. It's important to look at what you need next in your toolbox.
MATT: Right. Like Afton went to an entirely new language. Now, her toolbox is filling up on that side.
MIKE: Exactly.
MATT: I feel like a lot of people are very apprehensive. And there's kind of a bad stigma behind becoming a lead because of the meetings. But there are skills to be gained. Being able to communicate with business and understand their language and translate that to technical language it's a really positive thing if that's something you might have a little interest in but are apprehensive because you don't want to be in meetings.
AFTON: Yeah. We were discussing earlier how much time is spent in meetings. I don't feel like they were detrimental. In all those meetings, I felt like I was learning communication, collaboration, higher-level business. How do you make decisions? Project management was a big one. I spend a lot of time studying [laughs] how to manage projects.
So yeah, those are all really good skills to have, like Matt and Mike were saying. But realizing those are the skills you may have to focus more on, of course, again, depending on your team dynamic, but just to realize what skills you're going to need and that that may be your focus for that time. Being aware knowing what you're deciding, what you're choosing is important.
BEN: Kind of a different topic. You know, one of the things that I've seen with businesses is that a lot of times where they fail the most, it seems, is with management. We kind of think of management, at least I have, I guess, as kind of, like, this easy thing that you can learn really easily. And probably anybody can learn how to do it. But I've seen people manage coders, but they kind of are not being the manager. They really just want to code, and yet they're in this manager role.
They're kind of doing their coders a disservice because they're not really fulfilling the needs of that role, but they are the ones that have that role. And, you know, nobody else can really do it but them. And so, I guess that's one caution I would give out. Like, if you're a lead, be a lead. Don't be in the lead role and just try and keep just being a coder because you do pretty much everybody a disservice by doing that, I think.
MIKE: To go back to my talk about the hikers at the beginning, you might be the fastest hiker in the group. Hiking up ahead of everybody doesn't benefit anybody but yourself. It doesn't get the project over the line. The project is to get everybody up there. There's a lot of value provided by being that person who walks in the back and helps the others along. And acting like that's not the most important thing that you're doing is problematic.
Micromanaging and telling people what to do is usually not very helpful. Helping people out and, figuring out what the requirements are, and removing obstacles for people is immensely useful. You can spend all day removing obstacles for people, helping them along, and move the project forward much faster than you would if you were just chipping away at your own little piece.
JUSTIN: If you look at your effectiveness as an individual, you need to look at yourself as, like, how can I multiply my effectiveness? Where am I most effective? Once you understand that it's through helping other people be more productive themselves, it's kind of a game changer. That's one of the reasons why I was kind of attracted to this app sec actually was, you know, oh, I can go out and help a lot of people now develop more securely and more productively.
But, you know, as a team lead, you have the closest insight to all of your team members, and you know what their strengths are, what their weaknesses are. And you can go in and talk to them each individually and help them get over the things that are affecting them, and help them be more effective engineers, more effective communicators, and lots of different things.
And so, it's kind of a great opportunity to—you've probably heard of this—but be a leader servant, where you are helping others and, ultimately, you aren't being the great individual contributor that you possibly could be. But you are raising the overall work output of the group and helping them in their careers and, you know, just as individuals. So, I think it's one of the best ways to really help other people, you know, a great position to be in just because you can help them at that personal level.
MATT: Helping other people level up is extremely fulfilling as well. A great analogy would be sports. You might be the best player on the court, but if you're not a team player, your team isn't going to be successful. If you're just going out trying to score all of your team's points all the time and not passing the ball, your team isn't going to win. So, sharing that knowledge and picking things up for them, you get double covered; perfect time to lift someone else up and get them some points. And that's how you win.
As Mike said, the only person you're helping is yourself sometimes if you're not fulfilling those other needs as a lead. I feel like you're even doing yourself a detriment. And it doesn't reflect well. So, you just have to be really open to what the role is. And it isn't just going out and getting all the points for your team. It's helping your team win.
JARED: You know, Matt, I really like those sports analogies. I've been listening and reflecting upon my career and where I'd been a leader. And I've been thinking about when I first got into a management position when I was managing a restaurant; I came at it from the approach of...everybody's heard this phrase, "If you want it done right, you do it yourself." I stressed myself out. I was a very mean and angry person.
As I grew in a leadership position, I learned that that's not how you manage. That's not how you handle people. And when you're a lead, people are the most important aspect of that. At this point, as a lead, you should be coaching, and mentoring, and training, and allowing your team to also take leadership responsibility and empower them to do their role.
And also for me, I think that, if you want it done right, do it yourself, came from a lack of trust. And so, as a lead, you also need to trust your team to do it right. But also, you should train them to do it either the way that you would do it or the way that you would expect to have it done. But also give them the leeway to learn and expand there.
I don't know if this is even a controversial take, but I don't like the idea of people wanting to be leads. That, to me, always seems like a red flag. And I'd like to hear everybody else's experience. But I truly think that leaders are found by different leadership and say that, you know, "You are level-headed and can handle stress. And I think you can handle working and meeting these other people."
And for the most part, they step up to the plate and learn this new skill set. I've never really looked at it like, oh, I want to be a lead. It's that I've been asked to be a lead by somebody who saw potential in me. And I said I'll give it a shot and see where that goes.
MIKE: If I had somebody say, you know, "I want to tell people what to do," then I would not want them to be a lead on my team. On the other hand, I saw somebody who was already helping people around them, mentoring, taking their time to help somebody when they were stuck, going out of their way to remove blocking issues for somebody, or to go get a question answered. Well, that person is already doing what I would want from a leader. There's nothing wrong with aspiring to help people. I think that there is something problematic with aspiring to direct people tell them what to do. What does make things feel better is helping.
MATT: You also hear people say things like, "A good leader hires people who are better than they are." Team leads generally aren't management. They are just leads that help guide their team, right? As a lead, I feel like your goal should be to make your team members better than you, at least try. Give them the skills that you have and share them. Also, learn from them. So, you're gaining skills as well.
EDDY: This is sort of, like, a point-blank question to everyone. Has there ever been a time where you've been afraid to promote someone who is one of your highest producing individuals on your team to assume the role as a team lead, knowing full well that not as much code will be going out or, like, higher difficulty tickets will take longer, et cetera?
MIKE: Yes. [laughs]
MATT: Also, yes.
MIKE: Absolutely. Because there's going to be reduction and just absolute...the amount of code that's getting written. There's a trade-off there. Somebody who's good for the lead role; however, you probably won't lose that much output because the multiplier that Justin was mentioning means that they will be helping other people get more done. So, you don't take as much loss as you might think.
MATT: You may see a drop up front. But if they're doing what they were put there to do, you're going to see a lot of gain on the tail end because everyone else is going to be able to be more productive, and level up their skills, and make up in that difference, right?
AFTON: I keep hearing so many parallels to Parenthood. I just need to mention that real quick because [laughs] one possibly unique thing about our culture here is that we have a wonderful culture of mentorship and learning together. And I think that that must inform our feeling comfortable moving a high producer into a lead position and letting things slow down for a bit, but eventually level up because everyone's benefiting, learning, having good experiences, and growing together from this.
Just like, you know, I think it was Jared who said earlier, if you want it done right, you have to do it yourself. And my first thought was, yeah, I had to let go of that when I had to start teaching kids how to do chores around the house because [laughs] it's not going to be done right. It's going to take longer. It might not even get done.
But I need to start letting them learn how and do that job for a while, keep helping and instructing, and, eventually, they will grow better. Very like parenting, you want to give everything you can. It's going to take some time, extra effort, but they're going to level up. They're going to grow into capable, skilled people, and that is, you know, worth it.
MIKE: And if you don't give them that opportunity, your kids reach 18, and they're not prepared [laughs], right?
AFTON: Yeah. [laughs]
MIKE: And that happens inadvertently. You think, oh yeah, I'm trying to be helpful and trying to do everything. You help people out by giving them a chance to fail a little bit.
BEN: I think that's a really good point because it's kind of giving up control to some degree. One other thing I was going to say is that it's not necessarily the highest producers. I mean, that may be obvious, but there's some people, you know, that you can tell they would really hate being a team lead, [chuckles] you know, they just want to be in the code. And that's fine.
MATT: And it's not for everybody. It really isn't. Some people just have no interest, and it isn't what they want to do. And that's okay. One of the things that I just would love to be able to do is remove some of the stigmas that come with the role and have people have a more open mind to that opportunity. Because there's a lot of positive aspects of the role.
I personally...I love it. I love being able to work with the other teams, which, as an individual contributor, you don't get quite as much opportunity. You know, Ben, you and I work together a lot, especially recently. And it's great because I may not have had that opportunity otherwise.
AFTON: If there is a stigma, that can be mitigated to some extent by just having a clear structure in your organization, having clear definitions or descriptions of each role and what's expected. And if someone is assuming this new role, they know what they're getting into. They know what new skills they are going to need and what demands will be upon them. Then, people can just make informed decisions. Is that what I want or not?
I'm trying to understand the stigma that you're talking about, Matt. And I'm just kind of assuming that maybe if people think it's going to be something that it ends up not being for them, or if they have frustrations because expectations were not met, which could lead to a stigma of it being a bad thing or the meetings being a bad thing. But, anyway, clarity on what the role is, what the expectations will be, what the demands will be, I think might help.
MIKE: Well, and there's different kinds of meetings, right? If you're in a meeting where you're barely engaged, and people are talking about stuff that doesn't concern you, and it runs on for hours, that's excruciating for me anyway. [chuckles] You have to be attentive enough to see if your attention is ever needed. So, you can't really put your attention elsewhere, you know, you don't really need that attention there. So, you're in this in-between area where it's really hard.
That kind of thing can make anybody say, "Well, I hate meetings," if they've been in meetings like that. But this is kind of...it comes down to our individual responsibility. Especially if you have a lead role, you have an opportunity to kind of define what that meeting looks like, say, "Well, we're going to have an agenda. We're here for a reason. The reason that we're meeting is because we need to solve problem X. We need to talk through it." And the whole reason that you're meeting with somebody is because you need to communicate and come to some shared understanding.
And once you've met the purpose of that meeting, then you can be done. And the kinds of meetings that have an agenda, that have a clear goal, and that end with action items and a decision, those are invigorating. That kind of meeting doesn't drag you down. It actually is very rewarding. You can be architecting and feel much like...and is even part of the coding process in defining, you know, say, architecture, or determining requirements, even, you know, refining stories.
It's all part of the coding process, just as much as having your fingers on the keyboard, you know, typing code. The stigma of meetings or the sense that, oh, I'm just going to be in endless meetings, even if it was true, which it probably is not, the meetings that you're going to be in, that you can influence, you can make actually very effective. And it's not a negative thing. It can be a lot of fun.
MATT: Yeah. And I kind of have a personal rule that if a meeting doesn't end with any action items, that meeting was all for naught. Meetings need to have agendas. They need to have action items that can come out of them, and then they're productive.
MIKE: It seems simple. Like, well, it's really that easy? It kind of is. [laughs]
MATT: I would have no problem if people were in a meeting that I organized, and they got an understanding that they didn't need to be there. They can just drop. You know, hey, I don't think I need to be a part of this meeting. I'm going to go help out my team or take care of other things that need to be addressed. And, you know, maybe that's something that people could set as a rule. If you don't feel like it's necessary that you're in this meeting, you are free to leave.
EDDY: Let's say that you just, like, naturally enjoy being in a leadership role. Would it make sense in regards to being a team lead for a development team? Would you say that it's a requisite to have knowledge in programming in order to be effective in that role?
MATT: For an engineering lead, I would say yes. For an engineering manager, not as much. Though it is helpful when you understand what your team is talking about, right? And it can help guide them because that's part of the job, aside from just HR duties. But there are a lot of CTOs at companies that really don't have a whole lot of technical experience. They're just really good at guiding. They're great with ideas and helping build teams to see those ideas through.
MIKE: I think that somebody who's very effective does, however, understand the engineering process. Even if they are not necessarily in the code, they understand what it means to engineer something, that creative process of building things.
AFTON: Yeah, when I started as team lead and was trying to really grasp what it would mean to be successful in that role, I did a lot of research on the various roles in engineering. And most of what I came across when talking about team leads was actually referred to as a tech lead, a tech lead meaning that their role really is to be a technical leader, which meant they needed technical experience and, you know, a lot of development skills. So, above that, would be more manager, like they were saying. So, here, I believe, team lead is essentially a tech lead role.
JUSTIN: Just a quick comment about the CTO and any leadership position that isn't coding directly and that can go up from manager to director to VP. The ability to know what it takes to build something and know when, you know, there's some BS going on on the engineering side that's a very vital skill that those leaders need. If those leaders don't have the ability to detect when the wool is being pulled over their eyes or when they don't know what's really going on, or they don't have the skills to find out, they usually aren't that effective as a tech leader.
The best leaders I've seen, or some of the best leaders I've seen do, come from an engineering background. They founded the company as the original engineer, or they came up through the engineering ranks. And they happen to have the very great leadership skills that allowed them to be at the top. And those types of people actually inspire great loyalty and inspire their workers to work hard and to be able to see their vision.
It's not easy, certainly not. But if you do have those skills or if you have interest in going in that direction, it's worth researching how to do that, how to be a leader, because not everybody just picks it up naturally or anything. It's something that you study. It's something that you decide you want to go do. And it's something you practice. It's something that you interact with others and receive feedback on. And that's hard, receiving feedback. And actually, I'll go into that receiving feedback a little later.
But all those things, it's a lot of work to be those leaders, especially ones that can inspire their engineers and be able to share the vision that they have. And it's what inspires people, you know, to go that extra mile and to make sure that the work that they're doing is correct and that they care about their work. The great leaders can share their vision, and they can also understand what work is needed and what work is really going on.
AFTON: This is my first career job. And so my experience is limited to here at Acima. But I would imagine that what's expected of you, or what you need to be able to do, skills you need to have, or the amount of technical skill you need versus managerial skill could vary greatly depending on the company, like the size of the company you're working for.
If you're a brand-new startup and they're trying to get things established, the demands on you may require lots of technical but also lots of managerial skill to fill a role as the company is trying to get established. Or if it's a larger company and they have enough people and enough foundation to have just a tech lead who doesn't have to do anything managerial or just managers who don't actually have to know anything technical [laughs]...I don't know; I'm just imagining that that actually could vary greatly, depending on the company you're working for the size of the organization.
And one thing for me: when I started as a lead, I was trying to understand my role and what was expected here at Acima so that I could put some kind of boundary on what was expected of me because I know myself personally. If I don't know kind of what success means, then I'll just keep pushing and trying to do everything and get overwhelmed or, like, burn myself out very quickly. [laughs]
I tend to try to do it all unless I have some kind of ceiling I can say, this is as far as my reach needs to go, or these are kind of the boundaries around what I need to do to do my roles successfully, to meet expectations, to exceed them, to be effective, to have the greatest impact in my role.
MIKE: I think you're dead on, Afton. There's companies that have HR-only managers, right? They have no technical expertise at all. But they do a great job of the aspect of management that has nothing to do with technology. And then they have tech managers who are purely responsible for the technical side. But I think most companies, the roles will have kind of a hybrid of both. I think you're dead on, and figuring out what the requirements are where you're at is going to be really valuable so you'll know what the expectations actually are.
EDDY: I just want to add this has been extremely insightful. I'm better grasping the idea of what a team lead does. [laughs] Because prior to this, again, I fell victim to the whole, oh yeah, team lead, meetings, right? So, this was great.
MIKE: And it's been good to have you, Eddy, as that voice who's not done it before who can ask those kinds of questions. Really appreciate it.
JUSTIN: I briefly mentioned this before, but I think that team leads need to remember to be humble and to ask for feedback from their team members. Getting that feedback is key to leveling up your team lead ability. And finding a mentor who perhaps is another team lead or some other tech leader is also key. And that way, you can gather that feedback about how you're doing, what your weaknesses are, and what you can do to get better.
MIKE: Thank you. And maybe that's a good place to draw this to a close. As you're considering taking a lead role, find somebody who can talk to you about it, who can mentor you, and kind of explain to you what's going to be going on and can help you as you make the transition and grow your toolbox. Thank you to our panel today. It's been a great conversation. I guess we won't see you again, but you'll hear us again [laughs] on the next episode of the Acima Development Podcast.
The panelists continue for part two of their discussion on testing code with RSpec!
✨ Check out Part I here! ✨
Mike kicks things off with a maze metaphor, illustrating the importance of navigating code branches. He emphasizes the branch-focused approach for comprehensive test coverage and cautions against excessive testing of external libraries while highlighting the significance of testing public interfaces.
The episode also addresses the hurdles newcomers encounter when venturing into the world of RSpec. Hailey and Eddy share their initial struggles, likening it to learning a new language. They agree that familiarity with RSpec's unique language and structure grows with time.
In the latter part of the discussion, Eddy and David share insights on RSpec's error messages. Eddy expresses frustration with cryptic messages, particularly involving hashes and scientific notation. David recommends using the --format documentation option in RSpec to enhance error message clarity and suggests writing descriptive context, and it blocks for improved test readability. Mike highlights the importance of enhancing error messages and proposes an unconventional approach to structuring tests while emphasizing the value of starting with the unhappy path.
All said and done, this episode takes you on a journey through RSpec, covering testing strategies, best practices, newcomer challenges, error message improvement, and intriguing insights into test structuring. It underscores the significance of clear error messages and offers valuable guidance for enhancing test readability and effective debugging.
Transcript:
DAVID: Hello and welcome to the Acima Development Podcast. I'm David Brady. I'm hosting today. We've got a really great panel. We've got Ramses, and Jonathan, Freedom, Mike, a couple of people snuck in. I think I see Eddy. Hailey just walked in. This is going to be a good episode. We're going to talk about how to organize RSpec to make it a little more understandable and how to deal with some of the difficulties in it. Mike has a thing to drop on us.
MIKE: And the way that I'd like to kick this off is to talk about a maze, either a maze or a cave. Visualize your pick. You're either going to walk through a labyrinth above ground, or you're going to walk through a labyrinth below ground. Either way, you're lost in endless passages that branch here and there. You know that you want to find your way out, right? There is a way out, but going into this maze or this cave, you don't know which way that is. And how do you solve that problem?
I'll make a proposal here of a solution, a straightforward solution. And here's my proposal: Every time you come to a fork in the path, you have the ability to mark it, right? And this is actually a very simple rule. One way you can do this is just to always go right [laughs] first, right? You always turn right when you get to a branch. You explore to the right. And then, once you get to another branch, you go right. You get to another branch; you go right. You get to another branch; you go right. There's even a name for this in the computer science literature of, you know, you're doing a depth-first search.
You're going to go down as deep as you can in the cave, right? You're going to go follow that all the way to the end. And when you reach the end, you backtrack to the previous branch. And then, you turn left, and you don't turn left down any branch until you've explored as far as you can to the right. And then, you can go and explore down that branch to the left. And then, again, you have your right rule where you're going on as deep as you can. You come back, and you backtrack. When you finally have to, follow the left. And you keep on doing that, making sure that both sides, both branches, at every point until you've explored the full maze.
I actually read about this once. I've thought about this since I was, like, a teenager because I read once that they design mazes for which this rule doesn't work. I'm like, wait, what? How? Well, the way that you design mazes doesn't work as you have concentric rings, which means the branches don't quite follow the right rule. Because if you have concentric rings and your solution is at the center, you can have a wall all the way around at the outermost layer. All of the turns are left. And if you turn left, then you're just going to be going around a ring again. So, at every point, the rule doesn't work. But you can make some minor adjustments to it to kind of make it work.
But in a traditional maze, like the kind that would be underground in a cave, they can't do that sort of thing generally. You have to follow one branch or the other. And why am I talking about this for RSpec? I say this because our goal when we are testing code is to get coverage. We want to make sure that everything works. And a lot of times, we think, well, my code is really sophisticated. It does really interesting things, which is probably true. When you break down those interesting things, in the end, they tend to be binary decisions. You go right, or you go left. It's a decision tree.
As you follow down on your code, at every point in your code, you're either executing something, in which case you're always going through it, or you have some sort of condition. And sometimes, I will say, sometimes those conditions are implicit. It doesn't always include an if clause, for example. A return sends something out or a break. Maybe it's not explicitly doing an if, but there's some implicit types of conditions. Either way, it's a branch.
At every point in your code, it's either going to go straightforward, right? It's going to keep on executing through instructions, or it's going to branch somehow. And if that's what your code always is, which it should be, it's either going to progress linearly, go through procedural step by step, or it's going to branch. And so, if you want to have complete coverage of your code, then what you need to do is simply cover every branch.
I'm going to stop on that for a second because I think it's a critical realization that's really helped me with RSpec. Because if instead of thinking about my code as a set of functions and maybe I've got some anonymous functions, and classes, and objects, which is all true, from a testing perspective, I think that your code is just a set of branches. I don't really care about your objects other than as entry points. What I care about from the testing perspective is coverage. So, I care about the branches.
And thinking about it from that branching perspective changes your mindset. You're exploring the cave, right? And you want to explore every branch. And once you've changed that from thinking about it as this sophisticated, beautiful labyrinth, which it may be, from a testing perspective, you should think about it differently. You should think about it as a bunch of branches. It's a tree with branches. And if you cover all the branches, your testing is complete.
I'm going to pause there for a second to think about the metaphor. Well, RSpec has tools to do that, but I'd like to talk a little about the metaphor first. That's how I kind of wanted to introduce our discussion. I had that idea in mind before we talked.
DAVID: Now I'm very excited about this because I'm either going right where you want me to go or I'm hopping into, like, a just a weird hair up my brain spark, which is that when I sit down with a great, big thing to work on, I get daunted. I get blank page syndrome where I'm like, ooh, how am I going to get all this tested?
In the maze world, I've heard this called the right-hand rule or the left-hand rule. And it's got an interesting property that if you put your right hand on the wall, then when you get to the branch, you'll go down, like, the right-hand side of the branch. You get to the room at the end of that thing. You walk around the outside of the room...or the inside of the room. You keep your right hand, and now you're leaving the room with your hand on the other wall. When you get back to the branch, you're now touching the wall between the thing you just went down and the next one over. So, you just keep your hand on it, right?
The thing that I love about breaking it down this way is that it's very, very clear where you start, which is, to quote Alice in Wonderland, "At the beginning," right? And then, what do I test next? You've always got a next. It's hard to know how am I going to test all of this? I don't know. I don't know. But I know what I need to test first. And what do I test next? Well, when I finish the thing I was on, I'm just going to test the first thing that's left. It's a lovely, little recursive thing. You always know what's next until you run out of next, and that's when you're done.
MIKE: So well said. I've worked with a lot of people over the years who've looked at their code, like, where do I start this test? Because it is daunting. It doesn't just apply to testing. It applies to a lot of things. But we're talking about the testing problem, in particular, and that's exactly it. Well, what's the entry point of your code? And let's start by creating a context for your first branch. And there is your first step.
And once you've explored that, you know, and maybe you have to do some nested contexts in there because that branch branches. And you keep on exploring those nested branches until you get to the bottom. And you come back out, and you're like, well, okay, what's the next branch? And I maybe need another context [inaudible 07:02] explores the next one. And that's it. And you can run through the test just like that. And there's always a next step. It's really easy to think about. And the only thing you have to think about at every step is, well, what's the other branch?
EDDY: You know, Mike, I have a question regarding coverage. When writing tests for that file, in particular, should we always be shooting for 100%? And if not, what are the exceptions?
MIKE: Well, that's a great question. Let me answer it this way. And we're talking about RSpec. RSpec is so named because there's, like, a specification there, right? It's a way of specifying what your code does. And if we have not fully specified what our code does, then it isn't very good documentation, and there's undocumented parts of our code.
DAVID: I'm going to come at this from a completely different angle. I'm going to say something...here's my hot take: You should never be striving for 100%. You should be striving for what's the most important thing to test. Or like Mike's saying, literally, if you're going through an order, you branch. I like the branch, in my mind, between the most important thing that's in front of me and everything else. So, like, when I'm testing an API call, my first branch is the happy path. I want when I do call the thing; I want it to work.
Then, what I will do is I will branch into the unhappy stuff. What's the biggest, most important unhappy path? That's my next branch, and the next one, and the next one, and the next one. At some point, I'm going to realize I've tested enough or I'm out of functionality, especially if you're doing RSpec and you go in and you literally spec the code. You've all heard of TDD, Test-Driven Development. You go in, and you say, I'm going to call this API. And when I pass it this user and this status, I'm going to get back a 200 OK, and that user will be updated.
And I love how expressive RSpec is for this because it makes it very, very easy to specify what the code will do, and you haven't even written the code. You reach 100% the same way, which is you're like, what's the next thing I need to work on? Oh, I'm out of functionality to specify.
MIKE: I was just saying if you have a cave system that has multiple entrances, those should be seen as separate systems. Your code has a public interface, public methods. And those are the entry points, right? That's the entrance to the cave. You should go into every entry point that is public, and that's it. If it's private, well, then it's not effectively part of the code that you're testing because it's unreachable. The goal here is to specify every branch that is reachable through the public interfaces.
I'll put one other caveat here, which is that we should explore the boundaries of our unit of code because we're talking about unit testing here, not integration testing. We should explore the boundaries of our unit of code, which means that you get something that leaves, say, the class that you're testing. That should be mocked or stubbed, so you don't actually go beyond that point. You don't ever leave your cave.
MIKE: Mike, I take back every bad thing I've ever said about you. That was beautifully put.
EDDY: [laughs] I was going to say because then you get in the realm of integration tests, and that's not what you want.
DAVID: Yeah.
EDDY: But specifically, I was going to say, what if you have methods that just do trivial logic, but it's still public? At that point, should you be testing something so trivial as to, like, display a text or, like, decorate a text [inaudible 10:08]?
MIKE: Well, if your code is so trivial that it doesn't need to be tested, then why did you write it?
DAVID: There's actually a good answer to both of these questions. The testing push came around, like Y2K, late '90s, like with extreme programming. And those folks...and they were coming from Java where you could specify accessors. So, you could very easily say, this is a read accessor on this. It's a public entry point. Therefore, it is behavior; therefore, it should be tested.
And everyone kind of stepped back and said, "Yeah, but this is a language feature. It's never going to have a bug. It's never going to be a problem." And they collectively decided this is the one case when we do not test public behavior because it can't fail. Or if it does, you've got bigger problems, or you've literally misspelled the method name.
MIKE: You said something that I think was critical, which is related to what I said about not leaving the cave. You don't test outside your cave. That is, if you didn't write the code, you don't test it. If it's the language or the framework that is providing the feature, it's not your code, and you shouldn't test it because then you're testing somebody else's code. You're not testing your unit of code anymore.
DAVID: Right. 100%, I'm embarrassed to say how late in my career I got before really having this hammered home because it was this morning. I'm writing a thing that talks to an API. And I have always considered the HTTP library, like Ruby's Net::HTTP library, that's framework code. That's core library code. We don't want to test into that. But my application is going to talk to Net::HTTP. I might want to specify that the conversation there is handled correctly.
I've been on project after project after project where we've said, let's not use Net::HTTP; let's use Faraday. Or let's not use Faraday; let's use HTTParty. Or let's not use HTTParty; let's use Typhoeus. And just on and on and on and on all the way down the road. And I ended up getting to this point where I would walk around the application out the backend, where the cables go off into the internet. I'd use, like, WebMock and intercept calls going out over the wire to HTTP over the wire. It's a little bit of an exaggeration, but you get the idea. I'm all the way at the other end of Ruby catching these things coming out.
And I was talking with my team lead. And he's like, "Why don't you just stub the call to Faraday?" And I'm like, "But...but...but," right? Because if we change that library, it's going to change the conversation on my specs. It's going to break. I actually had to step back and go; I didn't write Faraday. I didn't write HTTP. I am writing the code that has the conversation with whatever web library. And guess what? That is exactly the kind of thing I want to test. I want to assert that I'm having the correct conversation with whatever web library I'm using. And I want to specify that it's having the conversation with that web library. You don't want to send Faraday calls to HTTParty, right? It's not going to make sense.
So, yeah, like I said, a lot later in my career. It literally was this morning. I'm not exaggerating. I'm like, oh, oh yeah, I had a heuristic to make that call the other way around. And the trade-off there was that, yeah, sometimes I end up testing library code that I didn't write. And, [vocalization], boy, yeah, sometimes you run into trouble because the library maintainer can change their implementation. And yeah, you see the trade-off there, right? It just spooled out of control. You don't want to do that. Never test a Rails private method.
MIKE: And, again, let's make sure we're making the distinction between unit tests and integration tests.
DAVID: Yes.
MIKE: And I think that's where we get into a lot of trouble. If you want to make sure your system works with another system, you should have a small set, I would argue, because they're really expensive and slow, of tests to make sure that integration works, which is different from your standard test suite that you run over and over and over again because it's fast and effective, and it doesn't break all the time.
DAVID: Right. Right. I realized the other part of the trade-off is that coming from API land previously in my career; I'm used to being handed a JSON document of post this to our REST server. And we will give you—then they hand me another JSON document—we'll give you this document in return. And having that and being able to specify that exactly I want this many bytes to go out, and I want these exact bytes to come back, then it does make sense.
And, like you said, integration test. Yeah, you don't want to test 401, 403, 405, 422, 404, every single possible 400 error. You don't want to test every one in an integration test. These things take forever, relatively speaking. Maybe I fire you the happy path, and I stub out with a response. And then I fire out one or two unhappy paths, and then we're done. We walk away.
MIKE: So, I've talked a lot about my idea of how to test branches. For me, it's been kind of an epiphany [laughs] when I saw this, and it's relatively late in my career as well, not quite this morning but not five years in, to realize, oh, well, all I'm doing is testing branches. But, you know, having that different lens with which to see the world has dramatically affected testing.
And I've seen it really work well for other people as well. People who were just banging their heads, like, where do I start? Were able to very quickly progress by thinking about things through that lens of, well, what's just my next branch? And there may be others on this call who've approached things that way, and I'd be interested in hearing other people's experience with that approach.
EDDY: You know, I'm kind of curious in gauging people's perspectives here. Everyone on this call, I think, to some degree, has touched RSpec for the past couple of months. I'm curious to gauge what other people's perspective was the initial exposure that they had to RSpec. Did it give a facade of difficulty, and if it did, to what degree?
DAVID: I got into RSpec with version 1.0, which put the should method on every object in Ruby, like, throughout the entire space. Of course, in Ruby, even integers are objects that you can call methods on. And so, you could literally write three dot should equal three. That was the moment that test-driven development really lit up. And I'm like; I can write this before; I mean, there was nothing stopping me from saying assert equal three comma three prior to this. But, for some reason, in my brain, assert equal three; three is something you write after. You know, assert equal, A plus B equals five, right?
In my mind, that's something you do after you have written the code, and you're just trying to button things up and prove to the maintainer that it works. But, in my mind, A plus B should equal three. It pushes you to say, hey, write this before you write the code. We're not going to say it does equal three; we're going to say it should equal three.
And I really liked that RSpec, when they got rid of the should monkey patch—which makes me sad, but I understand why people get rid of it—I liked that they kept that future subjunctive tense by saying, we're not going to assert. We're going to expect. And so we say expect A plus B to equal three. It's a little easier for me to write that after the fact and see it kind of in both verb tenses. But it does let me hang on to that bright torch of, I'm going to write this, and then I'm going to go write the code, which I realize is tangent to the topic of today, which is making RSpec easier. But, you know, it's my baby, and I like to show it off.
HAILEY: I'll speak on my first experience with RSpec. I feel like it was probably just a few months ago. I think as interns joined in on The Skills Clinic, we were working on some advent of code. And we were, like, in the middle of the project. So, we didn't see, like, the spec being created. I just saw, like, a completed spec file, and I think that was really confusing for me. Because, like, I feel Ruby is similar enough to other languages that I was able to understand, okay, this is, like, a loop. This is an if statement. You know, I'm returning this section of code, things like that.
But words like describe, and let, and subject, context, before do blocks I hadn't seen those before. And so, that was all really new to me. And to just see, like, 50 lines of code of things that I hadn't seen before that was really confusing. And then, once we ended up breaking it down, and once I was able to write my own spec and see them being written, not just a completed spec, that really helped me understand how RSpec works.
DAVID: Nice.
EDDY: That was my same experience when I first picked up on RSpec to [inaudible 18:26] in QA. When I first started, I was like, wow, what is this whole other language, right? Like, how is the structure, and why is every one so opinionated? [laughs] And how this is written. So...
HAILEY: Right. It seemed like a different language.
EDDY: Absolutely. You got some overlap here and there, very subtle. But overall, yeah, it can be a bit overwhelming if it's the first experience with it. So, I think that's, like, sort of, like, makes it a little difficult for new developers who are testing in RSpec initially, right? There's, like, some sort of ramp-up to it.
DAVID: Yeah. And there are some surprising things that come from that, right? If you pick up, like Jasmine, which is a JavaScript testing framework inspired by RSpec, then it has context and describe, and it. It's a function that takes the name of the thing that you want to describe or specify. And then, it takes a Lambda of just the function you want to execute when that happens. And that's kind of what you see in RSpec, right? You see, describe, and then a thing, and then do/end. And the do/end is like that...it's a proc. It's literally a block of code that's going to get executed as, like, an anonymous function.
But it's really easy to just go, oh, it's magic, and I don't need to worry about it. And that's absolutely true 99% of the time. But eventually, you start wondering, how does this function ever get called? And that's when you start lifting up the tablecloth and looking underneath RSpec, and you start seeing that, oh, that it do it doesn't define a method. It defines a class. A what? Yeah, it defines an entire class, an anonymous class. Its execute method...I can't remember the name of it. Is it run? It might be a run () method, but it's got a method on it that will, you know, execute the test.
And when you run RSpec over, like, a directory, it picks up every one of these files. And that it do makes a class, it do makes a class; it do makes a class. And then those three classes are inside a context, which makes a class. And the definition of that class is define these three classes that we just talked about. Once they are all defined, and everything is completely loaded, that's when RSpec says, okay, you know, roll call, who all did we get defined? Okay, cool. Start at the beginning and start running your stuff. And it starts executing it through.
And that is why you can end up with, like, this really weird stuff, like, where you have a spec that fails, and instead of giving you, like, the name of the spec, you end up with example three, bracket five, bracket two, and you're like, what...what is this? Well, okay, it's actually you were doing it do context do without a name. You were just doing, like, it do. Like, you used subject instead of saying, you know, describe thing. You're just like, well, describe do. You shouldn't do that, but you can. And there are people that if you can do it, they will.
And [chuckles], Robert, if you're listening to me, I love you. We can still be friends. I had a co-worker named Robert. He could point anywhere in a file, and he could tell you what the bracket offsets, the indexing scheme that RSpec uses under the hood. The point that I'm trying to make...I'm actually not going to talk all the way through to [inaudible 21:14]. I'm just going to assume that we all got lost in that weird classes of definitions because that's the whole point. It's magic, and 99% of the time, you don't need to keep track of it.
But the entire point of this is there are people who will defend, like, Test::Unit, which is really, really old, Minitest, which is getting old. Minitest is very, very simple. The entire source code for Minitest used to fit on, like, two printed pages back when printing was a thing that people did in the world. So, it was very easy to understand everything Minitest does under the hood. And RSpec was just this document the size of, you know, the federal tax code. And so, trying to get your head around what it does was very, very hard.
So, I 100% agree. Most of the heavy lift that RSpec does is to create this domain-specific language, a DSL for testing. Well, not for testing, for specifying the way code should behave and then making it behave that way. As long as it works the way you want, you don't ever have to open it up. And you're like, oh okay, yeah, once I've learned this language, then I can use it. And it's very fluent, and it's very easy to understand.
But, Hailey, you are 100% right that I started that with once you learn that language, and it almost sounds like I said the word just right or easy. Or how hard would it be, right? No, no. I fully admit that that once implies not until, right? You have to learn the DSL before you can leverage it.
MIKE: But I will say something interesting about this. I'm going to kind of go back to the cave idea, this maze traversal, which is that RSpec is actually kind of opinionated. It lets you do a lot of things. But that syntax that it uses, those contexts, for example, encourage...just like Dave was saying about that should or that, you know, is expected or, you know, expect, there's some suggestion as to which way you should go.
RSpec doesn't have a lot of top-level methods, but it has describe. It has it, which is where your assertions go, and it has context. The workhorse of RSpec is the context. And a context represents a branch built into the framework. If you think, well, oh, I'm going to set up tests for a branch, and I'm going to give it an anonymous function, and conceptually and in practice, that's what's happening is you're saying this branch is going to get an anonymous function that will run the tests on it. And that's what RSpec is doing.
If you want to know what that domain-specific language is doing, it is giving you the ability to set up a test for a branch. And I think seeing that and understanding that's what it's nudging you to do can help overcome a lot of apprehension.
DAVID: Absolutely.
EDDY: I do want to say that ever since I started testing with RSpec, I've hated red dots forever.
DAVID: You absolutely should.
EDDY: Anytime I see a red dot, I just hate it, period. Number two, I think what makes RSpec really difficult, especially for someone coming in fresh, is the fact that the error messages could be a lot better, right?
DAVID: Yeah.
EDDY: Like, some of the messages that you get for errors, you're just like, what are you talking about? Like, what do you mean no_args expected, [laughs] right?
DAVID: I have a strong opinion about that. Finish your idea, and then ask me about the errors.
EDDY: I was just going to say, I think what really makes it really difficult to pick up initially is just that the error messages that are spitting out, like, unless you have context on that, like, it makes it extremely difficult to really debug, like, what the actual bug is in your code.
DAVID: Yeah. So, here's my strong opinion. Please, please, please consider this. If you've never done this, do it as an experiment and, like, do it for a week. Do it every time. And that is, whenever you run RSpec, put dash dash format equals documentation. Or, if you're, you know, quick and in a hurry, dash F Space D. This turns off the dots. You don't get green dots, red Fs, and little yellow asterisks. What you get is this nested tree of text, and it gives you the object you're describing.
And if you've got a context of, like, you know, happy path versus unhappy path, it will put happy path on a line by itself indented underneath the object that you're describing. And then, when you're in the happy path, let's say we're going to describe the initialize merchant, you know, method, so you've got a describe, initialize merchant, well, that shows up as the third line indented twice underneath happy path.
So, you get this beautifully indented tree of text, text, text, text, text. And then, you finally get, like, you know, it should create it at timestamp, you know. So, it's like, it sets created at your RSpec declaration, right? You get to that line in the documentation, and that entire line of text turns green if it passes, or the entire line turns red if it fails. So, that's the first half of the experiment.
The nuance to this is run it in format documentation and read it as if you had never seen your code before or as if you were sitting down to train another intern on how your code works. And you really, really, really want them to be able to read that stuff on the screen and not have follow-up questions. So, have them just read your documentation and go, hmm, okay, seems legit, I got it.
Eddy, this then circles back to your point. If you take the time to type out correct clauses in your thing...and it's real simple, never type context without typing when after it. So, I don't write context happy path. Instead of saying context user is unauthorized, I will write context when the user is unauthorized or when user is unauthorized. And then we get to the it, which is, you know, it redirects to the login page. It displays a 404 error, you know, a 401 error.
Here's the thing: when you run this in FD, in format documentation, the last step is force every single spec to fail and watch it in the format documentation. You will end up seeing, describe this API context, you know, on the happy path when the user is authorized. It logs them into the homepage. You get this lovely little documentation thing. And you're like, okay, yeah, logically, that follows all the way down. I got it. Cool, no problem. It's green. Everything is good.
Now, you make it fail, and then you scroll down to the error message. And RSpec will take all of those nested snippets of text and it will chain them together into complete mishmash gobbledygook that nobody looks at unless you were using the grammar. If you've been writing context when and, you know, describe, you know, da da da, also with, you know, context with this thing going on or with this flag set, all of a sudden, that error message down at the bottom...and these are the ones where you get, like, we're no longer showing the blocks at test. We just got, like, an error and the line of code that it was on.
You get this chunk of red text that literally forms a sentence in English. On the happy path, when the user is authorized, and they log in, they get redirected to the homepage. And that whole thing is red, and it fails. Let's say we say the user's password, you know, doesn't match. We're going to assert that the text "Welcome, Eddy"...we're going to set this username with the name of Eddy. The text, "Welcome, Eddy," should be on the page.
So, you get this long, red sentence. You know, on the happy path, when the user is authorized, they log in, and they get redirected to home. That's right. It failed. Then the error message on line 273 of your spec file: expected to find welcome, Eddy, but that text was not on the page. Now, without opening the code or the spec, you know what was going on when it failed. And you know what the program did that was wrong.
And I promise you, if you do this, this weird, oddly specific thing will happen, which is four out of five times, you'll go, oh yeah, we commented out the user welcome thing. You haven't even opened the code, and you know where the bug is. You know what happened. And that is this weird, oddly specific, delightfully pleasing thing that happens if you write context when, you know, describe thing context when it does a thing. And then, you run the format documentation and make sure it makes a sentence. It's lovely.
And then, anytime you have an expect, expect 42 to equal 43, and then see what exactly is the error message. Because you'll end up with somebody else's code, and they'll be like, "Uh, yeah, we tried to log in, but we couldn't. Oh, and the error messages on line 229 expected 42, but it wasn't." What? This helps me not at all. Well, it does help you. It's going to give you the line of code in, you know, what file and exactly the line of code. But now you have to open that file, and you have to go to that line of code.
Whereas if you get the error message expected to find "Welcome, Eddy" on the page but I didn't, you know exactly what's going on. And much of the time, you know exactly what you just did a few minutes ago. Like, oh yeah, we forgot to turn this back on. It's so delightful when that happens when you can literally debug your code without opening it. And a good spec suite will give you that.
EDDY: Yeah. I just kind of wish, like, the error messaging was a lot better. Like, this is sort of, like, going off the top of my head where it's sort of, like, class double [inaudible 30:10] expected arguments.
DAVID: Unexpected method, blah, yeah.
EDDY: Yeah. Blah, blah, blah. I'm like, that doesn't really make sense, right?
DAVID: Force your expectations to fail and run them and see how they fail, and then reconstruct your context. If it's really oblique...we had a meeting earlier where we were talking about whether or not we should display a link. And the code underneath it was, is this object not invalid? You can infer that we don't want to show this thing if the object is invalid. But I didn't realize in the API that if the object is valid, we absolutely should show it. There's no other conditions to check, right?
So, if you get a red dot and it said, "Expected true got false," oh, that doesn't help. Does it? Right? So, if we then turn around and say, when the link is valid, it should show, then when that fails, you can say, hey, I expected the progress bar to show the link, and it didn't. Or the, you know, I expected it to be show link or, you know, to have the show link enabled, and it wasn't. Now, that error message takes you exactly where it was.
There was another developer on the call that offhandedly said, "Why don't we just put, you know, not invalid in the code that calls it?" Show link is a conversation I want to have with a progress bar. Invalid or valid is a conversation I want to have with the model underneath it. And I don't want to have to remember that valid invalid implies show link, not show link, and that nothing else is part of that implication, right? I don't want to keep track of that.
So, like, what you're saying, Eddy, we don't want to say, on line 73, this code failed, expected false got true. We want to say, on the happy path, when this link is valid, when I ask the progress bar, should I show this link? It should say, "Yeah, yeah, you should show this link." And then, you get the error message: expected false got true, or expected progress bar to be show link, which is a little bit awkward English.
But, I mean, we expected that you know, to have the show link status be enabled, but it wasn't. And you're like, oh, okay, yeah, now I know exactly where we are. I know what conversation we're having with what object, and I know what the semantic meaning of that conversation is. Does that make sense, Eddy? I just realized you've now said twice this is hard to understand. And I'm like, oh, no, no, no, [inaudible 32:22]. And I just realized I'm just throwing words at you. Is this helping at all?
EDDY: Yeah, yeah, yeah.
DAVID: You can say no. The listeners will laugh.
EDDY: [laughs]
MIKE: You know, Dave is saying use RSpec differently, and the errors will make more sense. Distill all that down. And I think that there's a lot of truth to that. It's easy to map, and I think it's kind of instinctive (I think I did it when I first used RSpec.) to map frameworks that are, like, Test::Unit style that are run assertion, run assertion, run assertion to RSpec, which has a different paradigm.
RSpec is designed to be thought of as a documentation generator as much as a testing framework. It says [inaudible 32:59] the same thing. And if you use it that way, you will have a different experience, that you will be much less likely to have those. This error makes no sense because you're looking at as documentation. And if it's formatted differently, then you don't just get a bunch of green dots with one red dot and a cryptic message. Instead, you get this documentation, and you get the line in the documentation that doesn't work.
And you're like, oh, the documentation doesn't apply here, and that gives me something. It may not be perfect. And a lot of times, the errors are just, you know, Ruby errors. So, they're language errors rather than RSpec errors. And then you have to make, like, oh, so, I have to figure out what's going on with my tests. But you at least have something to hang on to. I do think that changing that mindset is a big part of how you make those error messages less cryptic, is you think about the problem differently.
DAVID: Interestingly enough, that is the reason...the thing that we just talked through, the error messages in particular, is the reason that I won't ever use the subject method in RSpec if I can avoid it. And I definitely...if I use it, I will not write it do without text or context do without text. And the reason why is because RSpec will almost obfuscate the error message. Like, you literally will get, example, 3 of 5 of 1 expected 17 got 15. Good luck.
Now, not only do you have to track down where the code went wrong or where the spec went wrong, but you have to start winding up through the top of the file to figure out what did the spec set up before [inaudible 34:26]? Yeah, just type. Type some text on the context and the it.
I realize what I described sounds really hairy. Like, I've shown a couple of people, and they're, like, oh, this is too much of a headache. Context when it does, and run it, and look at it, and make it fail, and read the sentence. It will take you less than half an hour to completely internalize it. 5 or 10 times through the loop, and you'll have it. It's opaque at the beginning, but it's a skill that you can master very, very quickly. It'll click very quickly.
MIKE: And, again, on the branches, what else would you write? If you're describing when some set of conditions apply, well, you probably ought to have some text that says when some set of conditions apply. It's just the natural...RSpec is opinionated without necessarily saying so. Think about your branch of code. What branch of code applies when these conditions apply? Or maybe if or, you know, it's conditional. It begins with a word that suggests conditionality that, again, maps to the way that you're structuring it.
SPEAKER: Speaking to the RSpec, errors aren't top tier; I was working on something the other day. And essentially, some of it just consisted of adding a new field to just a hash that was returned by some function call. And I was looking at the RSpec because it just kept failing. And I was like, what's going on? Like, what is the reason for this?
And it said that it failed because all the decimal values that are returned were returned in scientific notation instead of, like, just regular decimal notation. And I was like, why is this happening? This doesn't make any sense. Turns out it was just because the test file wasn't accounting for that added field to the hash. So, it was like, it didn't tell me exactly what was wrong. And it actually told me something wrong that was wrong.
MIKE: But you saw it said, "These hashes don't match," right? And you looked at it and said, over on the left side, these are a fixed number of decimal points. And over on the right side, they're not. And so, they were things that RSpec could say were equal, but when it displayed them out, they weren't quite equal. And so, you were looking, oh, these aren't equal. Where's the problem? Because, you know, it kind of obscured it because you couldn't tell where the mismatch was.
SPEAKER: Exactly, yeah. It was a bit strange at first, but having a very written-out English sentence would have made that about ten times easier to recognize; oh, this is the problem. That's why this is going wrong.
DAVID: There's a subversion or an extension of this. It's interesting because, like, when we talk about RSpec exception errors aren't top tier, I'm having this instinctive reaction. And I'm trying not to, like, am I trying to defend my baby here, you know, out of just loyalty? And I realize, no. No, it's because that context when and the it, you know, describe noun, describe when, you know, it verb, da da da...RSpec, for me, is top shelf. It is the best error message. But I realize now it's because I write them that way.
I've tried to port that to Minitest and Test::Unit, and you can kind of, but it's a lot more work. It doesn't flow as naturally. And that might just be a translation and familiarity thing for me because I'm familiar with RSpec. But I 100% agree that hashes do not match, especially if it says expected, and then you get, like, two and a half lines of text with a dot dot dot in the middle of it because RSpec finally just said, I'm just going to have to give you an ellipsis. But I actually got two and a half lines of text with a dot dot dot in the middle, right?
You can get RSpec to give you just as much information and not waste as much screen real estate by just typing RSpec or or echo; it didn't work. And that will just suppress all the output from RSpec. And if it fails, there's a mistake in there somewhere. Good luck. Have fun, right? And hashes [inaudible 37:58] math is terrible. It really is terrible.
EDDY: Well, that's why I started to adopt hash including versus double splat, right?
DAVID: Yeah. So, there's a subtle trick also that you can do. You can write this; I say don't. You can say we're going to describe this hash, and all the fields should match. And you can write out; it should match. And then, inside the it block, you write, you know, for key value in expected, actual subkey should equal, you know, or expect the actual key to be the expected key, right?
And that's great, except that you're going to end up with an error message that says, hey, on line 27 of this thing, which is inside a for loop, you have no idea which index you were on when the for loop failed. Because that thing did 150 expects, and you have no idea which one failed, right? And you're going to get an error message that said something like, "Expected blank string, got nil." Oh, good luck. Which field out of that was it, right?
If it was expected, 123 Fake Street got nil; okay, I've got a street address that's missing, right? But it's when you get something that's, like, it could be any of them, right? Expected, you know, AAA got BBB. Oh great, where's my As and Bs? You know, what does that mean, right? If you're going to play that game, take that hack and pull it.
By the way, this is where the fact that RSpec is compiling classes becomes like black magic awesome. Because you can take that hash outside, you can't use a let, but you actually have to define it right there in the Ruby code of key value, key value, key value. But you do it in the source code outside of the let, or the describe, or outside of the it or the describe, and then you say a key value. And inside that key value, that each loop, you say it, and then in the text you say, should have field, you know, and then the field name key equal to, you know, field value. Or, you know, field key should match, right?
What happens when RSpec processes that file it hits the loop, and it generates. If there's 150 key values in that hash, it generates 150 it blocks, expectations. And because you put the variable in the it description text, now when it fails, that is the text that RSpec will give you in the failure message. You'll actually get a thing that kicks out and says, "Hey, address line two does not match, expected a blank string, got nil." Oh yeah, okay, yeah, we weren't reading in the department or the suite number off of the address. Oh yeah, look at that. We don't even have that column on the model. That's why it's nil, right?
You can make RSpec lead you by the nose and point you, right? You know, hold your nose right up to the air and say, this is it. It's right here, and this is why it happened. But you do have to make RSpec do it. You have to learn, again, like, context when, context when. If you take anything from this, put when whenever you do context, and then describe a condition when on the happy path. It really does help.
MIKE: If I make one other suggestion --
DAVID: Sure.
MIKE: Take this cave metaphor a little further. I love what you just said about making sure that every single expectation actually, you know, on the it block or on the context block has documentation. And one other place that people tend to struggle with in Rspec is how to do the setup. How do I set up my before or my let? And this is maybe a place where there's less clarity. It doesn't force you as much.
But I have found...and it sounds like my thinking is similar to yours. You say you put the unhappy branch first. Well, I would say that's correct. If you're exploring a cave and you're looking for the way out of the cave, or you're going through a maze, well, you're definitely going to go through the non-solution first, right? [laughs]
DAVID: Oh, that's interesting. Finish your thought. I do it exactly the opposite. I put the happy path first. But carry on.
MIKE: Well, and I think that there's a very compelling reason, an extremely compelling reason to put the non-happy path first and have the happy path at the bottom, and it's this if you do your setup for the happy path, so your let blocks, you know, your before each, whatever it is to do your setup, your mocking, your stubbing; if you set that up for the happy path and then you begin by testing your unhappy path, then what ends up happening is every branch of your unhappy path you're only saying what's wrong if the authentication fails.
And then, you're overriding one piece of your setup. It allows every single context to have just a couple of things that's going to say, "This is the thing that's wrong." And you're going to see an it block that says, "And it doesn't work." And it becomes trivially obvious to read through your spec and say, oh, this is the thing that's wrong here. This is the thing that's wrong here. This is the wrong thing; it's here. Because at every branch, the only thing that you're overriding is the one piece of your setup that is broken at that part of the branch.
And then, when you finally get down to the deepest level, you've reached the bottom of the cave. And hey, there's the door out. There's no setup at all because you've exhausted all of the bad conditions, and all that's left is, hey, the setup works.
DAVID: Oh, that's neat. You were halfway through that, and I was making the meme of the stick figure guy who's going "[vocalization], you know, I've got a reply for you." And then, halfway through, he's like, "Oh," just kind of deflates a little bit. And he's like, "Hmm, yeah, you're right."
I'll extend it one more step, which is that if you start with a working thing, you are blacklisting your errors. Instead of whitelisting one functioning thing, it's easy to go through and break one thing, one thing, one thing, one thing. Anything you forget to break will not get tested, and the object will pass. If you start off with a blank object and only populate in every single test, that can get exhausting if you're populating all the fields, you know, unrelated fields each time through. But there's some value in that, right? Sometimes you're like, I want this object to kick and scream and just refuse to be valid until the last possible minute. Yeah, I like that.
MIKE: I imagine you could thread through this in either direction. You know, some people work their mazes backwards.
DAVID: There is a left-hand rule as well as the right-hand. It works exactly how you think. Yep.
MIKE: And the key part there is that this is what's different in this branch. Here is everything. You want to make it really obvious this is the part that's different, and this is what happens. And you want it to be designed such that you have to go through all the branches to get to the end.
DAVID: I kind of like that. From, like, a documentation, like, teaching a maintainer how this works, I kind of like having the happy path be first, from a, you know, like, this is how it's supposed to work. Now, let's talk about all the ways it can go wrong. But I like that idea as well of, like, yeah, this thing is wrong. It will not be right until everything is right. So, I think that's totally valid. It makes sense.
MIKE: Right. I think that either way, starting with the wrong or starting with the right could work that the critical part is that you follow a direction like that, right? And this is another thing that people have problems with with RSpec. You have to go digging around and looking for what the context is [inaudible 44:30]. The only thing that you should see in your context is what's different. You could say that, well, I just can do all of my setup. Here's everything that's right, and here's the one thing that's different. But I think that that can actually be problematic because it's noisy. I want as little noise as possible.
DAVID: Yeah. I had it driven into me recently that there's no such thing as a solution; there's only a trade-off. And you have to decide what side of the trade-off you value. You might come into a thing where you know what? The left-hand rule is actually more important. I want to start with the wrong end of this maze and work backwards. And on another day, you might walk in and go no, no, no, no, we need the happy path. And then, we kind of don't care about the unhappy paths, so they're secondary. Let's just document the right way to do it, right? And so, it can go either way.
I have one last thought on the right-hand versus left-hand hand. If you're listening to this and you don't know who Steve Mould is, M-O-U-L-D, he's a British mathematician, scientist, YouTuber. He's really gotten on this kick lately of building physical models of logical ideas. And what he discovered is that you can use water to solve a maze. By pouring water into a maze, it will always solve the maze, which is really, really neat.
The reason I think it was lovely—and this is the right hand versus left hand—any system you divide into binary pieces will, when you get to the other side, fall into two separate halves. They might not necessarily be equal halves, but there will always be exactly two halves. And Steve discovered this in his...if you go watch Can Water Solve a Maze, he was laser cutting acrylic mazes, clear plastic so that he could pour colored water for the camera, for YouTube, right?
And he said, "This weird thing started happening. I started cutting out these mazes. And when the laser got to the end of the maze, half of the maze fell off of the cutter. And the other half, it was exactly two pieces, the left-hand side of the maze and the right-hand side of the maze." Whichever rule you follow, if you put your hand on the right-hand side of the maze, you will not touch the left-hand side of the maze ever. And vice versa, if you start on the left, you'll never touch the right half of the maze. It will divide into two exactly separate halves. I thought that was super cool.
MIKE: That is cool.
DAVID: Folks, this was lovely. Thank you for coming out on the podcast. Hailey, I appreciate your comments. Dom, Eddy: love having you guys chat on the call. This was a lot of fun.
From the publisher's feed