 So yes, thanks again. This talk gonna be about managing dependencies. And I'm sure all of you will be a little bit surprised by what exactly I'm gonna be talking about. So my name is, is a short version, some details where you can find me. I'm gonna talk about this also a little bit later. So I work in the company called Pocket Math, as you can see on my T-shirt. Pocket Math is also a very, very cool company, and no assholes, guaranteed. Yes, I've checked, I've checked myself. We are hiring, so if you're interested to know a little bit more about what exactly we are doing, how we are doing that, find me after this talk or after the meetup, or just use any of the links that I've shared before. Okay, so what exactly this talk gonna be about? It's gonna be about what exactly I, in this talk, mean by dependency. Why should we care about all of this? What can we do about it? Yes, so if we decide that we do have some issues with the dependencies, what exactly we can do about it? And some of the ideas that I'm gonna mention might be a little bit too much. So just stay with me, I'm gonna explain why I think so. And I'm sure that most of you are either gonna like it or hate me for the rest of this. So there's gonna be a lot of links in this talk, and I'm gonna send the link to the talk with all the links maybe on the meetup.com so that you can follow. So I'm sure if you will see or hear something that interests you, please follow up on those links because this, I only have 30 minutes, and most of the things that I would like to touch are big enough for separate talks, for sure. So do follow up. So mostly this talk is greatly inspired by Mike Perham and I hope that I'm not completely destroying his last name. So you might all know him. He's the guy who's doing sidekick. So if you're using background processing, I'm sure you've heard about it. So I usually read his blog and whenever he's writing about something, he's putting a lot of thoughts into it. So definitely check out, you can just Google by the name of the article, kill your dependencies. Okay, so what exactly do I mean by dependencies? Okay, so there's pretty much everything that your application depends on, right? Without those things, your app cannot run, including your app itself. So of course there's a hardware layer which we're not gonna discuss here because I'm sure you're all using some kind of virtualization technologies running in Amazon or Google or Azure or whatever. There's OS level, which again, I'm not gonna touch. I'm mostly sure that you all are using Linux in your production, so no issues there. Then there's your application code itself, right? And we're gonna talk a lot about this one. All the libraries you're using and any third party services which can be like storage, database, other services that you are consuming over API, et cetera. So our applications, right? We do this, we write apps and I wanna ask two questions. The first one is what exactly are we doing, right? So we are software engineers, what exactly does it mean? And the second one is why we are doing this, okay? So do you wanna shout what do you think about this one? Like what exactly do we do as software engineers? We engineer. We engineer, okay, cool. That's kind of given, cheating, but okay, cool. Okay, like most people would say like, well, we write code, right? Nothing to say here, we definitely do this. Like this is a big portion of it. Well, we build apps, right? So that code, is it a small library or framework or whatever, we build it for a reason, to build an app that's gonna use this code to do something. And after we build it, we still, there's a lot of things that we need to do around our app. But the better question is why do we do all of this, right? Like we write code, we build apps, we test this, we deploy, why do we do all of this, right? And the answer is very, very easy. It has nothing to do with code, it has nothing to do with technology. We are trying to solve business problems, business issues, challenges, et cetera. And this is very, very important. I'm gonna go back to this throughout the talk, right? So whatever we're gonna be talking about, we just try to memorize this, that whatever we are doing in our day-to-day job, we are doing to solve business problems. Okay, so we already decided, well, not decided, but figure out that we are solving business problems, okay? So what is the code then in this case? Well, it's kind of a site thing, right? It's just a side effect. Like in order to solve this issue, I have to write some code, okay? So it's not the direct necessity, it's just what we do, how we solve those issues, okay? So sometimes code might not be the best solution, right? There is a lot of issues which we can fix with code, but we don't because it's way easier to fix it by something else, by simplifying the business process or changing it or whatsoever, right? So when we do have the code, when we actually sit down and write it and test it and deploy it, every line of code we write has a price, right? So what exactly do we get with code? Well, what it brings us, right? Well, it brings us some bucks, right? We all do produce issues in our code. Whatever we do with all the CIs, with all the tests, we still produce bucks, right? So code gives us bucks. Any new features that we would like to work on usually means that we have to touch the previous code we have, which automatically means that adding new feature where you don't have any existing code is way easier than adding feature to existing code base, right? I hope we can all agree on that one. So after we did all of this, we still need to maintain this code, right? Again, we need to test it every time we touch it. Everything that what we're doing every day, we have to do this with every line of code we are adding, okay? So we do a lot of all of these things. So let's try to define what would we say about the perfect code, okay? Imagine we talk about the perfect code. So what we would like to get out of it? Well, everybody keeps saying, try building everything as small as possible, like the method should be very short. Your classes should be very short, right? You don't have to have a lot of dependencies. Everything has to be independent, sorry, everything has to be independent, right? If you're interested, you can definitely check out send the math rules. They're a little bit of extreme, but there's a lot of discussions around that. So definitely check it out. So we know it should be small. We also know it should be simple, right? We all heard about different design principles, stuff like solid, single responsibility, all of that. So we want to have code that's simple, meaning we can easily reason about it. We also want to be able to easily maintain this code. I said this three times already. We are maintaining code all the time, right? So there's a lot of topics and presentations about this. Again, there's a good link to the article I like about this. We are mostly trying to write codes for ourself because whatever we write, we'll have to go back to it. We have to reread it, understand it again. So we try to write code for humans, not machines. But then, of course, we want to be able to deliver the code fast and it has to be very performant, right? For me, if I go through this list, this is the definition of perfect code. I'm sure we can find out other qualities of the perfect code, but this is pretty much good enough, okay? So what if I say that the best code is no code at all? If we go through the list, it definitely satisfies each one of those, right? It's the shortest, definitely no code is the shortest code. It's very simple, easy to understand. You don't have to test it. You don't have to care about readability. You don't spend any time writing it and it works the fastest. I'm sure you've heard the same thing about networking, right? The fastest network call you can do is no call. Again, don't quote me on this. I'm not saying we shouldn't write code. I'm just saying that every time you're sitting down to write a line of code, double check. Do I actually need it? Maybe I'm over-engineering. Maybe I'm not even sure if I will need this in the future. Maybe I'm trying to guess what exactly I'm gonna need tomorrow and tomorrow it turns out I don't need this feature anymore whatsoever, okay? Again, the link to the article, no code, is a very, very interesting article. Definitely encourage you to check it out. So how can we help ourselves, right? So as I said, like before you write every line of code, you should definitely check out if you need it. So one of the very good ways to do this is to follow the five wise technique. So the idea is very, very simple. You state the problem and then you try asking why until you actually get to the root cause. And it doesn't mean that you will get the root cause when you get to number five. You might get it at number three or number four or number 15 and you might get multiple reasons. Yes, I'm not gonna read this out loud. You can quickly go through this. There's a lot of examples of this on the internet, in different domains. Like the link from Wikipedia, for example, has something about the broken car and people trying to figure out why it was broken, okay? So very, very simple exercise. Definitely Google this up five wise and try to use it when you're planning the feature, when you're doing retrospectives, et cetera. So there's also a link to the source of this exact example. So let's say we figure out, okay, we definitely need this code. Like we ask all the wise, we tried everything else, we definitely need to write code. So how can we do this? Well, first of all, sorry, I have to use this opportunity to mention this talk. If you haven't heard about this talk by Rich Hickey, who is the inventor of closure programming languages and overall unbelievably smart guy, definitely check out, he has awesome articles, he has awesome talks. This one he actually gave at the RailsConf. It's not related to Ruby or Rails, it's just overall about software engineering. And the idea is very simple. I'm gonna use one of those words. He tries to explain what is the difference between simple and easy, because we usually just use them interchangeably all the time. We don't actually differentiate them. But there is a big difference and he's trying to get into the root of that. So I'm just gonna quickly talk about it. Simple is something that's not complicated. Brilliant explanation, right? Like the opposite thing. But easy is not the same. Easy by definition is something that we already know how to do, which is convenient or close to you. So for Ruby engineer, any Ruby library would be easy and Java library would be hard. Even though internally the Java code might be simpler. Okay? So the main difference is that there are simple things and there are easy things. I'm doing Rails for five years, so Rails for me is easy. But Rails itself is not easy. It's a huge framework, very complicated. There is no one engineer who knows the whole code base very well, et cetera, et cetera. So by definition, for example, Rails is not easy. Sorry, it's not simple. But it is easy because we are doing this every day so we know how to do this. So for us, it's easy, okay? So when you work on something, just keep this in mind that if you decide to do something and it sounds easy, it's easy for you. Because easy is relative. Simple is not relative. Simple is always simple. Easy is relative. What's easy for you might not be easy for other of your team members. Might not be easy for whoever will maintain your code when you're gone. Okay? So definitely check out the code, check out the talk. It's very, very good and you'll get a lot of out of it. So again, like prefer simple and small solutions. We all know that the smaller the code, the easier it is to read it, to reason about it, et cetera. Refactor your code. Again, I'm not even sure why I'm mentioning this because I'm sure everybody knows that you have to refactor. But I keep hearing this. I keep hearing this on when people ask questions after the conference talks or after reading some blogs. Like how do I persuade my managers that we need to refactor? How do I ask permission? Well, you don't. You never ask permission. Refactoring is not a separate activity that you do. It's not like I'm working and then I'm refactoring. No, never. Refactoring is the process that never stops, right? Whenever you're touching the code, it's your responsibility to make sure you're leaving it in a better shape than it was before you touched it, right? If you follow this, you will pretty much never have to refactor, okay? Of course, like this doesn't cover 100% of cases. Sometimes you do have to do bigger changes which would require you to spend significant amount of time doing this. But in most cases, you don't need to do this. So proof of concept code. We all heard about it. Like, okay, let's push it to production as soon as possible and then we'll figure out. Or let's push it for this customer. He needs this for the next week. Then we can delete it. This usually never happens. This code would be there in your code base permanently, forever, that's it. You have to deal with it, okay? Which leads us to the last thing, to be okay to remove code. And then again, in most cases, being able to remove code and being sure that you haven't broken the whole system means that you have to design your code in a specific way. We'll get to that a little bit later. There is a great talk. I'm not fully on the same page with the guy who did the talk. But he did highlight some of the very, very cool ideas. So definitely check out that talk. Okay, so we talked a little bit about the code that we have to write. But in most cases, we are trying to leverage on as many libraries as we can, right? We all know that we don't wanna reinvent the wheel. We don't wanna re-use, sorry, we don't wanna write our own code if we can reuse something that's already there, already tested, already built by somebody else. So in your gempile, you can have a lot of things, right? And usually not all of the gems are of the same quality. And I don't know a lot of people who actually go into their gems and check out what do you guys have there. And sometimes you can have very nasty crap in there, okay? So some of the gems actually just duplicate the features from the standard library. And if you look through the documentation of the standard library for Ruby, you will be amazed how big it is. You can pretty much find whatever you want in the standard library. But we are a little bit lazy, plus we like to reinvent the wheel. We like the challenge, so we do tend to do this. And the last thing is that in some cases, we do take the gems, which can be just replaced by one or couple of lines of code, which means that we introduce a huge gem into our system when we actually need just a tiny, tiny fraction of that functionality. And I've seen weird, weird examples where people would need a RegEx for email validation. And they would actually include the gem that's doing all the fancy bits of email validation just to use the RegEx. It's okay to copy code, no issue with that. So it's also very tricky how to figure out which gems are okay. As I said, there are some bad gems. And in most cases, all the gems that you've heard about and which are widely used by our community are well-tested, well-documented and very good. But still, first of all, take a look at the maintainers. If you use the library, why you do this? Because you don't wanna write your own code and maintain it. Library still needs to be maintained by someone, right? So we are still talking about the engineers that are just on the other side. Number of open issues, number of open PRs is the project that is actively in development, et cetera. Usually it's relatively easy to tell. Everything's on GitHub, very, very easy. So do this. And the third thing, and I can't stress this enough, read the code of the gem. A lot of gems are very, very nice, structured code. So even if you don't find anything bad, you can actually learn a lot of cool tricks by reading the library code. Because the code that you write in your, let's say, Rails application is mostly like a little bit of business logic which you put into different parts of your framework. When you write the library, it's a more sophisticated, self-defined code. So you can learn a lot of good things just by reading the code of the gems. And of course you have to check the internal dependencies of the gems, okay? Because you can bring in a very, very small gem and you can say like, oh my God, it's so awesome. It's just, I don't know, three classes, well-tested. Everything's great. But then you open the gems back and it turns out this guy's using like 20 other gems. Which technically automatically means you are using 20 other gems. So the benefits you're getting out of using libraries is that you don't have to maintain that code but still somebody needs to do this. And hopefully you're getting the code that's better tested. Because if you wrote your code, you are the only one who's using it. If you're using a gem, hopefully some other people are also using it. So the chances of finding issues and making sure that they are fixed are way higher. Okay, I'm gonna show you a couple of examples. I'm sure all of you have heard about this gem, database cleaner. Who's using database cleaner? Okay, like half of the people here are using database cleaner. Well, it's a very useful gem. And I was very, very surprised to find this on the main read me page for the gem. So the question was why the author built this? And he said like one of my motivation was writing this library to have an easy way to turn on what Rails has by default pretty much. So what this guy did, he created a gem because otherwise he had to copy and paste this hacky code all the time because he wanted something that Rails has by default. So all of you should just freak out right now because you're using gem which Rails is doing for you by default. But that's okay, you don't have to because actually this gem is now doing way more things and it still helps you. But I'm sure most of you didn't know this, right? Because like who reads the read me of the gem, right? But it is interesting, different motivation. Again, knowing your maintainer, right? Who created this gem? Why? What is he planning to do with it? Like HTTP clients. I'm not gonna even talk about this, right? We have like 15 HTTP clients which are all based on the standard library net HTTP module. Why do we have 15 of them? Because we don't like the API layer of the net HTTP. Which I can understand totally, I've worked with it. It's terrible, not very friendly, it's hard to deal with. But I've seen people bringing the whole HTTP client library just to do one get request in their gem. Which come on guys, it's not okay, right? Same with JSON and CSV. People for some reason are using special gems for parsing JSON and CSV. Which again, those gems have the reason to be there. They do something differently. But in most cases, people who are using those gems, they don't actually need it. They just see like, oh, there's a gem to do CSV. So if I need CSV, I use this gem, right? No, it's all in standard library. In 99% of times, you don't need any of this. So all of this can be replaced by standard library in most cases, okay? And if you do end up having a lot of gems and like I'm sure we all have a lot of gems because like why not? We do have to do some maintenance. The simple thing that I would recommend, always commit your gem file log. Do I have to explain why? Because this guarantees that you always get the same set of libraries everywhere. On your server, on your deployment, on your staging, and on the other developers machine. Always do this, otherwise it can be very nasty. Always make sure that you're using something to check for new versions and vulnerabilities. So there's multiple different ways to do this. There are other gems, there are other automated services which are doing this. They're checking if your gem file is up to date. If any of the gems that you're using have any vulnerabilities, okay? I'm gonna share all of this. So like just make sure you follow the links often. Okay, so now the most interesting part and I'm not gonna talk a lot about it because we can easily have like serious of other talks about the internal code dependencies. But what I mean by that is the situation where you have classes, functions or methods or whatever which call each other directly, which reference each other directly, okay? So what it means is that you introduce a deep coupling. This method knows about this method and this class know about these five other classes and whatever. So testing this is usually very hard. Like in most cases for Rails application it's almost impossible to test your business logic without touching Rails. You have to load the Rails which takes like what, 15 seconds? You have to touch the database because like you're reaching to the active record models everywhere directly so you cannot easily stub it out, right? So testing is very hard and changing is also very hard because if you have to remove something or rename something you have to look in 50 different places to figure out because everybody's calling everything, right? So just a quick example to explain what I mean by this. So we have a class which inside the initializer references the other class, okay? And then we have these two methods we don't care about this one but this one is doing something with the orders, okay? And then in the end it uses clicks so it uses something else. It's a very simple code and like I assume you figure out the order, the fact that I'm calling dot all is an active record and everything. So testing this would definitely require me to do something with database or stopping the order or whatever, right? But the ideas here are actually very, very simple, right? I don't need to know about the orders. Campaign doesn't need to know about the orders. I can just pass them as the parameter to the initialize, right? So boom, campaign doesn't know about the orders anymore. All of this is just talking to the order. I'm just asking, right? And we all know the principle, tell, don't ask. Why I'm asking order about all of this? I can just ask him to do the calculation. So all of this can just go and live inside the order object, et cetera, et cetera, et cetera. There's a bunch of useful techniques that you can do. There's some links that I'm gonna provide what can make your design a little bit better. So there's dependency inversion principle which technically just means your business logic doesn't need to know about anything. It's completely abstracted and composition in object-oriented design. There's a great talk by Sandy Matz which I definitely recommend you watching. So again, like that was a huge topic. We can easily have like two hour discussion just about the internal codependency but this is not what we're here for. Okay, so then third party dependencies, your APIs, right? So it might be your own APIs, your other services and microservices is a hype word right now. It's a hotness than the new shiny thing so everybody's doing that. We're gonna talk about this a little bit, okay? Then you have some completely unrelated to your project things which like S3 or Qs or whatever. And when you're dealing with those you just have to ask yourself every time. Like how do I test this? Because again, this is dependency. Now my CI needs to be able to talk to S3. No, I don't want that. So now I need to either stop everything everywhere or do something else. So always think about this. It's a dependency. So now you have to deal with that. Is it easy to switch to something else? Like for example, we are running everything in AWS and we are so deep into that that switching to any other cloud platform would be pretty much impossible. Are we happy with that? No, right? But this is what we have. Then you have your data storages and again like we do have a lot of fancy things then in most cases we don't actually need, right? So we have caches, key value storages, databases, et cetera. And if you do have issue with performance and you need caching good for you it means you're already successful. But in most cases when you're especially starting to build something from scratch thinking about caching is just too early, okay? So do we need any of this? Do we really need it? Just always think about it. So most of those things are just premature optimizations. And I'm sure you've heard this a couple of times already that premature optimization is the root of all evil and you should avoid this at all costs, right? So think about it, you're not gonna need it. In most cases, right? There's a nice article, Yagni, if you haven't heard about this, definitely check it out. In most cases what we are trying, we're just guessing. We are guessing all the time. We're estimating like, oh, I did this thing twice. So it looks like I can do some additional abstraction and just remove some code duplication. Now you build like the whole abstraction layer. And then the third thing kicks in and it's not the same. You cannot reuse that abstraction. So just don't jump onto those conclusions too early. And like, if you're thinking about scaling issues think about it twice. Because in most cases I'm sure you don't have scaling issues. You're not Google, stop reading the success stories from Amazon and Netflix. If you're working on the project like that, awesome. I'm very happy for you. Give me a call, maybe I can help you out. But in most cases, we're not building anything rocket scientist, right? We don't have that scale. We want to play with all those tools. We wanna play with the tools that the big guys are playing with. They have huge guns. We wanna play with them. But in most cases we don't need it. And if we introduce those tools, we also, it doesn't come with free package, right? If you use those tools you're introducing additional layers of abstraction. If you have dependencies, it's hard to test. Now realize that you have two classes and you put HTTP JSON layer between them. Is it better? Is it easier? No, it's even harder to deal with. It's harder to deploy, harder to test. And it's terrible. So I encourage you to use proven, let's say boring tools like MySQL, Postgres, all of those things work. In most cases, yes, jQuery, why not? Who said your site needs to be SPA? Most apps never need to be SPA. You're actually hurting it if you're building it SPA, okay? So, yeah, think about it. So does it mean that simple coding means boring coding, right? Like I encourage you not to use new fancy tools. I encourage you not to read fancy articles about microservices and start splitting your code base. Not exactly. What I mean by boring, I mean something that's proven, that's good, but maybe when you go to water cooler the cool kids are not talking about it all the time, right? Why they're not talking about it? Well, because it feels boring to them. Most of the people who switched from databases like MySQL or Postgres to something fancy, ask them, they never actually learned that tool. It's not like they used 100% of what MySQL can give you failed and then moved to something else. No, they just give it a try and they didn't like it because it's like, well, yeah, I can read the book which is 30 years old about this, which automatically means it's bad. But no, like there's a lot of cool boring things, like Ruby is boring. Come on, Ruby is what, more than 20 years old now. It's not new whatsoever. Rails is boring. Rails was like what, 2003 or four? It's old. It's really old, but it's still fun and cool, right? So yeah, definitely there's great articles about this, great hack and use discussion. A lot of great stuff, just follow up the links. So I'm slightly getting to the end and like just trying to summarize. So why exactly all of this is happening? Like I've mostly talked about bad stuff, right? I'm not even talking about the good pieces because hopefully if you're doing this already, good for you, we don't need to concentrate on that. So as a software engineers, we are most happy when we are writing code which totally makes sense. We were always taught that this is what we are supposed to do, write code. So when we get to the office, we open up our laptops, this is what we wanna do the most. And we're trying to use this approach for everything. Any issue we see in front of us, the first reaction is like, I'm gonna write this down. And I'm doing the same mistake. Like I want to have my own cool dev block. So what is my first reaction? Should I use WordPress or something else? No, my first reaction is like, oh my God, I can try a new react. I can build this, I can build that. So it's okay. And it's okay to experiment, it's okay to play, but we need to figure out how to do this properly. So business problems, in a lot of cases, unfortunately, business problems are not that complicated. They're pretty simple, easy and boring in some cases, right? So what do we do with this? Well, we just try to invent the challenge for ourself. So we reinvent the challenges and we start playing with new libraries and frameworks even if we don't actually need this. And I'm saying not learning, because learning new libraries and frameworks is awesome. We're writing your app because you read that this framework is 10% faster, especially for your business, okay? We try new tools and services all the time, like, oh, this database is a little bit better because it can hold JSON and this one is better because it can hold, I don't know, geolocation or whatever, right? In most cases, we don't need that. And then, yes, new languages. And people start throwing this idea that microservices are very good because you can write every microservice in a different language so that you can use the best tool for every job, which on paper sounds awesome. What can be better, right? But yeah, it's not fun when you have to support five different services in five different languages. Believe me, it's not fun at all. It's very cool to write them, but it's huge pain, you know, where to maintain all of that. All right, all right. So quick summary, focus on business needs. Just keep this in mind every time you're working on anything. What is the business need here? Don't think about the code until you figure this out. Ask all the wise, ask them until you actually get the good response. Use the tools you're comfortable with, right? So in this case, I mean easy tools. Rails is not simple, but it's easy, you already know it. So if it works for you, use it. If it doesn't work for you, cool. You found your challenge, deal with it. It's okay to introduce new things. It's definitely okay. Just do it gradually. Don't switch your language and your framework and your database at the same time. If you wanna experiment, stop using Rails, use something else, or switch from MySQL to Mongo if you feel like you need. Don't switch all of those in one go. Keep remembering the simplest solution, the dumbest, the most boring solution is usually the best solution, right? And deleting code is as good or even better than adding code. Deleting code is just awesome. I'm very happy when I have to delete code. Okay, cool. So just another reminder, pocket math. We're hiring. If you're interested, definitely approach me after the talks. Thank you. I do try to do an experiment. I didn't do any blogging for a pretty long time, but I had a lot of drafts of the blog ideas. So I'm trying to keep up with that draft right now. And I'm gonna do like a small newsletter. So if you're interested in talks like this or ideas like this, definitely check out my site, mcdev.com. One of the posts, the last one which I did today is about the newsletter which I already set up so you can drop your email and I'll try to send you some goodies. That's it. Thank you. Do we have any time for questions? Questions for me? Yep. Why libraries that are maintained are better? I think that they are worse because they change. Yes. Something works. Good question. And it's not attached for five years. And that is good. Awesome, awesome. Of course, definitely makes sense, right? Again, what I said, you have to check the maintainers. Who created the library and why? Because for example, Rails. Like DHH is very open about this. He never built Rails for the community. He never built Rails for us. He built Rails for himself. And if it works for somebody else, awesome, use it, he's happy. But he always builds this for his own business. Same here. If the author of the library built something and then he needed something else and he starts changing it, it's terrible, right? Again, if it's not touched, it might be a good thing. It means it's complete. It's working, it's tested. But what happens if it works with, let's say, Rails? The major update of Rails comes in and somebody has to fix it to work with whatever are the changes. Recently, we haven't had any breaking changes in Ruby, but I'm sure you all remember switching from 1.8 to 1.9. There was a lot of breaking changes, right? So if the library is not supported, it can be good, but it also can mean that whatever, there are some breaking changes, there's nobody around to fix it. Look what happened with Asset Pipeline. Nobody knows how it works, and it's so hard to maintain this project right now. The other side of that is dependencies of dependencies of dependencies. This library might not have changed for three years, but it's six core dependencies have each changed in incompatible ways because each of them solves, their maintainers own a problem. So, oops. Yeah, yeah, so just keep remembering, if you're using the gem, usually the gem will also use some gems, and those gems will use some gems. That's why if you open the gem file, it can be pretty nice and tiny. Then you open the gem file lock, and you're like, oh my God, where have all of this came from? Because there you will see all of the dependencies with all the versions, et cetera. One question that I was gonna ask you when you were mentioning gem files, you talked about checking in gem file.lock has the ultimate definition of what's actually included. Do you prefer to lock down gem versions in the gem file? No, no. So if you're writing gems, it's usually a bad idea. And again, it's a pretty big topic. You can easily just Google, should I add the gem file lock into my gem? And there's a very, very good explanation why it's a bad idea. So for your end application, definitely. No, by lock it down, I mean, instead of saying, instead of in your gem file, like looking the specific versions. Yes, locking the specific versions of each gem. Well, again, like if you have the gem file lock, then I wouldn't accidentally get the different version. But if I run bundle update, I have no idea how far will it go with the update, right? I might go too far and now it's breaking changes or whatever. Usually if the gem doesn't depend on anything too big, like for example, everything that depends on active record, we would lock because we are not using the latest active record, right? And there are so many gems like state machines and validations or whatever. So for those gems, we will always lock the version because they hardly depend on something else. For small gems, which are usually completely out of scope of Rails or anything like that, we usually try to stay on the latest version so we wouldn't lock the version. And whenever we feel like it, we'll just update to the latest one. Yep. For startups and companies that are on Google, would you care to share your thoughts or recommend using Heroku rather than AWS or Azure? I don't care about the hosting because usually Heroku doesn't force you to do anything crazy. So if it doesn't work for you, you can easily switch. So it is your dependency, but it's not a very hard dependency. You can easily break out of it. If you would say like, should I start using S3 for everything? I would say like, yes, but like, just think about it. How easy would it be to migrate to anything else, right? So if you're not like deeply coupled with anything, I wouldn't call it a hard dependency, right? See. Yes. It's just an opinion question. Now that the industry is moving from a more Ruby on Rails kind of NBC into the front-end, back-end format, and there's a growing trend that things like Web Factor, Rails Web Factor, they actually have a jam to kind of integrate Web Factor into a Rails project. So, and then let's react on Rails. What was your opinion on all these coupling of front-end and back-end? Yep. Why your thoughts on it? Well, again, it's hard to call it coupling because technically you can integrate your JavaScript code into your Rails code in multiple ways. And usually the fact that you used something like React on Rails doesn't mean that you cannot just drop that jam and instead use a Web Factor. In most cases, you can easily switch, right? But if you, like, we, for example, are still using Rails assets, have you guys ever used Rails asset? It's a terrible thing, terrible idea, but it's kind of hard to switch away from it now because it's like which version was locked, which version was not locked, how do we include it? And there's like some things are included directly, some things through Rails asset, et cetera. So, it's a big mess and it's a very hard topic. I don't have any strong opinions about it, to be honest. I do believe if you have SBA, if you have a huge JavaScript code base, if you're going that path, maybe it's a bad idea to completely separate those so that it's easier to reason about them. But I'm not a big fan of SBAs, to be honest. So, I would try to stick to a single code base for as long as possible. Okay, cool, thank you.