
Code with Jason
Code with Jason
241 - Freedom Dumlao, Sin City Ruby 2025 Speaker
Freedom Dumlao discusses Flexcar’s switch from Java to Ruby on Rails, covering the challenges, successes, and lessons learned from the transition. He shares insights on balancing coupling and decoupling in microservices, the strategic parallels between programming and problem-solving, and his experiences at Ruby conferences. The episode wraps up with community highlights, dining tips for Boston’s Chinatown, and ways to connect with Freedom.
Life hasn't been the same since the pandemic. Instead of working at an office around people all day, like we used to, most of us now work remotely from home, in isolation and solitude. We sit and we stare at the cold blue light of our computer screens toiling away at our meaningless work, hour after hour, day after day, month after month, year after year. Sometimes you wonder how you made it this far without blowing your fucking brains out. If only there were something happening out there, something in the real world that you could be a part of, something fun, something exciting, something borderline, illegal, something that gives you a sense of belonging and companionship, something that helps you get back that zest for life that you have forgotten how to feel because you haven't felt it in so long. Well, ladies and gentlemen, hold on to your fucking asses. What I'm about to share with you is going to change your life. So listen up.
Speaker 1:I, jason Sweat, host of the Code with Jason podcast. I'm putting on a very special event. What makes this event special? Perhaps the most special thing about this event is its small size. It's a tiny conference, strictly limited to 100 attendees, including speakers. This means you'll have a chance to meet pretty much all the other attendees at the conference, including the speakers. The other special thing about this conference is that it's held in Las Vegas. This year it's going to be at the MGM Grand, and you'll be right in the middle of everything on the Las Vegas strip.
Speaker 1:You got bars, restaurants, guys dressed up like Michael Jackson. What other conference do you think you can go to, dear listener? Or you can waltz into a fancy restaurant wearing shorts and a t-shirt, order a quadruple cheeseburger and a strawberry daiquiri at 7 30 am and light up a cigarette right at your table. Well, good luck, because there isn't one Now. As if all that isn't enough, the last thing I want to share with you is the speakers. And remember, dear listener, at this conference, you won't just see the speakers up on the stage, you'll be in the same room with them, breathing the same air. Here's who's coming.
Speaker 2:Irina Nazarova. Oh yeah, here's who's coming For Freedom Dumlao Prathmasiva, fido Von Zastrow, ellen Rydal Hoover and me.
Speaker 1:There you have it, dear listener, to get tickets to Sin City Ruby 2025, which takes place April 10th and 11th at the MGM Grand in Las Vegas. Go to sincityrubycom. Now on to the episode. Hey, today I'm here with Freedom. Dumlao, freedom, welcome.
Speaker 3:Hi, nice to be here.
Speaker 1:Good to see you again, jason, good to see you too. So I first became aware of you and Flexcar at RailsConf. As we're recording this it's 2024. It was RailsConf 2024 in Detroit, railsconf 2024 in Detroit, and our mutual friend Irina Nazarova gave the closing keynote and you and Flexcar were featured in the keynote because Flexcar recently has switched, I believe, from Java to Rails. Yeah, and you were kind of the impression I got was that you were kind of a success story, use case of of switching to rails, yeah, and I'm curious to hear a little bit about that story and just any, any background you want to also give on, yourself and Flexcar.
Speaker 3:Sure, so well. So Flexcar for those who don't know, we're based primarily on the East Coast right now, but we are a company that does a month-to-month car lease for people primarily in Boston, atlanta, nashville, charlotte, but expanding of course, and I've been with Flexcar now for I don't know three years. One of the people who started this whole thing up but yeah, the RailsConf thing was a real surprise to me. So I had met Irina, so she had, I think, discovered me on Twitter. I was just like chatting with people, trying to get to know some Ruby folks, and I think I had mentioned to somebody that we were, you know, switching to Ruby or something. And she reached out to me and just said hey, I'm trying to talk to folks who are using Ruby in a startup sense, so I can get ready for this keynote.
Speaker 3:I'm doing, you know, do you have a few minutes to talk? And I said, sure, we made some time. We had a, we had a short conversation. She asked a lot of great questions and then a couple of follow-ups. And then on the day of it was really that morning she said hey, before my talk, I just want to check with you that all this is okay. And then I got a sneak preview of the talk. It was sort of shocked by how much we were featured and obviously, you know, proud, but it it meant a lot to us and the team once we were able to find out that.
Speaker 2:You know it was a story that other people found compelling.
Speaker 3:It was certainly exciting times for us. We were planning on a completed migration, you know, several weeks before RailsConf. So we were planning on going to RailsConf as recent Ruby community members who had completed a migration and it turned out that we were not ready to migrate until the day of Irina's talk, and so it added a lot of uh pressure. Once the once she, once, once her talk happened, we're like, okay, well, uh, I think she even called us out and said like and there's, they're launching tonight. And I was like well, I guess I guess that's uh, that's gotta happen now. Um, but we did. I think that was may 8th and you know it went about as smoothly as a major migration can go. And here we are, you know, no regrets whatsoever, and we've got a whole team of very proud Rubyists now at Flexcar. Even those who were initially skeptical are completely converted, which is great, are completely converted, which is great.
Speaker 1:Yeah, that's great to hear. We hear these famous stories repeated, like Twitter having started with Rails and then switching away from Rails, and so it's really nice to hear somebody switching to Rails and then being really happy with the decision. We've talked about some of this before, just in previous conversations. But what have been some of this before just in previous conversations? But, like, what have been some of the maybe pain points of switching to rails? I know we've talked about like um, you're not sure if you're writing Ruby in an idiomatic way, and stuff like that. I'm curious to hear those kinds of things.
Speaker 3:Yeah, honestly, that's. That's probably one of the one of the biggest pain points is, you know, our team was very clearly divided amongst front-end and back-end engineers. The front-end engineers were accustomed to writing TypeScript and React, back-end engineers accustomed to writing in Java with Spring Boot, and they brought a lot of experience with them to this project. You know, these are these people who've been building software professionally for years, and so when we switched to Ruby, we did a couple of things. We number one is, obviously we switched the language. That was the most obvious one and, I think, the one that people paid the most attention to. But you're also switching frameworks and you're switching your sort of job functions. A little bit Like, suddenly, the expectation was that everyone was capable of being a full stack software engineer. Now, you know, we still have people who lean one way or the other, for sure, but there's no ticket where somebody says like, ok, well, I've done this part, now I need a front-end guy to do this other part. That doesn't happen here, and the biggest challenges we had were really around how do we become good at doing this in this new language and this new framework and this new paradigm?
Speaker 3:Ruby is an incredibly forgiving language.
Speaker 3:You can get really far with some super bad Ruby code, which we have. If you look at a lot of FlexCard's code base, you will find code that looks a lot like Java code, because it was and it was just rewritten as Ruby and it worked just fine, because Ruby is the kind of language that allows you to do that. But we've slowly been getting better at understanding how to write great Ruby code, and, as we've done it, we've cleaned up the code base. It's not perfect by any means, but I think, jason, when you were visiting, you got a glimpse of some of what I'm talking about here, but the team is pretty excited every time they learn some new Ruby idiom that can solve a problem with less code or in a way that's easier to test or in a way that makes it so that we can do something faster than we were able to do before, and we keep discovering those, and that's what I'd say that was. The biggest hurdle, though, is just figuring out how to write Ruby like a Rubyist would yeah.
Speaker 1:The biggest hurdle, though, is just figuring out how to write.
Speaker 1:Ruby like a Rubyist would. Yeah, interesting, yeah. And something that I find kind of an interesting area is like when you're first starting out with a Rails application, there's kind of a well-beaten path. You can find tutorials that will tell you how to generate models and stuff like that. But once your application grows beyond a certain size, it's like I've likened it many times to like putting spaghetti on a plate. It's like if you're only putting a little bit of spaghetti on the plate, then a plate is, it works great. You put the spaghetti on the plate and there you go. A plate works great. You put the spaghetti on the plate and there you go. But if you then keep putting more and more spaghetti on the plate, pounds and pounds and buckets full of spaghetti, then the plate doesn't work so well anymore. And some people draw the conclusion of like, oh man, plates suck. But it's like no, no, no, it's not that plates suck, it's just you can't use a plate for that. You need to handle it some other way.
Speaker 1:And so I think a lot of times people, people's code bases grow over the years and rails come, comes with these wonderful slots. You know there's models, controllers, views, helpers, mailers, all these things, and it's kind of clear, at least in the beginning, what kind of stuff you put into which slots. But then eventually you run out of slots and it's like, oh, I've run out of rails, I need more rails to put my code in. But that's not actually the answer, and that way of thinking leads to things like service objects and interactors, which don't really fix the problem. They just move the problem to somewhere else, and what is really needed is design skill, and you have to come up with your own design. Have you run into any of those issues yet?
Speaker 3:So I would say we think we have, and then we have a principle, which is, use the framework as it was designed first. Before we go and try to like, just make sure that the framework itself isn't going to solve the problem for us if we just, you know, try to do it as close to as the framework is designed first and then make a choice to try to expand. I would say, you know, say we have a lib directory that is filled with stuff that I would say is a mixture of useful and questionable code. It's not necessarily a junk drawer, but definitely a lot of stuff that we weren't quite sure you know where it goes For us.
Speaker 3:You know, there's this constant conversation that we're having, which is, you know, if I've got this model, an active record model, say, and of course it's going to need to pull data from a database, but some of our models we like to mix in data that comes from another data source.
Speaker 3:Well, should we do that in the model? Should we expand the model or add a concern that does that, or should we instead just use some other object that we, you know that we bring up when we need to like where's the right way, and stash that in lib for the time being, and so we go back on back and forth on that. I think we're swinging currently towards the pattern where we use concerns when we need to break logical chunks of code out into their own thing. Where we might have used, say, in Java, we might have used, say, a manager or a factory or command pattern, we're finding ways of using concerns to mix that capability into the objects that need it. We like that. It definitely presents some unique challenges from our perspective in terms of how you test that, but I think that's just something we have to learn over time and there may be areas, I think, like you're saying, where we're just going to have to find, like where we run out of rails right and we now need to do something else.
Speaker 3:One thing that struck me, you know I've been building software for a long time and have exposure to quite a few frameworks and Django is the other. You know sort of popular, you know dry model view, you know presenter framework that Django is, and one of the things that I always admired about that framework, as I was using it, was that Django decomposes logical parts of your application into what it calls applications. So you have your Django project, which is composed of a bunch of discrete applications, each of which theoretically although never practically in my experience could be picked up and dropped into a different Django project somewhere and just continue to get along just fine. What I thought was nice about that was the ability to say, hey, all of the models, all of the controllers, all of the views and view models, all of those things which were related to each other, were all together.
Speaker 3:And I think one of the cognitive challenges in a Rails app for us has been that Rails will put you know all views go in one place, all controllers go in one place and all models go in one place. The closest thing to grouping you really get, if you're following the pattern of the framework, is to just say I'm going to have a naming or a folder structure that's the same in each of those folders and then that way I can kind of fake, have all of my stuff together. So I thought that's interesting. I still think I'd like to get my stuff all of my views and models and controllers that are related into one space, but it's probably more of a matter of taste than anything else really.
Speaker 1:Yeah, and I can hear where you're coming from. I've seen a common habit that I'm frankly not a big fan of, which is people see this naming scheme of having a models, folder, controllers, folder views, folder helpers, mailers, etc. And they continue that they add a decorators folder, app models, decorators, app models, services, app models, whatever it may be, and you know these. Basically, the folders are named for the design pattern that the files inside of it follow. Um, but I think those kinds of things are different in a different way than models, views and controllers are different from each other, Because why do we even bother putting code, why do we even bother organizing code at all, like we could just have one folder and put every single file in there?
Speaker 1:Why do we create trees of folders? And obviously the reason is because we might be interested in working with a certain area of code, but we don't know where it is, and so we need a structure that helps us find the things we want to find. And if you're dealing with something on the page, you know some kind of input field or something like that. Obviously you know that's going to be view related, and so you know that you's going to be V related, and so you know that you can look in app views. Or if you want something that's like related to some database query, you can bet that you're going to want to look in the models directory, and so you kind of know which one of those three that you're going to want to be looking in.
Speaker 1:And same even with like mailers and some certain other things, jobs, um, but is there ever a case where you're like I want to go and see all my um, all my factory objects you know, I'm not talking about in testing, I'm just talking about like factory pattern in your, in your application? It's like, no, you, you know like the domain that you're going to be working in, but you don't necessarily know what design pattern is going to implement it. So I don't think that way of doing it makes as much sense. Um, and and so like I, I think you're right that it's subjective, it's kind of a judgment call like when do you stop like?
Speaker 1:I think putting like with like makes a lot of sense, and by like with like I mean according to domain concept, I could see that going all the way to like you have all the billing related stuff, including all the the views, models and controllers inside of a billing folder. I can see that argument and that would make sense to me. I can also see the argument for, uh, having the app sorry, having the view, controller and model folders first, um, but what I don't think makes much sense is to have those like finer grain design pattern folders yeah, yeah, and whenever you know, of course, we're constantly looking for inspiration on how to do better.
Speaker 3:We'll look at you know open source Rails apps and things that were other people's Rails apps that they've shared, and looking for inspiration there, and we see that, you know, outside of the sort of the golden path that Rails provides, everyone's coming up with other ways to try to add in and expand on what the framework has provided, and it's very oftentimes just like add another folder, name it the pattern and drop a lot of stuff in there.
Speaker 3:We definitely see that all the time. You know it's funny in my mind it just never connected cognitively that the names tend to be the pattern of the thing that gets put in there, which makes me dislike our lib folder a little bit more now, because lib is absolutely not a pattern, unless you wanted to call Juncture our pattern. Now I'm really feeling it.
Speaker 1:Interesting. Yeah, I've noticed that too. I've poked around some open source Rails projects. Noticed that too. I've poked around some like open source rails projects, um, but mainly we just looked at the at the test suites, because well, I guess that presentation you saw in boston um, that was that was pulled from an open source rails project. Um it, you know, those open source projects often provide a good fodder for criticism, which is maybe kind of mean, but I figure, hey, you're putting it out there publicly. It's fair game for me to do what I want with. Yeah, you know a couple concepts that we've kind of alluded to but I don't know if we've called them out specifically are like loose coupling and the concept of cohesion, so like.
Speaker 1:I think I forget exactly what you said, but it put me in mind of cohesion, again, putting like with like. You have areas of code where everything in that area is related to the other stuff in that area, and then the loose coupling where you have. You know, rails projects tend to honestly have a lot of tight coupling. Part of that might be a symptom of the fact that in Rails everything is available all the time. You can reference any model from any other model, reference it from any controller, anything, so you can be really free-handed with all that stuff. But that freedom kind of comes with a price, in that it's really easy to create a tangled mess of interdependencies. Have you felt that pain at all, or or have you been able to keep things kind of loose, more loosely coupled?
Speaker 3:You know, I think we we've done a pretty good job of that. So, despite not having it set up the way I think I would have imagined it in my mind, we're following the framework guidelines and we do have, you know, related models and controllers existing in the same modules. So it becomes really clear when we're pulling something from a different module into this mod. So that, like that coupling is quite obvious in the code. Even just you know, by the fact of pulling something in that's in another module tends to be a very long line of code compared to the other lines of code in that code page. So I don't think we've done too bad of a job with that. At the same time, some coupling is kind of what we were looking for in this effort. So you know Irina pointed this out in the talk but our system we had around 70 Java microservices all at different levels of abstraction, and it was very difficult for us to get things done because everything was so loosely coupled.
Speaker 3:When I wanted to build a new feature or when the product team had a new feature we wanted to get off the ground. It meant that we would take more than one team. Oftentimes at least three different engineering teams would have to get involved, bringing their services to the table so that we create the functionality we were trying to create. And it just took forever because we would have to figure out how do we, given that these systems are separated and clearly cannot really know much about each other, without breaking the microservices paradigm completely, how do we set this up so that we can build this? A little bit of coupling, obviously. We don't want tight coupling, but a little bit of coupling. That's sensible means we can build stuff and get experiments out the door much faster, and that coupling was just not even available to us in the past. I'll give you an example here. So in our business, some common domain, things are things like vehicles and pricing plans and subscriptions and pricing plans and subscriptions.
Speaker 3:And in the old world all three of those things lived completely isolated, separated lives that didn't know anything about each other. So having a vehicle didn't tell you anything about how much that vehicle would cost. Or having a subscription in your hands didn't tell you much about what vehicle or pricing plan that subscription might be. You'd have to go elsewhere to get that. You know it doesn't really make that much sense for our business, because rarely do I have a subscription where I don't care about the other two things that are generally associated with it. So having access to the vehicle, that's a part of the subscription and the pricing plans part of the subscription.
Speaker 3:Without any effort it's been such a boon like we've been able to. You know, just since launching in May, we've launched at least a dozen major new features that we had been it had in the works for a long time before. And that's all because the coupling is available. But we just have to be very cautious because, like you and I both know, you know, tight coupling leads to us having the opposite problem in the future, where we can't change one thing without breaking everything else. And that's what we just have to be really cautious to avoid when it makes sense to connect two things to each other that you couldn't do with the typical microservices or correctly built microservices architecture. But if you do it too much you're certainly going to be wishing you hadn't. So it's really kind of a cool feature of the framework to me.
Speaker 1:Yeah, I used to think about programming principles being like right or wrong, or good or bad or whatever, and then more recently I've shifted my thinking toward costs and benefits and tradeoffs and stuff like that. I've like, I've like adopted kind of a whole like economic based view of software systems, whole like economic based view of software systems. Um, and I found the metaphors to be like really, really fitting and useful. Um, because people have all these arguments about like is duplication bad, for example?
Speaker 1:and it's like well, it's not exactly. That question doesn't even make sense. It's not good or bad, it's just that it has costs and benefits, and in certain scenarios the price is worth it and in others it's not. Same with global variables. Everybody is taught that global variables are bad, but that's not exactly true. It's just that they have a cost and sometimes the price is worth it and sometimes it's not.
Speaker 3:That's right. Yeah, I think when I work with engineers and architects who tend to have a very strict sort of dogmatic approach to those you know, best practices and principles I find it both challenging and entertaining. The entertaining part coming from the fact that I was that guy for a long portion of my career, where you know the stuff that I knew was right was the only right way. And you know those who worked with me my apologies to all of them, because I certainly inflicted my ideas upon all of them. And then the challenging part, of course, is that you know you really don't, I think, getting into a software engineering discussion about right and wrong, like you're saying. You're almost always having the wrong discussion. If it's right or wrong, it's like will this work in this case and will the cost that we pay for that be something we're willing to?
Speaker 2:pay.
Speaker 3:And if yes, then let's do it that way, and if not, then let's go find the thing that we are willing to accept instead. And if yes, then let's do it that way, and if not, then let's go find the thing that we are willing to accept, instead of making it a black and white decision.
Speaker 1:Yeah, that's the thing that often makes me kind of sad with testing is like people are seeking the right way to do it and they want to do it correctly and properly, and it's like that's understandable, obviously, but it's like properly, according to who, like who's gonna come and like give you a grade on this.
Speaker 1:Like what you should be focusing on is not doing it properly, but doing it in a way that's advantageous to you. And maybe this is a whole like, I don't know, maybe it's an extension of like, uh, the way people, the mindset people have in school, where it's like you do things a certain way and somebody grades you on it and there's no real, it's all in a sandbox, you know, and so there's no, there's no real application of it, and so you can't go by the results you get. You can only go by the grade you get. And so now people are applying that mindset to software, but you're not going to get a grade. I mean, maybe you are going to get a grade from your boss or whatever, but the thing that matters more is how it actually helps you or doesn't help you.
Speaker 3:Yeah, that's right. I think it's the. Did you solve the problem? And, ultimately, I think, the thing that you know. Sometimes as engineers, we have the ability to work on something where we're just enjoying the engineering, but most of the time we're trying to build something valuable that solves a business problem or an educational problem, and when that happens, the real thing you're aiming to do is solve the problem, and solving the problem is not always the same thing as the most ideal engineering design. Oftentimes they're at odds with each other.
Speaker 1:Yeah, and it's tough, I feel like every day of our lives as programmers we're dealing with this optimization problem where there are two competing optimization targets, where it's like you want to meet the business requirements for functionality, but then also you can't only meet today's requirements at the expense of not being able to meet tomorrow's requirements, and so it's like you need to be reasonably fast with what you're doing today. But but you can't be ignorant of the long-term cost of ownership of what you're doing, or else you're going to paint yourself into a corner really quickly. That's right. Yeah, and it's such a complex technical and psychological balancing act with all that stuff, that's right.
Speaker 3:I think it's. We've also labeled the compromise as something that people tend to see as negative, the compromises that we end up making in the name of solving the problem with a less than ideal engineering solution. We usually call that technical debt. We think of debt in sort of negative terms, but I think maybe there's a better word out there. I'm not necessarily a wordsmith, but I think at least technical debt itself probably deserves a rebrand of some kind. Debt itself is a very useful tool. Obviously, it's a destructive tool when a person or company has too much of it, but with debt a person is able to acquire a home that they wouldn't have otherwise been able to afford.
Speaker 3:And with debt, an engineering team is able to ship a feature in time to meet a customer demand that they wouldn't have otherwise been able to do. So I think it's worth saying that just because something that you're building is going to create some technical debt, I think that's okay. The real problem with technical debt isn't the debt itself. It's the organization's inability to make time to pay down that debt before it becomes too late.
Speaker 1:Exactly. In my experience, the paying down of the debt never happens, just more debt gets piled on top of it. I actually wrote a blog post on this topic just last Friday, because I've been uncomfortable with the technical debt metaphor for a long time and this is not original to me, I don't think but I've been using a different metaphor of blades. So, like I think of a code base as a shed full of saw blades, we can say, and some of those blades are sharp and some of those blades are dull. And so a sharp blade, of course, is maybe like an object that is nice and tidy and easy to understand. You can cut with it quickly because it's very sharp. You can see it and just know right where you need to go and the code and the exact change you need to make. It's super quick to work with. And then, obviously, a dull blade is the opposite and like. The reason I like that is because, like as you said, debt isn't intrinsically bad. You can buy things by going into debt that you could never buy otherwise, because you're just never going to have that much money at a time. But in the real world, debt is always paid back in a structured way, but with the saw blades it's like cutting with a dull saw is never preferable to cutting with a sharp saw.
Speaker 1:And it's also really clear, like when maybe it's not so clear, but I think it's clearer when the investments need to happen. Like if you pick up a saw and you're like, oh man, this saw is really dull. Let me spend five minutes sharpening this saw so that, instead of taking 10 minutes to cut this piece of wood, it takes one minute or whatever it may be. Or you know, you cut with that dull saw and you're like, wow, that took a long time. Let me sharpen this so that next time somebody has to use this, they can cut faster. And another thing I like about that is it's okay to have dull saws in your shed. Like if there's a saw that you haven't touched for two years and you don't think you're probably even going to touch it again. Like who cares? Like don't sharpen that saw. That's not a smart investment. So it maybe helps guide people toward where they should be investing effort, whereas technical debt it's like how does that guide you toward where to invest effort? It's maybe not so clear.
Speaker 3:So, yeah, I've been using that metaphor for a while as a person who, in his free time, makes a lot of sawdust in my garage, I really appreciate this metaphor. So I think it's great because you know if all your blades are dull you're sure you can cut some wood, but you're going to end up with some real sloppy tear out. So you know why not take some time and sharpen it up before your next project. Like that kind of thing is a really especially for those who like to cut wood, that's a really good metaphor.
Speaker 1:Okay, so I can't leave that alone, especially because you and I talked a little bit about that before. But can you tell us about your woodworking and such a little?
Speaker 3:bit about that before, but can you tell us about your woodworking and such Sure it's? I mean, it's still expanding and growing, so I've, uh, uh, a couple of years ago, bought a house so I could move out of the city and get enough space to actually have tools to do projects that are a bit bigger. Um, but typically I like to make things out of wood, usually something that's useful or fun, something people will use. Board games are common for me. There's an abstract strategy, ancient Viking board game called Neftafel that I really like playing, and so I've made quite a few sets and usually I just make them, play them and then give them away to friends.
Speaker 3:And I have a pattern for a bed that I'm planning to make for myself coming up soon, so that'll be my next big project. But yeah, moving into the house has meant that I've expanded beyond just what I could cut in a small apartment and hopefully be into full-on furniture by the end of the year.
Speaker 1:Yeah, by the way, that game that you make, what's the name of it again? Hnepetafel, hnefatafl, Hnefatafl.
Speaker 3:Yeah, h-n-e-f-a-t-a-f-l, I think, is the right spelling. I mean, if you search for Viking chess, you'll likely find it.
Speaker 1:I think there was a television show that featured the game, which is how I discovered it, and it's become quite popular since then yeah, I think when you first told me about it, um, when I was in boston, um I like googled it on my phone so I'd remember the name and I was like I, I think I told you like there is a chance that my kids had like heard of it before, because they're really into like norse stuff. And I told my kids about it and they're're like, yeah, I've heard of that. Yeah, so that was kind of funny, but I had never heard of it. It's like so it's kind of like chess, but it's like different because it's not symmetrical, right, like the two sides. Well, can you explain a little bit for us?
Speaker 3:Yeah, so, and there's a couple of different rules. There's a standard rule set and then there's a Copenhagen rule set, but the game is very similar. Either way you play it. One person will play as the king, and the king has a few defenders surrounding him, and the other person will play as sort of an attacking army that's trying to capture the king. So if you're playing as the king, your goal is to escape the board, and if you're playing as the attacker, your goal is to escape the board, and if you're playing as the attacker, your goal is to capture the king. And in order to make the game fair, usually you play it in twos, so each person takes a turn being king and then you know hopefully you don't have a draw, but you could. But it's really fun. The game board itself can be any size, from like a 7x7 size board all the way up. I think I've seen as large as a 22x22 size board so it scales up really well.
Speaker 3:And the larger the game board size, the more complex the strategy becomes, because the geometry becomes a bit more interesting.
Speaker 2:But yeah, it's a lot of fun.
Speaker 3:Definitely you know a simpler game to play than, uh, chess by far. You know you've really only got, uh, two different types of pieces, the king and the other pieces, uh, so you don't have to remember as many rules, but it's a lot of fun uh, and it's kind of cool to play something that has, uh uh, some history behind it, uh, and uh, it's just a little bit different I bet it's hard to find partners to to play against, because not many people are familiar with the game that is correct.
Speaker 3:Uh, fortunately I've got some tabletop gaming friends who I can usually trick into playing game with me. Uh, but uh, you know a game or two, and then we're on to something else.
Speaker 1:Okay, yeah, I've gone a little deep into chess in the last few years. Me and my boys started going to a chess club every Tuesday night I don't know, maybe two or three years ago, something like that but I always get beat really bad, and so I got tired of that and I'm not interested in playing online or anything like that, because I get enough time in front of the screen.
Speaker 3:Yeah.
Speaker 1:And people are like, go on the chess databases online and stuff like that, and I'm like that would kind of defeat the purpose of this hobby, this analog hobby that I'm trying to have. But we recently started taking chess lessons from the guy who runs these, these chess meetups, and his rating, dear listener, if you know chess, it's like in the 2000s, it's like 2500 or something like that like he's really really good, um, and so it's been fascinating to learn from him and to make parallels between chess and programming.
Speaker 1:Because, it's like fractal You'll never reach the bottom of it. As soon as you conquer one level of chess, it just opens up a whole new level of nuance, level of nuance. And then, once you've grasped that level of nuance, there's like 10 more levels of nuance inside of that. Each one you know, and it just keeps going deeper and deeper and you think sometime you might reach the end. But eventually you just realize it's infinite.
Speaker 3:Yeah, I think that's a great great analogy. And another one I think that's chess a great, a great analogy. And another one, I think that's chess, uh, uh, chess and programming sort of overlapping is. You know, when I play chess, uh, I'm always asking this question okay, how, from where I'm at now, how could I lose? Uh, and I'm just frequently trying to understand, like you know, putting myself in the position of the person I'm playing with, you know, how do I lose from here? And if I can think through that, then I kind of understand what the options that they might be thinking of are.
Speaker 3:And I think similarly when designing systems or writing code or just generally anything related to our companies. You know how does this fail, how does this thing end up not working the way and what are all those ways? And that's kind of a fun game to play with your team. If you're part of an engineering team. It's like let's just list out the ways this fails. Because once you can understand that and once you've done that exercise a few times, you start to find there are just some common patterns of failure that exist for certain patterns of software and they become intuitive. So you don't even have to ask the question because you start as you're going down one design path you inherently already recognize, like ah, this path leads to this kind of failure.
Speaker 3:Is that a type of failure that we're comfortable with? If not, then we need to take another path.
Speaker 1:So it's very similar in that way. Okay, um, this is a meaty topic, so let me. Let me ask you this um, and I have my own ideas, but I want to. I'm curious how you look at some of these things. Um, let's say there's a project that you need to complete and it needs to be done by one month from now. Doesn't really matter what it is, but, like if you have a fixed deadline and maybe somewhat of a squishy scope, it just needs to meet the business objective one way or another. How do you approach the like? What risks do you think about at the beginning of the project?
Speaker 3:Yeah, there, I mean you have to with a squishy scope. You've got to get some clarity, whether it's coming from your team or, ideally, it's coming from whoever's asking for the work. Right, like that's really where you want that clarity to come from. But if you can't get it from there, then the team that's doing the work needs to manufacture its own clarity, and what that's got to look like is a list of here's what, in this timeframe, we can commit to getting done and we believe that generates the value that is being looked for in this way and here's what's out of scope. We'll just explicitly define these things are not in scope for this one month thing that we're getting done.
Speaker 3:If you cannot get that from whoever's asking for the work, then write it yourself and then give it to them, because now you've set the expectation, this is what I'm delivering, and it gives them a moment in time where they can say like, oh, no, no, no, that thing you're saying is not something that you can get done. That's actually really critical to this. We need to put that back in and that's fine. Then you have to negotiate to pull something out, but you can't if you're working without some sort of plan for what you're going to deliver at the end. It's sort of like going on a road trip but not taking a map with you. Right Like you'll meander your way there, but you probably won't take the route. That's the best.
Speaker 1:Yeah, yeah, yeah, there's a lot to unpack, even just right there. So, like something that I think I was hearing you saying is like one of the big risks is simply building the wrong thing. Yeah, yeah, risks is simply building the wrong thing. Yeah, yeah, um, and it's like building the wrong thing can even take multiple forms, like it's like you could build something. You you could just miss the mark and it's like you don't get a bullseye, you get, you know, a couple circles out or whatever, um, or you could like kind of hit the bullseye, but also like you wasted time building other stuff too and it's like, all right, the dartboard metaphor doesn't really apply anymore, but it's like, yes, you built some of the right stuff and you got that part right, but you also blew some of your time budget building stuff.
Speaker 3:That what you weren't economical.
Speaker 1:With your time, that's right and and you're.
Speaker 3:I think the dartboard metaphor actually sticks, because if you think about playing darts which I play poorly, uh, but do play, you know, you, you, after every shot, you calibrate, right like you shoot and you're a bit too low, you calibrate and you throw a bit. Shoot and you're a bit too low. You calibrate and you throw a bit higher. Ah, now I'm a bit too high, so calibrate. And that's what you're doing when you're building software, too, I actually don't. I think knowing where you're going is really important. I don't think it's a guarantee that you're going to take the most direct path to get there, because you still have some exploration to do. This is still software, after all. And when you're building something new, especially something that's somewhat novel, what you're going to find is there's a lot of stuff that you have to try and say like, oh, is this the right way to do this? No, it's not. There's going to be some experimentation that you're going to need to take in order to get it done.
Speaker 3:And there's the Pragmatic, pragmatic programmer book, which I'm looking at your shelf just to see if it's on there, but I'm sure you've got a copy with all those books there.
Speaker 3:You know there's a. It talks about this concept of tracer bullets, which you know, I think today's terminology is. Maybe that's a bit grim, but tracer bullets are this idea that you know you're when you're shooting in the dark. You add some ammunition that you can see and follow all the way, so you kind of know where you're aiming day cycles early on in a project where all of the stuff that was a question like is this feasible, can we interact with that API and get data back in a reasonable time or a format? We could work with those kinds of questions that we knew we would need to answer. We would actually just do small, upfront, discrete projects just to answer those questions and then, having done that, the rest of the project would go so much faster because we were able to take a few shots and figure out some things instead of experimenting once we were halfway through and then realizing like, ah, we need to redesign the whole thing because we didn't realize, oh, that API only responds, you know, in increments of two seconds or more.
Speaker 3:So when you find that out late in the project you're going to need to redesign or some caching or something. It kind of messes you up. So so I think the dartboard analogy sticks. Uh, because that sort of constant calibration is is what playing a game of darts is like, especially for people who are bad like me. Uh, and so I would.
Speaker 1:I would keep going with that one yeah, um, that that makes me think of of some other stuff too. There's such a nuance between not doing waterfall big design up front kind of stuff, not doing like waterfall big design up front kind of stuff, and not being like um, not taking like a ready fire aim approach yeah.
Speaker 1:Um, because, like, it's absolutely true that your first swing at something is never going to be, you're never going to do it right, um, and so you have to do the wrong things so that you know exactly how it's wrong, so that you can do the right thing. Um, but that's not the same thing as just like totally flying by the seat of your pants and just doing random stuff um one of the biggest failures that I see is that developers start building before they even really know what to build Like.
Speaker 1:I remember I worked at this one place and they wanted help like kind of shoring up their testing practices in general, and so I would pair with people and this happened more than once where I would get on a session with somebody and they would be like hey, I want help writing a test for this certain feature. And I'd be like okay, what's the feature you're supposed to do?
Speaker 1:And they're like well, I don't really know I'm like okay, well, like I can't do anything for you, because that's the first step of this whole thing. You can't write tests for something if if you don't know what you're trying to do.
Speaker 3:Yeah, that's right. And I you know one thing it's funny that you say that there's a there's a conversation that we're having now at Flexcar, as we're trying to refine the code and coming back to some old best practices that I remember, you know from from days gone by, where, when you ask somebody that question of how it will work, really what I'm trying to get folks to think of is imagine how you would use this, write the code as though the thing that you're building now is already existing, like how would you want to interact with it? Um, what is that api going to look like for the, for the person who ends up using your code later? Imagine that first. Then you can write a test that looks like that and then you can fill in the blanks, uh, on how it actually gets, how it actually does what you're trying to get done like. Then you can go write that code behind it.
Speaker 3:We have a lot of code right now.
Speaker 3:That's the opposite of that, where we we wrote code in this very Java-centric style, but in Ruby, where you'll see, for example, a whole lot of rigmarole around building up a command object and then just taking this big command object and then hitting apply, which has been notoriously hard to understand what's happening, especially when it's a command object that then instantiates more and more command objects down the stack, but also just not really fun to work with and not particularly testable in the way that you would think, because all of the context gets buried inside of the command instead of being readily available where you're actually using it, and so those kinds of things.
Speaker 3:You know we're saying, hey, stop, stop, just building the way you did and instead build for the experience of the developer who's going to use the code that you're creating. And imagine that I think that is. You know, people are seeing the like. I'm sort of creating some comparisons like here's the code that we have, here's a different way to think about that same code. You know which code would you rather be interacting with? And it makes a big difference for folks to be able to think about it that way.
Speaker 1:Yeah, I am so happy to hear you say that, because that's exactly the way I think about that. Also, exactly the way I think about that. Also this I don't know if I picked this up somewhere or what, but I call that, like outside in design, where I start with. I've also heard it called coding by wishful thinking where you like start with the outermost API and it's like what kind of and, by the way, dear listener, like when we say API, like obviously the first thing people think of is like a REST API over the network and stuff like that. The kind of API we're talking about right now is just like what is the interface between one object in your code base and the place that that object gets used? Object gets used, um, so like what kind of api would feel very natural in that, in that part of code?
Speaker 1:Um, and this is like talking again about how programming is fractal, like we could have a whole podcast about just this topic here, because it's like there there are essential points and there are incidental details and there's stuff you want to see and there's stuff you don't want to see, and there's a real art to determining what should be shared.
Speaker 1:You know what should the external api be aware of. And what should it not like? It's it's kind of I think of it sometimes like there's a pipe or a hole in the wall or something like that, and you want that hole in the wall to be appropriately sized and you want the appropriate things to go through it, like what, what arguments do you want to send and what? Because, like that command pattern, dot apply thing, that like as you're kind of saying that like obfuscates, that that doesn't just hide incidental details, that also hides the essence of what what's happening. So in that case you'd actually want to pull more from the internals of what's happening to the external API so that you can see oh, it's invoking this billing related code or whatever it may be. But yeah, there's a whole art to that. That, again, is very nuanced.
Speaker 3:Yeah, and it's a very subjective thing as well. So, you know, for some people I think they've become accustomed to, you know, the big, chunky multiple layers of indirection sort of in the code base, and you know I can't fault them for that as a person who used to be really excited about that kind of code myself. The real problem with that type of code in my experience is somebody who's new to the code base and how quickly they can become effective. A great example from our own code is as we're working with our billing system. We've got a third-party billing system that we work with and there's a chunk of code where we're just trying to get the most recent receipts for a particular customer so that we can show them to the customer.
Speaker 3:And the way that code looked was it was a building up this great big command object that was, you know, needed a lot of context to be injected in there and then including, you know, the customer details In fact most of it was just customer details and then that would be applied and then that would call a bunch of other objects down the chain to go to our provider, get the data, serialize it and all that and come back. But you know the conversation we had was wouldn't it be better since what we're looking for is this customer's receipts If we could just simply have an API on the customer object, which was customerreceipts? We had a little bit of a debate on that one, but it certainly is more natural to somebody reading it what that is intending to return when we make that method invocation.
Speaker 3:The real debate that we got into honestly there is whether or not that's clearly a method invocation or not, because Ruby very easily hides the fact that, whether you're making an attribute, referencing an attribute or calling a method. But it was such a nice, you know, customerreceipts is such a nice way of expressing what I'm trying to do, compared to this massive rigmarole of building up command objects and then, you know, feeding them to another API object or API management object and then applying the whole thing.
Speaker 1:So yeah, yeah, and in my experience those kinds of API decisions pay off. I mean, you have to be judicious about it obviously. Like again the sharpening the saws thing. Is it like is this an important saw that we use all the time, or is it not?
Speaker 1:Sounds like that one probably was um but, but as long as it's like a thoughtfully made investment, um, in my opinion, those, those investments are work worth making and, like I would rather spend an entire day debating the name of a database table with somebody and arriving at something good, then making a hasty decision and then you have to live with with that, you know, just a little bit imperfect decision, but it's such a fundamental concept in the application that you can't afford even a, a small, um, a small, I don't know what you call it like, a small deviation from reality or whatever, because then you get a paper cut every day for the rest of your life. Yeah, yeah, so we should probably start wrapping up soon. But I do want to ask you one more question. You've been to a number. I think you've been to a number. I think you've been to a number of ruby and rails conferences. Recently you were at least at rails conf, of course, in detroit. Where have you gone to? Oh, you went to blue ridge ruby, right with ruby, that's right.
Speaker 3:Yes, yeah, yeah, how was that it was great. Uh, you know, obviously a very different type of conference from RailsConf, a smaller, more intimate single-track conference. But what was great about it was the ability to interact more directly with folks. It wasn't in RailsConf. I found myself being really interested to talk with people, but having to figure out where in the world are they right now because it's such a big space. So the hallway track, as it's called, is a little bit more difficult to manage. At the smaller conference, you know, everyone got out at the same time and we would all kind of be in the same spaces. So being able to ask questions about things you've heard, or being available to answer questions from people who were interested in what you might have been talking about with someone else, that was great. I really did enjoy that quite a bit.
Speaker 3:Also, asheville just a beautiful part of the world. If anybody listening here gets a chance to visit, you certainly should. And then, on top of that, we've been hosting some of the Boston Ruby meetups here at Flexcar. So Peter Tsai, who runs that meetup, has asked if we'd be willing to share our space and I said absolutely. You know, we don't want to be the type of community member that's simply taking. So if you're in Boston, you should come check out a Ruby meetup here at Flexcar.
Speaker 1:Yeah, and, by the way, dear listener, if you find yourself in Boston, um, I don't remember if I talked about this on the show before, but when I was walking I don't remember from one place to another Um, I think I was walking to the Ruby meetup, actually Um, and I walked through Boston's Chinatown and I like made a mental note. I'm like I want to come back here at some point because I really like Chinese food. I went to this place called Taiwan Cafe I think Peter's wife actually recommended it and it was really great. It was so good that I went there twice. I have no idea what I got, because it was all just Chinese characters, and I just like pointed to something.
Speaker 1:Um, the first night I had some like spicy beef soup Again, no idea what it was. The second one, I had a little clearer idea. It was some kind of Sichuan dish, and Sichuan is, uh, it's, it's a province that's known for its spicy food, and there was this thing I'd never had. I don't know if you've had this freedom, but, um, these, um, sichuan peppercorns. Have you had those before?
Speaker 1:yes, I have oh yeah, yeah, I had never had them but I had heard about them and they're like numbing sensation that they give um and it was um. It was really interesting and it was like really really good, but it was almost more like it was more that it was an interesting, novel food experience and so my like boston trip is forever linked with this uh sichuan sichuan dish that I ate. So, dear listener, if you ever find yourself in boston, uh, like Chinese food, check out Taiwan Cafe.
Speaker 3:Yeah, I also recommend and you know we have a great Chinatown in Boston. It's something that people often don't realize, but the community is fantastic, Very welcoming place to go. And you know, whatever your Asian food tastes are, you'll probably find some version of it there.
Speaker 1:so it's been definitely had more than my fair share of meals there nice, um. Yeah, and very last question for your freedom is there any place where people should go to um to find out more about you? Flex car, whatever you want to share, sure, I mean, I'm easy to find.
Speaker 3:there's not a lot of guys roaming around the internet named Freedom these days, but you can find me on Twitter. My handle is APIguy. I'm on LinkedIn with my real name and you can find all you want to know about Flexcar at flexcarcom.
Speaker 1:All right, and we'll put that stuff in the show notes and Freedom. Thanks so much for coming on the show.
Speaker 3:Thanks, stuff in the show, notes and freedom. Thanks so much for coming on the show. Thanks, jason, it's great.