 I'm Brian. Today's talk, I'm going to be talking about message-oriented programming. Hello. So a few things about me. In the Ruby world, obviously I'm a Ruby developer, otherwise I probably wouldn't be here. I've made a few things. One was obvious architecture, which had the distinguished thing of being called by DHH maybe some of the worst code he's ever seen attached to Rails. So that was pretty exciting. Thank you. Last year I did the Ruby web benchmark report, which is the most comprehensive hello world web app benchmark ever made in the Ruby world. I tested every framework, every runtime, every server that I could find. It was sort of crazy thing. So I kind of tend to obsess and worry about things that most people don't worry about. If you want to follow along with more of my adventures, there's my website, there's my Twitter. I also like puns. So if you follow me on Twitter, you'll get a lot of those. So why this talk? Why are we talking about message-oriented programming? So our code is broken. How many of you have broken code? How come some of you don't raise your hand? But we make some fragile, terrible broken code all the time. And so we should write better systems. We should write code that doesn't have so many broken windows. You know, we give XP and Windows a hard time, but that thing's been going on for like 10 years and people still want to use it every day, which is kind of amazing despite how terrible the code is. And the other reason why we should write better software and better systems is this is a picture of me and my family. And the software that we write is the stuff that our family and our kids are going to use. And I know that a lot of us write web apps and things, but the thing is that the software that we're writing is going to be powering things like life support systems, traffic systems, airline systems. Over time, software needs to be reliable and it needs to be safe. And frankly, a lot of our broken systems cannot be classified as either. And if you want to know just how broken our code is most of the time, watch the Watt talk by Gary Bernhardt. I probably said that wrong, but it's amazing. And he talks a lot about how just broken software is all the time. So a lot of times when people start talking about broken software and they start talking about how to make better software, they talk about object-oriented programming versus functional programming. And it's usually set in opposition like a fight. And the thing is, is that it's an argument about organization. That an object-oriented programming, you use objects and classes and polymorphism and so forth to solve a certain kind of problems. And functional programming, you use data, you use recursion, you use functions, closures, monads, all of those things. But really, you can write object-oriented programings that solve the same problem as functional programs. And so really, if you think about it, it's an argument about big versus small. At least I think that in functional languages, they tend to focus on functions because functions are small. I think you use a lot of small pieces to build bigger things. Whereas in object-oriented programming, a lot of object-oriented programming has been used successfully in, say, enterprise where you want to send a lot of average developers at large systems to write a lot of code. And so you have just a bunch of objects and code and stuff piled in a mess. And it tends to be big. Even a lot of our complaints about objects and what we consider bad design is really that objects tend to be big and we have big methods and so forth. So it's really big versus small. But I don't think that that gets to the real root of the problem when it comes to reliability of our software. I think that they're missing the point. Because both are still fragile. Both are still fragile, but sometimes in different ways. And they're both fragile very much around bad input. Because bad input is all around us. You cannot control user input no matter how hard you try. It is all around us and we all know it. We've all felt it. SQL injection, cross-site scripting, buffer overflows, nil, Furbian and microwave. We know what bad input looks like. But it's even in the database. Now how many of you think about the database as a source of input in your program? There's like 10, 15 hands in the audience. So the database is as much a source of input as the keyboard or a button click in your system. And here's the problem with bad input, even from the database, is that a lot of times bad input turns into bad output. Because when we have a bad input value, sometimes we have an error screen. Maybe we have a 500 page, something like that. We've all gone to a website with a 500 page. So you know, you get bad output. And I don't want to go to a website with an error page. If I type some value in, I want to get a working piece of software. I want to get a proper result. And then when you have bad output, say that bad output makes it into the database. Well, now the database is part of your input. So you keep having this cycle of bad input to bad output to bad input to bad output. And that is what a lot of our code ends up having to fight against is you have these little bits of bad input floating around your system. And as you have a bunch of components talking to each other, once the bad input happens, stuff starts to break. And then you see, you know, your standard error pages and those Rails error dumps and all that stuff. So let's go back to a building block. A simple thing that we all understand. And it is one of the most fundamental parts of programming. Input, processing and output. How many people in this room understand what that is? It should be everybody. Because it's a simple idea. You put some input in, something happens, and you get a result. Not much more explanation needed. So how many people have probably written, not Hello World, but the hi, my name is X, and then you type it in and you hit enter, and then it says like, hi, my name is Brian, you know, command line app. It's probably the second or third thing that we all wrote. So we've all done that really simple notion of input, processing and output. How many people have played Minesweeper? You know, you click a thing and yeah, a couple big fans up here. You click the button and if it blows, if you hit a mine, the thing blows up, you lose the game. Super sad. But that's again, input, something happens, output. Calculator. We all almost intrinsically understand how this is. Because you put like one plus one equals and then output, input, processing, output. What about the web? We don't often think about the web in terms of input, processing and output. We think about it in terms of frameworks. We think about it in terms of rails. We think about it in terms of all this stuff. But the web, you know, we have this request response pattern that defines the web. We have HTTP. We have RPC. We have JSON APIs. And it's really simple. You have a browser. You type in a URL that goes to a server. The server does some processing and it gives you back a web page. Magic, right? That sounds an awful lot like input, processing and output to me. And in fact, I would argue that they're pretty much the same thing. So really when we're building the web, we are doing not something that different than, hello, my name is Brian. So what was Alan Kay talking about and thinking when he was building and doing OOP? Because Alan Kay invented OOP and he's credited with it. But I don't think what Alan Kay was really working on is exactly the same thing that we work on when we think we're doing OOP. Because I don't think it was classes. Exactly. And he has this quote and it's somewhat famous because he says the big idea is messaging. Not classes, not polymorphism, not all that stuff that we make up. It is messaging. Now, what on earth does messaging have to do with OOP? I've got my classes. I've got my structures. I've got taxonomies. I've got all this stuff. I don't care about messages. When was the last time that we were really worried about messages going between objects as a thing? Almost never. But I don't think he was working on object-oriented systems the way that we think about them. I think he was working on network systems. And he didn't just work on GUIs and so forth. He also worked with ARPA, which led to a little thing called the Internet, which is somewhat useful to the rest of us now. And here is an early, I think, map of ARPA. But it leads to the question, then, of if he did OOP and he was worried about messaging, what is an object? What does an object really do? What is it really about? Now, we have this notion of code objects. Now, what is a code object? A code object, in reality, is it's a bit of code that has some processing that it can do, and it has some local state. And that's pretty much it. And I don't know if you've ever had this sort of discussion with another programmer, where you do a static method inside of a class, and then they go, why wouldn't this just be a function living on its own somewhere or something like that, or in a module or whatever? And it starts to go, well, then why do we do objects at all? What's the point of that? But really an object, at least in code, is this idea that you have this code, and it has its local state, and it has some functionality and some processing. So, okay, we have a code object. And then we have this idea of, okay, what about processes, threads, coroutines, things like that? Are those objects? Now, if you think about what a process is or a thread is and what they're really doing, what you have is you have some notion of a process has its local state, a program has its own local state, and it has some processing functionality that it can do. And then when a process wants to talk to another process, it has to send a message to that other process. You can't just reach into the other processes in memory. Well, I mean, I could, but things would probably break. So, you have this notion that processes, threads, coroutines, in a similar sense, aren't so different than code objects. Well, what about computers? Are computers objects? Now, Alan Kay talks about this notion as real computers as objects or real computers all the way down. And I have a quote here that's kind of long, so I'm not going to read it out. But the basic idea, in a lot of ways, is that he was saying essentially computers are objects. Computers have local state. Computers have local processing. Computers talk to other computers by sending messages. Simple idea in a lot of ways. And that he was essentially saying that the way we think about objects and the way we think about code in terms of data and procedures is kind of missing the point. Because real computers as objects, you can send messages, you can do things all the way around the planet. And that he actually calls the Internet possibly the only real object-oriented system in working order. Now, that's kind of an amazing statement because we all use object-oriented systems all day long, right? But apparently, ours aren't in working order. He also says something else here that I think is interesting that he says basically you can get any kind of language extensibility you want simply by agreeing on the conventions for the message forms. Well, that's interesting. So why is a guy who created OOP, which gave us classes and polymorphism and all that stuff, why is he worried about messages and message conventions? Because he was working on network systems. So what else are objects? Are people objects? Well, I think in a way we kind of are too. Because we have a kind of local state, we have our own local processing and we communicate with messages and protocols all the time. I'm doing it right now. Because really objects are things that communicate with each other to achieve work. That's what they do. So how do they communicate? How do objects in any of these senses communicate? Probably by shouting. But we have this sense of request response that we kind of tend to do in any kind of communication. A browser and a server communicating is not specifically different than me communicating to you right now. So we use message passing. And if you want to think about message passing as sending a letter to a friend, that's not a terrible metaphor. Because in a sense when you want to send a message between objects, you kind of put it in a packet and you kind of send it off and then they open it and do something with it and then maybe send something back. And protocols or those, that notion of a sort of well understood method of exchanging messages, they are how you send those letters to each other. So you could think of this as sort of like the postal service. You know, if you wrote a letter to someone but had no way to transport that message, it wouldn't be a very good message at all because they'd never get it. So you need protocols from messages. So let's talk about messages a little bit. You're looking at a message right now. You're also listening to a message whenever I talk. So a message, I'm going to say, I'm just going to define it as a container used for the transportation of information between two or more things. Basically it's a way to communicate. Messages can have many roles. Messages can have many formats. They come in a lot of different ways. But the whole point is it's about communicating. And messages imply protocols. If we did not have protocols, we could not communicate, period. So protocol, what are protocols? Well, think about the postal service. Now a protocol is a standard mechanism and structure for transmitting messages. And protocols are all around us. English is a protocol. You guys can all understand me because we speak the same language. If I was speaking Portuguese right now, most of you probably couldn't understand me. And I can't understand Portuguese. So it wouldn't work very well. Facebook is a protocol. Email is a protocol. Text messaging is a protocol. Wi-Fi is a protocol. USB is a protocol. The power sockets that we plug into are protocols. If they didn't exist, if there weren't standards around those things, we wouldn't have any of those. And so protocols are valuable. Like a million dollars valuable. Very, very, very valuable. So the English language, how valuable do we think the English language is as a thing? Would you say a million dollars? A billion dollars? I would say the English language in terms of commerce is worth trillions of dollars to the world right now. What about the phone, Facebook, Twitter? How many of us would love to own every telephone system in the world? Like you'd be a mega billionaire. You'd be the richest guy in the world. In fact, many of the richest people in the world are the people who own our communication systems. Also, USB, power plugs, all of those things are incredibly valuable. How awful would our computers be if we didn't have standard power plugs or standard USB to plug into, so on and so forth. I'm using this little clicker thing, and it works because it's USB. If they had invented their own way of connecting to it, it might not work with my computer. So it's nice to have protocols. We like protocols. So protocols are valuable, and there's actually a notion of how valuable they are. They're actually exponentially valuable because everything you add to a network system because protocols enable network systems, every time you add something to it, the network system becomes exponentially valuable because that one thing can connect to everything else. So without protocols, things go really bad, really fast, maybe in hilarious ways. So we invent crazy things. There's a way to connect and charge like five different devices. It's kind of weird. But we invent weird ways to connect things because we're like hardwired to find ways to communicate and connect things to each other. So if there's not a protocol or a way to communicate something, we'll invent a new way to do it. And this has been seen with all kinds of text messaging. I mean, people used to have these weird pager codes and things to communicate with each other. It's very strange. And without protocols, stuff breaks. So how many of you would be really thrilled right now if the power went out and the Wi-Fi went out in this auditorium? If we didn't have Wi-Fi, all of your computers would be basically useless right now. So having that protocol work is pretty stinking valuable. And without protocols, communication stops. Like I said, if there wasn't the standard language that we were using, stuff would break. Like, we couldn't communicate. Everything would be harder and slower. So if you went out to lunch today and they didn't speak the language and the menu wasn't in the language that you understood, how hard would it even be to order food? So without protocols, things are bad. And people freak out. I'm not sure how many of you experienced this back in dial-up days. It was great. So protocols, I'm going to say, are a requirement of effective communication systems. So I have to ask you all this. What business are you in? Are you making web apps? Are you writing code? Are you designing string generators that will generate HTML strings so that web browsers can read them? Or maybe, just maybe, we are all in the business of building communication systems because without communication, none of the stuff that we do has value. If you cannot communicate that information to someone else, they're not going to pay you anything for it. So the problem is, is that I think all of us are guilty of ignoring protocols in our software. So let's look at an example of some code. This is the most trivial example that I could maybe write. It's just dividing two numbers. Is it clean code? Probably. It's pretty simple. I'm not sure what else to really refactor out of it. I think you all understand it even after looking at it for a couple seconds. Like, oh, you're dividing two numbers. I don't know why you would do that, but all right. But what's the protocol here? What is the communication protocol around that little bit of logic? So I would say it looks something like this. You call some of two numbers, we'll say one and two. It does some processing, so it divides them. And then you have an output of 0.5. Now, notice the input here and the output there are messages. Now, I don't care if you're doing OOP or functional programming or something else, you are definitely sending messages when you call functions. So there is a protocol there, and you have to recognize it. So a few questions about that very, very, very simple method. What if you put integers? Well, integers generally work okay. What about decimals? We're basically fine. What about pi? Well, pi is a really long number, and we can't actually compute the end of it, so we're going to have to estimate or something, I guess. But if we wanted to use an actual value of pi, that may or may not work, I don't know. But what if you send in a string? What if I want to divide, like, hello world by 5? What should happen? I don't know. What if you send in an object? What if I just want to send in an object new and divide that by 5? Should order matter? Does order matter? In this case, order matters a lot, because the first one is the numerator, and the second argument is the denominator, and if you get that mixed up, you have some really, really incorrect values. So in this case, order matters, and I'm not sure that it should, but people could argue about that either way. And then in what context can you use this protocol? So protocols are definitely used in context. So in the context of this, is it reliable? Is it local? Is it just on that object? Is it private protected? If this were on, like, a remote API, do you have to have an API key? So you have to understand in protocols when you actually can use them. And then what if I pass in 0? Well, if I pass in 0 for the first value, you get 0. If I pass in 0 for the second one, it divides by 0 and the world ends. So that's not good. And then what if there's an error? We didn't really specify errors on that at all. If there's no error handling in that, why would there be? We're just going to hope that the language or the runtime does something fairly intelligent for us. So I'm going to go ahead and say that this is actually a pretty incomplete protocol because there's a lot of open questions. There's a lot of open questions. We just named a bunch. I'm sure you guys could name some more. It's fragile. You could put in bad data all day long on that and things would blow up. And maybe if you're using Ruby, it would handle it. It wouldn't. I don't know, but the point is that that code did not care if it's fragile. And it doesn't account for edge cases or errors basically at all. So, you know, most would consider it good code, though, right? Most consider it clean and small and beautiful and tiny, and it's doing the least amount of work that it has to do. And it's not complex. Like, what I'm talking about here is not a complex function. Now, imagine that that method or function is being full, like process a credit card transaction or something. Like, there's a lot of stuff that can go wrong there, and that protocol doesn't even think about it. So, I'm going to say that this trivial example is really actually not what we want because what we've done here by saying this is the simplest, most trivial thing that we could build, we've actually said we don't care about edge cases. We don't care about the protocol. We don't care about all the things that could go wrong because this is the simplest possible thing that we can build. And we're just going to hope that someone else handles that error. Now, maybe if you're on the edge of the system, you can handle errors a different way, but what if this is like three or four or five levels deep and then someone sends in bad data to this and then this explodes, and then that error cascades all the way up to the top? Well, we've all had that. We've all had these tiny little methods and these tiny little functions get like a nil value or something like that. It just blows up. And then you have to dig all the way down through the different layers and the different components to figure out what's gone wrong. So how would you fix it? Well, maybe you'd have a better specification up front. I could see that. I could say, all right, well, let's figure out all the things that are valid and not valid and let's account for that. That would help. We could add documentation. I would say documentation would help, but a lot of people would actually argue that documentation, like it's such a trivial function, would be documentation, but I think that you do because order matters for that method. So clearly we need some kind of documentation to say that the first one's the numerator, the second argument's the denominator. What about type checking? Now, type checking would solve some of the problems because if you had a type check, you could say, oh, well, you know, these have to be numbers, so you can have integers or floats or something like that and you can't have strings. Well, that's cool, sort of, but in the case of a zero value, does it? Because if you type check and a number goes through and it's like, cool, we've got a number, all right, let's run it through. Oh, gosh, that was the denominator. Denominator can't be zero. The type check won't save us in the protocol. What about TDD? TDD's supposed to save us and be like the best thing since sliced bread and I love TDD, but the thing is that tests don't actually lead you to creating a better protocol because tests check against your code, they don't really run at runtime and so you might have tests that are saying make sure you do this, make sure you test what happens when this happens and that happens or whatever, but the thing is, is that it would be better to actually test for proper values at runtime. So TDD helps, but it's not gonna actually ensure that you have a sensible protocol here and what about error handling? Well, we're not doing any error handling, so we probably should do something. So I'm gonna go ahead and propose a potential better solution and I'm going to say that with sort of a wink and a nod because you could argue that it's not. So this is my math. So I'm gonna basically put this inside of an object and up here I'm going to prepend a protocol which I'll show you on the next slide. So okay, we've added some documentation. Some people hate this kind of documentation because it's now littered your code, but it at least explains what's going on. We've then added, we've changed X and Y to numerator and denominator and we've made these keyword arguments. So now you can, as long as you pass in numerator and denominator, it doesn't matter the order and you've actually explained in the message format exactly what they are instead of just X and Y. So okay, we're doing the same logic but now we're passing back a hash with the result and an error and the reason we're doing that is because now we have a standard message format that we are going to be passing back to whatever calls into this. Now this is the protocol and it looks like a wall of text because it kind of is but up here you have a whole bunch of documentation. Okay. And what this is using is I don't know how many people here have used module prepend in Ruby at all. It's really cool. You can attach a module to the front of your object so it'll actually run, in this case it'll run this and then when you call super it actually runs this method. So it's actually a really cool way to kind of proxy in front of your objects and it allows us to do this protocol thing. So what we're doing in this protocol is we're actually checking for bad input here and bad output here and then we're actually calling in. So now we've actually taken those various bad states from the bad input and said okay we have these bad states but we're actually going to account for them and you notice that we're always going to send back error and result so that essentially we always have a standard message format to communicate with. So the problem is it got messier. I think most of us would argue that this is worse code and if we came across this in our Rails app people would probably freak out. Because protocols and messages are an inherent complexity in any kind of communication system that works. If you've ever worked with network systems and highly reliable systems just like the talk that we heard yesterday that there is a lot of complexity in building actual communication systems that are reliable and work and what we've done as an industry is that when we do methods and functions like that we basically ignore them and we say there's not that communication going on, there's not that complexity you won't have to worry about it but the thing is that this complexity exists whether we pay attention to it or not. So there's a few things that are kind of a prerequisite to having a good protocol. So documentation is a prerequisite to having a good protocol. If you've ever used a JSON API that you're not familiar with you understand what this is about you can't even use it. You can't even call things because you don't know what prams are there and they're not self-documenting because that's a pipe dream that will never happen. And so you end up with documentation being the only source of being able to do something useful it's the only way to communicate with a system in many cases. And so is error handling. If you've ever used an API or you've ever used any system that has no error handling sometimes it sends back a real value sometimes it sends back an exception sometimes it sends back an error object you understand that sensible consistent error handling matters. Things like error codes are stuff that we should be thinking about. But also it has to be easy to interface with and this is where I feel like type systems and things actually go wrong is that you shouldn't have to have so much information about how you interact with something to actually interact with it. We don't really worry so much about types and that's I think part of the reason why we like it so much is that it's really easy to interface with things. We don't have to think what type of type is this thing what kind of object is this do I have to send like a GX5 point objective to work with the coordinate system or something. We don't usually have to worry about that so much. So having something that's easy to work with is important. It's arguably the reason why we like JSON APIs instead of SOAP and XML but it's more work. Building these kinds of systems is absolutely more work to build. So do we want reliable systems? Do we actually care about the reliability of our systems? Is it okay to have error pages or other things crash? I don't know. But imagine you were trying to make a phone call on your cell phone and you hit a button and then the whole thing just shut down. Is that okay? I don't think it should be because we've actually built sometimes. So we've actually learned a lot of these lessons. We already understand protocols because we speak language and use them constantly. We use protocols like HTTP and Twitter and all of the weird LOL speak that we use and USB and Rails. These are all protocols and we use them all the time. If you've ever built a JSON API you've probably learned some of these lessons about documentation, about errors and so on and so forth. But I think that we have yet to learn about messages and protocols in our own code. Most of the time I don't see anyone writing that kind of error handling. I've never seen a lot of this kind of stuff. It certainly isn't what I would call Rails standard or Ruby standard in a lot of cases and it's not just Ruby. It's everywhere. No one, generally speaking, is worrying about messages and protocols for their internal APIs sometimes with their external APIs they do. So how do we get going? How do you start building with messages and protocols? How do we actually make an impact on our code base? Well, first of all you have to understand and think about the rules that govern our communication. So if we're building communication systems if you want to build a better communication system you have to understand how people communicate and how machines communicate. And so thinking about things in terms of communication instead of logic is important. Also think about the why's and how's of good and bad input. How does good and bad input happen in your system? How can you protect it? How can you actually handle it and manage it well? Erlang and the actor model have actually learned a lot of these lessons decades ago because they were building communication systems. They were building telephone systems worldwide. So they said, gosh, we've got to have these ultra-reliable systems. So how do we do that? Well, they care a lot about messages. They care a lot about protocols. They care a lot about communication. They care a lot about errors and failure and how that all works. So we can go learn about that. We can take those lessons and bring them back to Ruby. You can play with module prepend. That's the best tool I found to actually do this in Ruby. There are other ways to do it certainly. Other languages have not a lot of functionality or a lot of built-in things around protocols or data contracts or things like that yet. I don't know. And even just start designing with them between components. Start trying to say, when these things talk to each other, let's enforce a protocol here. So you've already actually done some of this stuff if you've worked with SOA and microservices. And it's kind of ironic is that we're not building these kind of protocols and messages and contracts and things into our systems when we're building internal systems. If you build the monolithic Rails app, like when models talk to each other, when controllers talk to each other, whatever, we don't really tend to think about these kind of things, right? So what we do is we say, well, this becomes an unmaintainable mess. So let's physically separate them into physically separate processes and physically separate machines in some cases. And now you have message passing. You have protocols. You have data contracts. You have these things. And we've basically said, oh, actually we do need this stuff in our code. But instead of doing it inside of one process, we say, okay, we have to physically separate them. It's the only way we know how. And so now you've actually taken on the complexity of deploying dozens of processes and dozens of services and all of these things, which if you were doing that from a reliability standpoint, that might be wonderful. But actually the reason if we're doing it because it makes our code easier to manage, well, we've done it maybe for the wrong reason. So I'm going to say that microservices created a physical boundary because we didn't actually create that boundary in our code otherwise. And so microservices have actually helped us to do this where we would never do it in a traditional monolithic web app. So think about the notion of input processing and output because really that's all we're doing. You generate a web page, you have an input request, you generate a big string, and then you send that off to the client and then it does stuff. We learned about that yesterday. But what's important here in this is not just the input, the processing and the output because we spend so much time thinking about that processing step. But that little communication step in between the message passing, the protocol, that's important. It's so important and we give almost a few things about where I think we're going as an industry and as people. I think we're going to have more network systems. We have the internet of things happening. We have all these big ideas happening but we're going to have a lot more devices. We're going to have a lot more network systems. You have a lot more multi-processor kind of systems. And you have things like Docker and all these containers running on the same system. So we're not going to have fewer network systems. We have more network systems. The more processing power we have, it's because we can't. So hopefully there is more discussion about better tooling. Maybe there will be a better vocabulary around these ideas. And maybe there will be more languages built around these notions of message-oriented programming. I mean 30, 40 years ago we didn't have OOP languages, now we do. We didn't have so much functional programming, now we do. So maybe at some point someone will take up this notion of messages and protocols and say, this should be more first-class tooling around it. So we're going to have more language. And then I think that what we might not always realize is that there is going to be a higher expectation of reliability from our users. People want stuff to work and when stuff doesn't work we get mad. Simple as that. So the longer that we are building software the more reliable that people expect things to be. We expect that when we turn on our car that it turns on. We expect that when we try and drive it somewhere we get there, right? No one would argue that. But 100 years ago when cars first were made there were jokes like, as soon as you drive it home you might as well drive it right back to the factory for them to fix it. Cars were not that reliable. Now cars you only have to do an oil change every once in a while. Maybe fix a big component every few years. And they go hundreds of thousands of miles. It's amazing. But 100 years ago that was not the expectation. So I think Ruby is a great place to start because Ruby as a language lets us play with a lot of these ideas. But it's not the only place to start. You can mess with Scala, you can play with Erlang, Elixir all of those things. And so really the big idea is we spend so much time thinking about logic. We spend so much time about algorithms and all of these things. And that's wonderful. But we almost never spend time thinking about the communication between these things. And as we have more network systems and more components that have to talk to each other, the communication becomes a much bigger deal. So that's it. That's my presentation. Thank you. I don't know if I have time for questions. I try not to go too long. Here are the image credits. And hey, slide 100. We made it. Thank you. Three questions? Anyone? Yeah. No, like that's real code. What I'm saying by building that is I'm saying that that we're trying to understand and deal with those errors and those different edge cases and so on and so forth. Sure. And I agree. But my point is that our tooling and our software doesn't necessarily give us good mechanisms or abstractions from what I've seen to actually handle those very well in a lot of cases. And so in the absence of like that was maybe a ridiculous example, but we don't have in the same way that say assembly code is big, obtuse and terrible and we don't like it so we have higher level things to manage that. We need higher level tools, better tooling to actually handle the creation of these protocols and these interfaces.