Welcome to Elixir Outlaws, the hallway track of the Elixir community.
Chris: Alright! You were so delayed.
Amos: I was delayed.
Chris: You were so delayed.
Amos: I blame, I blame your latency.
Chris: My latency? You hard lined into the gig, my friend.
Amos: Huh, me too. Oh wait, I'm not hard lined.
Chris: I'm one hop away from the backbone.
Amos: I'm not hard lined in I guess. I'm going over wifi.
Chris: Well, your computers crashin, mine's multitaskin'. It does all my work without even me even askin'.
Amos: You've been hanging out with MC Plus+. And Monzy.
Amos: Oh, now I feel old. I don't even know if they're around anymore.
Chris: Is that a thing? I just assumed you made that up.
Amos: Oh no, that's a, it's a hard core nerd computer science rap.
Chris: Yeah. It's a real niche, it’s a real niche market.
Amos: Hey MC Plus+, if you're a such a hardcore computer scientist, why don't you track numbers start with zero? Just saying.
Chris: Did they not? That seems like a real obvious.
Amos: Yeah, they should have, but whatever.
Chris: Yeah. That's, that's uh,
Amos: There's, there's a good, not safe for work one, uh by Monzy called "Kill Dash Nine" That's pretty funny.
Chris: Yeah that's hardcore. That's that's that's some real, that's real cringy.
Amos: All right. I can't wait for somebody to go out and listen to that because we mentioned it.
Chris: Yeah. All right. How's it going? What's how's your, how's your past seven? How's it been going?
Amos: Um, it's it's been good. It's been good. I, uh, I, I got to write a little Elixir at a client with, uh, Connor Rigby, too. So that was pretty cool. Uh, I haven't been able to do a lot of Elixir lately, uh, because I've been playing in Ruby land and Terraform mostly lately. So.
Chris: Which of those do you like more?
Amos: Terraform or Ruby? That's a, that's a horrible question. It's like, would you rather me stab your left eye or your right eye?
Chris: Yeah, that's what I'm asking. Which of those, which, it's like asking, "What's your favorite thing about Internet Explorer 7?"
Amos: It's not Internet Explorer 6?
Chris: That's one of my go, that's one of my go-to interview questions, if I want to break the ice.
Amos: Oh, that'll work.
Chris: What's your favorite thing about Internet Explorer? So.
Amos: I like it, uh, I might have to use that. Uh, we're hiring right now. So I've got a whole list of people to ask it to
Chris: It's not an actual good interview question, to be clear.
Amos: Oh, no but it's a good breaker.
Chris: Yeah, it’s a good icebreaker.
Amos: I think I would have to say that I like Ruby better.
Chris: Fair enough.
Amos: Terra, Terraform. I don't know. I'm going to the same complaint I always go to it's like pointing out the huge wart is that, uh, just one example in Terraform is that if you want to do a loop over something and automatically names the variable inside the loop each. And you get no control over that.
Chris: Yeah. There's so many ideas in Terraform, but just, I don't know, like, like, like it being declarative. That's actually a really cool idea, right.
Chris: And it's interesting to me that so many alternatives to Terraform are coming out that are procedural. Like they're highly imperative, highly procedural, where that's not really what you want as far as, as I'm concerned. You want it to be imperative. It's just that everything else it's like, it's like kind of like saying like, ah, what's, what's a good analogy for this? I don't have an analogy. It's just the trappings and how you have to use Terraform. And then all the other weird idiosyncrasy things are, are obnoxious and that makes it not, not as pleasant. But there are good ideas in there.
Amos: Yeah. Um, I think I just don't, I think I'm just not that interested in like building servers. So the things that I get out of stuff like Terraform is, um, I, I get excitement whenever I'm like, what can I take out of Terraform? Or what can I reduce? Like if I have some kind of duplication going on, that's the only excitement I get out of doing something like Terraform, because building servers, I could really care less. I don't feel like I'm solving problems.
Chris: Yeah, for sure. Well, and especially depending on where you're working, right? Like there's a, there's a class of problems where that is a, that is like a full-time job. Um, and, and it's worth doing it and you can solve some really interesting problems by doing it. Like if you've got to run hundreds and hundreds of servers that, you know, that that could be fun to some degree, like that's a, that's a worthwhile problem to solve. Uh, if you need to run five or something, I don't know.
Amos: It's probably, probably not that exciting, then.
Chris: It's like, just put that on Heroku dog. Like, like why are we- Why are we wasting time with this?
Amos: Just crank up the dinos.
Chris: Yeah. I mean really though, like crank up the dinos, I dunno, your Heroku bill needs to be what, like what's a hundred thousand dollars divided by 12. Like it needs to be that amount a month before you should not use Heroku is my, as far as I'm concerned.
Chris: Yeah. Well, I think the other thing that I, um- And it's probably more than that really,
Amos: You think it could go higher.
Chris: Yeah. And then I think realistically, the number probably should be higher than that. Unless you just have tons of ops experience, you know, and you're good at that. And that's a main part of your problem or it's, you know, it's so trivial for you. Like it's so it's, it's like so easily reachable that it's worth automating yourself.
Amos: If you have a bunch of microservices its probably easier to run on something like AWS, but I think AWS is part of the reason why Terraform drives me nuts is-
Chris: -Oh yeah, that’s-
Amos: -I mean I got to-
Chris: Here's the telling thing when Terraform is the best UI for AWS, that really explains the entire problem.
Chris: There you go. There you go. Yeah. Like I think the big thing is that you have like these arbitrary security string things that are generated, um, by AWS and server names. And so you end up having to pull all these names into these big configuration files. And if you need to stand up like two to, uh, like let's say you have your entire stack and then you need to stand up another entire stack in the, um, for like another region or something like that, like you have regional stacks,. You have to go in and get all of these things out again, unless you want the regions all to be able to talk to each other. And sometimes you just don't want that. So it becomes this jumping back and forth between the web and the Terraform. And then you're looking at the Terraform and you're like, what the heck is that ID? And you gotta go figure out what server that is. And so it just gets, it doesn't seem to buy as much help with AWS as I would like it to.
Chris: Yeah. I mean, all of it, you really have to do so much of it yourself. Uh, and it really comes down to how good are you at using this tool? How much do you know about using this tool and how, how, like how, I don't know, it's like it's code, it's like anything else, right? It's, it's how much are you cultivating this and taking care of it and uh, spending time on it and re uh, I don't know, like moving stuff around and, and keeping stuff clean and easily understood. It, it, it totally depends on your level of effort. You can't just use Terraform. And it's like, you really have to invest in it and you have to invest in some knowledge about how to use it.
Amos: I think like all code and all projects, it needs to have a kind of a constant grooming and.
Chris: Yeah, exactly, exactly.
Amos: And I don't do enough Terraform for it to become, to become knowledgeable enough to be able to do that grooming really? Or whatever.
Chris: Yeah. Yeah. For sure. Yeah. I feel the same way. I feel the same way. I feel like I'm gonna make a mistake every time I use it, because it has so many little, like, if you run this in the wrong directory, you just broke everything.
Amos: I know I'm going to make a mistake every time.
Chris: Like it's, it's I don't know. It, it has some weird idiosyncrasies.
Amos: I don't even think that I can fix a typo in Terraform without breaking something.
Chris: That's really true.
Amos: Maybe that means that I should spend some more time, time working on it.
Chris: Yeah. Like anything, right? Anything that feels uncomfortable probably is a good indicator that you need to do it more. That's a pretty good, it's a pretty good litmus test for whether or not you should be focusing on something. It's like, how comfortable you are with it.
Okay. Okay. Now I have you and Daniel Erante telling me that I have to do this. Daniel works with me and he does most of the Terraform. And he's like, dude.
Chris: Yeah. I mean anything. Well, I just think that that's a general rule. Anything that you feel uncomfortable about doing, you should probably do it more. Like you're probably not- especially if it's like relevant to your job. That probably means it's something that you need to get comfortable with.
Amos: So what's the most uncomfortable thing for you that's relevant to your job?
Chris: My chair. I need to get a new one really bad.
Amos: I guess you need to sit more.
Chris: And I need a new one super bad.
Amos: Uh, I've been trying to get out of my chair. So-
Chris: So spend some time with Terraform is what I'm saying.
Amos: All right, fine.
Chris: It'll be fine. It'll be fine. It's just, it's just ones and zeros. You're all going to be fine. It's going to be fine.
Amos: I'll work on that. What else have you had on your mind?
Chris: Oh, man. Okay. Oh, I'm so glad you asked. I'm so glad you asked. We already talked about this a little bit in the back channel. So, you know, you, you, you, you know, it's coming, but I want to talk it through because I've, I've been, uh, I've been thinking about this for a long time. Uh, I think actually I was, I was reminiscing with Steve friend of the show, uh, the other day. Cause we talked about this at Lone Star. Like what, two years ago? .
Amos: Is this author Steve, I think?
Chris: Oh, I like author Steve. He's a nice guy.
Chris: Uh, and I presented the idea to Steve and to, I think Ben was sitting there and Chris McCord and like, I'm just gonna keep name dropping off a little bit here.
Amos: That's what we do.
Chris: Um, yeah, so we were sitting there and talking to people and I presented this idea with no real conclusions to it. And I think I've refined it somewhat, but, but, but here's what it is. Uh, I'll stop being vague and just describe it. So I have been thinking a lot about the idea of so-called business logic. And I want to lead in with basically saying that's a dumb term. It's a really dumb term. And it's a, yet another one of these like programmer weasel words that doesn't mean anything. It doesn't like convey anything. It's like refactor. It's like, it just means whatever you want it to mean. Business logic is whatever I want it to be, and whatever. And everything else is not important. That's what business logic means.
Amos: Alright, thesaurus Keathley. What term should we use?
Chris: I don't, well, so this is the thing is like, let's actually, let's, let's, let's explain why it's dumb. Why it's even a w and here's the thing, first of all, doesn't mean anything . Doesn't convey anything. And second of all, I think it's, even if you, if you could align on a definition, you're like, well, it's the logic relevant to your business. Like, obviously. It's like, I think that's wrong. I think it's incorrect. I don't even think, and I don't even think it captures the majority of what businesses do. Uh, like are huge swaths of things that businesses actually do. So let's, let's be at the risk of being comically reductionist, uh, way too reductionist. What, uh, what is the, what does a business do? It takes in data. It manipulates that data, stores that data, and then presents that data to a user in the form of information, in some sort of novel way. And we we've had this discussion before. It's like every business in the world is competing with spreadsheets. If someone can do your, your job with a spreadsheet, they're just going to do your job with a spreadsheet. So you have to be better than spreadsheets.
Amos: And it's a high bar. High bar.
Chris: Why is, why are spreadsheets amazing? Well, because they take data, they store that data, and then they turn that data into information that then can be, like, used by humans to make decisions. And even companies like, I don't know, like PagerDuty, right. PagerDuty takes in information, stores it, and presents it to you in a novel way. Or the novel part is alerts. You know, like there's plenty of ways to, to, to dress that up. But at the end of the day, that's what they do . Well, so here's the interesting thing. People talk about business logic, especially when it comes to like web services and web apps and stuff like that , as this sort of middle layer that sits in between things like rendering and templates and web pages and interfaces and storage. And we, and we call all this stuff in the middle, like the business logic. I just think that's wrong on the face of it because storing data and presenting that data as information to your users is inherently intrinsically a core and important part of your business. Why else do you have a business if displaying the data that data to a user is not a core part of it?
Amos: So, so, uh, I, business logic, right? So I, I view it as this is, this is the, the set of rules, the data transformations that, let's say you have somebody that works at a, uh, an auto shop and they plug in like, what car you have. And it turns some numbers and tells them, I don't know how much oil you need. That's like a basic storage. Yeah. You can do it a spreadsheet. Um, so maybe this is not a great example. But all of the stuff that, that technician doesn't care that it's stored in a database, they don't care that it comes from a web interface or a GUI or whatever. So it's all of that, maybe a better term would be like that manipulation logic, the transformation logic there in the center. And the validations of, of data structure, what the data looks like and the value ranges that are possible.
Chris: Well, I think they actually absolutely care about all of it. And the reason is because when that technician looks to get an answer, they want to get an answer. They want to see immediately what the answer is. That answer can only be divined based on how it is presented, how the information is presented to them.
Amos: Do you think that business logic puts too much focus there and says database doesn't matter, or,
Chris: Oh, sure. A hundred percent that’s- but that's not all of it. I think like a hundred percent. That's part of it. And, and we'll certainly get to that, because that meme of the database doesn't matter, needs to die. That is that's a bad meme. Like it's not, it's, it's, uh, it's, that is,
Amos: It is an important decision.
Chris: That is some nonsense. That is some real nonsense. Like, that meme is silly. It is ridiculous. Um, and we'll talk about that for sure. But I just mean in a general sense that, like, the technician does care, how - they don't care, what database you use, that's your purview, like in the same way that when I take my car in, I don't want to know what all they're doing to fix it. I want them to know how to fix it. Like in the same way, if I go to the doctor, like I'm trusting someone else to understand, to like, make good choices, because I don't understand as much as they do.
Amos: So the term business logic is just trying to separate, like whether you store that in a database or a flat file or anything like that from the, the logic of data validation and things of that nature.
Chris: I don't think you can separate those two things.
Chris: I actually don't think you can separate those two things in it, as much as, uh, you cannot separate them in importance. Like, or you can certainly separate them and build and build systems in layers for, like, for sure you can separate out functions and modules and classes and all these things, and you can bring all of your design to bear on the problem. Amos:
So is it good to separate them?
Chris: Yes, absolutely. And we'll, and again, what we're going to get to that, but I need to do, we need to tackle this idea that like, that somehow the stuff in the middle is somehow more important than all the other stuff around it, because I think that leads to a dis a type of decision-making where you assume things like rendering or let's call it what really is, encoding and decoding, kinda are generic operations that we can sort of give away to a framework to handle. Um, same with storage. Like storage. we, we use all these intermediate layers that attempt to make storage a generic thing. And those tasks are not always generic. Sometimes they are like, you know, it's the classic ORM problem where it's like, it's, it totally works right up until it doesn't until it doesn't support some feature of your database. And then you're like, now you've got to get outside the rules, right. And, and I think that's where this starts to break down is cause we start to assume that what the business cares about is this stuff in the middle, and I just think that's fundamentally wrong. The business cares about how you store things. It cares about the database you use. It also cares how you present that information to a user, and we need to elevate those kinds of decisions to users. And in this case, users meaning us, meaning developers. Developers need to be able to make smart decisions about how they're rendering and how, and, and like that needs to be a conscious choice. It also means that all of that stuff needs to be easily composable so that we can reuse it and start to interact with it.
Amos: So in listening to you, I feel like this, this term comes out of how most, most companies, businesses work in that, um, the storage out of the database and what database to use and how you write to the database and how you get data out of it is all developer decision. Pretty much. Yeah. You, you might have to meet some requirements, but the business, um, probably shouldn't be coming to you and saying, well, you've got to use Postgres, or you've got to use, um, I don't know. We, we want you to store everything in memory and ETS.
Chris: We need Oracle. Or whatever.
Amos: They should not be telling you to use ETS versus a map inside of a gen server, right? Like, that's, that is a decision that you have to make technical. And I think that's where that, that separation comes in, because that's not something that, that your end user frequently cares about. They don't care about what database you have. They might care about some characteristics of how quickly data comes out, what the characteristics of the system that you as an engineer have to make the decision on that database layer. But I don't think that that makes business logic, like a terrible term. Maybe the way that we focus on it is, is worse.
Chris: Well, and I, I think unfortunately, people use that term basically to just like, mean whatever they don't like or don't want to deal with, or they use it to justify design decisions that I think are, uh, often at odds with building simpler systems.
Amos: Do you have an example of that?
Chris: So again, like the storage thing, like the storage, making storage, not a business logic problem means that you make a certain class of design decisions. Uh, so it, a great example of this is like, Oh my gosh, I'm going to get in so much trouble for this. So, okay. So like a great example of this is Phoenix contexts, right? I admire like what they're attempting to do there, which is to emphasize the idea that you should build systems in layers. Like you should build a system such that you interact with the t-with one layer, it interacts with layers beneath it, and you shouldn't, and you should use encapsulation and not have to care about the layers beneath it. But there's all these memes now about, and they are just memes. Like they're just decisions, co totally arbitrary decisions, where you do things like, you should never use queries and repo calls in your controller actions. Why? Why? Like, literally, why? Why is that a rule? What's a rule because, I don't know, that's not business logic or whatever, or maybe it is, or what it's like, it doesn't belong there, whatever. But like, but like, it just, it astounds me because people say that kind of junk and then they back it up with just sort of ad hoc, arbitrary reasoning. And no one will sit and talk about why. As far as I'm concerned, taking in data, like, let's say you've got an API that takes some JSON in, taking JSON inand co and doing some data transformation to convert that into a repo call, like into a query, that's just functions, just like call functions, compose functions together, like,
Amos: Right, but, and I-
Chris: Why do we need to, why do we need to, why do we need to draw these like arbitrary lines, uh, around the stuff we control and the stuff they don't control? And the stuff we control is business logic and the stuff they control isn't, which is just wrong. Like, it's just, it's, it's fundamentally wrong because the business does care about those things. So, um, because I don't want to get too hung up on this, I'm just gonna like leave it at, I think business logic is a flawed term. I don't want to debate the term itself. I'm never going to use it again. I just think it's because I think it's flawed. I think it's, it's totally flawed and we need, we need actual, meaningful conversations about this stuff, if what we want to do is build some, is builds systems out of simpler stuff.
Amos: So you, so you want to get rid of the term because of where it puts focus.
Chris: Right. Well, and because I think it, uh, I think it clouds the actual reasons behind the design decisions that we make. I think it, I think it adds a specific color to the way that we talk about design decisions. And I think that color leads us in the wrong direction. Uh, and I think it also, it, it, it's really important to, to tease out why we do what we do. And the language we use is really important. And that's kind of why I get so hung up on these terms, which is like a totally, I mean, it's, it's totally a pedantic argument, but it does kind of matter. Like it matters in how we talk about this stuff because it changes the way we view it. So setting aside the term itself, which I think is just, you know, silly, as I've said, it's important to kind of figure out, like, why do we make decisions that we make. Why do we make the design decisions we make in our systems? Uh, and so why do we have rules, like, you can't call repo and query actions in the controller module, but it's totally fine for this other, you know, module we arbitrarily call the context to like, have functions that are totally allowed. Like, why is that, why is that allowed? Like, why is that a thing?
Amos: And are they, are you, are they even allowed in the context? That's even another argument. So-
Chris: -And how many contexts do you need and how, and, and are you supposed to have a context should always be plural. And the schema is they're singular. And like, those rules are dumb. Those are, those are just like they're ad hoc rules to justify on already ad hoc design.
Amos: And, well, I think some of those rules are really in place so that whenever you have a new developer come on, they can understand the structure of your system a little faster. If we have kind of a standard across everybody who writes Elixir, or most people, but-
Chris: -Right. I don't know why we needed a word to define modules and functions, but I guess- So, in any case-
Amos: I mean, for me, for me, it's all, like almost all of those decisions are based on encapsulating logic that goes together. So if, if for some reason, I, I don't know, like I changed the type of a column in the database, like, let's say originally somebody made it a string, but it's really always an integer. And we end up changing it to an integer any to, to use it. And so I changed that column. I don't want to have to change a bunch of stuff in my controller. I don't want to have to change a bunch of stuff in my view. So that's how I choose where to put things is, is the stuff that's probably going to change together, I try to keep together.
Chris: Right. Well, and, and to be clear, I do, I'm not, I'm not saying that you shouldn't use modules and functions and build systems and layers. I just think it's important to tease out the layers. So, okay. So let's, let's talk about that. Let's get into some specifics. So I think there's sort of three main reasons that, uh, we create the separations in our systems, especially for, and this is very colored, let's be clear. It's very, very colored by, you know, my me working on web services by where I see the majority of the community focusing their attention to just like web apps and crap like that. So, so it's all very with that in mind as, as like the context here, but that said, I think there's a bunch of reasons why we do make, like, why, why we try to create isolation, um, between systems . And the first is cause we want to isolate ourselves from things we don't control. So if you've got a library, uh, it's often beneficial to wrap that library in a module you control so that you can stub out certain functions, so that you can, uh, swap out the implementation or manipulate the implementation such that it makes more sense for your domain. Like there's a good place to control that sort of stuff. Like that's a, that's a common pattern. Uh, and it makes sense. It's interesting to me that we don't do that for a lot of things. Like it's interesting to me that, you know, people don't do that for Phoenix, the Phoenix rendering engine, for instance, like people don't attempt to isolate themselves from that. Like they don't put their own module around rendering. They don't put their own module around plug, uh, and they often don't do it for Ecto, unless you count contexts . And some people do that for context, but most don't, like, there's not there's- And they don't, and like, they don't attempt to really like stub that stuff out. In, in my experience, in my experience. Uh, and that's pretty interesting to me. Um, that's kind of like an interesting, just thing to note about the Elixir community.
Amos: The Phoenix to Ecto is almost like one whole layer.
Chris: Yeah. Right. So-
Amos: And so, and then you, well, I, I guess this is where, like the idea of hexagonal architecture comes right, is that you have this core and that's what, what we currently call business logic, that sits in the middle.
Chris: Right. Right. And that's the thing you have this thing in the middle. And that thing in the, but the, but again, like going from the idea that all of it's relevant to your business, so you want to control, like, why do you care about like, why do we have this arbitrary thing in the middle? So here's why I think we do. Part of it's because I think part of it's like just naturally, like, we want to isolate ourselves from stuff that we don't own. Um, there's good reasons to do that. And I'm not saying that that's bad. It's just like, that's, that's just what we do . The second is because I think we want to create reuse, like having contexts that have generic functions in theory provides you a lot of reuse of those functions, because you can use them in other contexts. You could use them in other controller actions. You could use them in not a web service, in theory. There's a lot of that kind of talk about stuff. I, uh, have never seen the efficacy of that play out on a long enough timeline. I think on a really long timeline, all of your control, like you get this one-to-one mapping thing where all your controllers call like very dedicated functions that do an operation for that controller. And it's because at the end of the day, like, I mean, unless you're just, unless you just really don't care, like, are you, you're a pretty low scale, like you end up needing to optimize that stuff. You need to optimize queries, you need to optimize the amount of data you're going to return. And so it's really hard to build a generic interface for each one of those disparate actions that are also optimized. So it ends up being that the controllers do most of the optimization work because they know what they need. And there's really not a good way to reuse all that stuff. Uh, also side effects. And that is the, the biggest reason. And I think the, the major reason why we isolate stuff is because everything else around us is highly imperative. It's highly, highly imperative. Yeah. And it's all side effecting.
Amos: I'm going to air quotes. The "business logic" is often you can do with no side effects. If you can get all the data, pass it through like everything in the middle, I mean we can face it, is like an ETL.
Chris: Yeah. Right.
Amos: Shh. Don't tell anybody.
Chris: But I think that's, I think that's what most businesses are. It's, it's basically ETL. Uh, and yeah. Like we often talk about like, " Oh, if we just have this pure business logic," right? And it's like, yeah, but like rendering is part of your business logic. Like showing people stuff on a screen is part of what makes your business a successful business. And like, the only reason we're isolating ourselves from any of that stuff is because it's all imperative and it's all procedural. Like it's all, it's all side effects and there's no way to get around the side effects because that's just not supported by the tools that we use. So there's no way to just say, like, here's the things I want to do. Like you can't just describe like, there's like right now, everything, every controller that you write is an imperative procedural thing. And.
Amos: Is there a way around that?
Chris: All your business logic, all your business logic, in theory, is probably really declarative.
Amos: Is there a way around that?
Chris: Yes! Yes! Absolutely there is! So that's the thing is, imagine a world where you could just say, okay, I've got a, I've got this route. Uh it's it's going to have to be a git, it's at this URL. Uh, it'll have these holes in the URL where I can like get IDs. It has have these headers. And if all that's true, I want to take that data and transform that data into a query. And then when that query is done, I want to run the query. Like you could describe all of that as a series of operations or effects that you want to have happen. And it could all be pure. Every part of that could be pure. Cause it's just a description essentially, of a thing that you'd like to happen. And then you hand it off to a thing that runs it.
Amos: So you build some kind of data structure that says "These are the steps that I want it to take" ?
Chris: Sure. Yeah.
Amos: And then if there's a, the data structure could be smart. Well, the, the thing that reads a data structure could be smart enough to know if it can do different parts of those in parallel or what order or anything like that.
Chris: Right. Yeah. And there's actually, like, there are libraries out there in the world, uh, not in Elixir, in other languages that literally can work out, cause they do like a topo sort on a graph and can work out these things depend on this thing. Uh, these can be running. These can be run concurrently though cause nothing depends on them. And then they're both, you know, relied on by this and then they can actually like do forking and error handling like for you. Because they just understand all that.
Amos: And this is out in the world?
Chris: Yeah. That totally exists. Yeah. Yeah. Yeah. That's totally, I think that exists. Not for Elixir that I know of.
Amos: But, but can do, do you know off the top of your head?
Chris: Yeah, so, there's a library, there's a library called, uh, HAXL, that Facebook wrote, um, or people at Facebook wrote. Um
Amos: Don't say that too loud.
Chris: Well, a long time ago.
Amos: I can't use it if it was written at Facebook.
Chris: That's true. Yeah. Um,
Amos: Just a second, I gotta go delete my WhatsApp real quick.
Chris: But uh, yeah. I mean, like, there are, but I mean all, I mean, to be clear what we're, what all I'm describing here is just like free monads. But, uh, which if you don't know what those are, you should go look them up. They're cool. Um, but like you could do it that way. You also could just do it with function composition. There's no reason that you have to do it- everything is as a pure function. Um, it could just all be function composition, um, and like ring enclosure, uh, uses that idea. Uh, and I think uses it to really good effect. Like you just have a series of transformations for each route and that's it,. Uh, and any middleware, just returns is just a function. And then you just compose functions. And the cool part about just composing functions at that point is that like,- What's the, what's the most composable thing in the world? It's a pure function. So now you can actually compose all that stuff and you can elevate, like, everything to the same layer. Like you full, you have full control now over how you want to encode- decode , how you want to render things, what you want to provide to your user. Like you get to elevate all of that into the same sort of like pipeline and compose it arbitrarily. That to me seems super, super interesting. Now like, its all vapor-ware, like, it's all just like ideas, right. But, you know, I think that there's something to that idea of "What if you could just compose functions?" Like why, why do you need to plug into all these things?
Amos: What's the closest thing that you think that we have in the Elixir community?
Chris: I don't think we have anything close to this. No, I don't think we have anything at all close to this.
Amos: Is it time to try?
Chris: I mean, maybe you could argue that all the witchcraft stuff is the closest thing we have to this, but like, that's just, it's just tools to build this kind of thing. But like you could just as easily build, you could pretty much just as easily build these same sort of pipelines and like using, using whatever. Uh, but no, I don't think, I don't think anyone talks about this kind of stuff, because I think it's too easy just to be procedural. Like, I think it's too easy. Like, like MVC is just too easy. MVC's wrong. Like, I mean, that's the real takeaway is like MVC is a terrible pattern and it doesn't fit well if what you want to do is like function composition. Like if the, if your goal is to do function composition in MVCs, terrible.
Amos: Well, and going, going against that takes a change in the way we think. And that's hard.
Chris: Right. And its pretty easy for like, you know, everybody coming from rails and .net to just be like, well, this looks like Entitity framework, or this looks like Rails, and I can just do this again. And obviously like, I've, I've been a proponent of just saying, you know, listen, build your Phoenix app like you would have built your Rails app. And I think that that's, that's still good advice, but, like, maybe, maybe what if we thought, like, totally differently about this entire problem?
Amos: Well, look at everything else that you interact with in the world. A recipe. Procedural. Uh, putting together that ungodly pain in the butt thing that you bought from Ikea that you really wish they actually had some words instead of just pictures, it's still procedural. Um, so every everything we interact with, it feels like, outside of the computer system is procedural. So, so it's hard to change that way you think. So, so if you want to change the term to change the way we think, how do we need to change the way we think? Like, what is the first step of getting there?
Chris: Yeah, for sure. Well, I don't know. I mean, that's kind of why I want to talk about it. Cause I, this is just something I've been thinking about for a long time. And it just occurs to me that like, if, if what we're truly concerned about, and I don't know that it is, but what if, what we're truly concerned about is like solving business problems, these are business problems. These problems, we like to pretend aren't business problems are, and we need a way to elevate that. We need a way to talk about that. And I think one of the, one of the things that we really care, we want to maybe strive for here is we want to create more reusability. We want to create more chances to, to, to, to reuse and compose functions. And I personally think that that's a very good way to begin to combat complexity is just function composition. Um, but that means that you need to be able to talk about like how, how those functions get composed together. And, and it's really hard to do that when you have everything just like basically creating side effecting APIs everywhere. But there's no reason you couldn't describe, I mean, especially with like SQL, there's no reason you can't describe a SQL query as just data transformation and an operation that you want to have take effect because that's like, I mean, SQL is already declarative.
Amos: So what would it, what would it look like to you? Would it just look like SQL? Just-
Chris: Uh, I mean, well, the API for composing SQL together? It probably just looked like maps. I mean, it really just looked like data. Like I'd rather just compose maps together and then say, do this please.
Amos: Um, that feels like, like active record or-
Chris: -Well, but the problem is, is, is all of the bits, like, you can't talk about, the effect as an effect. The effect is you a function call, you call the function and it, and it does a thing and it returns you an okay. Or an error, or it raises or whatever. But like, you can't talk about the desire to, to do an effect as a first-class thing, currently. I mean, you could talk about that. There's no reason you couldn't talk about it that way in Elixir. It's just that we don't. Like we don't as a community talk about side effects as things that we would like to have happened. Because we're not Haskell. And like that's just is what it is, but, and, and like the tooling around composition, like that is pretty poor just generally. Like you can't really compose functions, and the only way to compose functions is to compose them in a function as a pipeline. There's not a way to like compose a function, like pipes are not reified things, right? And I think that that hurts our ability to talk about function composition.
Amos: Pipes do?
Chris: Uh, no, no, no, just, just generally, that there's not really a good way- the only way to compose a function is to like, create a pipeline of stuff and put it in a function and then pass that other function around.
Amos: Right. Right. There's not like a composability operator or anything.
Chris: Yeah, yeah, yeah.
Amos: Yeah. So you create an anonymous function with a bunch of stuff inside of it, or
Chris: Or a named function with a bunch of stuff inside of it, but either way. Yeah. There's- and you can't, you can't manipulate that thing. Like it's just a, it's a, it's a name that you can pass around at that point. Like you can't continue to compose other stuff on it outside of using a pipe and then pass that stuff around. Cause you need to do that level, that same little like song and dance to do it all. And I, you know, and again, all this to say, like, I I'm really happy using Elixir every day. I've just been thinking about this idea for a long time. And none of it's necessarily all that novel, plenty of other people, plenty of other language communities have, like, worked this out already for themselves. Especially like functional language communities. But it could be interesting, right? Like that could be, I think that there's merit to the idea that we need to elevate these ideas and make them like first-class things. And there's no reason that we couldn't just, like- everybody always talks about like, just doing data transformation, how much they like it. Like, what if you did it?
Chris: That seems pretty good to me.
Amos: Right? And I have a lot of this too. Like I, I spend a lot of time, like, going through functional programming books and Lisp books and mathematical books, and, and because I, I find these things to be safer and more interesting. And I like the way that it changes the way that I think. But, but that, that doesn't make me feel like the business logic name is, is such a horrible thing. Maybe where people are putting their focus in it, cause they assume business logic is the only important thing. I think that is a problem, but I, I, I don't know if changing the term changes that. Clarifying the term, maybe. Cause, cause to me that is still the business often doesn't care about how things are stored. They care, like, they care about performance and some other things that you, you as a developer, as an engineer have to consider, but I'm still okay with the, when I sit down and talk with an accountant about the things that they have to do and the functionality that they want, that is still business logic to me. And so I'm, I'm okay with the term, but I hear you. And I agree with you and I, and I, I struggle to get there. I struggle to figure out how to, how to build these systems and push that boundary further and further to the outside and be able to compose functions. And, and I, I feel for people who are just getting into this the most, because I've been doing this for a while and this rabbit hole is still big and difficult some days.
Chris: So let's talk, let's talk for a second about why it is that you even want to move- I mean, this is the thing that happens a lot. I hear this, this is another meme, right? And thanks Gary Bernhardt for that talk, but this whole idea of like the imperative shell functional core.
Amos: Yep. Yep.
Chris: Why is that a thing?
Amos: Or the hexagonal architectures? Same thing right?
Chris: Yeah. Which, which became hexagonal architecture. It would be with ports and adapters and whatever else.
Amos: Yeah, goes by 10 different names. Um-
Chris: Why do you, why do we, why do we talk about it like that? This is an actual question.
Amos: Like why did we choose those terms? Or why is it such a big deal?
Chris: No, I just mean why is that a, why is that- Why was that important? Why was that talk important? And I've watched that talk too. And I do think it is important, but why was it important?
Amos: Well, to me it's important because that, that, well, one thing is that cores is way more testable because it is pure functions, right. Um, maybe we should define that. I think we have before, but uh, I'm going to anyway. So a pure function is, is, um, it's a map of, in math, I would call it a map of inputs to outputs, every input maps to the, so if you input one thing and you input it again, later, you get the same thing, the same output. So it's a, it's a, what is that called? A range and a domain. And so, right, right, right.
Chris: Phew, man, domain range-
Amos: -My brain hurts. Um, and so anything in the domain maps to the same thing in the range every time. So you could actually replace the internals of whatever your function is with a table lookup, if you had a big enough table, right? I can't do that with time. Like I can't say, Hey, what time is it? That's not a function because the next time I ask you, you're going to give me a different answer. Its the same input.
Chris: Right, yes. For sure. Okay. I, I allow, I allow this, this definition of purity.
Amos: Thanks. There's I was trying to like get it down to small essence. Um, so those things because of that are very testable. Um, they're, they're nice to look at and testing side effects sucks. And knowing when side effects happen gets very complicated, the bigger your system becomes. So if you can shrink the number of places that you have side effects, oftentimes you can actually shrink the number of side effects you have in general, because of that. So it's like, it's like a, to me it's like a giant magnifying glass. And, and so you have all of your input and you're trying to focus all of your, um, all of your side effects to a little, little bitty pinpoint of light.
Chris: Right. And well that's, I think, I think the really important thing about that talk to me is that it, it's acknowledging that, uh, side effects are going to happen and they matter. Because we have to work in the real world, we have to do things in the real,
Amos: Well, if he had just put ammonia around it, then you don't have to think about it.
Chris: It's just a burrito, you know, or whatever. But you know, like we're, we're - that talk was really important because I think it acknowledges that side-effects matter. And then, and how we deal with those side effects matter, like the errors around those side effects matter. And actually this is, this is still a thing I think is not well solved by, you know, most like free monad interpretations because the errors do matter. Like, and what you do when you get an error matters. But this is like where the whole, like, railway oriented coding thing really falls apart is because like most of the time you actually care about the error. Um, and you can't just pretend it didn't happen or it doesn't exist. Like you actually do care and you want to have a fallback and you want to do other stuff and you want to take advantage of all those things. And so you have to code around all that stuff. Like, you know, it, that analogy pretty much falls apart outside of pretty trivial things.
Amos: Yeah. It's like, as soon as you have to start batching data to large amounts of data, then you're like, well now what do I do if only one of the things fails. Do I stop everything, do I roll back every- So yeah, the errors matter a ton. And what you do with them.
Chris: And to be clear, I don't have a solution for that. Uh, and maybe like the whole functional shell imperative, whatever, whatever, you know, maybe that's maybe that is the, the, the right approach. Um, but in any case, like I think that's one of the important things is that it acknowledged that side effects have to happen. We just want to isolate them. We want to like move them to the boundary of the system, right. But all that being said, like, what if you had a way to describe side effects as data and, and like, at that point, why do you need to move them anywhere?
Amos: Wouldn't they still be-
Chris: I mean, acknowledging the fact that acknowledging these are, I'm actually asking because, uh, I mean, I'm talking from both sides of this point, cause I'm saying in one hand, it's like, I totally get why they matter and I don't have a good solution for it. But what if, what if you could, what if you just leaned into it and built a system such that you could care about, the errors, have fallbacks, all that stuff, but it also compose nicely and you were able to just build up this description of all the stuff that you'd want to do. And I don't even know how this would work for like, and there's so many things where this falls apart , where you want to talk about, you know, doing a gen server call across a distributed network and all these sorts of things, you know, it's like, you know, all of it falls apart, as soon as you move distributed and all this, all that sort of stuff, right. And then at the end of the day, it's like, that's why pragmatism wins out. And we do what we do, but I just think it's interesting. I think like, oh, what does a system look like where you, where we didn't, where we relied more on data manipulation and a lot less on sort of random side effects.
Amos: (Dramatic movie voiceover) In a world…
Chris: Right. Like I don't, I don't know. I don't know. I don't know what happens, um, in that like, and I don't think that the current solutions that, that I've seen presented in other places really ca- like do enough for you. Or they're missing, you know, it's like the railroad oriented programing thing where it misses, like, this huge use case, this huge other swath of stuff that you actually do have to care about as a, as a developer and a maintainer of these things. But yeah, but I don't know. I, I I'm intrigued by the idea. And I think that, I don't know, um, I I'm continually compelled by the idea that we could be building systems from much simpler bits. Like, like how do you render Protobuf in a, in a fricking Phoenix controller? You can't like, you actually can, but you can't build it, you can't build a generic thing that does it. Like it doesn't, you literally can't plug generically plug Protobuf decoding into, into Phoenix's rendering engine. You know, cause it's, it's, it's actually, because that's just not how it works.
Amos: Right. Everything's custom there.
Chris: That's not how it works. You, you can do it, but you've gotta, but you have to do it yourself. And at that point, like why didn't you just have functions that compose together?
Amos: What I just heard from you is like an hour-long discussion about your next project.
Chris: No, I'm not going to build this at all. That's what we're talking about on this podcast, because I want other people to go solve this. I've got too much other crap.
Amos: Hopefully somebody else will do it.
Amos: Um, I did, I did have an interesting thought whenever you said, uh, we reached back to pragmatism and maybe that's, uh, another term that we should have a discussion about sometime, because I often find that pragmatism is really just, "What do I know better than something else,
Chris: Oh, absolutely!
Amos: So as you learn more, as we push these boundaries, our pragmatism becomes different and we say, "Oh, maybe we should be doing this. This is more pragmatic." And it's only more pragmatic because you have more knowledge now.
Chris: Right? Mm. Yeah, for sure. I agree with that. So, yeah. So I don't know. I don't know if this was helpful or even useful or even coherent. Uh, it's probably not. And it probably came out sounding more like a rant than it against like the status quo, than I really mean it too, because I actually quite like the tools I use every day. I don't have anything against the tools I use every day. And so if anybody messages me about, like, "You guys really need take back what you just said about Phoenix. You hurt my feelings." Like, no, get over it. Like, this is, this is, uh, this is, this is us talking about, about stuff. I'm not here to say that that stuff's bad. I'm like, what if it was- cause the thing I'm describing could be just as terrible. Let's be clear.
Amos: It's just, what if it's-
Chris: A thousand times worse or whatever. Yeah. Like, you know, it's easy to sit here and just say stuff. And I actually, like I said, quite like most of the tools I use every day, so I'm not too, I'm not complaining actually complaining, but, uh, it's interesting to me. And I do think we put too much emphasis on the sort of us versus them, like my logic versus this framework's logic. I think we do, I think we do that to our own detriment. So yeah. So that's what I've been thinking about for the past couple of days slash years.
Amos: All my life.
Chris: Specifically in the past couple of days. Yeah, for sure.
Amos: Yeah. I know that we talked about it earlier. I don't know that you've changed my mind on calling it business logic, but, but, uh, uh, you definitely have me thinking more about where can I push those boundaries and, and how should I think about them.
Chris: Good. That's what I'm here for. I sharpen you like a knife. All right. I, I hone, I hone your philosophies. I provide the foil for, for all of your ideas, for all of your preconceived notions, I'm here to tear them all down.
Amos: Well, thanks. Thanks. I feel like it's more like a prison shank that you're sharpening the a knife, but-
Chris: -Well, you know, listen, I'm not stuck in here with you. You're stuck in here with me.
Amos: Just myself. Just to be clear.
Chris: Yeah, I don't know. I, um- (makes incoherent gagging noises)
Amos: I think we should just end it like that.
Chris: Yeah, that, that's what, that's what I got. That's what I got. That's all I got. I don't know. None of this is coherent yet because it's, it's, it's like, I, I feel like I'm onto something, but I don't have an actual answer for it yet. So we'll see. Check back in like six months.
Chris: I don't have all the words yet. Ready yet. I have not. I've not honed my sales pitch. This is, this is me developing a real tight five on, on why this is a good idea.
Amos: I'm sure that we'll hear more of this as we go.
Chris: Yeah, for sure.
Amos: I mean, this will definitely come up.
Amos: Well, I wanted to come in and talk about design today. So this is good. Cause we talked about design.
Chris: Yeah. I don't know if it was helpful.
Amos: Uh, well.
Chris: I'm gonna go out and say not helpful
Amos: Well, you got my brain going. Maybe it's time to go on a walk
Chris: Yeah, I'm gonna, I'm definitely, it's like the first sunny day and we've had a week. So I'm definitely gonna go for a walk.
Amos: Oh, nice! Got some Sahara dust out there?
Chris: Uh, no, not too bad. Not too bad.
Amos: It's the year of the plagues.
Chris: I'll tell you what? 2020. Worst. Year. Ever. (Amos sighs) Alright.
Amos: Go home, 2020. You're drunk.
Chris: Yeah. No doubt.
Amos: All right. Well it was nice catching up with you.
Chris: Yeah. Uh, we should do this again sometime.
Amos: Yeah. Maybe, maybe we'll try. Next week.
Chris: I, the next week is working for me. Let's do it.
Amos: Alright. Sounds good.
Chris: Be safe. Enjoy your holiday.
Chris: And by the time this comes out, Binary Noggin might still be hiring. Check our website. There's a little, uh, hamburger in the upper right-hand corner. There's a job description up there. And uh,
Chris: He doesn't mean one of those menus. He means a literal hamburger.
Amos: I should change it to be a hamburger.
Chris: He means a literal hamburger.
Amos: All right, thank you.
Chris: Let's call it a day.
Amos: Take it easy.