« All Episodes

Interview with Mark Engelberg (Part 2)

Published 10/11/2017

In today's episode, I interview Mark Engelberg. Mark creates puzzle games, and most recently created the "CODE" series of games in collaboration with ThinkFun. Mark's insights into learning and teaching are fantastic. I hope you enjoy this episode!

Today's episode is brought to you by Swiftype.

Swiftype is an AI-powered search platform that delivers fast, relevant and customizable search results for websites, applications and businesses. Swiftype's suite of products have revolutionized the way people find information across their organization and on public facing websites. Integrate easily with tools like GitHub, JIRA, Confluence, Dropbox, and more for even better searching power. To learn more about Swiftype Search or for a free trial, visit swiftype.com/developertea today!

Transcript (Generated by OpenAI Whisper)
It's just easier to compare two immutable data structures than mutable ones. So if you want to teach the kids how to test their own code, it's just easier to do that with functional programming. So I just, I love it as a starting point. And then I found that kids who begin with that, they later, they don't have any trouble adding in the mutation stuff later. It's just like this becomes this extra spice, they sprinkle in where needed, because it is a more powerful tool. Mutation lets you do some things that you can't do without it. But you learn to use it only when needed. And you already have these years of experience of writing most of your code in this very clean subset that's easy to test and easy to read and easy to understand, easy to verify it's correct. And you're only using the mutation only when it's needed. Whereas people who come the other direction, they're kind of used to using mutation everywhere. So it becomes something that they have to train and practice with a lot of exercises to try to learn how to restrain themselves from using this powerful tool that also unfortunately has the potential to make the code more fragile and harder to understand if you use it excessively. And so learning to not use it so much is actually sometimes it's harder to go that other direction. How can children learn through play? And what can we as adults learn from children? It seems like there's this switch that flips at some point and we go from playing to working. And the overlap there becomes very small and perhaps it is not there at all for some people. So what can we learn from children? That is one of the things that we're going to be discussing in today's episode. We're talking about puzzle games with Mark Engelberg and Mark is the creator of a series of puzzle games that helps teach children and really people of all ages how to code, how to think like a coder, a good programmer would think. So these games are teaching excellent fundamental skills in thinking and procedural aspects. We're going to talk more about the specifics of the game in this episode as well. My name is Jonathan Cutrell. My goal is to help you become a better developer each and every day, even if that's only by a very small percentage. Today I want you to become better. And if you want to become better, it takes work. It takes sacrifice sometimes. It takes changing an opinion. Sometimes it takes listening to something and letting it sink in so that later it blooms. In other words, it's kind of like you're putting a seed deep inside of your brain so that later it will and will actually grow into something useful. So maybe that's what today's episode is for you. Maybe you are actually interested in expanding the way that you think by not just engaging code directly, but maybe playing some of these games that are created. So again, my goal on this show is to help you become better. Help you become a better developer. Help you become a better thinker. And if I've been able to do that for you, I'd love to hear your story. If you'll send me an email at developert.gmail.com, I read every single one of these stories. And I try to reply to every single one as well. So please reach out, let me know where you are in your career and how this show and some of the ideas that you've bounced around and maybe the conversations you've had as a result of this show, how that has helped you. I love hearing those stories. It's energizing to me. Thank you so much for listening to today's episode. I want to get straight into interviewing Mark Engelberg. Some of them was common things that I see especially in beginning CS tutorials and learn X language is, for example, building up a collection of things, using a for loop to iterate over a different collection. And you're adding to your appending something to an array. And once you've gone through this for loop, then you have a new array. And that's an example of that's a very simple and usually a pretty easily controlled example of something that if you use everywhere can become a big problem. I've seen if statements that could never be hit, but it's difficult to figure that out. It's difficult to figure out when you're three or four nested if statements and you're trying to build up an object or a dictionary inside of these if statements based on the presence of some key or something like that. This happens all the time. And in JavaScript it happens really across the ecosystem. Won't focus on any particular language here. But when you have that nested and lots of deep logic and you can't look at it and understand what's going on, really if you can't look at it and understand what's going on, how do you know that it's right? And the only thing that really tells you whether or not it's right is if you have a very well-structured test suite, the problem is so often we don't write test suites that truly cover every scenario. They don't truly cover every edge case. And in fact, there's some theory that says it's impossible to cover every scenario, every test case. What's not impossible is to write code that will work every time. That is actually possible. That is actually possible to do. And when you can reason about your code, when you can look at what you've written and know, any time I give it this, it will work. Every single time if I pass it this letter or number, if I pass it this structure, this data structure, no matter what I do, this piece of code is going to work the way that I expected to. You know, if you write tests, this is for, as a Rails developer, I've seen plenty of tests that have a hundred lines worth of setup. And the reason that they have a hundred lines worth of setup is because in order to test the behavior of a given method, well, you have to have a scenario, right? And that scenario is really all of the data surrounding that method. It's typically found in integration tests or what are called feature tests. But so much of this code is setting up a scenario, well, what if the scenario actually goes wrong? What if one piece of data that you have set up in that scenario? What if that actually isn't working that way in production? Or what if something gets corrupted? What if, you know, and there's so many things that you have to look at and test for, for that test to even be valid in the first place, and that you almost feel like you have to write tests for your tests, right? Like it's, it's a very strange and large, it's up being a lot of code, and it's up being, and sometimes more test code than you have in production, on your production code. Yeah, I mean, the latest thing in the, at least in the functional programming community, is a big focus on generative testing. Have you talked about that in any of your previous podcasts? No, no, I'd love to hear more. So generative testing is focused on this whole idea of, you know, that it's difficult to write exhaustive test cases yourself. So why not let the computer write our test cases for us? And it turns out that's a lot easier to do when you're in a functional programming language than in an imperative one, because usually testing in a imperative language, it revolves more around trying to think about, kind of what invariants have to hold as some data structures changing over time, and it's difficult to track that value, as it flows through multiple things that are changing it. But with, like I said, with pure functions, as long as they're tested in isolation, each one is working the way you expect, then they're going to compose together the way you expect, because nothing's changing something out from under something else. And the way generative testing works is you describe kind of what is the kind of data that's going to be inputted into this function, and you describe some kind of properties of the output that it's going to be put, you know, that's going to come out of this, and then maybe some properties that it has in isolation, maybe some property relative to the input, and you describe this, and then the system itself generates, you know, thousands upon thousands of sample inputs. All kinds of crazy stuff that you wouldn't think of yourself, if you were typing it out manually, it's going to check all the weird stuff for you, just going by your specification of what kind of data needs to be input into it. It's going to generate lots of bizarre examples. It'll generate the normal stuff, and then also really strange stuff that fits your specification. It'll pass it into your function, and then it'll check that it obeys all these properties that you're saying the output has to hold. And it'll do all that for you, and people routinely find that when they apply this to functions, that they, this technique, to functions that they thought were pretty solid, it's pretty common to discover new interesting edge cases and things that you just hadn't thought about, because you were thinking like who would actually ever do that in real life would pass that kind of input to it, it just didn't cross your mind, but the system will find it generating random inputs. Yeah, well, and the thing is, you know, this is a bias that I think, I talk a lot about cognitive biases on the show. Writing code and then assuming it's going to work, or writing a limited number of test cases, and assuming that you've covered things, this is a confirmation bias, right? Because when you write those tests, and they do indeed cover what you thought they were going to cover, and your code works as you expected it to in those test cases, then it's easy to believe that you're done. It's easy to kind of check that box and move forward. And the problem is, you're not, you don't have the luxury of seeing the code for the first time. You don't have the luxury of recognizing inputs that you had never thought could be input, right? Yeah. And so that's a problem. And I love this idea of generating those inputs, because then you're not in control. This is actually a good reason to use something like, you know, random data generating software packages. This exists in Ruby testing. I assume it exists everywhere, but fakeers, right? So having something that generates first and last names, rather than deciding your static first and last names, that way you get a wide array of inputs into your tests, so that after running them 100 times, you've had 100 different inputs, with the same conceptual data types and that kind of thing. And one comment I've sometimes got from programmers when I talk about this idea of starting with functional programming, they sort of say, well, what good is it if, when they get to the real world, they're not going to be able to use this stuff anyway. And what I found is that you can use this in the real world. First of all, even in mainstream languages, most people who have spent some time doing functional programming say that it transforms the way they think about regular programming languages as well. And they will automatically find themselves programming in a style with more pure functions and relying on mutation less, making programs that are easier to test. They're looking for tools like generative testing and a mainstream language. Like it changes the way they think about it and they bring that approach to the regular programming language and it makes the programs better. But on top of that, there's a lot of choices emerging for people who want to use functional programming in their actual jobs. I use on a day-to-day basis a programming language called Closure. And Closure is a dialect of Lisp that runs on the JVM so it can interoperate with, you know, your existing Java code. And it's a really wonderful functional programming language that has sort of the full suite. A lot of the educational programming languages, they only include the barest minimum of data structures because as a learner, you're mostly going to be coding your data structures yourself to kind of learn how they work. But as a working programmer, you want that stuff built into your language. So Closure was one of the first programming languages that took the same suite of data structures that you expect from a modern programming language and gave you immutable versions of all of these things. That make it easier to write these pure functions. So it comes with something kind of like an array. But when you update an element, like it does it in near constant time, but it actually is returning a new data structure that shares a lot of underlying memory with the original data structure and only the elements immediately surrounding the one you changed is actually taking up a new slot of memory. So it's very efficient. It's much more efficient than like copying over a whole array and then just changing one element. Like that would be horrible performance if that was the way it was implemented. Sure. And so it gives you something like an array, it gives you something like it gives you a list, it gives you sets, it gives you hash tables or maps or dictionaries as they're called in different languages, gives you immutable flavors of all these things. And a really wonderful set of functions for working with these data structures that where the functions kind of consistently work the way you expect on all the different data structures. So you can take those ideas from a functional programming language you learn and you can carry it over to professional life if that's what you choose to do. Yeah, yeah, absolutely. There's, I've done a lot of work trying to incorporate some of these ideas into languages that I use that are not enforced. They're not functionally enforced. And there's so much, for an example, if you have functions, let's say you're writing JavaScript, that's a pretty common language. I don't like to hyper-focus on languages, but sometimes it's worthwhile to talk practically. With JavaScript, you can write functions pretty much anywhere. They're all over the code that you write typically. And a lot of the time, I've seen a lot of code and I've written a lot of code that has a function that does something rather than returning something. And this is kind of a code smell. If you're writing functions that only do something, especially if you're writing a lot of them, then you're probably going to benefit from thinking of ways that you can return a value from those functions and use it moving forward. It's kind of weird. You'll see what I mean, kind of thing. Once you start writing that code, you're gonna see how it changes the way you think. Instead of thinking in terms of what steps can I take, you're gonna start thinking more in terms of what transformations am I making? What am I, what is this function providing me? How am I using what it's providing me in the overall structure of what I'm doing? So you don't have to be, you don't have to perfectly adhere to every single rule of functional programming to start practicing some of the things that functional programming you can benefit from. You can do this in Ruby, you can do it in Python, you can do it in JavaScript, you can do it. Pretty much every single language, there are ways of practicing this stuff. I've actually done an episode specifically about that where you can actually benefit from functional programming in other languages. I don't remember what episode number it was, but it's been a while since I did it. But this is something that I think is really important for people to, if you start thinking about your code in new ways, this is one of the ways to start viewing your code. How can I make it better? This is an excellent route to kind of take those first steps down. Definitely. Today's episode is sponsored by SwiftType. Search is not an easy thing. There's a lot to consider when you start thinking about search. You have to index words and you have to wait them and you have to understand when phrases fit together and there's smart operators. And if you're building your own search engine for your site, then you're probably doing something wrong. And you have a lot that you have to learn to be able to do it right. And SwiftType is going to help you by giving you AI-powered search that delivers fast, relevant, and customizable search results for websites and applications and for businesses. And SwiftType Suite of products have revolutionized the way people find information across their organization and on public-facing websites. And for public-facing data, for example, searching your own website, you can create and deploy a website search experience tailored to your audience in just a few minutes. And for internal organization data, stuff that's not necessarily accessible on a website, you can securely search for your files, your tickets, your pull requests, basically all of the stuff that you already used like GitHub, Andera, and Confluence, and Dropbox. All of these services, SwiftType is going to allow you to search across all of them. You can customize through APIs as well. So you can customize the search experience through the API for clients and for content ingestion, querying, and management. Now SwiftType is SOC2 compliant. SOC2 is a standard of privacy, security, availability, processing, integrity, and confidentiality. And SwiftType has gone through all of the measures. Maybe you didn't even know existed to make sure that your users are safe and that you are providing the most secure search experience as possible. And more importantly, for your business, all of your data is going to be safe. You can start your free trial, and you can learn more about what SwiftType has to offer with SwiftType Search by heading over to SwiftType.com slash Developer Tea, that's SwiftType.com slash Developer Tea. Thank you again to SwiftType for sponsoring today's episode of Developer Tea. So Mark, we've talked about a lot of things. One thing that I would like to do with you is take a step through each of these games that you've sent me, because I think each of them has a different aspect that is important to pull out and explain a little bit about these fundamental concepts, fundamental skills. We already mentioned one of them, which is translating the thing that's in your mind to a computer, encoding that information into a computer. And which game was that? Did you say that best covers that? That was Rover Control. That's the second game in the series. And that's the one where you have the various lines of different colors, correct? Yes. OK, and so we have the other games. We have on the brink and robot repair. Let's talk about on the brink. And if I remember correctly, this is the one where you actually provide instructions for the robot to move throughout a series of tiles, is that right? Yeah, so on the brink also is involves controlling a robot to move around a maze. And this one, you're moving on a maze of colored squares. And each square determines which procedure you're going to execute, and you have to build those procedures up. So the fundamental instructions are move forward, turn left, and turn right. And you're building procedures just out of two instructions to keep it really manageable. But you're building a red procedure, a yellow procedure, and a blue procedure. And as the robot lands on a space, it's going to then execute that procedure until it's done. And then it's going to look at what color it's standing on and do that one. And you're trying to find the procedures that are going to get this robot through the maze. And what I was really focused on here is I really wanted to convey to students what I think is one of the core ideas of computer science that I want them to come away with, even if they don't become computer scientists. And that's the idea of procedural abstraction, the idea of making components that are reusable. Because I think that's what makes us able to build such amazing things in computer science. We start off with assembly, and then we create a language that lets us build on top of that. And then we write some functions, and then we put those functions in objects. And then we use those components to build whole libraries. And then we use those libraries to build these amazing programs. And it's just we keep building layers on top of layers on top of layers. And so that's what this game does. Initially, you're just building the procedures out of these simple instructions, the turn left turn right move forward. But then in the second half of the game, as you get to the more advanced levels, we give you a whole new set of cards. And the new cards are themselves, procedures built out of the forward left and right commands. And you're building procedures out of those procedures. And on top of that, you're trying to find procedures that work in multiple locations on the board, which is something a lot of games don't really focus on so much. A lot of. So that is kind of what I think my hope is that a kid playing this will get a taste of this is what, I mean, like the other game, microover control, they're also practicing mentally stepping through these programs. It's a different kind of execution model than microover control. But it's also exercising at skill. But what I really hope they walk away from is that feeling of computer science is about building things out of things and then building things out of those things. And that's what makes this so fun. Yeah. There's kind of an interesting corollary that I have never actually realized until you mentioned this. And kind of recognizing some things that I pull from, the human language, we use a lot of things that essentially they're symbols. So the words that we use, they call back into some information that we've encoded in ourselves for that word. And we have various procedures that we think of. I can say test driven development. And that means 100,000 things. And so that word is in a good way, I would say, loaded. It has a lot of information that is communicated there. And so the idea that I'm thinking of is, when I was younger, I played football. This is like little league football. And one of the things that we learned is how to identify a play. It's a play that has a name and it has some identifying information. Some of it is important. Some of it is less important. Some of it gives me instruction. And some of it is more like, once again, a signal, a sign that points me to the shape of the play. So dive 23 or something like that. And what's so interesting about this is, in many ways, this same concept is applicable in so many scenarios. In programming, it's kind of like saying, you're creating a method. You're creating these modules. These repeatable or packaged modules that they have a single pointer, if you want to call it that. They have a single name, a single way of identifying them. But they mean more than one thing. And if you can compose these things together, then you can look at it and say, OK, I've got these five pointers. I've got these five things that I can put next to each other. And I can organize them in a way that's meaningful. And ultimately, those five pointers can mean 100,000 execution things. They can mean so much more. But all you have to really do is understand what those pointers mean in terms of the architecture of the application. Does that make sense? Yeah. I think you're talking about what's a very core skill, which is to think in terms of modularity. Yeah. And in terms of abstraction, we can learning to trust the various levels of abstraction to do what they say they do. And this goes back to our previous discussion about having code that is reliable and tested. And all of that is so important to be able to create reliable abstractions. Abstractions you can trust to do the thing that you say they're going to do. Yeah, it's fun for me to watch kids play on the brink, because when they get to those advanced instruction cards that are procedures, they always start out moving their robot and stepping through every single element of the procedure. But a lot of the procedure cards are designed in such a way to have an overall effect that's easy to understand. So one of the cards is we call it long-turn left. And it's like you move forward a step and you turn left, and then you move forward again. So it's like three components to do this bigger left turn. And what you see is that after the kids have used the procedures for a while, they start trusting, just like you said, they start trusting that the procedure does what they understand it does. It always does this large turn left. And they'll stop stepping through the individual steps. They'll start automatically just doing the whole long-turn left as one action. And to me, it's always a thrill scene. I mean, have that epiphany right there. And in front of my eyes, now they can go from, instead, I think it's relieved a whole bunch of mental effort to from going from the point where they had to step through everything to where they can now think of it as one big action. Now they can reason about things at a much higher level. And it makes the puzzles much more tractable and seeing them go through that is really cool. And that's exactly the perfect explanation of what abstraction is, is being able to say, OK, I'm going to trust this thing. And I no longer have to tax myself cognitively to put that robot through every single step. And I know some patterns now. I can use these patterns reliably to accomplish something. And now I can compose these things a little bit faster. I can do, I can remove the cognitive load a little bit and say, OK, yeah, I know what that does. And I can move forward and do more complex operations. And a really cool part, I'm going to ruin some of the plot twist of the game if that's OK. Really cool thing that happens in later pages on the brink is you start to see that previously you're providing them with, hey, OK, these things are what you're going to need to be able to solve this. These particular moves or procedures, you need to turn left and one move forward, right? Or whatever the particular thing may be. And later on in the book, you remove that. And the student, the person who's playing the game has to decide what to use. And the truth is they may decide to use. There's not only one solution to every single puzzle. Is that true? There is one solution to every puzzle in this game, yeah. In this game, OK. It's designed so that there's only one solution. So it feels, I think you're right, that it feels very freeform and that was really intentional on my part. One of the criticisms, well, you fooled me. I guess that's the best way to put that. That's awesome. Yeah, one of the criticisms I've often heard about other programming games is people say there's something, especially programmers will point out that there's something kind of artificial about it. Because as a programmer, we're never told, you have to write this program using exactly two of these function and one of this other function. Like there is an artificial concept of constraints that make it a puzzle. And I really wanted to design a system where in that expert level, we could say, use whatever instructions you want out of, I mean, you're still limited to the cards that we've given you in the set. But we're not telling you specifically what to use. And it feels much more freeform. It feels much more like writing a real program. And the maze itself is very carefully, cleverly designed so that there is exactly one solution. But it feels very freeform solving it. And that is exactly what I was going for. Yeah. And it's what's so interesting. You can draw these cool parallels to the professional developer's job. In this case, we have a set of tools, like documentation. I know what methods are available to me. And it's my job to take these methods and compose them. And it's not a set of resources. It's a set of things that I can compose together. And I know what tools I have. I have more than enough tools to solve this problem. Now which ones will I use? And so that is a meta-level problem-solving aspect of this that I think is really interesting. So I want to move on to robot repair. Can you give an overarching idea of the narrative of robot repair? Yes. So robot repair, the skill I was focused on there is the idea that logic is something that's very fundamental to computer science. And it's something that isn't given a lot of attention in computer science curricula. We need, every day we use AND and OR and NOT. And maybe sometimes we'll use more exotic things, like exclusive OR, or if you're doing digital engineering, you might not use NAND or NOR. We use these things, but we're often left to just use our own intuition from English. Like teachers will say, OK, this programming language it has AND or not, use it the way you think you should go. And it turns out that's not a very effective way to teach those things, because a lot of those things don't behave quite like what we think of from English. Or a lot of times in English we're really using the exclusive OR. Like if I say, I'm going to dinner or I'm going to a movie that if I did both, you might be very surprised by that. Because it sounds like I'm saying either this or this, but not both. In computer science, of course, we always mean the inclusive OR unless otherwise specified. And people have a lot of confusion about how to negate these things to negate an AND or negate it OR. So what I wanted to do is I wanted to develop a logic puzzle that would really stretch players' abilities to interpret and understand all the logical connectives. And I think that having that foundation is just very valuable in computer science. But then on top of that, there's this whole extra level to the game that I think professional programmers will really appreciate. Even though this game is marketed towards kids and young players, this game in particular has this whole other level that I think adults and professional programmers would really get a kick out of. The logic puzzles in there are modeled after a famous NP-complete problem called the Satisfiability Problem. And the Boolean Satisfiability Proudness The Way It Works is you're given this really complicated logic formula. And you have to find the truth values for the individual variables to make the overall formula work out to be true. And that, it turns out, is an NP-complete problem. And it's such an important historical NP-complete problem that computer scientists have spent decades coming up with really good heuristics for solving it. I mean, obviously, an NP-complete problem. If you have a large enough problem, it's going to overwhelm your computational resources. But most real world problems, like hard problems, can be modeled in terms of the Satisfiability Problem. And if you have a good solver with good heuristics, most real world problems have some kind of structure to them that can be exploited by these heuristics. So you can take these hard problems, model them as a Satisfiability Problem, as a formula where you're looking for true false values, pass it into one of these state-of-the-art solvers, and you get back the individual values, and then you translate that back into your original domain of your problem, and you have a solution to your problem. And it's a really powerful tool to have in your toolkit to understand how Satisfiability Problems how they're structured. And as you solve these problems as you play through this game, you're actually going to learn on your own. You're going to discover yourself a lot of the same strategies that Satisfiability solvers use. So you'll get more of an intuition about what kinds of problems can be cracked by the solvers, because you'll understand the processes they go through. Sure, yeah, that's so interesting. And these are things that as a developer, if you're listening this episode, and you're thinking, wow, I've never even touched anything related to NP complete. I don't even know what that means. Then join the club. Probably most developers probably have not had the chance to dive into something like that. And I fall into that group. I haven't had a chance to really take time and approach any kind of problem like that in order to solve something greater. Most of the time, the academic things that I do are barely touching the surface on most of the kind of popular algorithms. So this is really cool, because what it means is basically you've created this puzzle game. I want to be very clear about that. You've created this puzzle game that introduces concepts that leapfrog into that really high level domain. And what that gives me hope as a developer to think, OK, hey, maybe the stuff that feels intimidating when Mark is talking about this, he says, NP complete. And I have a very limited grasp on what that even means. Maybe some of these problems are more accessible to me than I expected before I encountered this. Yeah. And one thing I would recommend to people who are kind of intrigued by this and want to see more about what this means in practice when I talk about modeling one problem in terms of another. I gave a talk at a recent conference. It was actually a closure conference. And you can find the video on YouTube. It's called solving problems declaratively. So I gave this talk. And the sample code is going to be in closure because that's the conference I was at. But I've shown the talk to people who don't understand closure. And they said they were able to mostly follow the just of the talk, even without knowing the details of the closure syntax, because I talk about it at a kind of a high level. But what I do is I take a kind of a classic puzzle game problem and I demonstrate how to turn it into these different models that they're solving engines that already exist to solve these things. And I show how you kind of solve it using the solver and then you translate it the information back into kind of the original problem statement to solve that. And I work through that for a few different solvers, including the satisfiability solvers. So I would recommend checking that out as a taste of, because if you get a feel for that technique, it's something that can apply to a lot of really interesting hard problems, things that maybe you're not even sure how you would go about tackling, how you would write a program to solve this thing yourself. But you don't have to worry about that part. If all you have to do is translate it into a model that there already exists a solving engine out there to solve it. Can you give an example of a type of problem that would be good for? Well, the satisfiability solver, for example, there are a lot of NP-complete problems that come up with certain kinds of resource allocations, routing things through a network optimally, or if you're writing a compiler, the allocating different values to different registers, it turns out that doing that effectively is NP-complete as well. And so a lot of these are challenging problems that come up in ordinary things we do. And finding the optimal solution is hard, but you can pass it to one of these solvers, and it'll do that for you. Oh, OK. Yeah, that makes sense. So this is a problem set that is really, we've talked from the very lowest level introductory CS concepts in these physical games, these foundational ways of thinking, all the way up to really complex and sophisticated algorithms. And what's really cool is these games kind of lead people to those spaces. And I really respect that about the design of the game. So thank you for creating something so cool. Thanks. It's been fun for me. And just amazing to see how much can be done through a game. I think it's not obvious which of these computer science concepts can be turned into something playable. So it's been really fun to explore that space. Yeah, yeah. I remember a game that I played on my PC when I was younger. It was called, I believe, the incredible machine. Oh, yeah. This game. So much fun. And this concept of components, and really, I feel like this is kind of another generation of a similar concept. Some of the ideas you've brought to these games is that. But I'm really, perhaps just as impressive to me is the fact that these games are in target. These concepts are becoming popular. They're not just a niche subject anymore. It's not just a kickstarter thing anymore. Yeah. If you have listeners in other countries, they might not know what target is. But it's a big, kind of, that's a good point. Yeah. Where you can kind of buy a lot of different things here in the United States. But it's one of the big kind of a target in every city that has more than 20,000 people entered or something. Yeah. And it's really exciting to have a chain like that carry these games. And I think all kinds of people are going to get exposed to this that wouldn't order daily. Yeah. And I know that I, you know, this is the kind of stuff. I just recently had my wife and I had her first son. And I didn't personally. That would be a difficult process. But, and this is the kind of thing that I'm really excited to see, you know, laying out in front of him and his future. The idea that, hey, you know, for so many years, the professional life was relegated to, you know, you really start thinking about that maybe around the age 16, right? And because we, we, and this is a whole different discussion and we don't have time to go into it tonight, certainly. But, you know, thinking about, what am I going to do in the world, right? You don't really have that responsibility when you're very young. And sometimes you don't even have that responsibility until after college. And a lot of people view that as a burden more than, you know, a gift or an opportunity. And this is so cool to me because what we're doing is, you know, with games like the code series that you've created, Mark, we're allowing people to start thinking about, hey, what cool stuff is there in the world for me to get involved in? And not just, you know, limited to only the things that you can do in grade school traditionally, right? But we've, we've moved past that. It's a new era in thinking, not that we're saying, hey, you should start thinking about your job when you're five years old. That's, you know, that's ludicrous. But instead, jobs are no longer just intended to bring home money to pay for food, right? Jobs are no longer just about paying bills. We have the opportunity to do really interesting and unique things in the world. And we should share that with our children and with, you know, the people who are in college or who are switching careers way late in their careers. We should share that exciting and inspiring opportunity. So again, Mark, I feel like, you know, the work that you've done with these games is going to do some of that work. And I really appreciate it. Well, thanks. That's sort of my dream. So I appreciate that. Mark, I appreciate your time tonight, once again, for coming back onto the show, you know, joining me in the evening. It's not an easy thing to do. And I really appreciate your extra effort to make this episode great. I have two questions that I ask all of the people who come on the show. And you happen to have already answered these to me directly. But I'm going to ask them again for the benefit of the people who are listening. The first question is, if you and I were to sit down and have tea and you hadn't never talked to me before, what would you wish that I would ask you about? Well, as a parent, I always love it when people ask me about my kids, of course. And in the context of computer science, also because my big focus is on trying to start computer science to start kids on these concepts as early as possible. Because I homeschooled, I think it also makes a lot of sense for someone to ask me, how did this work out with my own kids? Because I started them very young on this material. And so slightly different answer for both my son and my daughter. My son really took to this really quickly and just loved it. And I started him on these kind of computer science concepts really as early as eight. We got, I mean, before that, he was kind of dabbling in playful programming kind of things, but by eight kind of got more serious about it. And made programming part of his everyday routine made tied his math curriculum to that. And it worked out fantastically and he became really expert at this stuff really early, as you might imagine. And by the time he turned 16, he realized he had the skills to go out and get a professional software engineering job. And so that's what he did. My daughter, I did a lot of the same things with her from a very young age. And she also was really good at it and enjoyed it, but not quite in the same way. It wasn't the kind of thing she wanted to be doing every day. And that's OK too. She's going a different direction. She's going off to college this year, going to be studying stage management. She loves theater. That's her passion. But what I have seen over the years is that those early years that I spent working on these foundational math and computer science concepts have really just made her a significantly better problem solver, a really strong thinker. And it's really helped her in every other thing she's done. So I'm really glad she has that experience in her background. And I can see that it's going to help her even though that's not the kind of career she wants to go into. And that is perfectly OK too. Yeah. And that goes back to that discussion we were having earlier. Having these skills that goes beyond programming. And it really is about becoming a better thinker and more strategic thinker. So I totally agree. I hope to pass on some of the same thinking skills to my children and really kind of espouse that on this show. So the second question I like to ask everyone who comes on the show is if you only had 30 seconds worth of advice to give to developers who are listening and they come from all different backgrounds, all different experience levels, what would you tell them? Well, we spent some time talking on this show about functional programming languages. And I would say I would recommend to Developer To spend some time learning a different programming language that you use every day. Maybe a functional programming language, maybe something different. The point is it should be a programming language that forces you to think in a different way than you're used to thinking every day. And the reason is because that's going to give you a whole new expanded tool set, a new way of thinking about problems. And it will give you more, when you face new problems, you'll have a new way of thinking about it that will allow you to solve things that maybe you hadn't solved before. That's excellent advice. And you actually stayed under 30 seconds. I don't know that anybody who comes on the show has actually stayed under 30 seconds. Every once in a while, I'll have somebody who says, be nice to people. And that's a great answer. There's plenty of advice in that. But you kind of hit that mark right on 30 seconds. So that's kind of impressive. Mark, thank you so much for coming on the show, for doing something great, and for being so accommodating with tech issues and overall being an excellent guest for Developer Tea. Well, thank you very much. I know I'm going to continue to explore this space of creating puzzle games that teach programming. And so there's some new things coming in the pipeline down the line, and maybe we'll have an opportunity to have another conversation about that stuff in the future. Yeah, top secret stuff. And things that actually, you and I have discussed off the record that are worth paying attention to. And following Mark, especially if this episode is intrigued to you, Mark, where can people find you and follow you and know about this stuff in the future? My Twitter account is Mark underscore Engelberg. That's M-A-R-K underscore ENGL-B-E-R-G. And I use that as a way, mainly, to tweet out things relating to new games I have coming out or new talks that I've done when a video is out or something. So it's pretty low bandwidth. If you want to sign up for that to follow me on Twitter, I would promise not to spam you with too many random things. It'll just be updates about when I'm up to. Excellent. Mark, thank you so much for coming on the show. And thank you again for all that you've done for the community of developers who want to inspire, especially young students in this field. Thank you so much. Thanks. Bye. Thanks so much for listening to today's episode of Developer Tea. And thank you again to Mark Engelberg for joining me on this episode. I had an excellent time interviewing Mark. He was so kind and gracious to do the interview a second time after we ran into some technical difficulties. So I really appreciate his patience with me. And thank you so much for listening. And of course, go and check out Mark's awesome games. You can find him in Target. You can find him online as well. Thank you to Mark. Thank you for listening. And thank you to SwiftType for sponsoring today's episode of Developer Tea. SwiftType Search is a fast, reliable, safe, and AI-powered search system that you can get set up on your website in just a few minutes. Head over to SwiftType.com slash Developer Teato learn more about SwiftType and to start your free trial today. Thank you so much for listening to Developer Tea. Make sure you subscribe if you don't want to miss out. In future episodes, just like this one, and also different than this one. We cover tons of topics. We do three episodes a week. And it's so important that you subscribe, if you don't want to miss out on topics that are relevant to you. So subscribe and whatever podcasting app you're using. It takes just a second. Pretty much a single button click. Most apps don't even require you to sign up for an account. So go and subscribe to Developer Tea. Now, thank you so much for listening. Until next time, enjoy your tea. your tea.