S11E12 Package Management Intro: Welcome to another episode of Elixir Wizards, a podcast brought to you by SmartLogic, a custom web and mobile development shop. This is Season 11, where we're branching out from Elixir to compare notes with experts from other communities. Owen: Hey everyone, I'm Owen Bickford, senior developer at SmartLogic, and I am your host for today's episode. For episode 12, we're joined by Wojtek Mok, developer at Dashbit and HexPM team member, and Amal Hussain, engineering lead, community organizer, and podcaster. In this episode, we compare package management with Elixir versus JavaScript, Go, and maybe some other languages. So welcome to the show, Amal and Wojtek. Amal: Hello, hello. So happy to be here. Thank you for inviting us. Wojtek: Hey everyone, thanks for having me on. Owen: Awesome. So before we jump all the way into the weeds and start unpacking, first let's go with Amal. Like I said, previously, I'm a huge fan. You want to tell us a little bit about your background, kind of elevator pitch of who is Amal. Amal: wow. Oh, it's been a while since I've done an elevator pitch. Let's see. first of all, thank you so much for having me. I love the Elixir community. , it's an honor to be in your space, , in your very warm and fuzzy part of the internet. So thank you. My name's Amal Hussain. I, am an engineering lead, so I've coined that term for myself because I've been swinging between staff principal and an engineering manager for a few years now. I've kind of landed now, in management and I think I'm staying there for a little while. So, I've crossed over to the dark side. But I've spent, my career working in and around, JavaScript for the most part. I've certainly worked with other stacks. , but. I think community that I'm the most excited and passionate about is the JavaScript community, specifically the Node. js community these days. I've spent some time working at NPM, which is actually the company in the project that, hosts and manages JavaScript packages, , I spent some time there, was there throughout the GitHub acquisition. And exited after that, , and, I've worked at Stripe, as a staff engineer, I've worked at, Indigo AG as a principal software engineer, most recently at Cisco as an engineering manager, and, and yeah, my job was recently restructured, , and I've decided I'm, I'm not transferring to an internal team, so I'll be interviewing with companies in the new year and excited to see where I land next, but, sticking with engineering manager for now. And I do a lot of community work as well. , technical education via a podcast. , that's listened to thousands of engineers, , weekly called JS party, , and, generally just involved with the JavaScript community as well. So that's a bit about me. Owen: awesome. That's all I realized immediately. I'm like, Oh, I should have brought my JS party shirt to the, to the party. Amal: Yeah, you should have, gosh, shame on you, Owen. Owen: I know. I know. , so we're still in the elevator. I've skipped the floor. I was supposed to get off of because everyone here is so cool. Voy tech. What's your elevator pitch. Where do you come from and what are you up to? Wojtek: Yeah, , I'm from Poland. I'm based in Krakow, Poland. As you mentioned, I'm a developer at Dashbit. I've been Elixir ing. , I think professionally since 2016, learning a couple of years prior, before, which would come as no surprise to many folks. , I was, uh, Rails developer and then I think at this point I'm allowed to say that back in the day , I started, with PHP. Perhaps relevant to, this conversation. I've been on the HEX, , team , also since 2016. I guess I can take maybe some credit of where HEX is at, but it really goes all to Eric, , Meadows, , who started the project and. Over the years, he did the majority of the work. , I think the , power laws like really apply to many projects, to hex, , certainly as well. Owen: Right on. and I'm just remembering, I've got a support question for you. So some later, uh, so, uh, I'll save that for maybe after the podcast, right? Like I've got an account. I need to delete or something like that. You know, uh, Amal: This is a really great way of getting tech support, you know, invite people to your podcast and just Wojtek: Very Owen: All right. I'm all I got JavaScript, JavaScript questions for you. Uh, no. Uh, so have we all written PHP at some point? Cause I know I have. Amal: Yeah, many many years ago. I was very lucky to have not written PHP for too long Only because for me Ruby on Rails still is definitely, my favorite overall developer experience, when it comes to, server runtimes, that are more turnkey, you know, I think, it's, very opinionated, but, was very happy to write Rails code, and then Java code, and then once I discovered Node, I think it was just game over for me, that's, It's been my preferred go to, but, only because, you know, Node lets you have, you can create the Ruby on Rails experience within Node if you'd like, right? I'd love the, like, choose your own adventure that you get with Node. , you get to really design your architecture and your dependencies. And, , it's, flexibility just allows for, I think, , more of an unshackled developer experience, which, I think as I'm more senior now and can make better choices, I prefer that flexibility of , having that high ceiling, , which I think, , can be a little bit more challenging in Rails, which has very strong opinions about the way you should do everything. As great as those opinions are for me, for the most part. So. Owen: Right. Pivoting a little bit to package management, the topic of the day, I am, as of, was it this year, last year, I'm officially an open source developer. I have a package on hex PM. for, pass keys essentially for WebAuthn. , so it's like a drop in WebAuthn component for LiveView apps. Just to, I guess, , shamelessly self promote a little bit. Voitec, I know you've got a, uh, so REC is the first one that comes to mind, cause it's in almost every project I'm on. If we need to hit up HTTP in some way, what are some other packages you've got out there in the wild? , Wojtek: I don't really have other , things that I started myself that are relevant. , I suppose, , yeah, well, so I hope with Xdoc, , as well, with Ecto, as well, maybe slightly less, uh, these days, , and. I did write a MySQL client five years ago, , as well. So I, I, I guess maybe this four, rec, xdoc, ecto and MySQL. Yeah, I'm probably, uh, misremembering, but yeah, Owen: no biggie. Just like the most, widely used packages in the entire ecosystem. Wojtek: no, not, not at all, Amal: you said my SQL client. I, I think the real question is, are you team OORM or team? No, ORM. You know, that's the real question. Wojtek: I also mentioned ECTO, which is the ORM, so definitely in that Amal: Mm-Hmm. . Okay. Yeah. I'm, I'm personally like team, no, ORM. I'm, I'm kind of done with oms. Every ORM I've used has , let me down at some point and, , it's either caused like a performance bottleneck or it's. wE've just had limits with the API, we hit that limit where like, oh, you can't do a certain thing. Or even worse, a popular ORM that we were using a few years ago hit like, end of life, you know, they announced end of life and so what do you do? Right? Like , Yeah, I've just gone the route of no ORM and I've, I haven't really looked back really. I've, Wojtek: Yeah, that's cool as well. You should check out ECTO. I think it's not quite like the others. , it is slightly, , maybe closer to the no, ORM than most. , I don't know how to describe it, but I think it's, yeah, I think it's, pretty good. Owen: Whenever I'm explaining Ecto to someone who's not an elixir. Normally, I say it's kind of our ORM, but it's not really an ORM. So It's just kind of like Elixir syntax for your queries, Amal: It's my favorite kind of ORM, really, you know? Owen: right? Like it just compiles down to SQL anyway. Amal: an ORM that doesn't look or feel like one. Owen: Right. Wojtek: Yes. I think it even says on the tin that it's, like a toolkit. So it's like a bunch of components, , that are orthogonal to each other. So not really like a whole, I, I mean, it's a whole package, but it's, it's separated. Yeah. Owen: Right on and Amal, you've been programming for a while, if you've got either some packages you've maintained or contributed to over the years. Amal: I'm not a library author. I've been really heavy on the consumer side as a tech lead. and I've like peripherally been around a lot of famous packages and package authors, if you look at like some of the top maintainers, that have packages on NPM, like Six of them, I would consider good friends, , so in that sense, I feel like, , I'd say almost like a package groupie, you know, I'm friends with them. But no, I, for me, I've been like leading application development. So that's really been my focus. I've worked on open source, I've contributed to different things, but, my bread and butter, within my career has really been like leading application development, for teams. And, as a tech lead, , and now manager, I've definitely developed, , what I would consider a kind of a rubric, for, how I pick my dependencies. Cause I think being on the consumption side, it's really important to understand, like, how do you even vet a package? there's all these options, how do you weigh them out? , and how do you weigh them out against? the needs of your team and then just also generic best practices. Right. We're kind of spoiled for choice within the JavaScript ecosystem. I mean, if you're looking for any one thing, there's like, here's 25 packages that, that do it. Right. And so, how do you pick, how do you decipher? Those are kind of the exercises that , I've gone through with the teams that I've led in the past. It would be great at some point for me to write a blog post and publish it or something. Right. I think more teams need to, have a better muscle around how they pick their dependencies. Because the reality is once you pick a dependency , you're in bed with it for a long time and, it creeps throughout your code base. It, gets used in, in all kinds of places. So. I think managing the gate , is very important. Any time spent vetting your dependencies is not time wasted . , so often people just pick the most popular thing, but sometimes it's not always the best thing for you and your project. Right. Wojtek: If I may just add, I, I totally endorse. And, , I would just add that, if you pick dependencies, you're stuck with them, but you're also stuck with the transitive dependencies, the ones that they bring over Amal: Oh, right. Absolutely. All their luggage. Wojtek: yeah, other luggage. And that's something that, I think people sometimes forget about, but I think it's a huge factor as well. Amal: Absolutely. I mean, when I'm evaluating a package, , it's a serious thing. Looking at the packages dependencies is also part of the exercise, right? Because you want to know who are they bringing to the party, , who's also going to live in your house. That wasn't a directly invited guests, but they're indirectly there. Owen: the in laws. Peace. Amal: yeah, the in laws, the friends, I would say more so, they're perhaps not in laws, but they would say that , they're subcontractors or whatever, right? Like, they're useful, like, these, these subdependencies are not, they're not bad necessarily. But I think understanding, like, the health of them is important. I'm happy to say, we have projects in our community, like xState, , that really pride themselves on, like, zero dependencies, right? and I'd really like to see more projects like that, it's not always possible, but I think it should be a point of pride for a library author to say, Hey, I have low dependencies or no dependencies. Right. , it just makes it easier to maintain, especially in the world of JavaScript, where we have this thing called peer dependencies. for example, , if you have package a package, a requires these other packages. And, hey, if you are dependent on these other packages being in my system, how strict are you with versions? What's the backward compatibility between things? How well do things talk to each other? I'll use a front end example, like with react, you know, if I'm using some react component and it has a peer dependency and it's like, Oh, you have to be at this version of react, but no higher than this version. That's too strict for me, you know? Peer dependency evaluation is also very important because at the end of the day, like as much as we want to think about these things in isolation, like our dependencies are also interdependent, and so there is a tree, a literal tree, especially in JavaScript land, there's a dependency tree that gets created, right? And it's this super time machine, and weird things happen in NPM land. Like, for example, you would never expect that. Uninstalling a package would install something, but that can happen, right? Because if you uninstall something and all of a sudden, , the tree analyzer sees, oh, I can now update my version of this other package. Now that this other package is gone, that kind of stuff also happens. Right. So it's important to think of your dependencies a bit more holistically And see how they, play well with each other. Owen: All right. And then staying on the using packages side of this conversation. What are some practical approaches? Let's say you're working on a project. Maybe it's your product company or your side project or a client. And let's, assume that security is important. I think it should always be important. And you're looking at, I don't want to necessarily pick an example, but I don't know. Uh, time library or something with dates or tables or something I guess I'll start with you Vojtech, , I'm thinking about, I work in an agency and I've got clients I can write a lot of code. I can. Create my own dependencies internally, but you know, there are some things that just don't make sense for us to write. So I'm going to need to reach out and grab a package somewhere. And if I'm looking at hex, I get some amount of information, you know, is this recently updated? , how many people are using this? Those are some kind of cues to me as a user. And then looking at the repo, what's the issues tab look like? And PRs and it's not just like quantity, but, are there severe problems that people are reporting that kind of thing? That's kind of where my mind's at Wojtek: Yeah, I would say these are definitely , good ways to think about this. , I would again echo what Amal said, like, yeah, you need to choose your dependencies carefully, but like also look at what other dependencies they bring, ideally they bring zero or, as least as possible. , And, I think looking at the issue tracker is certainly helpful. It sometimes can give you a wrong impression, though. , like some of the packages are, you know, are done, it rarely happens, but it turns out software can sometimes be complete. And then someone can be like, oh, this package hasn't been touched in two years, I'm not gonna pick it, but then yeah, you should absolutely pick it, cause it's been, super stable. So I don't know if there is a concrete advice to to give, Amal: and I would say that looking at the last time the package was updated isn't always a very good metric in the sense that sometimes, let's say a package is just doing one plus one, right? Like one plus one equals two is like a constant thing, right? if it's an algorithm or something very stable, right? The main thing you want to look out for at with something that's, Hey, it just works. It shouldn't change. It shouldn't require a ton of updates. Like the main thing you want to be looking for in that case is security, right? are there security vulnerabilities that have been reported on this code that would now make it something that should require an update, and, and if the answer is no, then, then that means that like, okay, if it's, if there's no security vulnerabilities on this, and this package hasn't been updated in two years, but it solves my problem. Like I can absolutely use it. Code is code. Right. And that's why I think for me, when I'm on the consumption side, the first thing I start with similar to what Wojtek said, you know, starting with security you know, you want to start there, right? If something doesn't pass that test, there's no point in going towards any of the other steps, especially if it's a new package that you're adding. And for me these days, the best in class, developer experience and just tool for doing that is socket, socket. dev. And socket is not just JavaScript. Now supports Python and Go dependencies as well. And I think they're actively adding more communities. , but Socket. dev is, is just a great resource for just saying, Hey, like here's the version of the package that I'm interested in importing. Does this pass the security smell test and yes or no? , that's where I typically go. So once I know that it doesn't have any security vulnerabilities, the next thing is like, okay, am I using this in the server or the client? Based on where I'm using it, I'm going to have a different set of constraints and requirements, right? So for example, if I'm using something in the client, bundle size is very important to me because I'm now increasing the size of my dependency tree. I'm shipping more bytes to my users. And so I want to make sure that that is as efficient as possible. And so for me, performance, matters, greatly. So I'm typically looking for, like, what's the most performant way for me to add this dependency to my, to my application. , on the server, , definitely, like, bundle size, and I'd say the size of the project matters, but less so, right? Because , that's not code that, has to be shipped over the wire as much, for users. So, um, so those are the two kind of places that I typically start. Owen: So that kind of covers like me, a professional engineer making too much money goes in and looks at package to decide whether it's appropriate. Right? There are tools that we can also use. I know NPM introduced NPM audit several years ago. , we have similar tooling in Hex as well. I think at Hex audit, there's also a separate dependency you can add in for, for a mix audit. I think there's like two different audits you can run on your Elixir project. Is that right, Wojtek? Foyte? Wojtek: I think there's hex audit, that looks at, whether, any of your packages has been retired. It is been a while since I used it, to be completely honest with you. Yeah, I'm trying to be a good library author and don't bring any packages. Owen: Oh, right. I Wojtek: So why would I have to, you know, Owen: you're like, I write all my codes. So so hex audit is like, do you have any dependencies that are out of date? Obsolete. Mix audit is the one that actually looks for known vulnerabilities. Wojtek: Oh, that's a, that's a third party. Yeah. That makes sense. Owen: Yeah. Like a deps audit thing. So. Amal: I think there's something worth double clicking into Owen, which, Wojtek just brought up, which is around like, oh, I . Try to write it on my own. Right. So sometimes people say, Oh my God, this NPM package, for example, left pad, you remember left pad, So basically there was this package. Right. So that it was just like one line, right. One line of code or something like that. But it was this package that was used. Thousands and thousands and thousands of times a week. , and it sort of brought down the internet when there was a whole issue with it, I won't get into, but basically like it brought up this discussion of like, how big should a package be in order for it to be a package? And my whole thing is like, I don't actually care if it's one line or a thousand lines. It's a module is abstracting away some piece of functionality. And I don't necessarily need to know how. Right. The point is, it's abstracting away a problem for me and I get to leverage the solution. Whether that solution is one line or a thousand lines is less important, less, you know, I'm kind of evaluating performance. But, I think it's perfectly fine to abstract away. Things in modules and packages, even if they're small, , that's the whole point of modules, you know, big modules, small modules, they're all equal because they're all solving problems, right? They're solving problems for you. So, IT's okay for a package to be small. Owen: I'm glad we've double clicked here because I think this the season we're comparing notes across communities and I, my impression is that this is a kind of a bit of a philosophical difference between the elixir and maybe the javascript ecosystems where elixirists Seem to prefer to have the fewest dependencies possible. And then, NPM, don't want to paint with a broad brush, but it is a much larger community and it does seem like the inclination is to find the dependency that will solve a problem first and then write it, write the code for the thing as a kind of last resort almost. Hey, am I being fair? Is that fair to say? Amal: no, no, absolutely. And I'll give you, I'll give you some numbers to back it up. Google has , you know, they've got all the bots that do all the indexing and whatever else. Right. And the statistic that came out of, Google's bots a few years ago was that out of every 10 lines of application code running in the wild. Nine of those lines are third party code. That's nine of those lines. So only one out of. Every 10 lines is code that you wrote for your application. And for me, like you're thinking, Oh my God, like that's, that's insane. But for me, I think that's open source working. That's a good thing. We want that. I don't want to reinvent the wheel. Like if somebody has a solution for something, I'd rather use that. And I think the benefit to doing that is also that. That solution is maintained by someone that's really focused and dedicated towards it and knows all the edge cases. And so as things shift in the community, or as there's new standards, or as there's new things in JavaScript or whatever, as there's better ways of doing things, that dependency gets updated, right? and if I wrote that same solution in my code, it's not my primary focus. . It's probably not getting updated, that's the benefit, , to leveraging open source and, absolutely, I think that was a fair statement. And I, want to echo and say that, I think that's a good thing, , because ultimately, , we don't have infinite time and you want to spend most of your time as a software engineer writing code that only you can write for your customers and your users, right? Like if I'm, starting some new SaaS company and my first thing is like, Oh, I'm going to rewrite a new HTTP framework. That's not necessarily a very good use of my time, right? How is that serving my users? It's not right. I should just NPM install. Set HTTP, whatever HTTP framework I want, and then just go on and write the code that is going to serve my customers, you know? And so I think that's, I think that's a good thing, Owen. What do you think, Wojtek? I see you nodding. Wojtek: Yeah. I basically agree. , at the same time, I somehow found myself writing an HTTP client, uh, a couple years back. So there is that. But, be fair, , I think I, had a, like a different take that maybe was not explored. So that was kind of the reason, , to do that, , but in any case, yeah, I think it's really hard to come up with these, like concrete rules, like what constitutes a package or what, doesn't. Pretty clearly something like left path was a very bad idea. . It's okay to paste to vendor in some code, but I think it's totally okay to have very small packages as well. For example, one of the packages that we maintain is, like a small tool, but, I immediately thought about it. So it's a Nimble TOTP. So TOTP, like the authentication codes, one time password, something, something, right? Like, yeah, it's, it's a small package. It's maybe, I don't know, like 50 lines of code or whatever. Anyone could write something like this, , by themselves, you know, from scratch. But yeah, it's a fine package, I think so. can be a small package like that, or it can be Phoenix, you know, web framework and kind of everything in between. I don't, know if there are any particular rules for Amal: Yeah. Agreed. Owen: on that note, I find myself sometimes , I will find a package that maybe it's simple. Maybe it's not, , but there's just something in there that doesn't quite fit my needs. Even if I'm not installing the package, being able to look at all the source code and think about, okay, like I can take cues. I can actually learn. Level ups in some ways just from like reading other people's code. So that's just, it's just so great that we have an open source, kind of a marketplace to be able to share things and, , you know, people are generally, I think, well supported enough to keep these things going. But yeah, being able to like, look at some source code and even if I can't just install it and use it right away, I can come to a better understanding of how it works and how I might do it a little bit differently, or maybe open a PR and extend things a little bit. That's another thing you can always do. Amal: absolutely. And there's even this package, the name is escaping me, but there's a tool that you can use in, in NPM that, , this isn't part of NPM. Somebody wrote, wrote this package, but , it basically allows you to patch something. So let's say you find a bug in your dependency and I don't know, the maintainer is on vacation and isn't going to merge your PR for the next like three to four months, but you have a solution and you don't want to fork it or anything. So there's, it like lets you basically, pull your PR code in. And so it does like a temporary patch in place. Like, I think that was really cool. I'll, we'll try to link the, the name of that tool in the show notes so that you all have it. But, but yeah, I mean, that's a, real problem. Like sometimes when you have to do something that a Dependency doesn't support, you're kind of at the mercy of maintainers at that point, right? , it's tough , and sometimes your PRs don't get merged or don't get reviewed in time. And, you know, that's a real reality. And I know that, , that Microsoft, Azure, for example, they get, they have security guarantees going way back, to really old versions of node their dependency tree for their SDK is, is severely edited from what's available on the free and open source world. Right. Because they actually go in and retroactively patch security updates if they don't get patched , in the dependencies themselves. So, just. Saying if you think that's complicated, like, I, I feel sorry for the folks at Azure that, you know, are maintaining their own, their own custom trees. Yeah, Yeah, that's hard. Wojtek: A team. Amal: for a team. Yeah, literally. But yeah, we all appreciate, cloud providers and, and, and them making sure that our code is running in secure environments. Like that's good, right? Owen: Yeah, we don't have to run our own data centers. That's pretty convenient. Amal: Exactly. Owen: so like you mentioned being able to refer to a specific branch and a repo, that's very helpful. That's one thing I know we have in, in hex. , you can point to like just a version and it will go to the default hex repo. You can provide it an alternate repo to look for packages. You can also give it a, a git, Location and even tell it which branch to look at. So I really love the flexibility we have here with hex. Before we get further into the weeds with how these things work, I'm curious before we had package managers, were we writing things down on paper, floppy disks, CDs, like how are we sharing code, , before package managers were like a real thing, who knows, Amal: Oh my God, the dark, , the stone ages. I don't even know if you need to go that far, actually. Just look at Java really. , somebody was pointing out the other day to me recently, like, Oh my God what's going on with Java? I'm having to edit an XML file in order to add a dependency. You don't have to go that far to, to look at painful experiences. Of course, like now this, this process is abstracted with Maven and Gradle and all this stuff, but it's still under the hood. What it's doing is editing an XML file. And I think in Ruby land, I remember when I was writing a lot of Ruby code, there was the Gemlock file or something like that right like and that was a that was I wasn't so bad and then you would do What was it? There was like what was the command for? Installing your dependencies or running them. I don't know there were some commands Wojtek: like bundle install or, Amal: Yeah, bundle install Thank you. You'd bundle install your gems, you know. I personally am very biased, but I think the JavaScript community has the best in class developer experience when it comes to package management. Especially the fact that, we've totally democratized Publishing of packages by putting NPM publish in, right? Like it's available to everyone and anyone, who wants to publish a package. It's right there. You have Node, you have NPM, you can publish a package., but yeah, I try not to think about the, the dark days, but I don't know. What about you, Wojtek? Wojtek: I think that in the dark days, people were just vendoring in the code. , so the dependencies became part of your project in some corner, , of the repository. If you've had a repository , in the dark ages, even, which sounds pretty terrible, but at the same time, It is accurate, right? It is accurate. All of these dependencies are part of your project. So maybe there is like one, , I wouldn't say silver lining to it, but some, Kind of truth to that, Amal: F T T P, you know? Not, not F T T P, I mean F T P, sorry. Wojtek: oh, FTP, uh, yeah, like, so like for me, FTP and PHP, it's like peanut butter and jelly. Um, you know, still, Amal: Yeah. I can't believe I said FTP. That's how, you know, I'm like, that's how much I say the words FTP anymore. I was like, just like merging it with HTTP. Owen: So also thinking a little bit about history, NPM exists, uh, has existed for, I don't know how long, do you know the number, like the year off the top of your head? Amal: Node is about to turn 15. So I think, it's about 15 years almost. Yeah. Owen: Got it. Amal: Mm hmm. How long, how old is Go, actually? Owen: Good question. You'd have to ask a go time. We don't, we don't talk about that here, Amal: Okay. Mm. Owen: I don't know. I know Elixir crossed the 10 year line this year, last year, I forget when. So. There was some prior art, you know, with NPM and, and maybe Java as well. I'm kind of curious, what lessons we were learning from, Wojtek: Ruby gems, definitely. Owen: oh, RubyGems, yes, not a Rubyist. So what were some lessons you were learning, , both in the positive direction, like I want to do that in Hex and also some problems you could avoid by creating a new package manager for Elixir. Wojtek: It was Eric who started the project and did most of the work. But, some of the things that come to mind for me is the log file. I think NPM has a log file these days as well. I know it didn't, didn't used to maybe, you know, five or 10 years ago or something. Amal: It was optional, But now it's always there. Wojtek: it was optional. Yeah, so hex, , definitely started with a log file. , and then, we also. I suppose it's the same with NPM. probably taking ideas from NPM, but we were installing all of the dependencies locally to your project, which was not always the case in prior tooling. I remember, I think Gems, like before Bundler, you were just installing Gems like globally. Amal: I remember that. Wojtek: And so. kind of installing things local to your project, right? Not a great idea. Amal: Yeah. Yeah. I remember that actually. Thank you. Thank you for saying that actually. I didn't, I don't think I had mentally made that, like, I didn't register that. , but you're absolutely right. Yeah. Everything that you would install would be available globally, which I'm like, whoever thought that was a good idea, you know? And what's, interesting about NPM is you can install things globally. You know , instead of NPM install, like foo, you can do NPM install dash G foo, you know, and that'll do it globally, but like, why would you ever like, you know, there's so few reasons why you'd want to do that. Maybe you have a CLI that you use across all your projects and you'd want to do it for that Wojtek: think this is the only reason, right? Amal: That's the only time that I think you, you, that would be justifiable. So, yeah. Wojtek: But yeah. so talk about dark times, I think. Yeah. , so I think, bundler paved the way to kind of obvious idea in hindsight, but , Install things locally, have a lock file so that whenever another developer is going to, Use your project, they're going to have the same dependencies because they're going to be locked with the lock file that is in your git checkout. Amal: Yeah. Yeah. And I remember, with N.P.M., there was this whole evolution of locks, right? Because, by default, if you install something, , if you have a caret, it'll auto update any time you do an install. And of course that creates unintended diff sometimes, , so there was this like, initially it was like NPM shrink wrap was a thing where you would like shrink wrap and you know, and I'm so glad that that we've kind of now moved towards that being the default. But yeah, like without shrink wrap, , it was just kind of every time you installed something you might be pulling in an update unintentionally and then that could also break something unintentionally too. So, , And I think one thing we should definitely talk about in this show is SemVer, right? Because, SemVer, , great in theory, most people generally know what it is, but, , for library authors, sometimes libraries don't follow SemVer and even if they look like on paper that they're following it. And then you have projects like TypeScript, you know, which is very widely used, doesn't follow SemVer at all because every single release of TypeScript is a breaking release, believe it or not. And so they have this whole, like, , you know, 3. 1, 3. 2, 3. And then once they get to 3. 10, then they roll over to 4. And so, what's kind of odd about TypeScript is , you have this, weird pattern for like, when people update. , you'll see a lot of people start to update when you get to like, 3. 9 or 4. 9 And because , everyone's getting ready for like, what they think is the big major release, you know. But that's not the case. There's every, every change is a breaking change. And so, what I wish we had with SemVer is like, I wish we had a way of enforcing it and verifying it. And I wish we had tools for library authors so that they knew when they actually broke something intentionally, or when, like, when it's a patch, when it's a minor update, when it's a major update, like, I wish there was a way for us to programmatically do that. And I'm hoping like AI will help us with that problem, to be honest, like, I think that's a very good use case for AI. So somebody please create that someone with more time than me. But don't you all think that's, you know, wouldn't that be useful? Wojtek: Yeah, big problem. , definitely. And yeah, some tooling around that would be definitely helpful. I, I remember Elm had a cool, um, the language had a kind of built in tool that like if you change your function signatures, uh, like, you know, you're in a breaking way. They wouldn't let you publish a minor stemver, Amal: that's so cool. Wojtek: pretty obvious, right? Amal: so many, good ideas from Elm in general, like that community, they just have it figured out, you know? but yeah, that would be fantastic. Wojtek: Yeah, I think the compatibility, , like the breaking changes and stuff is a very, very important topic. So I'm really glad you brought it up. I, I would say that, Elixir the language and a lot of packages are actually pretty good about this. So like Elixir was, Elixir 1. 0 was released like 10 years ago and we are still at one, so it's, it's going to be 1. 17. There is no breaking changes for 10 years. everything is, uh, maybe there were, maybe there were like very, very minor that, you know, like no one would really, but yeah, that, that's pretty cool, right? That It's a 1. 0. It's gonna be, it's gonna be Amal: Yeah. Wojtek: and there are no plans for 2. 0. Amal: That's so cool. Yeah. For anyone who can't see, if you can't see Owen's face, he's throwing up, he's throwing up air horns. He's like, yeah, look, sir. Owen: I was trying to get the, uh, the Mac thing to, to do laser show for, there we go. Yeah. This is great for the podcast. Amal: go. Owen: We need sound effects. Yeah. No, no Amal: Yeah, Owen: for 10 years. It's Yeah, Wojtek: Yeah, not bad. Not bad. Same for Phoenix. Phoenix is at one. Owen: one Wojtek: I don't even know. Is it one seven? No, that's Elixir 1. 7 or something like that. You know, again, pretty stable. Like if you, if you have a project, Phoenix project, way back, it's still gonna, it's still gonna work. , , but at the same time, I would say that maybe in Elixir community, we are a little bit, maybe too, maybe too cautious, So to speak in that, like, uh, like we are not gonna, we are not gonna publish that 1. 0 because we know that we are on the hook for kind of keeping it forever. I'm definitely, guilty, , of that. Owen: So I think what's crucial and why we can, maintain a major version for so long and elixir without, , having to go up to the next, you know, version two, version three, version four is , the tooling for deprecations. You can make changes and you can make them without breaking old code, but you can raise warnings so that anyone who upgrades to a minor version will be notified. And then, You kind of are relying on those users to see it when they're developing or have their CI, the pipeline set up to catch those warnings and, not let them out into their production code base. Amal: That's fantastic. I'm so glad to hear that. I mean, so we have in NPM land, there's NPM deprecate, right? So package authors can formally deprecate. their package and have a message and a redirect for folks, depending on what the status is. If it's like deprecate and use, use this other thing or deprecate like as in because, Oh, um, this is now native to JavaScript. So you don't need a package. You can just do this with the language. Like there's lots of reasons why a package could get deprecated. Or if it's not being maintained, for example. But I think for us, An issue that we have in our community is that people just don't read command line warnings, right? And without tooling to enforce it. It's really hard, right? And so this is where I again, there's room for engineering leadership teams to institute more kind of rigidness around command line warnings don't think it's good hygiene for us to ignore stuff like that, right? The other kind of point that I'd love to dig into, which I think Wojtek brought up around breaking changes , I wish as a community that we exercised more diligence around APIs actually, and put more thought into extensibility of APIs and. growing an API without breaking it, right? There is a way to do this without constantly breaking everything. And so it just requires more diligence and thought. It also requires going slower, , but I think the benefits are so greatly outweigh the cons, you know? node is a great example of that. Node, huge project, huge hockey stick arc, right? , Node, , first had, everything used callbacks, you know, and then when promises came to the language, for example, FS, if you wanted to work with a file system, you would initially, everything would be using callbacks. And now you, you can use, the promise version of the same APIs. But unfortunately, what that means is, , Node now has Um, they have two sets of code paths that they have to maintain, right? They have to maintain this old callback style thing. And then they now have new APIs that use promises that use built in features in the language. , and unfortunately, like, it means that they can't go as fast as they want to with performance updates or upgrades or, right? Because they have this, all this legacy package, but the decision that they made to, , prioritize backwards compatibility means that You can take an application that was written in, you know, 2004 and run it in the latest version of Node and it will still work for the most part, . , and so just having upgrades be seamless and having people be able to upgrade their version of Node without constantly having to , allocate hours and hours of engineering time , to do updates. For me, , the priority of constituencies is correct. Right. In the sense that , they push the burden down to the maintenance of node versus pushing it out into everyone else's code, you know what I'm saying? , so I think that's smart. I wish, I wish we did that more, Wojtek: Yeah, if I, if I can add, and by the way, , once again. Thank you so much for bringing this up, , the growing KPIs is really interesting topic. , I'm going to try to find a link, but there is a very nice talk from Rich Hickey about, growing KPIs and, , if I remember correctly, it goes like this, that , let's say you have a function, , and then, for a particular argument, it now accepts more. Than it used to. , that's fine. You know, your existing code didn't use that new thing. So it's gonna have to continue working. If it accepted less, it'll be a breaking change, but if it accepts more, it's cool, it's fine. And then if, if this function, if it returns, , less than it used to, that's fine too. , you had a code that was checking for, for something, but this thing is never going to appear anymore. That's okay. That's compatible. But if your function returns more than it used to, that's a breaking change because your code. So it's actually a pretty simple, uh, rule, uh, right? Like, you accept more, you return less. That's all you need. And then , if you cannot make it, just add a new function, you know, it's not, it's not going to be the perfect name that you came up with, initially, but it's going to be a new function or a new module or whatever. , and then, yeah, , keep the old one for compatibility. That's all you need. I'm way oversimplifying, but, , I think it, I would say it covers 80 percent Amal: yes, I would agree and 80 percent is a good chunk of coverage too, in terms of use cases. I would say even more than that. I think 80 percent is being conservative, but, this really just comes down to fundamentally understanding the power of design and really just Putting the time in to really think about extensibility and, the way you even shape your, your arguments, you know, the data structures that you choose to use, , these are all decisions that , will save you come time to make a change, it's either going to be a two line change or like a thousand line change what's it going to be, you know? I wish there was classes on this stuff, quite frankly. Like, I think this is the kind of stuff that I really wish we could teach to, to more people because it's teachable. This is not esoteric knowledge. Like, I think it's something that we can easily address as a community if we put our heads together. Owen: That's true. I was thinking when you, when you started talking about SemVer and I think he's spelled it out. Semantic versioning is what we're talking about there. at one point I'm thinking, well, yeah, semantic versionings, it's kind of like an opinion. It's like, I think this is a major change or it's a minor change or whatever, but yes, tooling to kind of distinguish and, you know, and help the maintainers make that decision would be great. I can't believe it's already been an hour and I really regret that we have to stop recording. I think my last kind of major question before we start wrapping up is, does everyone here have a favorite dependency from any language? I have a slightly trolly answer, but I'll go last. Amal: Oh my God. This is a hard question. I don't want to go first. Owen: most used, you know, Amal: I don't know. Owen: your, your rubric is. Amal: Honestly , it's going to be for me, , probably my linter. My linter is going to be the thing that I use most consistently across all my projects, regardless of whether it's on the server and the front end. And I think one thing I would love more people to do is, is generally write more custom linting rules to enforce conventions and standards across the things that you as a team agree on that you want to do, right? , stuff that's very specific to your code. Linting is a great way to even just tackle bugs, right? For example, if you're fixing a bug, the first thing you should ask yourself is Could this have been addressed by a linting rule? I know that sounds kind of crazy and a little different, but if the answer is no, this could not have been fixed by a linting rule, then the next thing you should ask yourself is, could this have been fixed by a unit test? And the answer is most likely going to be yes. For either a linting rule or a unit test. And then if the answer is no for a unit test, then it's going to be an integration test or end to end test. Right. But there are ways to like use lint, linting rules to even address, bugs, believe it or not. So I'm just saying, don't, don't underestimate the power of a good lint, a good lint, config. Owen: right. Um, and Wojtek you got a favorite package? , Wojtek: It's a very tough question. I don't know. Maybe it's going to be on brand, but talking about HTTP clients. I think one of the most influential for me actually, the package was, Mint, which is, , very low level, , HTTP client that mine actually uses under the hood, , cause I'm not smart enough to write the thing that actually talks, over the network correctly. Owen: I doubt that Wojtek: No. And so the reason I say it's very influential to me because it was, I think very,, it was very deliberate in what it's doing and what it is not doing. And, , I don't think often, kind of people talk about. from that angle, what it is doing and what it is not doing. So, very briefly mint, for example, doesn't have the process, connection pool that you would have in a high performance clients and, and things like that, it kind of leaves it up to you. So it's not very usable in the sense that like, I need to, you know, download some stuff really quickly. Mint is not very , to. Achieve that goal because there is a little bit of boilerplate, but it is very, very deliberate in in that it's going to do the low level stuff is going to be very, very fast performances. , very important. , yeah, I don't know. It influenced my design, , my kind of ideas about design, in other projects to kind of make sure there is that low level thing that that you can always use that doesn't have any opinions. It's just the tool that you can use for, you know, for anything. And then maybe you have other tools that build upon this to, to be that opinionated, kind of easier to use, and I think it's kind of cool if you have both. You know, earlier we talked about like, , let's say you have a package, but then I don't know, something doesn't work or you need to like make a slight change. What if like the low level stuff is public API and if the higher level stuff doesn't do quite what you wanted to do, just use the low, low level stuff yourself, you know, without forking, without anything, I don't know, Amal: Yeah, primitives for the win. Owen: Right. I thought, I really did think you were about to go into REC. I would, I would be fine with some self promotion. , we definitely use REC here quite a bit. So REC is the thing you're talking about. That's built on top of, of, Mint for the kind of the easy HTTP requests. Yeah. All right. Well, my, go ahead. Do you have something to add? Wojtek: I was just gonna say, I just maintain direct, I don't actually use it, so it's not my dependency. Owen: gotcha. Wojtek: No, just kidding. Owen: So my, my trolley, my earnest, but trolley, answer my favorite dependency is tailwind Amal: Oh my gosh, you know, Owen: because I know how much, I know how much I'm all loves. Amal: I was just gonna say, I was like, was this, were you sent to like, it's not that I, listen, I have no hate on Tailwind. It is a tool. Absolutely. It's not, it's not the tool. I think for me, what irks me is The resistance from developers to actually learn CSS, just learn it, it's like we want to, it's like building a house with JavaScript, drinking JavaScript, eating JavaScript, like, you know, not everything has to be JavaScript, like there are three primitives on the web. JavaScript, they all have their place. Um, and for me, bringing a tool into the party that's so opinionated and, ugh, I don't, I don't, you know what This is, I'm gonna stop now, Owen. Owen: I love about Tailwind is I do, you know, I, I am familiar, With CSS and I could write everything I'm writing in Tailwind could be in a CSS file or many CSS files. Amal: Amazing. Then that's great! CSS. Owen: What I appreciate is that. The, overall like elevator pitch for me is fewer tabs. I can work on my components and I'm not switching between files to make those changes. Right. I got my semantics, my HTML. And, if I want to override the defaults, it's fairly straightforward for me, Defaults work really well across the board. But yeah, Amal: That's awesome. I'm really glad to hear that. That's great. I wish everyone who used Tailwind had your, understanding and mastery of like core CSS, you know, cause I think that's the thing sometimes when there's too much magic, like developers don't I don't know. I mean, this is, I, I have a tough time with this, right? Because I'm, I, I, I'm very. Conscious of being like this purist grandma that's like learn the fundamentals learn the thing, you know But and that feels slightly gatekeepy at times, right? But like it's worth it. I don't know what else to say it. you know, so so yeah Owen: right, well, thank you for, for not leaping off the call immediately, whenever I said tell went. Amal: Where'd she go? Yeah Owen: So, right. And we'll never know what Vojtech's opinions were on Tailwind. I don't know. You're fully back end, right? You're not even writing any front end code at all, are you Wojtek: I think it's great. And I, I like opinions, as long as I agree with them. Yeah. Uh, or opinionated rather. Yeah. Right, Owen: right. yes. Right, and as long as you can vote them down and, you know, veto them whenever you need to. Wojtek: No, I, yeah, I dunno. I, I think opinion United software is cool, but if, you know, if you don't like these opinions, just don't use it. Use something else. It's, you know, there's plenty. Yeah. Owen: Well, as much as I'd love to stay on this call for another three or four hours, I do think we have to let you guys go. So you can get back to working or not working, whatever it may be. Amal: I'm on fun employment Right. now. So Owen: employment. Yes. Amal: I'm going, I'm, I'm going to a Hanukkah party after this. That's what I'm doing. So, Owen: Awesome. Amal: uh, I've got, to make a salad for the Hanukkah party, but, uh, that's what I'm doing after this. Then I have to go next, next week. I start interview prep officially though. So it's not too much fun. for too much longer. Owen: Oh, you're doing prep in the middle of the holidays. Amal: Yeah, because I'm, flirting with companies and, , they're, ready to seal the deal. So I have to start interviewing in January or else I'm gonna have, angry recruiters, Owen: Gotcha. Well, before we, process. kill this episode, , Vojtech. Do you have any plugs or asks for the audience? Any, contributions you want from these newly minted maintainers? Wojtek: a good question. Kind of echoing what we, what we discussed, , Write packages. Maybe we didn't talk specifically about that, but like do write packages because then people can look at the source code, learn from it, uh, as you write these packages, kind of be, I think about the API design, , don't make breaking changes on a whim. Think about your dependencies, as well. I'm going to plug hex a little bit. We definitely don't, We suck at marketing, but we have a lot of, nice tools, as you evolve your packages or as you use your dependencies, you can check what, see what changed. So we have, the div, uh, div thing. We have the preview the hex preview service. you can see what's actually in the package because, so that's more in the security, realm. What's on GitHub and what's actually in the package can be very different things. So we kind of, uh, got you covered. But yeah, , definitely Keep, writing those packages, with as little dependencies as possible. Owen: Awesome. And Amal, any final plugs or requests for the Elixir community here? Amal: You all are awesome and you're such thought leaders and, uh, so just keep, , thought leading, I would say. , it's a small community, but I think very mighty in terms of, , patterns and best practices and, , design. so , And Hex is so cool. I can't wait to Like, Dig in and check it out. I've been Like, clicking around, today and checking that out in preparation for today's call. , I think for me, I'm just going to piggyback off of what, , Vojtech said, which is, publish packages. And I would say just have one thing out there. But I would say more importantly, if. If you could look at your code base, you know, on your teams and on your projects and figure out what can be abstracted, like what's something that can be shared across and be made into a package and then you can have an internal one, So definitely a good way to kind of abstract and, clean up your code a little bit. so just look internally and see what you can kind of abstract away. But, but I, would say have one thing published, at least one thing, you know, that way you understand the, mechanics behind publishing a package and authoring a package. And hopefully that'll you better use and manage your dependencies as you kind of understand all the, all the moving pieces. So, yeah, and it's fine if it's like a little hello world thing too, like just, just something, you know? Wojtek: I, again, basically agree. And by the way, if you're going to have just one package, Owen doesn't have to be passkeys. That's like a pretty high bar. Like, this is a really cool project. Owen: uh, we really could talk forever. I, I've got to cut myself off, and, maybe go, write some smaller packages or something. Thank you both so much for joining us, uh, Amal, and Voytech. if you're listening to this episode, maybe if you get in just in time, you'll be able to hire Amal as well, by the time this thing is released, it seems like the competition is stiff. Amal: Oh my God. thank you so much. It's been such a pleasure. Thank you. Thank you. Thank you. and, Wojtek, so nice to meet you as well. I'm excited to follow your work. Wojtek: yeah, I had a great time as well. Uh, thanks, thanks everyone. Great to meet you as well, Outro: Elixir Wizards is a production of SmartLogic. You can find us online at smartlogic. io, and we're at SmartLogic on Twitter. This episode was produced and edited by Paloma Pechenik for SmartLogic. Don't forget to like, subscribe, and leave a review.