CHARLES MAX_WOOD: Hey everybody and welcome back to another episode of JavaScript Jabber. This week on our panel, we have Steve Edwards.
STEVE_EDWARDS: Hello from a very sunny Portland.
CHARLES MAX_WOOD: AJ O'Neill.
AJ_O’NEAL: Yo, yo, yo. Coming at you live from back cramps. Getting old. Back cramps.
CHARLES MAX_WOOD: I'm Charles Maxwood from topendevs.com. Now, AJ, you were talking about, as we were talking about what to talk about today, we had our guest cancel last minute, who apparently was Dan. He had something come up, but anyway, yeah, you were talking about like these. I can't, I can't remember the term you used for like of craftsmanship. OK, but yeah, it's the the one I'm familiar with is the the Python one.
AJ_O’NEAL: Zen of Python.
CHARLES MAX_WOOD: Yeah. But then you've also got I mean, I've seen some that are just kind of like Minaswan and in Ruby, right, where it's Mets is nice and so we are nice, which is, I guess, not a craftsmanship thing. It's a community thing. But
AJ_O’NEAL: yeah, I would I would not. But I think Ruby has dry. I think that Ruby invented dry and rest.
CHARLES MAX_WOOD: Yeah, and Rails also has convention over configuration.
AJ_O’NEAL: Which that is an anti-principle, but that's another argument.
CHARLES MAX_WOOD: It's an anti-principle.
AJ_O’NEAL: Well, it goes against the Xenopython explicit over implicit, but maybe we, how do you wanna do this? Do you wanna go over the whole of them and then dig down into them or what?
CHARLES MAX_WOOD: Well, I'm kinda curious just because I guess I see some value in it, not every community has them. And so I'm wondering, is there something about say, you said Go has one as well, right? Kind of a list of principles that they try to adhere to.
AJ_O’NEAL: Yeah, the Go Proverbs.
CHARLES MAX_WOOD: So is there something about Python or Go that tends to push people into saying, hey, we're going to espouse these ideas? We also have like the Agile Manifesto, which is more, I guess, generalized and has more to do with the process of writing software than the actual crafting of software writing code.
AJ_O’NEAL: Yeah. The agile manifesto is more about the man, the management process. I think anybody who is a consultant should be familiar with the actual agile manifesto.
CHARLES MAX_WOOD: That's a whole other podcast episode.
AJ_O’NEAL: Well, because there's, I just want to be clear. People say agile and you know, they hear agile and they tune out because what they're familiar with agile is, is waterfall that's been rebranded agile. And that is broken down into say weeks or months rather than years. But, and I guess you could say that if you look at it under a certain lens, that agile process is just a waterfall process that is broken down into weeks or months, but it's, it's more than that in terms of, of a philosophy. And then if you are doing short-term work with multiple companies, the agile manifesto is something that I believe you really should take to heart as well as the 12 factor app.
CHARLES MAX_WOOD: Right. But let's throw back because the 12 factor factor app is another one that's kind of more generalized. It's not just one community,
AJ_O’NEAL: but all of these apply to everything. So the Zen of Python, literally, I don't think there's a single stanza that is Python specific.
CHARLES MAX_WOOD: No, that's fair.
AJ_O’NEAL: Is about craftsmanship and it is not about specifics of linting or anything like that. The go proverbs are a little bit more specific in terms that they reference things that are go things. But again, they are the go proverbs maybe can't as well be applied to some of the older languages, but modern languages, the go proverbs apply to really well because all modern languages have these sorts of features about them, which I, you know, we can go into that if we go into that.
I remember working my tail off to become a senior developer. I read every book I could get my hands on, I went to any conference I could, and watched the videos about the things that I thought I needed to learn. And eventually, I got that senior developer job, and then I realized that the rest of my career looked just like where I was now. Where was the rush I got from learning? What was I supposed to do to keep growing? And then I found it. I got the chance to mentor some developers. I started a podcast and helped many more developers. I did screencasts and helped even more developers. I kind of became a dev hero. And now I want to help you become one too. And if you're looking forward to something more than doing the same thing at a different job three years from now then join the Dev Heroes Accelerator. I'll walk you through the process of building and growing a following and finding people that you can uniquely help as you build the next stage of your career. You can learn more at devheroesaccelerator.com.
CHARLES MAX_WOOD: Yeah, I guess my point though is what drives the Python community to adopt Xen of Python or create Xen of Python when other communities kind of haven't. I mean, this is a JavaScript podcast. Xen of JavaScript doesn't really exist, right?
AJ_O’NEAL: Well, I would say most communities do have these. I would say that the communities that don't have them are the ones that are driven by committee rather than by leaders. So even early on in the days of node, and I'm going to be a little bit derogatory here, but they're, they're college kids, right? I was a college kid around the time. Yeah. When node came out, I was a college kid. So we're in the same peer group more or less, you know, they're just more prestigious and smarter than me, but still it was kids without experience that were creating node and NPM. It was not software engineers that had a battle tested approaches and methods. And they were very kind of hippie in terms of we don't need to make decisions as a community of leadership because the crowd is going to make smarter decisions. Cause there's that whole kind of meme that was going around at the time that don't underestimate the intelligence of the crowd or something like that. Cause there was a couple of use cases where they found. There were some studies done that if you ask a crowd to solve a problem, you get kind of these genetic algorithms out of it. And so a crowd of people can solve an algorithm faster or better than a few really, really smart people working together for these particular use cases. Which I think that's absolutely true, but the opposite is true as well. Anyway. So, and then node. So they never made choices about how to do things, or they were really lukewarm about making choices of how node should be written and what's a good way to write node and whether the guiding principles of node. And they kind of said, well, we're not going to make any choices. We're not going to develop a standard library. We're going to throw everything to the community and the crowd is going to make better choices than we can alone, which is not reflective in the broader world of software communities. And then node got handed over to a committee. Same thing with JavaScript. JavaScript, when it was led by Douglas Crockford, he was a strong figure. He was a strong he was a figure you could like or dislike. But he had discipline and he had principles and they were never codified into stanzas of a creed, but you knew what it was that he believed and what he expected and he was very clear about that. But then Microsoft and the Microsoft guys and the Ember guys kind of took over the committee and edged Crockford out. And then as it became less of a leadership situation and more of a committee situation, the ideals got muddled and you have conflicting implementations and conflicting syntaxes of, well, why do we need three or four different ways to do the same thing? But that's what happens in a committee. When you have something that's driven by a committee rather than a set of leaders that people believe in, it's the old, if you, if you don't stand for something, you'll fall for anything. And committees are are not likely to produce. I mean, even Rust, Rust has a committee, but it's not that it just has a foundation. There are actual leaders in Rust who are the Rust dudes. But Brendan Eich is not part of JavaScript anymore. And Crockford's not really part of JavaScript anymore. So the people that were the JavaScript dudes aren't really part of JavaScript. And same thing with HTML. Who's the HTML dude? Who are the HTML people? And let's not...The truth of the matter is it was dudes, but I'm not meaning that in a derogatory sense. It could be ladies and there were lots of ladies early on with the early programming languages. You know, of course we've got her faces in my mind, the general, the Navy general, or I don't even know if I'm using the term correctly. She's my favorite. She's the one who says it is easier to get forgiveness than it is to ask permission or easier to ask forgiveness than to get permission. But so in HTML and CSS and JavaScript, we don't have a face. We don't have a group of people who are buddy-buddy who are making decisions in tandem. We have committees and political alliances is what it seems to be. And they can't even agree with each other. You've got the what WG, which is managing some part of the standards. You've got the East CMA, which is managing another part of the standards. You've got the W3C, which is managing another part of the standards. And you can see this as they come out with standards there. APIs don't even agree with each other. They don't accept similar objects. They have dissimilar names. So that is why I think in the web development community, we don't have credos and such because we don't have, we don't have a community in the tribal sense where there's a leader who, whose ideas we buy into and choose to electively believe in together.
CHARLES MAX_WOOD: Okay. So there's so much there that I kind of want to respond to, but I'm not going to.
AJ_O’NEAL: Well, do do. I mean, why not? I mean, call me out if you think I'm wrong. I am I'm ill informed on something or, or if you just disagree that the committee method works or.
CHARLES MAX_WOOD: No, I think, I mean, mostly it was just the, you kind of put like Doug Crockford in as the guy that was running JavaScript, but my understanding is that it was always a TC 39 committee, but
AJ_O’NEAL: it was, but he was a strong arm. He was the face. Yeah. He was the one that you could believe in. No one else was getting up, giving conference talks and saying, this is what the future needs to be. This is what we should believe in. This is a path that will take us to success.
CHARLES MAX_WOOD: So I guess the other thing though, is that does then a Python then come from Guido? Is that his name or?
AJ_O’NEAL: Sorry. Yeah.
STEVE_EDWARDS: Guido van Rossum.
AJ_O’NEAL: Yeah. So it does not come from Guido. It comes from Tim Peters. But it is part of the, there's, there's these things called PEPs P E P. And I don't remember exactly what that stands for, but this one actually came out fairly early on. This was PEP 20 back in 2004. So a little bit later than, than I thought it was, but Tim Peters, I, I'm not super familiar with the Python community, but I am led to believe that he is one of the inner circle. Maybe he was just a rando. But let me Google that real quick and see. But this was something that was blessed by the inner circle and, and put forth in official Python documentation as this is what we believe in. And you see this Scala has one of these. I have actually, there's a list that I have, if I can find it where so Tim Peters known for his major contributions to the Python programming language and its original C Python implementation a pre 1.0 CPython user who was among the group of early adopters. So he was, so where you have say Ryan Dahl was the creator of Node and Dino now. And then Isaac's was one of the people early on that came into the inner circle. And then that became the NPM foundation and whatnot.
CHARLES MAX_WOOD: Right.
AJ_O’NEAL: So I, it sounds like that kind of thing. It was one of the inner circle people was the Tim Peters that came up with it. And like I said, it's in the official. It is actually built into Python. If you type import this, when you open a Python interpreter, it will print out the Zen of Python.
CHARLES MAX_WOOD: Okay. So what's the story behind the adoption of the Go Proverbs then? Is it the same kind of thing?
AJ_O’NEAL: Yeah, but it took a lot longer for the Go Proverbs to come about. And part of that is the mentality of the Go community is to move slow and deliberately. And there's this aspect of discovery. We're looking for patterns that are going to help us to have fewer errors and to have greater success in developing correct programs. And that's really the key thing. You'll notice there's no syntax sugar in Go. The idea, both that, Crockford echoed this as well. If you want syntax sugar, you should just use an editor where when you hit tab, it auto completes for you, right? And that's part of what the GitHub Copilot and some of those other systems offer a little bit better tab auto completion. In some cases, a little bit worse because you have to go delete more. But anyway that's the kind of thing where if you're doing redundant tasks that an automated tool could look at and see, oh, you want the same loop that you just did in this other file, but you want it to apply to this variable instead of that variable here. I can auto complete that for you. So there's a very little syntax sugar and it's more about over time. What do you learn about the language and its uses and its intentions and what went well with the intention and what didn't. And then they come out with, here are some defensible arguments that we can make about the language. Should I just read through the Xenopithon and the Go Proverbs?
CHARLES MAX_WOOD: Yeah, I think we're kind of to that point, but I kind of wanted to just get context around this because it's interesting to me, you know, some communities kind of have this explicitly written out, you know, as Go Proverbs or Xenopithon and others don't. And then as you move into different communities, yeah, you've got some, I mean, there's kind of the Ruby way where there's kind of an idiomatic way of doing things and there are reasons for that and there are values behind it, but it's not been explicitly drawn up in ways that we do things. You know, the same thing with JavaScript. If you go look at a series of Express programs written by experienced Express developers, you're going to see a lot of patterns repeated. Not all of them, but a lot of them. And so there are going to be some variations, right? But the point is that, yeah, it's interesting to me that...Yeah, we have these, you know, these groups that are saying, Hey, these are the things that we value, not only at the, the level of when you write the code, but these are things that we value as we build and design the language and the ecosystem around it.
AJ_O’NEAL: And by the way, Ruby does have a, an official one called the Ruby doctrine.
CHARLES MAX_WOOD: No, it's the rails doctrine,
AJ_O’NEAL: the rails, sorry. So the rails, it's rails.
CHARLES MAX_WOOD: So the rails doctrine does exist. And yeah. We should do a Ruby Rogues episode on that. Anyway, but yeah.
AJ_O’NEAL: Okay. So sorry, if there was a question there, I missed it.
CHARLES MAX_WOOD: There, there wasn't. I just, I just find it fascinating that we have this. So, so yeah. So I'm curious then as we go into this, cause you've been writing go lately, I think more than Python.
AJ_O’NEAL: Yeah. I was never, I was never big into Python early on when I was in college. I discovered Python because people talked about kind of the ethos of it that when you went to Python meetups back then, and I don't know what Python meetups are like now, but I imagine that because of the ethos of the language and the community, it's probably held over, over time, but there was a real strong sense of discipline and a strong sense of we're looking to find the best ways to do things and things that are easy to read and easy to teach and easy to understand, and that drew me into Python and that's in mingling with Python people granted this was early, early, early on where I had only used PHP and basic to that point. And then, and then school introduced me to Java and classmates introduced me to Python and Python Isis, it told me what this whole everything on rails was about. And then I went to the Ruby meetings and the Ruby meetings led me to node because someone had a Ruby meeting presented on node. And then, you know, the rest is history, I guess, conference talks and such, I learned about Go and then through friends, I learned about Rust, but that was kind of, yeah, I took a path to learn about these things and I never, so I never was deep into Python. I was just learning it to understand software better and didn't know what it was I was looking for yet in a programming language.
CHARLES MAX_WOOD: Makes sense. So yeah, so let's go ahead and dive into one of these. I don't know if we want to do a Go Proverbs or Zen of Python. One other thing that I'm curious about really quickly is, you know, I know you've been writing go, but is there one set of these that you identify with more than the other?
AJ_O’NEAL: I would say all of them tend towards the same. So I would recommend studying each of them. And as you're writing code, think to yourself, is this code defensible? Can I do I have a defensible argument for why I make the choices I make? Again, if you don't stand for something, you'll fall for anything. One of the great crockford isms is you're not paid to use every feature of the language. You're paid to create correct software that works well. And I think I also had a friend in college who, I think this quote comes from somewhere else and I, I might be flowering it up a little bit better than the way she said it, by the way, that I remember it was the constraint of the medium defines the art it's not in taking every Liberty that you create art. It's in constraining yourself to a certain set of values that you create art. So you could take some trash and some paint and everything that's around you and put it in a pile and call it art. And it wouldn't make any sense. But if you only took the trash and you didn't take the paint and you constructed it into something, it can become art because you did something unusual. You took odds and ends that were in a trash bin that you could clearly identify as this is the sort of thing and a trash bin, a Coke can, some paper, some paper clips, whatever. And you could call this office montage or whatever, kind of beside the point. But the idea of, well, people get really upset about the idea of their art. They think their code is their art and their white spaces, their art and your white spaces, you may see that as your art, but I'm going to argue that you shouldn't as a software engineer, because that is not what creates the, that's not what makes code run well, easy to read or fulfill any of the functions that it is supposed to fill. Whereas if you constrain based on principles and you selectively choose not to do things because you are disciplined in a particular way then I view then that to me that is the art of code is finding the disciplines that reduce what you use in a language to a set of code that is Expressive in a way that is more correct.
CHARLES MAX_WOOD: You hurt my feelings.
AJ_O’NEAL: I probably did I probably heard a lot of people's feelings, but you know if they listen to the podcast they're getting they're getting more accustomed to that
CHARLES MAX_WOOD: anyway So, yeah.
AJ_O’NEAL: So let me go through the Zen of Python. I'll just go through it quickly. I won't do any commentary and I'll go through the Go Proverbs. And you'll see the Zen of Python is very applicable to all code and it's quite subjective. It's a little less concrete, but here it is. The Zen of Python by Tim Peters. Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although, practicality beats purity. Errors should never pass silently, unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. And I am gonna comment there, that is one of my favorites. There should be one and preferably only one obvious way to do it. Although that way may not be obvious at first, unless you're Dutch. I think that's because the inner circle was mostly Dutch. Now is better than never. Although never is often better than right now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea. Let's do more of those. That is the Zen of Python. And if I go over to the Go Proverbs, they're not quite as maybe poetic, but so Go Proverbs by Rob Pike, simple, poetic, pithy. Don't communicate by sharing memory. Share memory by communicating. Concurrency is not parallelism. Channels orchestrate, mutexes serialize. The bigger the interface, the weaker the abstraction. That's a great one. Make the zero value useful. Empty interface says nothing for those not familiar, marker interface. Go format style is no one's favorite, yet go format is everyone's favorite. A little copying is better than a little dependency. Those are words to live by. Cisco must always be guarded with build tags. Sego must always be guarded with build tags. Sego is not go. With the unsafe package, there are no guarantees. Clear is better than clever. Another one for the fortune cookie. Reflection is never clear. Errors are values. Don't just check errors, handle them gracefully. Design the architecture, name the components, document the details. Documentation is for users. Don't panic. Now, the Go Proverbs, if you are only familiar with untyped languages, then a lot of these things may not make sense. The Go Proverbs are intended for languages that are concurrent, meaning, well, that means a couple of different things, but let me be a little bit more broad than that. For programs that are intended to run on multiple CPU cores at the same time, and for languages that have a more strict type system than what Python provides. Because Python does have a strict type system, but it's not as strict as Go. And Go actually came out of Python. Go is a spiritual successor to Python. If you listen to the early talks that comes across fairly clearly. I don't know if they explicitly stated, I believe that they do. I believe that they actually do reference that the goal was to make something that was as pleasant as Python, but as powerful as C.
CHARLES MAX_WOOD: Right.
STEVE_EDWARDS: So here's a little clarification question for you, AJ. You had said complex is better than complicated. What's the difference?
AJ_O’NEAL: That's actually one of the ones that I don't understand that well. And I went to look for a talk where somebody explained that and I did not find one at the time that I was looking for it. But I think that it probably has to do with the say, think of complexity and computer science terms that sometimes you have great cyclomatic complexity, meaning that there are lots of branches in the code. If else switch calling out to another function that calls out to another function. So I would say that that is complex and that there are many pieces that must interact together. And I think that complicated is when I would say complicated code comes out of, for example, have you ever tried to dry something up? So for those not familiar, DRI, one of the Ruby principles, don't repeat yourself. Have you ever tried to dry something up? And at the end of that refactor, your code is more difficult to understand than it was before.
STEVE_EDWARDS: Oh yeah.
AJ_O’NEAL: That is what I would consider complicated. You are making choices about which things should be variables and which things shouldn't be variables and how something should work to try to force it into a pattern that's hopefully you realize before you're done, it doesn't actually fit with. And so the code is not just complex and that it has many interactions, but it's complicated and that the interactions are not intuitive, easy to read or likely to produce correct results.
CHARLES MAX_WOOD: Yeah, that makes sense. So I guess what I'm wondering is somebody put together a list of these ideas for JavaScript. I mean, do you have an idea of what would be in them?
AJ_O’NEAL: Well, yes and no. I think that in the Crockford talks, you could take several of his slides and you could create something like this. I just don't think that they would be popular in the broad community because these things are driven by committee and we don't have leaders to. So let's say that I were to come up with these, it would go terribly because people would say, well, who are you to decide what good JavaScript is? There's no reason to put belief in me. You've got a, Kenzie Dodds has some principles that he espouses for react, but react actually has leadership. That's one of the few good things about react is that there are leaders in that community. And so if Kent C. Dodds comes out and says something, there is some buy-in because if you believe in react and you believe in testing, you have already been exposed to Kent C. Dodds and you most likely believe what he believes. So this goes back to the Matz is nice. So we are nice of, of Ruby.
CHARLES MAX_WOOD: Right.
AJ_O’NEAL: The leader determines the values and pulls people towards those values. So. Crockford was a little bit of a grumpy butt. And so he rubbed people the wrong way. And I wasn't rubbed the wrong way by him because I, I'm a little bit of a grumpy butt myself and I believe in principles are more important than your feelings. The purpose of code is correctness, not to express your inner self. If you want to express your inner self, express your inner self by what you create, not by the way that you use Simi Collins. But I think it would be difficult at this stage. We'd have to have some leadership would have to pop up somehow, it would have to be leadership that has some sort of influence and direction and steering. I don't think it could be someone that exists entirely apart from that. And that's very difficult because the committees are driven, as far as I can tell, more in a political fashion by people that are more interested in, that are not necessarily web developers, or not necessarily the type of web developer that most web developers are. Because they make things that are... I don't know. There's just some mistakes that it seems that anybody who had been programming in JavaScript for five years, who had been doing it professionally, who had used a couple of different frameworks would recognize like, Oh, this clearly is not a pattern that's going to work because this has been tried across this framework and that framework. And we know that if you structure the data this way, it becomes more difficult or, you know, or if you, if the syntax is this way that it, it becomes more confusing to read or, or whatever.
CHARLES MAX_WOOD: Right.
AJ_O’NEAL: So but I think that these principles apply to JavaScript just as well as any, I mean, name one thing, now granted with Go, you don't have channels in Go. You have channels typically in typed languages where you have multi-cores. I guess there's no restriction on it. It has to be a typed language, but channels are something that exist in languages. Definitely that you have to be dealing with multiple core CPUs in order to have channels be effective. Interface is something that you only get in typed languages. Although I think even if you are in TypeScript, or if you think about it, if you understand what an interface is and what it means in documentation as a library, as an API, I think you can understand that an empty interface, otherwise known as a marker interface, doesn't say anything. So as you go through these clear is better than clever. That makes sense reflection, and we don't call it reflection and untyped languages. We call I don't know what we call it, but reflection is when you iterate over an object's keys rather than, and then check its type. So what you have to do to do a JSON dot parse and JSON dot stringify in any language, whether it's typed or not is considered reflection. So reflection is when you, you don't access the, the properties of an object by its, its known keys, but you, you access it in a generic way, like object.keys does. Errors are values. This is another one that is applicable to all languages. So as you go through this, there are some, there's some terminology in the go proverbs you may not be familiar with as someone who doesn't work in type languages or in multi-core languages. But if you do understand the vocabulary, it's not difficult to understand how it applies. It's just a lot easier to understand how it applies to go because the, the language is designed around constraints that help you to follow these principles for the most part. Well, some of them are letting you know, don't, this is a bug, not a feature. For example, empty interface is necessary. It's necessary because we have to be able to do things like parse and stringify JSON, but it is not something that should be used as a beneficial feature of the language. It is an escape hatch when there's an appropriate case and nothing else will do. And there are several cases where popular libraries, even in the standard library have used the empty interface and it has become a dumpster fire. So it's just codifying. Like, yes, we always intended it to be using sparingly. And as we've observed, it should be used even more sparingly than we originally had thought. And same, same thing with the, the Zen of Python. Like I said, readability counts and absolutely wonderful one. Special cases aren't special enough to break the rules. Although practicality beats purity that, you know, this is something to live by in the face of ambiguity, refuse the temptation to guess. I quote that all the time when you're having a discussion between a couple of developers and you're trying to decide on some future benefit of the API that doesn't exist. It, you know, you're going to need this thing in the future, but you don't know what, what it is, you know, that management's going to ask you to put profile pictures into the data and you're trying to figure out how do you do you link it? Do you base 64? And what do you do in the face of ambiguity? Refuse the temptation to guess. This is a guiding principle by which no one has ever been fired for this. I don't think you simply say we don't have enough information. We're going to shelve that decision for when we have more information and the other parts of the microservice are available for us to test against or whatever, whatever. So I would say that, especially the Python one, because it's such simple language that is not program specific, this can all be applied to JavaScript. I mean, find one thing on here where it would make your JavaScript code better to follow these stances.
CHARLES MAX_WOOD: Right, I know that makes sense.
AJ_O’NEAL: Of course, it does fly in the face of what some people are taught. So for example, with the reintroduction of C-sharp, through TypeScript, people are going back to things that we know are bad. But that's what it is. It's not even, it's not even, I mean, you're laughing.
CHARLES MAX_WOOD: You have to go punch. You have to go punch that every time.
AJ_O’NEAL: But it, but it is, that's what it is. It's not TypeScript was not made for JavaScript developers. If it was made for JavaScript developers, it would look a lot more like go. It would be a light, flexible type system that has very little complexity to it. And is, is very simple to reason about. And that works with JavaScript in a similar way to how JavaScript already works. TypeScript is not that way.
Are you ready for core web vitals? Fortunately, Raygun can help. These modern performance metrics play an important role in determining the health of your website, which is why Raygun has baked them directly into their real user monitoring tools. Now you can see your core web vital scores are trending across your entire website in real time and drill into individual pages to focus your efforts on the biggest performance gains. Unlike traditional tools, Raygun surfaces real user data not synthetic, giving you greater insights and control. Filter your score by time frame, browser, device, geolocation, whatever matters to you most. And what makes Raygon truly unique is the level of detail they provide so you can take action. Quickly identify and resolve front end performance issues with full waterfall breakdowns, user session data, instance level diagnostics of every page request, and a whole lot more. Visit raygon.com today and take control of your core web vitals. Plan start from as little as $8 per month. That's raygon.com for your free 14 day trial.
AJ_O’NEAL: But in languages like C sharp and Java, what we learned and C plus plus is that the complexity of inheritance type systems is bad and leads to code that's difficult to reason about. And bad as a moral word. And so we need a technical reference to say why something is bad. If the moral good of code is to write correct code that is easy to read and easy to reason about and easy to enhance in the future, then we know that inheritance type systems are bad because inheritance type systems make code less visible, it less clear on where certain properties of an object come from, and they make it more difficult to modify the program to add additional use cases. There are numerous reasons that we can empirically say inheritance type systems are a bad idea. And so the way that languages like Go and Rust handle this are a more modern approach with a looser coupling of how the type system works. And you can write more expressive code that is more correct and easier to extend. And you use different features to do this. But anyway, I got off the rails there, as I often do. Never. All right,
CHARLES MAX_WOOD: well, we're kind of getting toward the end of our time. What were you calling these again?
AJ_O’NEAL: So I call these creeds of craftsmanship. And I put a link there to enumerate some of them because most languages have them and most of them tends towards the same thing. Although there are some of the Ruby ones and Python ones come into conflict because Ruby is of the mindset of convention over configuration, which I don't think has to be in conflict with explicit over implicit, but the way
CHARLES MAX_WOOD: that the rails more than a Ruby idea.
AJ_O’NEAL: Oh, okay. And I, I, sorry, I get those mixed up because I was introduced to Ruby through rails. And so some of the creeds, I,
CHARLES MAX_WOOD: most people were. And to be perfectly honest there too, sometimes there's conflict between, uh, the core ideas that are espoused at the Ruby and Ruby core level and the rails and rails core level as well.
AJ_O’NEAL: Oh, okay. Well, in any case, I don't think that these things have to be contradictory. I think that you can prefer convention over configuration and you can have very well known conventions, but at the same time, you can do it in a way that's explicit. For example, generators, you generate a file and you have a convention that has been set out and when you generate the file, the file has stub code that follows those conventions, but I don't like the idea of you run a single command without a config file and it does a bunch of magic and you don't know why one option is chosen over and over and over. That's no, that's your opinion. Not about the creed itself. There's definitely benefits to convention over configuration. And I do not doubt that, but we have the Zen of Python, the Go Proverbs, wet, dry and aha. You've definitely heard of dry. If you've been a developer for more than six days, I mean, that might be a little bit ungenerous, but dry is one of those things that gets pounded into you very early on in your career. And then wet is something that you may hear of hopefully you hear these three together because they're complimentary. Dry is don't repeat yourself, which is what leads to very complicated code if you adhere to it in a sense of practicality beats purity. If you are purist of don't repeat yourself, then you will end up writing complicated code that doesn't do anything sensible because all words can be condensed down into a single column of words, if that makes sense. Every construct of code is repeated because we need for loops in multiple places. We wouldn't abstract away every possible condition of a for loop into one function. Anyway wet is write everything twice, which is basically saying, yes, don't repeat yourself, but make sure that you've written it twice first. And what I will say is typically three times is what I go with. I go with, if I write similar functionality three times on the third time is when I start to say, maybe I should abstract this. If I only wrote it twice, I may never go back and abstract it. But if I get to the point of writing it three times, I might say to myself, well, this looks like something where it may benefit from abstraction, I have to investigate, because sometimes the small differences, the small nuanced differences between two similar bits of code are so different in the way that they're used that if you try to abstract them, you end up with what I talked about earlier, complicated abstraction, where the abstraction no longer is indicative of what the code is supposed to do because of its switch statements and stuff make it complicated. And aha is avoid hasty abstraction. So the three of these, they go hand in hand. They're not in conflict, they're in concert. And so I'd suggest that you learn examples of all three of them together, and you will be a great software developer in that regard. And Kenzie Dodds is the one that coined the term avoid hasty abstractions. I was trying to come up with one. I think I came up with a Rye, which was, I don't remember what it was, but it basically was the same thing, avoid hasty, I don't remember, repeat yourself with purpose, purposefully repeat yourself or something. Ripe, ripe. That was trying to do repeat yourself with purpose, but he coined the term aha. And I actually think that that one is better than, and I'm glad that someone came up with something that, that captures that sentiment. The agile manifesto is more about process, especially as if your contractor 12 factor app is about deployment. It's about how do you, how do you structure your code so that you will be able to deploy it effectively? It has to do with how you use environment variables, secrets how you prepare the code to be deployed in the system. So it's a little bit higher level, but still worth knowing. You've got the laws of UX, which we didn't touch on at all, but these are principles that anybody who is doing HTML and CSS should be familiar with, and particularly anybody who is doing design. And if you have on your resume that you are a UX person and you do not know the laws of UX, one, you're not a UX person. Okay, that's a little harsh. There is discipline that is necessary to differentiate between UI and UX. UX is not just about putting pretty colors together. It is about creating a user flow that works towards human psychology. And the laws of UX are kind of the canonical textbook principles that you would learn if you studied UX in any formal fashion. So they include things such as, I'll just rattle off a few here, aesthetic usability effect, which everybody gets that one. Unfortunately, that's, that's the the catchall of if you can't do anything to make the UX better, just make it pretty instead. That one everyone understands. Doherty threshold, Fitts' law, gold gradient effect, Hicks' law, Jacob's law, law of common region, law of proximity, law of prognons, law of similarity, law of uniform connectedness, Miller's law, Occam's razor, Pareto principle, Parkinson's law, peak end rule, Postol's law, serial position effects, Tesler's law, von Restoroff effect, Garnet.
CHARLES MAX_WOOD: Wow.
AJ_O’NEAL: Effect.
STEVE_EDWARDS: So what about the law of the jungle? Is that in there too?
AJ_O’NEAL: I think it is.
STEVE_EDWARDS: Okay, good. Kill to be killed?
AJ_O’NEAL: But this. These are principles that if you adhere to, you cannot help but fall into the pit of success with happy users. I would just say that the very first one I mentioned, because it begins with a letter A, I think these are in alphabetical order, if that was right. I don't know, maybe they weren't. But the aesthetic usability effect is the one that's like the empty interface. It is to be used with extreme prejudice because it is the easiest to do and it has the worst results. But anyway, you've got the rails doctrine, things like rest convention over configuration. Well, actually those are different rails. Oh no, they, these are in the actual optimized for programmer happiness menu is a Macassi, which I guess I'd learn what that is.
CHARLES MAX_WOOD: If I'm a causey,
AJ_O’NEAL: oh, Macassi.
CHARLES MAX_WOOD: Yeah.
AJ_O’NEAL: No one paradigm, exact, beautiful code, provide sharp knives, value integrated systems. Progress over stability. Okay, that right there, software engineers rolling over in their graves, push up a big tent. So there's that with progress over stability is one that progress should not be over stability. It should be in concert with stability. That's a scary one right there. And then there's a bunch of other ones that I've linked to toward go to I think is an excellent blog article by the go team. And it talks about exactly how in the face of ambiguity, they refuse the temptation to guess which was, it was, it was a bug, not a bug. It was a missing feature. Well, I guess kind of a bug in some of the code related to time, the time object, and there was a big, a big kerfuffle with cloud flare that was a result of time being off by a leap second or something. And, and so toward go to talks about a lot of things, but I really appreciate their candor in talking about how they failed to provide the appropriate tools in the language. But how in waiting until there was actually a, cause lots of people complained about this potential problem, but no one had had the potential problem. And so when someone actually had the problem, they were able to investigate the underlying cause and it became apparent what the correct solution to the problem was rather than just throwing darts at a problem without understanding what the real effect behind it was. And so they took time to solve a bug that you know, ticked a lot of people off because they're like this. At some point, this is going to cause a problem, but they just kind of came back as well, maybe, but what would that problem look like and what would the solution look like? And people didn't have convincing arguments there. And then dangers of dependencies, the fallacy of false or fallacy of, of, uh, premature optimization in defense of not invented here, the Crockford on JavaScript talk, and then there's a couple other things, things I never use and go is an excellent talk that has general applicable principles. The most surprising one for most people would be don't use else. And that defend that position is completely defensible. You should use else only in very exceptional cases. And he explains that very well and he's a very polite person and he he comes across very easily. You know, it's very easy to like him and agree with him on his likeability, but is he also makes good sense. And I think one of the problems we have is too many other people that make good sense or grumpy and too many of the people that make no sense are very likable.
CHARLES MAX_WOOD: Yeah. Well, I don't know. I mean, I think a lot of it just comes down to personality and willingness to push on stuff. I find that some people have the personality of just not wanting to rock the boat. So even if they're right, they just don't want to go and say the thing that's true. But at the same time, I also find that other people, you know, they're willing to go out there and yeah, maybe they're a little more cantankerous and they're willing to go out and defend a hard to defend position or defend a correct position even though they know it's going to be a fight.
AJ_O’NEAL: Well, this is the funny thing in software development is that there are positions which are not hard to defend. They're extremely easy to defend. They are, they are borderline obvious. They are along the lines of if A then B, if B then C, then of course, if A then C. This is something they are, they are reductionist principles that applying the most base level of I don't know, I'm using fancy words. Let me, let me rephrase that and not sound so pretentious. So we get if a then B and B then C then of course, A equals C meaning if, if one cause creates an effect and that effect creates another effect, then the original cause will always create the final effect. This is the principle of the transitive property of geometry is what it's called. You. You learn this in middle school, although you may not remember it because you may have hated that class and it may have been really tough with all the triangles and all that.
CHARLES MAX_WOOD: Yeah, but the point is, is that some of these things go against kind of the common accepted way of doing things and there's gonna be some pushback and some people just aren't willing to, they're just averse to conflict, even if they're right and even if it's easy to defend.
STEVE_EDWARDS: Yeah, I've seen that in other open source communities. I can remember one discussion in particular and another community where they were trying, I believe the issue was trying to determine, well, actually it was across multiple issues, whether it was a new technology to be adopted or a way of doing something. And the complaint was that it was always the people who were the most vocal who got what they wanted, not necessarily what got the most votes or what had the best-
CHARLES MAX_WOOD: Or who made the best argument.
STEVE_EDWARDS: The best argument for it, right? It was who was the most vocal and whoever was the most vocal, and in some cases maybe well-known, those- the points that were being pushed by those people is what got adopted as compared to, you know, really looking at what is the best option and why.
AJ_O’NEAL: And this is something that confuses me a bit in the software industry. I know that there are things that are a matter of opinion where there is not one truth, but there are, this is what I would say. We don't know what the correct ways to do something are, but we know what the incorrect ways are. And that's what a lot of these are about. And there, there as much as about, can we exclude the things that we know to be incorrect that we know don't work as they are, can we tend towards the things that we know do work and tending towards the things we know do work, for example, explicit over implicit and convention over configuration. They're both correct, but they, they can be in conflict. They could be in concert, but they often end up in conflict because of the way that people who adhere to them and here to them so strictly and have a difficulty seeing that they can work in concert. But there are other things that we can know for certain do our best. So for example, if the implementation is hard to explain, it's a bad idea. We know this, we know that if you cannot explain it, then it's not workable. Now, obviously, if you're talking about the underlying DNS sec protocol and you're speaking to somebody who primarily writes scripts in Excel that makes sense. But within a peer group, if the implementation is hard to explain, it's a bad idea. And so there are, there are things that, and in JavaScript in particular, Crockford was really good on identifying here's things that we know don't work. We know they don't work. We know that they lead to errors. And he, he got a lot of pushback in that. I find that some of that's really, in fact, his, he opens many of his talks with a statement, he says, this statement should not be controversial, but for some reason it is. If there are two ways to do something in one way always guarantees success. And the other way can be useful, but often lends itself to confusing, unreadable or failing code only use the way that always leads to success. He doesn't say it exactly that way. I'm, I'm rewording his words a little bit, but this should, that should not be controversial. It should not be controversial that if we have two ways of doing something and one always works, that there is not value in investing in the other one. If you have a better option, why would you ever use the inferior option? But people do because they're like, Oh, I like the way it looks like, well, who cares how it looks. If, if you cannot transfer the knowledge of the code between individuals who are less intelligent than you, or not less intelligent, less knowledgeable is what I meant to say between people who are less knowledgeable than you and perhaps less intelligent than you, then, then you are writing code that is tending towards failure that you shouldn't do that. Yeah. By the way, I, I did find my, my draft of the joy of JavaScript.
CHARLES MAX_WOOD: Awesome. I'd be curious just to see what it is.
AJ_O’NEAL: So do you want me to read it?
CHARLES MAX_WOOD: Um, yeah. And then we've got to wrap up cause I'm, I've got a hard stop.
AJ_O’NEAL: So I may, I may censor myself on some of these because they're not, they're not necessarily right yet, but I don't think so. I mean, it's censor is kind of a strong word. I don't think anything's, I don't think anything here is really that contentious. We'll see. Number one. No one ever regretted not being a ninja. And this corresponds to G13. So I have each of these, I have marked with how they correspond either to the Go Proverbs or the Zenith Python marking with either G or a P. Code is easier to read from top to bottom than from left to right. And this was actually mentioned in the what I never use in Go talk, but I would put it with P6. And it certainly shouldn't read from right to top. And that is in reference to the way that Try Catch gets used. No one ever regretted putting constants on the left. P2, return or break early. And this goes in with the one Go talk about, don't use else. If you avoid using else, you will return or break early and you will have better code. Use as few braces as reasonable, keeps blocks as short as reasonable, never nest more than twice. And maybe twice is a little too aggressive, maybe three times, maybe thrice is what it should say. Never nest more than thrice. I like that, that sounds better. Let's go with that. And that's a little bit more generous and a little bit more easy to agree on. And that's P five and P six wet dry, but always aha. That's G 14. Duplication is far cheaper than the wrong abstraction. Now that is actually a quote from someone else. It's a abbreviation of a quote from Dykstra who is one of the fathers of programming or at least algorithms put gatekeepers at the gate, not at the doors. This is P three. This is in regard to security authentication, that sort of thing. Premature optimization is the root of all evil. That one's already taken. I don't think that should be there. Write code that the other half of the world's population could use. And this has lots of meaning, but in particular, there's the other half of the world's population from the people that are writing code that is not usable. Typically because there's so many dependencies and it's so large that they won't be able to get it on their connections, for example. My church has an app for the scriptures, for the Bible and some other scriptures, the Book of Mormon, Doctrine and Covenants and such. The app is a gigabyte. Its job is to display text on the screen. It violates this principle. It is intended for the entire world, and yet people who would be able to make use of it can't by the very nature of it is so large and so cumbersome to get that if they had a phone that supported the app, they would not have a way to use a connection to get it in a reasonable amount of time at a reasonable cost. For every set, solve the problem that is for just one item, then add a second function to do the loop. For every measure, countermeasure. Make prettier. That's G7. JS hint. G7 P3. Read me driven development. G17, G18. Also, this is the Stack Overflow guy. I think he had a, no, it wasn't Stack Overflow guy. It was GitHub guy. GitHub guy has a blog article on this. And 16 this is particularly JavaScript specific return something or don't return anything you see people writing confusing code where they return Next or return res dot end or they return something that has no return value and it's completely confusing because you might look at it and say well, what is this returning true is it returning false? What is the result of this return? Why are they returning this and it returns undefined? And so instead of putting something on two lines, they're putting it on one and making the code more difficult to read and understand. So you see that pattern all over in JavaScript, but you should either return something or return nothing. And then lastly, return a wait. And this is something that is controversial, but it's clearly not controversial. If you look at the consequences, as you are refactoring code, you are more likely to accidentally forget to put an await in code because you previously had a return and you needed to add a couple of extra steps. So you delete the return and then you add extra steps and you forget to add the await. So every function that can return a promise should be an async function, unless you are writing code for an interpreter that doesn't support async, in which case, you know, I totally understand that. But every function that can return a promise should async, and you should only return if you're returning something. And if you are returning something, you should return a wait, because this leads to code that is readable, understandable, and refactorable.
CHARLES MAX_WOOD: All right.
AJ_O’NEAL: Some of those were a little bit too generic to be in the joy of JavaScript, but it's just a little ditty I'm working on.
CHARLES MAX_WOOD: Cool.
STEVE_EDWARDS: That sounds very joyous.
CHARLES MAX_WOOD: Mm-hmm.
Hey folks, it's Charles Maxwood and I just wanted to jump in here and let you know about something that I'm doing. It's free. It's out there just to help you get answers to your questions about the things that you're running into with your career. So if you have questions about how to get further ahead in your career, how to start a podcast, how to get a better job, how to get a raise, how to deal with a situation at work with your boss, or just maybe you're stuck and you don't know where to go next. You know, how do I get from junior to senior, senior to whatever's next? How do I become a speaker? How do I get to the next level? That's what I'm out here to do. So every Wednesday at 12 o'clock Mountain Time, I'm gonna be doing a call and it's gonna be free, totally free. Go to devchat.tv slash level up and you can register for the call. It's using Zoom's webinar software. So it's pretty straightforward And what we're gonna be doing is I'll do 10 minutes and I'll just show you how I do some form of how I level up and then we'll just answer questions. And it's not gonna be a question and answer like, hey, what's your favorite flavor of ice cream? And then I say, rocky road or whatever, right? Instead, what we're looking for is more along the lines of, yeah, I have this situation, how do I handle it? I'm trying to figure this thing out, how do I figure it out? I'm trying to stay current, how do I stay current? And if you have any of those kinds of questions, I'll bring you on the call. We'll ask some deeper questions. We'll make sure we get you a solid answer. And I'm really looking forward to helping some people out. There will be no sales, no selling, no nothing on these calls. It is literally just 10 minutes of training and then Q&A. So you can go check it out at devchat.tv slash level up.
CHARLES MAX_WOOD: All right, well, I'm gonna go ahead and push us to picks. We're kind of over time. I definitely need to go take care of some stuff. So Steve, do you wanna start us off with picks?
STEVE_EDWARDS: Sure, I'll go with my dad joke for the day, which a little bit of exclamation Chuck and I have what is otherwise known as the chrome dome. I prefer to think of it as God made only so many perfect heads and the rest he covered with hair. But amen brother. So even though I have shaved my head for years, I still have a comb. I just can't part with it. And then also, you know, there's that whole fast and furious movie franchise, which I think nine is the most recent release. And I just heard that they're going to make a tenth iteration of that franchise. And they're going to call it fast 10 your seat belts. So those are my picks.
AJ_O’NEAL: I'm smiling, but you didn't quite generate a laugh.
STEVE_EDWARDS: Well, that's better than nothing.
CHARLES MAX_WOOD: You couldn't part with a laugh or a comb. OK. All right, go ahead.
STEVE_EDWARDS: He's got he has too much hair.
AJ_O’NEAL: The main thing that I would pick is this this list of the Creeds of Craftsmanship. It's something I reference bits of these quite frequently on the show. And this list is not hosted where I want it to be right now. It's just a get issue, but I think that that, well, you know, it works. But I know that I can be abrasive. I know that I have these strong opinions and sometimes that's a turnoff. So if you can just let your forgivingness or your whatever it is inside of you that looks over the flaws of others and, and is gracious enough to pick out the, the benefits that they have to offer despite their flaws. I implore you if you are, well, somebody that's listening to this podcast, you're involved in software to, to take a look at these, give them a glance over and give some of them a serious study. And as you're writing code, think about how it applies, think about what you can do, how you can avoid errors and how you can tend towards success. And if you do know of any other creeds of craftsmanship, I am going, there are a few others that I didn't go over at all, such as patterns and see closure rationale thinking and react. I don't know if that one counts or not. Scholar rationale. There's a few other ones that I know of, but if you know of some that I haven't mentioned, I would love it if you would make a comment on that issue and bring them to the fore because I'm always interested in, in seeing what else is out there. But. But please do take a look at these things because they, I don't know, I believe that they really will help you. And I believe that if we can tend away from these Twitter memes of HTML is a programming language and tend towards true principles of software design that help us be better as a community, and if we can find someone to lift up to be a great leader in that, it'll result in a better, sounds a little far-reaching, but it'll result in a better world. If we had software that was more accessible and more correct, it would result in, in a better world, more and people would have information to more knowledge, they would be able to use more tools and they would be able to rely on those tools. And I think that's, that's my plea. With that aside, there are, so I manage a couple of meetups, uh, somehow. I don't, I don't even know how that, that ends up working out, but I do. And recently, because of the way that the new meeting room that we're in is set up. We We had some trouble with the getting the TV connected and I've always had trouble with HDMI. It's it's because there's too many different standards. There's HDMI 1, 1.1, 1.2, 1.3, 1.4, and then there's the corresponding HDCP for every version of HDMI and every device in the chain always have to has to obey everything. And so whenever I get HDMI stuff, I've learned to try to get the best that's available, even if it costs twice or three times as much because there's a greater chance that plugging it into things will work. And it is, it is nigh unto impossible. No, it is impossible to find a HDMI certified coupler. If you need to extend an HDMI cable, those don't exist. Nobody has the cojones to, to certify their coupler, probably for a very good reason that if you have a coupler, it means that something is on the other end of the coupler, which means that your coupler is likely to fail an exorbitant amount because the cable on either side could have some slight mismatch in the hardware or, or built-in chip specification. Uh, but there is a brand called ZestKit and they do have certified cables. They do not certify their extension cable or their coupler, probably for the reason that I mentioned, but their other cables are certified and it appears that their coupler and extension cable live up to the same standards as their straight cables, but probably just don't get certified because anytime you plug something into something else, you know, then you'd get complaints and people would say, well, you certified this and you said, but you plugged it in something else that wasn't certified, you know, anyway, so I'm just going to put a link to the 10 foot HDMI cable from ZestKit and their coupler, because this is something that if you have had the struggles of trying to plug in things to HDMI and the screen turns green or magenta or it flickers or whatever, you know what I'm talking about. So for those of you that have that. There's, there's something that I hope can help you, especially if you're a meetup organizer or doing that sort of thing. And then of course, as always follow beyond code, if you'd like Facebook, Twitter, YouTube, uh, all right there. There's my personal live streams as well as the, the beyond code channel.
CHARLES MAX_WOOD: Cool. I'm going to throw out a few picks of my own. Um, I do want to remind everybody podcast bootcamp, podcastbootcamp.io also top end devs, we are doing the rebrand, got some stuff coming down the pipe. I'll probably announce it when I'm ready to, but I've got some pretty exciting plans. Also go check out JavaScript Picks, JavaScriptPicks.com. And as far as picks go, a few things that I want to throw out. One of them is I can't ever remember like which shows or which episodes I picked stuff on. I finished Masters of Doom, which is a book about the game development basically in the 90s and early 2000s through Doom and Quake 3. And it was a terrific book. I really enjoyed just the storytelling there. I have listened to a few other books since then that I'm also enjoying. One of them that I really liked was How to Get Shit Done by Sean Whelan. I try not to swear on the show, but that's the title of the book. So yeah, it was really, really good. It's like an hour and a half listen. It's really short, but it was really terrific. So I'm going to pick that as well. And then...Let's see, right now I'm listening to The Road Back to You, which is a book about the Enneagram. It's personality types and it's by Ian Morgan Cron and Suzanne Stable and it's pretty good. It's got kind of a Christian bent to it, so if that is not your flavor then you know that's fine. They talk a whole lot about different personality types and how they manifest and things like that. And anyway, I'm really enjoying it just from the standpoint of thinking about, okay, where do I fit? Where do people around me fit? How do I interact with people? They pretty well pegged a lot of my idiosyncrasies and I've really been enjoying it. So the road back to you. And then I know that there is a, I think it's the last book in the Expanse series is coming out within the next month or so. And so I started listening to Leviathan Wakes, which is the first book in the Expand series.
AJ_O’NEAL: Me too.
CHARLES MAX_WOOD: So yeah, digging those. So if you're into that, I'd go pick them back up again, but I'm listening to it on Audible. So there you go.
AJ_O’NEAL: Warning, there is some strong language in Leviathan Wakes, at least right out of the gate. I imagine there's probably some spicy scenes in there as well from what it seems to be alluding to.
CHARLES MAX_WOOD: Yeah, they curse a bit. They don't, I think they acknowledge that certain characters hook up with other characters. They, throughout all the books, you're aware of that. It doesn't get very explicit.
AJ_O’NEAL: Okay, good. It turns out in Lightbringer, well, my wife has warned me that there's some spicy scenes that are not as in as much detail as a good romance novel would be, but are more detailed than you might want to have playing in the living room with the kids.
CHARLES MAX_WOOD: Lightbringer.
AJ_O’NEAL: The Broken Eye, no not the Broken Eye, the Blinding Knife. Oh yeah. The first one was the Black Prism, the...
CHARLES MAX_WOOD: Yeah, yeah, some of those they get, it gets a little bit more. Anyway, yeah, good books though. Anyway, those are my picks and yeah, I'll go ahead and wrap this up. Till next time folks, Max out.
STEVE_EDWARDS: Adios.
Bandwidth for this segment is provided by Cashfly, the world's fastest CDN. To deliver your content fast with Cashfly, visit cachefly.com to learn more.