AMOS: Welcome to Elixir Outlaws, the hallway track of the Elixir community. ANNOUNCER: Without further ado, the live recording of Elixir Outlaws. Round of applause! ANNA: I like that you brought props. DAVE: I did bring props. CHRIS: I don't know if I like this. ANNA: This is the show. CHRIS: I've had my coffee. ANNA: Um, so you've had your coffee. CHRIS: Yes. AMOS: I just got distracted by microphone. ANNA: You were having a really intense conversation like two minutes ago. Which is why I brought Dave, so like. Do you want to fill us in on what you all were talking about? CHRIS: Just real quick before we get started, like, does anybody listen to the podcast? ANNA: Oh, that's a good question. Oh, that's right. AMOS: We have, so we have stickers for friends of the show. CHRIS: Those five people are gonna get stickers. ANNA: They'll get all our jokes, 'cause they're friends of the show. AMOS: So yeah. I mean, should we get this out of the way? ANNA: Oh, we're not talking about talking about that. CHRIS: We're not talking about more purely functional district. AMOS: Really? I'm bringing it everywhere with me. So Chris made me buy this book. Purely functional data structures? Chris calls it the Saki book, Okazaki book. I call it this, this don't buy this book. It's terrible. ANNA: It's not terrible, come on. AMOS: This is a CS degree in a book. CHRIS: This book is not that thick. This is a reasonable sized book. ANNA: Yeah, but it's very dense. CHRIS: It's very little math. ANNA: That's true. CHRIS: It's really good. ANNA: It is good. It is good. CHRIS: It's a very important book, but you have a mental block. AMOS: So that's why we switched to this book. ANNA: Which is also really good. AMOS: And this is, and this is harder to read - a philosophy of software design. ANNA: Has anybody read that? Oh, cool. AMOS: Anybody read this? ANNA: I just ask them. AMOS: Explain this to me later. All right. Perfect. And then, so, uh, we've been reading a philosophy of software design lately. DAVE: You call that a pause? AMOS: It is kind of a pause. From this. CHRIS: I was, um, theoretically prepping my talk and I have to get later. Right. But I wasn't, what was actually happening was we were talking about this book while I was talking at David about this book. AMOS: That's how the podcast normally goes. ANNA: Chris talks and Amos and I are like like wait. CHRIS: And we were talking about this idea of skipping over the part where you criticize me. It's easier when - this is the person that we've ever been the same room as we record this, which is, uh, awkward. Um, I normally just look straight ahead and I can see everybody. I mute them through most of it. ANNA: He needs the space to hear himself talking. CHRIS: And I have pants on, which is weird 'cause normally it's just a video screen. Uh, we've been, we were talking about this book and we were talking about this idea that, uh, Dave, that you've talked about, uh, at other conferences and stuff like this, about this notion of doing componentized design in Elixir, I was talking a little bit about one of the metaphors, um, that that really resonated with me when I read. Pause, pause. When I read apause, uh, which was this notion of creating modules that are deep in nature, uh, where deep is where deep means that you have a very, um, small interface. And what you're getting out of that depth is like a lot of power. It's handling a lot of things for you and it's giving you a lot of power. So I was asking Dave, number one, like, does that analogy, what do you think about that analogy? And then two, how does that, if we assume that if we, if we can reach a point where we think that that analogy is good, how do we apply that to componentize design and Elixir applications? Is that fair? Is that more or less captured? DAVE: Yeah, definitely. ANNA: And that's in contrast to, as opposed to a bunch of shallow modules that you have to kind of compose together each on their own, not being very powerful, like the contrast between the deep module, AMOS: How the book talks about it too, is that a shallow interface has a lot of public methods and maybe a lot of stuff that you have to call to get anything done. And it doesn't do much, but a deep one has very few, the public interface is pretty slim, but does a lot, so you'll have fewer methods, but they are very deep. DAVE: And I think that ties into the idea of being a functional language as well, because one of the nice things about a functional language is that you can parameterize what you do by passing functions in. So your strategy, if you like can be functions that you pass in, and this allows you to keep the surface area of your individual, what you want to call them. Components, modules, whatever, pretty small, but still be extendable. Cause I think that's the key is that quite often, when people think components, they think self-contained closed little module, but I don't think that's what he's, I haven't actually read the book. I'm just doing the legal description. But I think the idea is that what we're looking for instead is controlled composability of being able to chop things up and then put them together in interesting, different way CHRIS: At the time that y'all walked in. I described the notion of, well, if we hand this one, let's say a data abstraction layer that like, let you talk to databases. I don't know what kind of libraries in Elixir would do that. So if you have a library that lets you do that, and all it did was sort of let you talk to databases. Then on top of that, you could layer on this know a higher abstraction that handled things like validations and stuff. And you pushed back on that. I pushed back on that. DAVE: Right. I pushed back on the idea of layer because to me, whenever you talk about layering, what you're talking about is building on top of which means you're coupling. Yeah. And so if you had your abstract non-existent database query library that we're talking about, and then we split out from that abstract non-existent library, things like validations and updates, and what's got stuff, we just kept it as a pure query library. And then if you start with building things on top of it, then it's really no different to building things on the side of it. You still end up with, by the top layer, which is the layer people will use, you still have a monolith it's just less efficient. Whereas if, instead you say, well, to me, the idea is you're building obstructions and you're keeping them separate because self-contained instructions are easy to deal with. Right. So if you had your query library and then you had your validation thing, then how are they going to talk? Well, right now they're intimate. In fact, they're intimate all the way through to say Phoenix, Oh, sorry. A mythical web front end. So you have everything all kind of coupled together. Whereas if we were to talk about small modules of abstraction, then we'd have a query library, we'd have the library that did validation. And then we'd say, okay, on how the two of them that are talk to each other. And we would, because we were thinking about this in terms of obstructions and components, we would not link them together directly, but instead we would think about abstraction. And what's the rule. When you want two things to talk, they talk through a higher level of abstraction, always. So you would introduce the abstraction, which was some kind of data transport thing or data definition thing. And now suddenly not only do you have your queries and your forms, but guess what? You've just introduced validations to it. Cause that's what that extra obstruction is. But the cool thing is that's now independent as is the form stuff as is the query stuff as is the web thing. And so they're all mix and match. If you don't like this, you can switch it up for something different. And so that's, I think thinking about using some of the good OO principles to apply - in my talk tomorrow and then talk about how I think we are actually a better OO language than most, and we should be applying or principles. Right. So what we did, and so the idea is of, um, always abstracting up is I think a good, solid principle we can apply. We do it, not just at the function level, but also at the module and component level. CHRIS: So I think I struggled with this a little bit because I have this intuition that if we've built a higher level, if we built a validation thing, so we've built a way to express data structures and validations about those data structures. In many ways, I don't know how I feel about this, but my intuition is that you, if you're using that API, you actually don't want to know anything about how those get transformed into queries. Because the minute you have to know about how those things get transformed into queries, or the minute you have to care about the queries themselves, and you have to juggle both those worlds is where you start to add cognitive complexity, because now you've got mental overhead and all this kind of stuff, but you have to understand how those things work in collaboration. And I think in a lot of ways, I think that's why I use the sort of notion of, of layering. Cause like in a lot of ways, I'm not sure that you can get away with building a powerful module in practice that isn't coupled to underlying implementation. So if I built a validation schema, um, expressive thing on top of queries, I think that's naturally going to be coupled in that way in order for it to be powerful. Does that make sense? DAVE: I know what you're saying. Right? Um, but at the same time, I can think of quite a few counter examples where you can build on obstructions that you don't know how they work. I mean, I have no idea how maps are implemented - so, uh, in this particular case, think about the queries things, right? The query actually does not interact with the data store. Right. All query does is populate the data store. So I think what you'd have is you would have a query module, which was provided ideally at runtime, it was parameterized with a database adapter and the data store adapter. And both of them just have a very simple interface because remember, we're always talking about minimal surface area interfaces, right? So we have two very simple interfaces when you bring it up, it's kind of dependency injection, but without all the crap, right. And you bring it up, you give it those two modules. And that way you can have a Postgres with - what we're talking about, validations, right. A Postgres with strict validations, or you could have a, my sequel with no validation. So you could have a, uh, Reddis with Lord knows what you know - nothing. Deliberate, deliberate corruption, validations. Yeah. CHRIS: Whatever, whatever the validation is that throws off your data away. DAVE: Well, the thing is, is by doing that, right, suddenly you've gone from a monolith where you take it, leave it into you get control and it doesn't have to be that you, you know, with sensible defaults, you don't have to think about that. But if you wanted to, like, there's a couple of times where I wanted to break out validations. Right. You know, I can't do it really easily. Um, I'd like to break out form data and I can't do it very easily. So if I could just plug these things in, if we design software in such a way that all of these concerns become pluggable, become independent modules, like you're saying with very small surface areas. So it makes them easy to replace. I think we're in a lot more powerful position and we are uniquely in a position to do that in Alexa. There's not many language that will let you do that. CHRIS: Yeah. I think, I think that's the key, um, this runtime, I mean, that's the thing that keeps me in Elixir, more than anything else is, is the, is what we get from this. This is just better than anything else I've worked on. Like the runtime just gives us more, DAVE: I think the runtime, but also I think there's a, a sense of possibility in the community as a whole, um, which is, uh, to be honest, it feels a lot like Ruby felt back in 2002 or three, um, there's energy. We can do things differently, you know? And I think one of the things that keeps me going is the ability to be basically a pain in the ass to people say, you know. I know, I know, um, that's this is the new softer kinder me. Basically you say, come on, let's not blow this. Let's not, let's not do things the old way. Right. But let's take what we have here, which is, I agree with you. It's, it's probably the most potent runtime available at the moment for the today's world. I mean, the amazing thing is he was designed back in the eighties and now it is just coming into its own. And that really says an awful lot about some foresight. It really is. Now this is the world. This was meant for, this is the universe that this was meant to inhabit. Right. And this was the universe that this is meant to push forward. Yeah. And I think if we don't make these kinds of decisions and if we don't take the opportunities that it gives us to do this kind of thing, we're kind of throwing away an awful lot of opportunity. How's that for responsibility, it's all your fault out there. The world could be better except for you. AMOS: So the, the runtime gives us a lot of opportunity to make things more modular just in the way that it's designed and the way that you communicate from process to process, component to component. But, um, in this layering and abstraction thing, when we start talking about databases, for instance, I have a big problem when reading stuff about this is every database library I've ever used is so thin that I know exactly what's underneath. Like the query language looks exactly like SQL. So is there, is there, are there layers of extraction that we could really build that are, are different and more agnostic to the data underneath and how do we access it or are we just stuck in this? Well, everybody knows SQL to a, to some extent. So let's just make that our obstruction or is there something SQL - it's about, you know, the, the interface to SQL is huge. So, but when we put an abstraction on top of it, why don't we just talk directly to it? Why do we have this abstraction? And it's just as big as the original and looks like the original. DAVE: That's a really, really good question. AMOS: Do you have an answer? DAVE: Yes. Don't do it. ANNA: Wait, that doesn't answer the why. DAVE: No. I mean seriously, why you're absolutely. Right, right. There, there is like the original active record. One of the big selling points is now you're a database agnostic. You can move between databases and not worry about it. AMOS: Except for when you can't. DAVE: Well, except for two things, a you can't, because in reality, it's never worked, but B what was the problem in the first place? Right? That was not an issue. I don't know anybody who ever said, Oh, you know what? Let's switch from this to that. All right. And actually did it just seamlessly by throwing out a module and plugging a new one. Right. It doesn't happen. So that's not a problem we need to address. Right. Instead we need to think about, yeah. Okay. We do need to make access to these things easier. For example, if I have to page through a table, I really don't want to write the cursor code myself. I'll have someone else do that for me. Thank you very much. All right. So that's a good abstraction. I'll use that. But the real question is why do we write our applications with a database, right. With one bloody great, complicated interlinked, highly coupled database, right? And then we feel the need to stick a layer of abstraction on top of that. And now with context, it's a layer of abstraction on top of that, right? And have everything all linked together, right? The reality is that's where the complexity in our applications comes from it's because we view our data store and we view our user interfaces both as being monitored. And then we sit there and try and nicely structure the code in the middle. You can't do it right. Monolith shall talk to monolith via spaghetti. All right. That's the only way of doing it. But if instead we viewed our data sources as smaller, specific functional components. Dare I say service. I know, I know I said the word, but something, maybe not, not services as in microservice, but service, as in something that supplies something, right. Then you don't have that issue anymore. Sure. You can use Ecto or you can just go straight to the database or you could use Mongo or whatever you want to use in each individual loan. You don't have to have that verse surface area of knowledge because you're doing very specialized things in each one. And then people say, well, what about transactional integrity? What about transactional integrity? If you have a transactional integrity, that means we already have a solution for that. Right. Processes are transactional. So if you want transactional integrity across two different services, you put a transactional service in front of it and now you've got transaction. AMOS: It sounds like Chris as a, well actually, DAVE: I mean, what I'm doing here is I'm building up, building up and then we'd all sit back and he can take the rest of the show. CHRIS: I'm ready. I was with you up until the transactions thing. I think, I think that's, that's reasonable. I think TriNet, I think my, I mean, sort of my fundamental pushback on that is, um, most companies are basically competing against like most like software companies, specifically software companies. And that might include, you know, your team that you're working internally at your big dark matter enterprise somewhere. Is it, this is, I've said that twice today nobody's understood that term. It's like theory says that all those people exist, but no one's ever seen them. So yeah. Uh, but like you you're out somewhere and you're working on stuff and you have internal customers, you're building a company internally. Right. You can think of it in that way. Um, we can strain that metaphor enough. Most people building software to solve people's problems are effectively competing against spreadsheets. Like you have to be better than spreadsheet. That's that's layer one. You have to be better than a spreadsheet. Cause otherwise we'll just put it in spreads in Google sheets and we'll just, or, or whatever, you know, side note, I had a really good idea for a startup, which is basically Kafka, but spreadsheets on Kafka and I'm ICO in here soon. Speaker 3: Um, so Speaker 2: Yeah, while Bitcoin's low, I figured I'd get in there. So, um, you know, that's, that's bare minimum one, a and because at the end of the day, like what matters is data? And then most companies present data in a novel way. You're, you're better than a spreadsheet because you present the same data. You could store it in a spreadsheet, but in like a better format or a more useful format or allow better like interactions with that data. Is that like fair? Speaker 4: Can I refine that just slightly. Of course. I don't think data is worth a it's information. That's important. And information is what you do with data. CHRIS: Well-played. Yes. Yes. I agree. So I think in that regard, we do have to care about where we put that information and how we store it and things like transaction integrity and stuff like that, because I don't know that processes always can give us that. Like, and, and in that regard, I, I, I have this, whenever people talk about this stuff, in context of elixir, I have this like super knee jerk about it because, um, you know, there's, there's all these complexities. Like I want to be that guy, but like, it's like, there's all these complexities with like distributed networks and all this kind of fault tolerance stuff. And like, so, so don't go replace your databases with processes necessarily. Please. DAVE: Let's turn that round. Right. In every application, I would say that there's probably an 80, 20 rule. 80% of the data is either transient or not particularly important. 20% of it is business information. So that's data becoming information. Yeah. Right. So for example, session data, right? Yeah. Sorry. Who gives it a - care? For example, there's been any old days in the days of, of rails, you know, we use the stick, a law session, data and database, and it was transactionally secure. Great. Who cares? Stick in memory. Second processes. So I think that whenever you look at a solution, moving things out to independent components, I think you have the option, right? So you can say this data is transient stick in memory. This data I'd like to keep it. But to be honest with you, I'm, I'm accepting the fact it's going to get dirty over time. Right. Okay. Whatever this data is, 100% mission critical. It cannot get corrupted. Right. Well, you know, what, why would you take something that important and bundled it in with all the rest of the crud that you don't care about? Right. If it's separate strategy, separate rules, separate parameters, right? That's the one that goes into multiple redundant backend databases. That's the one right? Where you have fail safe. That's the one we have audit logs. That's the one we add extra validations, blah, blah, blah, blah, blah. Right. So I think that what you're saying is a hundred percent. Right. And I think argues my point. It's saying is no, you take, you take that stuff and you move it out where it is secure, where it is, where it can be nurtured the way it has to be nurtured. Now, does that mean that you do transactions and processes? Probably not for that data. So what I'm suggesting is that say we had two tables, right. And individually they're okay. But together they are - it's important right now you can read from those tables all day long, nobody cares. Right. It's writing to them. That's important. So do we have two services, one for each table? No, we have three, well four or whatever we need. There's no rule that says you have to have one per table. That's a Rails thing that we've adopted by mistake. Right? We don't have one model per table. Now I know we've got, we've been, we did contexts, which is fine, but even so there's still this philosophy of a model per table or a set of whatever context per table. And that's not the way it is. Right. So in this situation, we can have as many front end services and as many backend data stores as we want, they're not going to be one-to-one and we can ensure transactional integrity when we need to, we can also ensure seriously, high read performance when we need to, right. The two or the two conflict, the two are totally different. So you don't want to put them through the same mechanism. You don't want to put it through the same database connection. Right. You want to have separate. Right. Right. So it strikes me that what you're arguing is very strongly to split the thing up. AMOS: I just thought I'd let them talk. New Speaker: Is that what you're arguing? DAVE: My wife always says men have only got like 10,000 words in them, which is why we're so sparse. I think I finished using all my words. My words are used. CHRIS: Should we do question? Is that a thing? AMOS: I mean, I think Dave said it all, Dave said everything that I was going to say. ANNA: My only question is just right now, my only question is how this relates to the conversation we're having with James last week. AMOS: We just made a new lots of friend of the shows, all these friends in the show. So I need to know everybody's first name before I leave here. ANNA: Yeah. I mean, I don't know if there's, I mean, we've talked about this a little bit last week where like, there is this line of like actually being able to break things down. Right. And making sure that there are like deeper, more specific things, but then a little bit about when you're coming in and you just start working on a system and you're newer to programming or newer to the community. Right. Finding that balance of like, how do I get work in quickly? Right. Right. I'm just curious your thoughts on how that competition relates to the one we're having or anybody's thoughts. AMOS: I, I don't know if it relates perfectly to the conversation that we're having, but there's some level of the abstraction there that in order to get moving quickly, like the more layers that you have to know beneath the abstraction, the less useful the obstruction is and the harder it is to get going. So I don't know how that exactly relates to the conversation that we're having. Unless we go back to the, now everybody needs to know data. CHRIS: So like the, where the, where this would go wrong in my, in my opinion is if you end up with, um, the grid, the grid example that I loved out of that book was like Java buffered file reading. Um, which is like in order to do buffered file reading, which is basically what you always want to do. You need to like get an IO reader object that you pass to a biologic that you pass to like a file reader object that you pass a buffered file reader object. It's like decorators all the way. And none of those are actually giving you much power. The idea being that you can't use any of this stuff, uh, without having any, uh, other bits, when actually all you wanted to do was read a, re a file in a buffered fashion. And I think, I don't think components like, um, uh, prohibit you from doing that. And in fact, I think if you design them well, and you have a lot of power involved. ANNA: That's kind of what I was getting at. I here is anybody in the audience have thoughts about what we're talking about, or thoughts at all. CHRIS: If you've ever had a thought, you can come up and ask us. AMOS: If you need a soapbox. Yeah. Oh man. I think, I think we, I think we failed. Brett. Go make something up. Go ask this question. Oh, here we go. Here we go. Yes. You can have a sticker if you have you ask the question. QUESTIONER ONE: Yeah. So I have a question about, um, I think it was a little bit unclear when you guys were talking about how you should design say something that's sitting on top of a database language, right. So, or sitting on top of a database or a data query. And you, the question was that was asked was, well, you know, what is the point of having some abstract language if it's just as complex as the underlying query language, right? So, you know, even dropping of SQL, like what would be the point of having something integrated with Neo four J but it was exactly as complicated as cipher or exactly a specific to the thing you wanted to do or that the specific to the underlying technology. So I guess I'm curious, what are the, if you wanted to build something that's sitting on top of data query and you wanted it to go to like two very different types of databases, how do you solve that problem to where you have something simpler that has any power that would make those kinds of queries? DAVE: Have you ever seen, um, what's it called? Pentagon Wars. I think it is. And never the movie, it's a, it's a fictionalized account of the procurement of the Bradley armored fighting vehicle. All right. It is hilarious. It's a really great movie. It's got, I've never read them. The guy's named Carey. He was in a princess bride for the carry something or other, thank you. Yeah. And it's the story of how they won. They got the budget to produce this armored fighting vehicle. And, uh, it was supposed to be a true carrier. Right. So they maximized it as a troop carrier. So they put all this extra space in it and then they had a meeting and some guy said, but what happens if it comes under fire? So I said, Oh, well, we're going to put like a, let's put some, um, big guns on it. So they put a couple of 50 cows on top, but that actually loaded it down. So they had to get rid of two of the people. And then somebody said, next meeting. Well, we put the 50 cows on top and that's going to make it a target. So we're going to have to beef up the armor. So they put extra arm around it and then had to get rid of three more people and whatever else. Right. And so throughout this thing that there's this period of like three minutes in the middle of the film where they watch the requirements being switched 180 degrees on this vehicle. Right. And the problem was, they're trying to have one vehicle that did multiple thing. And I think that's the same issue that you're talking about implicitly is you say, well, what happens if I want an obstruction that will talk to this kind of database and this kind of database, and then, Oh, I need these kinds of features in this kind of feature. Right. And now suddenly you're back into active record. And I think the, the question is rather, how do we not, how do we build this obstruction? It's how do we think about doing this kind of stuff without having to put the kitchen sink into our abstractions? Right. So rather than one obstruction, are there multiple, for example, the ability to read data based on some set of keys is an interesting thing to be able to do. You can do it in sequel. You can do it in, I don't know anything just about right. Uh, that might be an abstraction, right? We don't necessarily have to have just cause the database lets us do 1,001 wild things. We don't have trust in writing abstraction that gives us all of this house. And the one thing, keep it simple, keep it exactly what we want to keep it focused. And I think life gets easier. And particularly if, as a community, we can come up with ways of, I don't want to use the word specifying, but describing what our obstructions do, then it would make it a lot easier to find what we're looking for and apply it. I'm just, I'm just really sick of having to spend a week learning a brand new thing. CHRIS: Uh, I think I have, like, I think there's merit in having, you're talking about, you know, data access, like specific, like we bring, if we're being concrete about that, I think there's merit in having a unified way to do that. And, and specifically it sounded like you were asking about like how like, is there a benefit and value to having a way to compose queries? I think that there is, I don't know that I would be the right person to do the design of that necessarily, but I do think that there's power in that because what that provides to you as, as like the end user of that is a unified way to talk about data, access to theoretically, anything we were talking about this earlier, um, like with link, um, if you're from like the C-sharp world, um, probably heard of that and like that's a pretty good way of like actually just interacting with any sort of data. Right. I think that there's like there is power there. Um, and because what you're getting is you're providing a way to, um, if you do it right, I should say, um, and I did, and this is why I don't know that I'm the right person to design these things, uh, because I probably wouldn't do it right. If you provide a way to start composing those together, there's a lot of expressive power that you can bring to bear to do that, right. DAVE: Except in functional programming, we already have a way to do composition and that's with function. So what we're doing right now is we are building data structures. Why aren't we just using what's built in and building composing functions because then I can compose functions both within my database layer and in separate layers. So if I have some funky query Tufts that only I need to do in my application, I can compose in those functions into the general query mechanism. So I'm not trying to burn down a house. Right. But I am, I am saying that we need to think about different ways of expressing these things. And for example, we tend to think of things as data and code. Why, because 90% of the people in this room come from an object oriented background. And that's the way you've been brainwashed into thinking about it. Me too, me too. It's data and code and never the Twain shall meet particularly for a seizure or a C plus plus developer. Right? So it's, that's the way we think what I'm saying is throw that away, right? That is a house that we'll burn down. And instead think of it just in terms of not functions but functionality. So when I'm thinking about composition of searches, I want to think of it in terms of functionality first then to say, okay, now I would like as a functionality to be able to compose these things, right? So then I can add a composition, but I'm not in any way committed to building myself some descriptor of the query that I want to make. Right. I think that's a really big mistake. Get into the habit of abstracting away strategy from implementation. So in this case, you'd be building the query it in the way link does independent of the actual mechanism underneath it. Right. And I think we can do that and it doesn't have to look like SQL and it doesn't have to pay another dollar. AMOS: Yup. So like instead of a where clause that building up, you can, if you want to do it, compositionally, functionally filter, then maybe another filter and another filter. And you can build that up over time as the, as requests come in or whatever. And you, you store that, that function off. And I think it was Eric Meyer. I've heard, say, you know, that's the big difference between functional and OO is function. Functional is our data. There's, there's not this special house over here. That's just for the code. Like you were saying that that's hard, switch, switch, switch. And, and almost everybody I run into, that's a hard place to go - like how many, how many computer science degrees out there, if you, if you went to college for computer science, most of those are all OO C plus plus very Microsoft driven. A lot of them like, here's your vs code, have fun, you know? Um, and, and they're all based on OO. So it it's a tough paradigm after many years. DAVE: I, I actually, I teach undergraduate elixir. Maybe the only one - I have a course at SMU and you would be amazed if you catch them young enough, they jump in with both feet because it actually I'm finding it's way more intuitive for people to learn a functional style than it is to learn a lifestyle. Because when an OO style so much has deferred, whereas with a functional style, it's only in your face, it will just have. And so once you show them like composition and how you can build more complex students through composition, you can't stop them. I mean, they're just, you know, they're off, they're having a great lot of fun. So yeah, it's, it's, I think you're right. People don't teach it. Um, but there's a lot wrong with computer science education. ANNA: I think for those of us that don't did come from, OO, like, how do you, cause it is hard. I agree with you. Like, how do you shift that paradigm? Right. Other than continuing to remind yourself, right? I try to just, I try to think more than I type that's. I think that's really should be the goal for most of us, even if we are continuing to do elbow or switching, the functional is step back. One of the things in, in, uh, a post as you coined this beautiful, uh, is he says design everything twice. Uh, even if you think you've got it designed right. The first time and the problem with we have a room full of smart people here, most people will probably run into this is the smart people feel like, well, my first intuition was the right one because it always has been, but our problems are get are bigger and harder than, than most of the things that we dealt with throughout school or even early career. And, and they're continuing with distributed systems get bigger and harder. And so let's think twice, even if you know that the first one is right, do it a second time because you'll learn something. DAVE: I mean, like woodworkers say measure twice, cut once. Yep. Forensics said be prepared to throw the first one away. And in fact, I think it's actually always, when you think about that, I want to go one step further and say, when you design something, even down at the small micro level, at a single puncture and you want to reassess it, don't say, how do I redesign this? It's if I was told to totally replace this with a different way of doing it, how would I do it? And actually come at it from my major degrees and see what plugs in. AMOS: And, and even to the contract for a change. Yeah. Like maybe it throws an exception now, does it need to right? Uh, what, what weird thing can I do differently? Um, I don't know those. I try to throw out random questions when I'm in a group doing design work and thinking about how we should design and abstract, something, I will come up with weird stuff. Like what if, what if every parameter was a function and you couldn't pass it at any data directly, it had to be through functions or the core closures. What if we did nothing but, but anonymous functions and they are ridiculous, but you learn a lot and come up with it. It changes the way you end up at your final design. We asked for questions and we have a line of people. We have two minutes, right? You putting up your fingers two minutes. QUESTIONER TWO: Yep. Hi, Kevin Brown front of the show, Hey, this may need to be its own episode, but I'd be interested to hear what you think about CQRS. And if that applies to de modularizing or mantra arising between queries, I, I missed the end of your question. Like the database connections, your application, what are your thoughts? CHRIS: Uh, that is a showing you, insourcing is good. Uh, CQRS some of the fence on, and you want to make it, you want to constrain it to a very, you don't want to make it your enterprise wide, uh, way of doing things. You want to make it very small. That's my two-minute answer. AMOS: Events sourcing, wait, wait. It's really important that that thinking instead of typing, because once you have the events and the messages going out that are events, it's, it's really difficult to change them. So do a lot of thinking and, and white boarding and throwing away, lots of code before you ever commit to anything. Do we have time for Hannah? QUESTIONER THREE: And these lines of like how to design modules, uh, design in general, do you think the design needs of a program or starting, uh, are the same as the design needs of a senior person? Who's been programming a wow. And spoiler alert. I think the answer is yes. DAVE: What do you mean by need? QUESTIONER THREE: It like, so this question of like deep modules with these like really amazing high level IP APIs versus like small composable whatever's like, do those apply is the answer, right? No matter where you are in your career or level of experience. DAVE: My personal take on that is that one of the great ways to learn when you're just starting is by copying and I continue to copy today. And there are two ways to copy. One is that you look on, I dunno, some book somewhere, so overflow, overflow, or somewhere, and you just copy code off that that is uncurated and typically ends up with these kind of Frankenstein projects that you don't want. Right? So I would encourage beginning developers not to do that, but I still think we need to set an example. And one great way of doing that is simply to make the way we favor being the easiest way to do it. So we want to have people writing lots and lots of processes. So we don't want to have to force them to write a gen server for every single one. Now we've got tasks, we've got agents, but we still have this big gap in the middle where you're sitting there writing handles, and you don't have to. So as a community, I think we should object, uh, adopt shorthand ways, DSL ways of creating like really simple services. So for example, I mean, I wrote some Google Jeeves, uh, where if you wanted to create a pooled process, it's literally one line of code to say, this is a pool process. Then you just write the implementation. Right. That kind of thing makes it easy to code things the way we think they should be coded. So if we can come up with some kind of general agreement on how we think things should be coded, or we just have an ecosystem where it fights it out, and then we create these things that make it easy for people, and then you see what works. And I think that way, beginners get to use halfway decent structures. And as we get more experienced, they learn to override the stuff they don't like. And then at some point say, this is crap and replace it with something that they've written. ANNA: Can we give it up for Dave? Thank you! ANNOUNCER: Give it up for the Elixir Outlaws. Okay. Thank you guys. That was a lot of fun.