Embedded - 438: There Is Nothing That Is True

Episode Date: December 15, 2022

We talked with John Taylor about his book, how to handle data, and the open/closed principle of software development. John’s book is Patterns in the Machine. It was mentioned on Embedded Artistry ...and is part of their Design for Change course. John also has a blog (PatternsInTheMachine.net) and a github repo that is a companion to his book, showing the PIM framework. Transcript

Transcript
Discussion (0)
Starting point is 00:00:00 Welcome to Embedded. I am Alicia White alongside Christopher White. Our guest this week is an author, John Taylor, author of Patterns in the Machine. Hi, John. Welcome. Hello. Thank you for having me. Could you tell us about yourself as if we met at an Embedded Systems Conference?
Starting point is 00:00:28 My name is John Taylor. My day job is I am a principal software engineer for a medical company, Avanos Medical. I've been in the embedded space ever since college, about 30 years plus. And obviously, I've written a book, Patterns in the Machine, that we're here to talk about. And that's pretty much me other than, you know, I like doing this for, I write software even when I'm not working. So that makes me a serious software nerd.
Starting point is 00:01:02 All right. We do this thing called lightning round where we ask you short questions and we want short answers. And if we're behaving ourselves, we won't ask why and how, and are you sure? And what about, are you ready?
Starting point is 00:01:13 Yep. Should you trust the software folks? No, never. What is the best open-ended question? What is the best open-ended question? I think that one right there. What is your least favorite programming language?
Starting point is 00:01:32 That's a good question. I've been doing C, C++ for so long, I don't do much else. I guess C or C++ then. That's one way to look at it, yes. How often is the hardware late? It's always late. In fact, I just got the display for our board that I was supposed to have in June. And I got it Friday. What is your favorite fictional robot?
Starting point is 00:02:00 Robbie the Robot from Forbidden Planet. Which direction should you move the cursor? Move it to the right. If software is not soft, is hardware not hard? Hardware is always hard. And where does firmware come into that? Is it firm or not? It's mutable, but it's hard.
Starting point is 00:02:22 All right. Do you have a tip everyone should know? So, and you've made reference to it, there's a chapter 17 in my book, which is a bunch of rules for development that we sort of talked over. My favorite one, and this is paraphrased from Reddit from just a few weeks I found ago. Two weeks of coding can replace two hours of planning. That reminds me of something a co-worker used to say, which was, we don't have time to do it right, but we have time to do it twice. Yep. I've had people say that to me seriously,
Starting point is 00:02:59 and I feel like maybe they didn't understand the inherent sarcasm there. So patterns in the Machine. This sounds like a William Gibson novel. Is it? No, I am not that talented. That was just the title that I came up with. I'm not exactly sure how I got there. I just remember driving to work one day and by the time I got there, that was the title I had decided on. But to be honest, I really liked
Starting point is 00:03:35 the title and I think that's why I got publishers interested in the book, not because of its content, but simply by its title. It's a good title. But what do you mean by patterns? Patterns is basically just a glorified buzzword for best practices. And obviously, best practices is yet another buzzword. So it's really just, I mean, this is not going to be a short answer. Oh, I'm sorry. We're done with lightning round. Take as long as you want.
Starting point is 00:04:08 Okay. So best practices are really just ways of doing things that your company or you evolved over your professional career or you've gone to read books or gone to conferences that these are know, these are very similar things that everybody has to do. Here's what we've decided that works best from our experience. And that's really what the book is about is a bunch of patterns. They're not new or anything. The sort of what's different is the emphasis more on strategic thinking and strategic patterns versus tactical patterns. So it's just really just sort of here's a recommended way to do something that has produced results in the past for other people. You have something called the model pattern. Is that what it is?
Starting point is 00:04:58 Data model. The data model. Yes. What is that? That is, that's just the name I've got. Data model. Yes. What is that? That is, that's just the name I've got. It actually started when I worked with Carrier back in early around 2012, 2011, somewhere in that time frame. And they called it the data dictionary.
Starting point is 00:05:25 And they had actually borrowed it from some concepts from AutoSAR. We had a bunch of automobile refugees when we did some hiring in HVAC. And basically, you have data that exists and your system is data-driven. And nobody owns the data. The data basically is ownerless and it's unto itself and you can read and write and get change notifications off the data. So it's not necessarily anything new. It may be new on how it gets applied in an embedded system. Originally, when I first went first experimenting with it and doing it, it was like, oh, this is Model-View-Controller. Yeah, I was going to say, it sounds similar. Model-View-Controller has all sorts of different connotations to it. And that's changed over the years.
Starting point is 00:06:13 Yes, it absolutely has. So that's where the model part from data model comes from, is the Model-View-Controller concept, sort of the original MVC concept before it was bound up into all this GUI stuff. What about design patterns? I mean, it sounds a little like you're describing publish-subscribe, or is that not related?
Starting point is 00:06:39 It has publish-subscribe in it. So the core things of the data model are, one, it's type safe. People think, well, that's not a big deal, but yeah, it really is. So that's huge. The other is it's thread safe. So I can safely read and write model points regardless of what thread I'm in, and I don't have to worry about thread safety.
Starting point is 00:07:09 And then they have publish subscribe semantics. So a chunk of code, a module can subscribe to change notifications to a model point, which solves a lot of – it's a very good golden hammer. Sometimes I'll admit I abuse it when I really shouldn't use it that way, but it works well for a lot of things, the publish-subscribe semantics. And there's a lot of other things that you can do with the data model that's really handy. There's a lot of things, especially when it comes to debugging and troubleshooting, that the data model is very helpful with. So is this a design pattern? I mean, you said best practices. bugging and troubleshooting that the data model is very helpful with.
Starting point is 00:07:47 So is this a design pattern? I mean, you said best practices. Are these the same as what we're calling design patterns like Model-View-Controller? So the data model is more of a design pattern that you could think of like out of the Gang of Four book or whatever. And then obviously the book provides a concrete implementation of that pattern. Right. You have a GitHub repository. Yes. But it's got like a whole framework thing. Yeah. So the core of, so part of the book was, if you're going to have a book, you got to have example code, right?
Starting point is 00:08:29 Well, I didn't, but I understand that some people might want to. O'Reilly certainly wants me to. And so over the years, obviously, I've worked on this framework. I call it loosely the CPL C++ Class Library. And it's just a realization of a lot of things that are in the book. It's by no means the only way to do what I talk about in the book. But the core things of that framework is it provides a platform independent OSAL and then some very basic middleware type functionalities. And one of them is an implementation of the data model pattern.
Starting point is 00:09:15 So yeah, there's a framework there. Then there's an example thermostat application that's built on top of it. Part of that was to validate some of the original concepts of the data model and actually put into practice. So it's one thing to say, oh, hey, this is a great idea for a framework or a pattern. But until you actually use it in a real application, you usually find some rough edges that have to get knocked off and reworked and things like that. So you said OSOL, Operating System Abstraction Layer. Correct. So it's like a hardware abstraction layer except with any operating system, whether you're using FreeRTOS or Zephyr. Correct.
Starting point is 00:09:59 So it abstracts away the core OS primitives. So things like mutexes, threads, sum of fours, elapsed time, which unfortunately gets complicated on an embedded system if you want to be portable. So it's basic core functionalities like that. And so one thing I talk about in the book is being platform independent. And once you can do that, you can write automated unit tests. So if you have an OSAL, whether you run on Windows, you run on FreeRTOS, there's even a bare metal implementation of it in the library. So you can run if you're bare metal on the target. Um, and so it just, once you have that decoupling, it just opens up a lot of, um, flexibility on how you actually go about developing.
Starting point is 00:10:50 Um, I'm going to go off on a little tangent here. It's like I do on my day job, I do probably 85 plus percent of my work on the simulator, which is a functional simulator. Uh, you know, not a dedicated hardware simulator of instruction set or anything like that. And not just having to burn the flash every time is a huge time saver. I totally agree. And having an offline simulator is so important to me, especially functional.
Starting point is 00:11:22 I don't necessarily want to test the spy flash driver on a simulator. Right. But I do want to test my KV store if I'm using a little database or EEPROM-like thing. Right. So the functional simulator isn't about hardware performance
Starting point is 00:11:39 or anything like that. It's just if I can exercise my app, and yeah, I'll worry about the performance you know once we get on a target and like once oh i finally have my lcd so i can see my ui on the target you know we've developed a third of our ui and have never had an lcd yet for the target um so um anyway i'm i can talk a long time about the benefits of having a functional simulator. I tend to agree, and there's many, many projects. I wish I had one.
Starting point is 00:12:10 But if you don't do them early, it's often too late in the project. Like, I've come into many projects where it's like, where's the simulator? Oh, we don't do that. Right. And that's the point. That's absolutely. It's really easy to do from the very beginning and almost no extra overhead. But if you try to retrofit it in later,
Starting point is 00:12:31 it's almost impossible depending on how later later is. So it's one of my claims of you can do things the right way and not take longer. So it's not hard to build a simulator. It doesn't add any extra work to build a simulator. It just requires more extra planning up front. While we're on that subject, how do you like to build simulators? Is there a platform or framework you go to or do you build from scratch? It's just built.
Starting point is 00:13:01 So my approach to building simulators, once you have the OSAL, you can run on any r toss on any operating system right um and since it's functional you don't really care about the real time part of the os so you can run on windows or linux for your simulator um and then you just do when it comes to the hardware you just do things on a case-by-case basis. It's like, oh, I've got extra off-board EEPROM. Do I want to try to simulate the SPI driver, the I2C to it? Probably not. Do I want to simulate the command set to the E2? Probably not. But there's another layer that says, oh, I'm going to read and write to the EEPROM. I'm going to give it an offset.
Starting point is 00:13:47 I'm going to read so many bytes or I'm going to write so many bytes. That layer is very easy to write a simulator. You just replace the EEPROM, the reads and write, with just file operations. So you just do it on a case-by-case. So like I talked about our project with the LCD, our graphics package provides a Windows simulator. So didn't have to do anything there other than utilize a feature that came with the library. And some features, you know, you don't simulate
Starting point is 00:14:13 because it's not worth doing. So there's not a framework per se other than you just, the only minimum framework is that you have an OSAL that really is platform independent. And you just go from there. It's like the console UART. You use standard IO on the simulator for your console UART. Philip Johnston over at Embedded Artistry wrote a blog post about the open-closed principle.
Starting point is 00:14:41 And he said that your book was important for that and that he actually modified one of his courses, the Design for Change course, after thinking about how you put together your open-close principle. What is that? So the open-close principle, I don't have the text in front of me. It's basically says something like, your code should be open to extension, but close to modification. So at a high level, what that means is instead of
Starting point is 00:15:19 editing existing code to add new functionality, you just add new code um if you look at what the if you look at the if you go in a wikipedia or go to other people's um more definitions of what open close is it's basically talking about putting in interfaces um and then you know decoupling clients from the implementation. For me, I somewhat take the open-close principle pretty literally. So my claim is if you write decoupled code, your code is change-tolerant. And if you're change-tolerant and you're decoupled, then if you want to add something new or go in a different direction you're not editing existing code you're just
Starting point is 00:16:11 adding new code you may be throwing some old code away but you don't go in and hack up the existing code um and if you build things that way and and there's sort of an art to it. I'll go into that a little bit. What that does is basically now you're building your application by basically off an a la carte menu. It's like, oh, I need an egg roll. Let me go grab an egg roll. Oh, I want a taco. Let me go grab a taco. I apologize. I'm winging my menu metaphor off the top of my head. But what you want to do is when you build a widget, you want to break it down to, you want to, first off, there's first thing you want to do is you want to separate on how you create the widget from how you use the widget. Because usually when you create a widget, there are some very specific things,
Starting point is 00:17:02 some very dependencies that you can't get rid of. So take for example, file operations. A read-write operation on a file is pretty generic, has very little dependencies if you look at the actual function signatures and the data types that you need, right? So it's very easy to have a very abstract read-write interface to a file. But when you go to create a file, that gets pretty complicated, right? Oh, it's a file name.
Starting point is 00:17:32 Well, is there a path in the file name? What's my file system? Do I have forward slashes? Do I have backslashes for directory separators? Do I even have directory separators? So if you can separate creating a file from how you use a file, then that lets you basically, by doing that, and I know I'm sort of meandering, you decouple the usage from how you create it. And then what that means is, and I talk about this in the book, it's called the main pattern, pretty unimaginative name. You basically, you push all the high dependencies to one spot, basically one place where you
Starting point is 00:18:19 create everything, and then you wire all these sub components together. So you pass people reference to a file instead of passing them a file name. This is just a rough example. And so your main code isn't reusable and yeah, it's platform dependent or at least parts of it are to a certain extent. But that's a very small portion of the code.
Starting point is 00:18:45 That's like 3 portion of the code. That's like, you know, 3% of your code. And the rest of it is independent and doesn't have these dependencies. And so what that means is, if you want to add something new, you're not going to go in and, you know, now I have a new file that now runs on little fs on my board um i don't have to go in and hack up anything i just add a new instance that knows how to use the generic file read write and it yeah it has a specific create but i can pass now an instance of my interface implementation that runs on little fs just as works just as well as if I was passing it a POSIX file or a Windows file handle. And I'm sort of... But what I was trying to get at is
Starting point is 00:19:37 if you want to add new things, set your code up so they're adds, they're not rework into the core code. Now, that main code that I talked about that has all those dependencies, you don't waste your time trying to make that generic. You just say, okay, this is specific to this platform, building this variant of the product, and you just leave it at that. That actually was going to be my next question about how much effort do you put into this? There's the, I mean, there's another concept that you aren't going to use it. Idea of don't overbuild your code.
Starting point is 00:20:18 How do you balance that with the open close principle? So from my perspective, first off, 80% of your code is never going to change. 20% of it is. You know a good idea of what some of that 20% is going to be, but the reality is you don't know. So for my perspective, the easiest way to deal with it is you just assume everything can change. But at the same time,
Starting point is 00:20:45 when you go to, okay, it's like, okay, I want to have a generic read-write file interface. Coming back to that, don't spend hours or days trying to figure out, well, what is the best general purpose,
Starting point is 00:21:02 best abstraction ever for that? You say, no. What maps, how can I define an abstract interface for my persistent storage that I have on my board that I won't need any glue logic to convert that interface into my implementation? So basically, you build it for what you have. You put those interfaces in and those
Starting point is 00:21:26 semantics of the interface may you know are going to map one-to-one with your platform but you still have that interface and once you have that interface that's your decouple point so don't spend time trying to come up with the one rule you know one interface that's perfect, do one that gets you the decoupling that is very lean and easy to implement for your platform, and then worry about the second implementation or the third implementation later when you get there. Because a lot of times, you never get a second or third implementation. Sometimes you do. Processors get changed in today's world, right, with the supply chain issues. That was kind of an interesting exercise in what we usually think doesn't change. I mean, I've seen companies that are just always microchip, always ST, don't change the chip.
Starting point is 00:22:19 And then suddenly they're changing the chip and it's really traumatic in different compilers. Do you have anything that can compute? Right. Yes. I mean, there's advantages. Well, today you don't really have a choice. But there's advantage to staying with a particular tool set because your EEs are familiar with it. You're software guys.
Starting point is 00:22:40 You learn the nuances of the chip. It's one less tool set you have to learn. But if you assume you will always use the same micro, you can't do that anymore, at least not on new designs. That would be very foolish. So the CMSIS ARM interface, does this fall under the patterns that you like to see? I mean, it does abstract a lot of the operating system away as well as the hardware. Yeah.
Starting point is 00:23:11 So you're talking about the CMIS from ARM? CMSIS. Yes. But yes, we're talking about the same thing, whatever the letters are. Yeah. So that's ARM's attempt to provide some basic OS abstractions. And there's nothing wrong with that. Though, in my experience, none of the available, whether they're open source or commercial, RTOSes really take advantage of it.
Starting point is 00:23:41 There's usually some reference. If you look at FreeRTOS, there's a little bit in there that they utilize that for. But I'm not saying you have to use PIMS OSAL. You just need an OSAL. And if the ARM one works for you, great. What I am against is, and I can't remember whose it was, but they define their OSAL by their particular implementation. There was no definition of, here's the interface. They just, okay, here's on Win32, here's what it is. On this hardware, here's what it is. Win32, here's what it is. On this hardware, here's what it is. And on Linux, here's what it is.
Starting point is 00:24:28 And yes, they all had the same methods at the end of the day, but there was no one definition of what the OSAL was. There was just implementations of it. And so if you're trying to figure out, well, what's the source of truth for how my mutex is supposed to work? You didn't have that. All you had was, oh, the mutex API is the same function signature across all three RTOSs, but there was no definition of the semantics for it. So if you're going to do something, if you're going to have an abstract interface of whatever kind, whether it's an OSL or something else, the key thing is you need to define the semantics for it.
Starting point is 00:25:09 And there needs to be a single source of truth for that. And that really should be, as I talk about in the book, that needs to be in your part of your header file. So for you hardware guys out there, I'm a firm believer that when you write documentation for your software in the header files, ideally they read like data sheets. They're not just, oh, here's the syntax, but here's what's expected of them. Are they thread safe? Are they not thread safe? Who owns the memory? Who doesn't own the memory? Does the caller have to supply it? Things like that. So a lot of people have asked me how do I define an API
Starting point is 00:25:45 or an interface, if that's what you want to call it. If you have a pile of code and you have some ideas of what you want it to do, how do you get from here to there? While following
Starting point is 00:26:03 the open-close principle and making good APIs? Well, so this is, there's a lot of questions in that question. Oh, oh, this is a whole career, yes. Right? So it all, I mean, there's two ways you can do it. You can go top-down or bottom-up, or you can do a combination of top-down and bottom-up. So you either start at the top, and you start your big bucket,
Starting point is 00:26:30 and you start breaking it into smaller buckets, and you just repeat ad nauseum until you get down to something that ends up being at the code level, right? The other is you can start, well know i have this cpu and i know i have this and i'm going to have these mini i squared c peripherals and these bi peripherals and i'm going to have these a to d so i know i'm gonna well i'm gonna need drivers for all those and you know my you know this i squared c is know, a humidity sensor or a moisture sensor. And so I'm going to need something for that.
Starting point is 00:27:08 Right. So part of this is how do you decompose a big picture into something manageable? And that's to be honest, I've been doing this so long, it's hard for me to think. I can get to A to Z quick because it's like, well, I can go from A to D. And then from D, I can go to J because I've been there, done that. And then I can get to Z pretty quick and I don't think about it anymore. So that's hard. Now, I'll back up a little bit.
Starting point is 00:27:47 And so let's say we talk about the driver up. We're doing a bottom-up design. And this, once again, I've done this enough, so I'm going to say this is a way to do it. So one of the – I'm going to come back to the model, data model, is one thing, and I don't talk about this in the book, but how you write drivers and how you write application code is two different ways of doing things. This was very apparent when I was at Carrier and we were looking at the AutoSAR stuff.
Starting point is 00:28:20 They have very specific rules and layers when they come to doing drivers and all that kind of stuff. And there's a reason for it. That's different kind of, your concerns are different when you're writing a driver or a comm stack or anything, something like that versus an application. So one thing that data model is very good about is you can decouple your application from your driver by putting in model point instances. So if I have a driver that reads 12 A to Ds, it can read those A to Ds, do whatever filtering, however fast it needs to do it, all that,
Starting point is 00:28:58 and then dumps the final result into a model point. And then the application just reads the model point. So an application can get an A to D value without having to know anything about the driver. So one thing, so if you're starting from the bottom up and it's like, well, first off, you should have done a system architecture. We'll come back to that. And if you're doing a bottom up, it's like, oh, I've got to get this data, whether it's inbound or outbound. If it's inbound, I'm going to read this data, stick it in some model points based on my
Starting point is 00:29:30 requirements, and I'll be done. And then if it's outbound data, I'm going to like, well, I'm going to get the source values from the application. It's going to write into these model points. I'm either going to pull it or get change notifications, and then I'm going to go drive them out on whatever the physical hardware interfaces are. Anyway, so blah, blah, blah. I don't think I answered your question. whatever requirements, because you never get all the requirements at once. And to take that and then to try to figure out how to decompose that
Starting point is 00:30:08 into something that you can actually implement. I want to go back to the model for just a minute, because I really like the idea. And like you said, it's similar to how modern applications on desktops and mobile are often architected, where there's a model that is the business of the application, but it is not the thing that is necessarily displaying or moving the data. But embedded, sometimes we have a lot of performance requirements
Starting point is 00:30:37 that require us to do DMA or to have things be as low-level, autonomously shipped from one end of the program to the other without a lot of layers in between. How can that be squared with the model? So say I'm doing something with networking where I have high performance and I've got an interface on one side, I get packets in, I've got to do something with them and route them out to another interface,
Starting point is 00:31:02 and I have to do that as quickly as possible. It strikes me that shoving that in a model and having somebody grab it out and do stuff would add a lot of latency. Is there a way to have model and non-model kind of things side by side, or is there another way to square that? Oh, yeah.
Starting point is 00:31:19 So to your point, the data model only works for certain things. If you want to, like, if you're pushing a lot of bandwidth or you're pushing something very fast, the data model isn't really appropriate. It doesn't really work for just some of the reasons you just said. And that's fine. It's not an all or nothing thing. Yeah. Right?
Starting point is 00:31:48 So some of your data, by the time it gets to the application, there's no performance. There's no real-time, super real-time performance that your application can't meet or it's you're not moving you know you're not streaming out you know uh a video stream where you've got this constant data going out sure um so like on one project i worked on that we used the data model is we to provide the data that would go into the outbound. We would end up actually eventually doing HTTP requests. But that was all handled inside the modem. And so we had this stack and so we had a separate interface to that whole modem which was you know it was a itc inter thread communication that was complete that was separate
Starting point is 00:32:51 from um the data model so if we wanted to issue an http request or get notifications of the response that was through a different kind of mechanism but you, you know, basic config data, things, data that was not necessarily static but didn't change very often, when we were building or parsing those HTTP requests or fonts, they would get stuffed into, either pull from auto points or get stuffed.
Starting point is 00:33:19 But trying to actually do the HTTP requests or do the responses, you know, you use whatever is appropriate. In one example, we had to stream data between the off-board real-time processor and the Linux GUI board, basically. That interface, you know, had real-time requirements and all that. That was not a model-based interface, a model point-based interface. That was a data-packet-driven interface.
Starting point is 00:33:55 And yeah, some of the data that went across there ultimately either came or was sourced from or stuffed into a model point. But the thing about PIM is it's very much it's not you can only do it this way you do whatever way makes most sense for whatever that is and if you end up having you know multiple if you have multiple sort of like sub architectures that's okay with the one caveat you actually thought about it ahead of time and decided that's okay. With the one caveat, you actually thought about it ahead of time and decided that was okay and not necessarily just, oh, I ran into a new problem. Let me figure out how to, you know, I'll solve it now. That brings me back to, you really need to do your software architecture first. And that's a true waterfall activity before you get into detailed
Starting point is 00:34:41 design. And those kinds of things would have been addressed in architecture because one of the things you want to do in the architecture is, what are my real-time constraints? What performances do I have? What issues do I have about RAM? Do I have enough to do it this way? Or do I need to really save every bit and byte of RAM? Does your book talk about how to do software architecture?
Starting point is 00:35:07 Yes, I'm pretty sure there's a chapter in there. So in there, my definition of software architecture was pulled from somebody, I can't remember the reference, but it's the important bits. and so it's not that there, that it always looks like X, Y, and Z. It's like, what, what, basically, what, if you, after your project was over, what were those, what, if you do a post-mortem on it, what were the really important aspects or what you, what you had wished you hadn't had to change by the time you were done. Those are the kinds of things that you need to talk about in your architecture. So if you have some real-time performance requirements, those need to be discussed in your architecture document and how you're going to address them. And the easiest way for me is,
Starting point is 00:36:01 let me start with my hardware. Let me go down all the every hardware interface and say, what am I going to do with this? And what is its real-time performance? Oh, it's relatively slow, so I don't need to do a DMA driver for it. And it's like, well, no, I've got to sample my A to Ds at 2 kilohertz, and I've got 12 channels I've got to sample. I'm going to want to DMA that and set that all up, and I need to make sure that nothing else in the system is going to prevent that, and if there's any limitations on how much jitter I can have and those kinds of things. So those are the kinds of questions that you need to think about.
Starting point is 00:36:44 And I'm just talking about drivers. I mean, that's easy when you talk about embedded systems to focus on the hardware-specific things, but there's other aspects to your application that you need to talk about. You need to ask the question and then say, yeah, this is a concern, or no, it's not, or it's somewhere in the middle, and this is how, in general, we're going to address it. So when you say architecture and postmortem, and you mentioned not necessarily being able to describe how to do the layering of an API,
Starting point is 00:37:23 how does your book help people who haven't been through it? Or is it for engineers who have already been through a project or two and are looking for more information? So it's not a beginner's book. It's more of an intermediate. It's definitely for people that have at least done a embedded project. So I don't go into, you know, it's not a book on, it's not a recipe book. It's not, you know, here's a template for this kind of document or whatever.
Starting point is 00:38:04 It's really talking about, here are things you need to think about and you need to put some focus on strategic thinking and those problem-solvings before you jump into the tactical. What made you decide to write a book? I honestly don't remember. I do remember, so this all happened around the COVID timeframe, slightly before, is I just decided that I was going to write a book.
Starting point is 00:38:38 Sort of knew what it was about, not exactly. And I was going to do it whether I had a publisher or not. Even if I had a self-publish, I was going to go ahead and finish it. And so it just went from there. It took about probably about a year and a half from start to finish. Now, all that said, I'd been working. I pulled from my cold bases. I had been doing the example thermostat app in my spare time, you know, for years. So this, it may have took, you know, less than a year and a half to go from, okay, I'm writing the book to having it published. It took decades of source material to get there. What books, blogs, or
Starting point is 00:39:24 conferences have been influential for how you think about embedded system development? So I am a computer science graduate. I am not an EE, but I've only done embedded. That was my first job out of school. So if you remember embedded systems programming when it was the magazine circa 1990s and when embedded system conference was a conference in person, COVID pretty much killed that. I think it had started to go away before COVID, though.
Starting point is 00:39:59 So things like that. One of my my second job out of college, I was working for Allen Bradley up in Wisconsin, working on their industrial automation. And their group had complete, if you remember back in the methodology war days, there was a methodology called Schleyer-Miller. And so they were really into C++ and Schleyer-Miller methodology and they sent everybody off to training and we had all these case tools. And so that was my big exposure to C++
Starting point is 00:40:38 and object-oriented and all that. And if you aren't familiar with Schleyer-Miller, which most people aren't, one of its key tenant was, it was, their approach was, it was a translation step from design to code and not an elaborative step from design to code. So basically they were advocating,
Starting point is 00:41:00 figure out all the problems in your design, solve the solution in design. And then once you've done that, if you the end all be all the case tools you could push a button and your design documentation they could you know auto generate the code they never got to that point but you know that was the idealized um concept that they had so that was a big influence on me. Another was my first boss out of high school, not a high school, out of college. He was, he was a really, he had a lot of patience with a new grad. Let me put it that way. I have some listener questions from William. What is your take on Rust? Although I feel like that may be kind of a bait,
Starting point is 00:41:52 given that you have a blog post about that. So, yeah, my problem with Rust, well, Rust itself, I don't have a big problem with. Anything that finds errors at compile time is a good thing. My problem with Rust is the problems it solves, I'm trying to figure out the best way to say this, is I don't see those problems day to day. So I can't remember
Starting point is 00:42:23 the last time I had a data corruption issue due to threading. 99% of my designs do not do dynamic memory allocation. Yes, there is an occasional error but memory errors are not um you know they're very infrequent so all the things that rust pitches that it solves um those aren't the big ticket items when it comes to the problems we have in the projects i work on so part of it was part of it is Rust solves some problems, but it's not solving problems that I have on a day-to-day basis. Those problems just aren't there. I mean, yes, there are bugs that fall into those camps, but they're the exception. They're not the rule. And then the other complaint I have about Rust is, at a big picture, I see this as companies and big tech basically wanting to commoditize developers. They want the lowest cost engineer. And so instead of realizing that, oh, software is hard and there's a certain,
Starting point is 00:43:49 you know, certain skill set, certain ability that you need when you hire engineers, they want to get it dumbed down enough that anybody and everybody can write software. And then basically now we're the equivalent of McDonald's. I'm going to push back on that a little bit. Have you tried to use Rust? No, I have not. It is not for people who don't know what they're... I have tried to learn some Rust and it is extremely difficult.
Starting point is 00:44:14 One of the key Rust phrases that I've heard from people who really like Rust is that it is hard to write bugs in Rust because it's hard to write Rust. Yeah, I agree with a lot of what you're saying, especially on the, you know, solving problems that maybe aren't applicable to all situations. And I think they're sort of situating themselves to safety critical or security focused things, you know, where you really don't want people things, you know, where you really don't want people having, you know,
Starting point is 00:44:48 any buffer overflows because that would be a disaster and would lead to privileged escalations, things like that. Which may be not what happens on a small control system somewhere. So, yeah, like you said, it's not applicable everywhere. But it's not easy.
Starting point is 00:45:04 It's not an easy language. Well, and that makes, actually, that makes a lot of sense. Because when I look at the projects I've been on, the issues don't go away. How do you own, you know, you have to pay attention to thread safety. You have to pay attention to who owns the memory, right? How do you make sure you don't have buffer overflows? Those issues don't go away in a language like C, C++. It's just those burdens are shift to your design. So if you have a crappy design, you're going to have those problems, right?
Starting point is 00:45:40 So it's still hard. It's just that- Moving the hard around. Right, you're moving the hard around. You're moving it from okay here's the language I've been using for 20 years how do I solve the problems or here's a brand new language that's different
Starting point is 00:45:54 that prevents these problems or poses a model on you that then prevents those problems but I claim that even if it prevents those problems it still leaves me with the ones I face today. So, I mean, we had a race condition. In fact, there's a race condition in the model points in their published subscribe. It's not a data integrity issue. It's an issue of
Starting point is 00:46:20 how the observers get synchronized with the data point value. And if the data value changes very fast or changes at exactly the right time, your application appears to get a double notification. Right? So there's a race condition, what I consider a race condition, but it's not something that Rust is going to solve.
Starting point is 00:46:46 It's a problem that the definition of the interface and the semantics of it wasn't correct. So I do have a fix for that now. But so it's like, okay, if I spend all my energy to learn Rust, it gets rid of the class of bugs that I already have, but I still got to deal with the bugs I already had. I don't see... Anyway, I'm not saying I'll never do Rust. I'm just not in a hurry right now. Fair enough.
Starting point is 00:47:18 Fair enough. We'll still get emails, but that's fair. We won't send them on to you. We'll absorb them. We'll put them in our rust bucket. William also asked, when you see good
Starting point is 00:47:35 patterns used technically correctly, but with no thought put into the usability of the product, creating a poor user experience, what do you do? He goes on to say usability of the product, creating a poor user experience. What do you do? He goes on to say that we've all used software and hardware that's a technical marvel, but is awful to use for anyone who's not an engineer.
Starting point is 00:47:58 Just to give you more. Yes. And one of my pet peeves on that one is it's a little better now, but if you've ever owned a Ford and the Ford Sync, that user interface for the Ford, especially like the first two or three generations, is horrible. Unless you have like the super top-end screen size. I don't know if you're familiar with that, with the Ford Sync interface. I think I accidentally used it in a rental car once.
Starting point is 00:48:28 It's just horrible. And I can see where it makes perfect sense to an engineer, but it makes no sense to your typical driver. I'm an engineer and I don't understand it. So those, I mean, the moral of that story is you don't have your engineers design your user interface because you're going to get a user interface that makes sense to an engineer and they are so not the demographic of your end product. So how do you do that? That's really your your project your company what they're willing to how are they going to resource your project right if they're not willing to pay for somebody
Starting point is 00:49:15 for industrial design or design factors um you're you're going to get what you get uh and one last question about your book. You wrote your book with your brother. Christopher writes music with his brother. What was it like writing a book with your brother? It went actually pretty smoothly. I mean, I don't have anything to compare it against. I will say when we were growing up, we did not get along as young kids or teenagers or even early college.
Starting point is 00:49:51 We just did not get along. But we had been, you know, we both got off married and gotten married and been physically separated. And then we just sort of, when we came back together, I guess we forgot why we didn't like each other. I don't know. Um, but it worked out really well. Um, you know, shortly before we wrote the book, uh, Wayne and I actually worked at the same startup together for a while. Um, I left, um, shortly before we started reading the, uh, writing the book. Um, but, um, it went really well. Um, I mean, I know my limitations as an author, you should have seen it in the emails. Um, so if Wayne had a suggestions like, okay, fine, I'll take it. Uh, I'm not going
Starting point is 00:50:42 to push back. One of the things he would always sort of push back when I was generating content was don't write a API reference book. You're writing for, you know, it's not so much you need, you need to keep the readers engaged. And so it's important to get ideas and concepts across and not worry about if that sentence is 100% factual in all cases. Does that make any sense? So much sense. I mean, that's the problem with embedded systems. There's nothing you can say that is 100% true all the time.
Starting point is 00:51:20 Right. I mean, use DMA. No, there's plenty of places where you should absolutely not use DMA. Use a watchdog to keep your system more stable. Well, yes, but don't let it kill you when you're doing over-the-air transfers because then you'll die and it ask questions, and I answer them, but I always have to say, well, in most cases, in general, for most of the things I've worked on, except for some cases, it's just there's nothing that's true. Right. And I would want to put all these qualifiers into one sentence. And he's like, no, don't do that. So, but anyway, but, and really Wayne is actually a lot more interesting than I am. He's, um, his sense of humor is, is just, I mean, it's a little dry, but he's hilarious. So if he had been on this call, he would have
Starting point is 00:52:22 kept us entertained. Um, I Actually, I do have one more question. What is your favorite part of the book? Obviously, the chapter 17 was a fun chapter to write. And so the Tao of Development, or I forget what the title is. After proofreading the book so many times i have a hard time reading it um over again it's been a couple years now um i really enjoyed writing it all uh like i say it was and wayne you made a comment it's like he really because he's done co-author stuff with other people before um i sort of knew what i wanted to say um and so um just once i was out on paper it was like okay we're good um so it was a really interesting experience um i do i a lot of i will i plagiarize myself at work. I will sit there and copy paste stuff out of my book into documents.
Starting point is 00:53:30 Or if I'm having to write up a how-to or something, I'll grab a paragraph here or sentence here and paste it in. So part of this is just all this stuff that was in my head now that I have it on paper. I don't have to keep remembering it all. Oh, yeah, I do that too. Also, if you go to an in-person interview and you take your book in your bag, there's plenty of fun with pulling out the book to answer a question.
Starting point is 00:53:57 See here in my book, I wrote how did you solve this problem? It's just brilliant. Yeah. Well, John, do you have any thoughts you'd like to leave us with? So I was thinking about that. And obviously, there's a lot of different topics in the book. And there are rat holes you can go down. But I would say, and this is, it frustrates me at work because I just see history repeating itself over and over again. So my hiring thought would be, you don't have to settle for the status quo.
Starting point is 00:54:38 You can write quality, robust software in the same time or less than just sitting down and hacking it out at the keyboard um and i i wish i was able to be able to convey that in such that people can understand that and like go with it but my practice until somebody actually is exposed to it and has that light bulb moment they don't get it. But you don't have to settle for the status quo. We can write software that is change tolerant in just the same amount of time or less than writing crappy software. Our guest has been John Taylor, author of Patterns in the Machine, a software engineering guide to embedded development.
Starting point is 00:55:28 He also has a blog on patternsinthemachine.net and he is a principal engineer at Avanos Medical. Thanks, John. Thank you. Thank you to Chris Turr for producing and co-hosting. Thank you to our Patreon listeners lab group for questions. And thank you for listening. You can always contact us at showitembedded.fm or hit the contact link on Embedded FM.
Starting point is 00:55:49 And now a quote to leave you with from Jeff Atwood of Effective Programming, more than writing code. As a software developer, you are your own worst enemy. The sooner you realize that, the better off you'll be.

There aren't comments yet for this episode. Click on any sentence in the transcript to leave a comment.